mem-overflow: test malloc and realloc corner cases
[platform/upstream/glib.git] / gio / ginetsocketaddress.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Authors: Christian Kellner <gicmo@gnome.org>
21  *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
22  */
23
24 #include <config.h>
25 #include <glib.h>
26 #include <string.h>
27
28 #include "ginetsocketaddress.h"
29 #include "ginetaddress.h"
30 #include "gnetworkingprivate.h"
31 #include "gioerror.h"
32 #include "glibintl.h"
33
34
35 /**
36  * SECTION:ginetsocketaddress
37  * @short_description: Internet GSocketAddress
38  *
39  * An IPv4 or IPv6 socket address; that is, the combination of a
40  * #GInetAddress and a port number.
41  */
42
43 /**
44  * GInetSocketAddress:
45  *
46  * An IPv4 or IPv6 socket address, corresponding to a <type>struct
47  * sockaddr_in</type> or <type>struct sockaddr_in6</type>.
48  */
49 G_DEFINE_TYPE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS);
50
51 enum {
52   PROP_0,
53   PROP_ADDRESS,
54   PROP_PORT,
55   PROP_FLOWINFO,
56   PROP_SCOPE_ID
57 };
58
59 struct _GInetSocketAddressPrivate
60 {
61   GInetAddress *address;
62   guint16       port;
63   guint32       flowinfo;
64   guint32       scope_id;
65 };
66
67 static void
68 g_inet_socket_address_finalize (GObject *object)
69 {
70   GInetSocketAddress *address G_GNUC_UNUSED = G_INET_SOCKET_ADDRESS (object);
71
72   if (G_OBJECT_CLASS (g_inet_socket_address_parent_class)->finalize)
73     (*G_OBJECT_CLASS (g_inet_socket_address_parent_class)->finalize) (object);
74 }
75
76 static void
77 g_inet_socket_address_dispose (GObject *object)
78 {
79   GInetSocketAddress *address G_GNUC_UNUSED = G_INET_SOCKET_ADDRESS (object);
80
81   g_object_unref (address->priv->address);
82
83   if (G_OBJECT_CLASS (g_inet_socket_address_parent_class)->dispose)
84     (*G_OBJECT_CLASS (g_inet_socket_address_parent_class)->dispose) (object);
85 }
86
87 static void
88 g_inet_socket_address_get_property (GObject    *object,
89                                     guint       prop_id,
90                                     GValue     *value,
91                                     GParamSpec *pspec)
92 {
93   GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object);
94
95   switch (prop_id)
96     {
97       case PROP_ADDRESS:
98         g_value_set_object (value, address->priv->address);
99         break;
100
101       case PROP_PORT:
102         g_value_set_uint (value, address->priv->port);
103         break;
104
105       case PROP_FLOWINFO:
106         g_return_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6);
107         g_value_set_uint (value, address->priv->flowinfo);
108         break;
109
110       case PROP_SCOPE_ID:
111         g_return_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6);
112         g_value_set_uint (value, address->priv->scope_id);
113         break;
114
115       default:
116         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117     }
118 }
119
120 static void
121 g_inet_socket_address_set_property (GObject      *object,
122                                     guint         prop_id,
123                                     const GValue *value,
124                                     GParamSpec   *pspec)
125 {
126   GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object);
127
128   switch (prop_id)
129     {
130       case PROP_ADDRESS:
131         address->priv->address = g_object_ref (g_value_get_object (value));
132         break;
133
134       case PROP_PORT:
135         address->priv->port = (guint16) g_value_get_uint (value);
136         break;
137
138       case PROP_FLOWINFO:
139         /* We can't test that address->priv->address is IPv6 here,
140          * since this property might get set before PROP_ADDRESS.
141          */
142         address->priv->flowinfo = g_value_get_uint (value);
143         break;
144
145       case PROP_SCOPE_ID:
146         address->priv->scope_id = g_value_get_uint (value);
147         break;
148
149       default:
150         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
151     }
152 }
153
154 static GSocketFamily
155 g_inet_socket_address_get_family (GSocketAddress *address)
156 {
157   GInetSocketAddress *addr;
158
159   g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
160
161   addr = G_INET_SOCKET_ADDRESS (address);
162
163   return g_inet_address_get_family (addr->priv->address);
164 }
165
166 static gssize
167 g_inet_socket_address_get_native_size (GSocketAddress *address)
168 {
169   GInetSocketAddress *addr;
170   GSocketFamily family;
171
172   g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
173
174   addr = G_INET_SOCKET_ADDRESS (address);
175   family = g_inet_address_get_family (addr->priv->address);
176
177   if (family == AF_INET)
178     return sizeof (struct sockaddr_in);
179   else if (family == AF_INET6)
180     return sizeof (struct sockaddr_in6);
181   else
182     return -1;
183 }
184
185 static gboolean
186 g_inet_socket_address_to_native (GSocketAddress  *address,
187                                  gpointer         dest,
188                                  gsize            destlen,
189                                  GError         **error)
190 {
191   GInetSocketAddress *addr;
192   GSocketFamily family;
193
194   g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), FALSE);
195
196   addr = G_INET_SOCKET_ADDRESS (address);
197   family = g_inet_address_get_family (addr->priv->address);
198
199   if (family == AF_INET)
200     {
201       struct sockaddr_in *sock = (struct sockaddr_in *) dest;
202
203       if (destlen < sizeof (*sock))
204         {
205           g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
206                                _("Not enough space for socket address"));
207           return FALSE;
208         }
209
210       sock->sin_family = AF_INET;
211       sock->sin_port = g_htons (addr->priv->port);
212       memcpy (&(sock->sin_addr.s_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin_addr));
213       memset (sock->sin_zero, 0, sizeof (sock->sin_zero));
214       return TRUE;
215     }
216   else if (family == AF_INET6)
217     {
218       struct sockaddr_in6 *sock = (struct sockaddr_in6 *) dest;
219
220       if (destlen < sizeof (*sock))
221         {
222           g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
223                                _("Not enough space for socket address"));
224           return FALSE;
225         }
226
227       memset (sock, 0, sizeof (*sock));
228       sock->sin6_family = AF_INET6;
229       sock->sin6_port = g_htons (addr->priv->port);
230       sock->sin6_flowinfo = addr->priv->flowinfo;
231       sock->sin6_scope_id = addr->priv->scope_id;
232       memcpy (&(sock->sin6_addr.s6_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin6_addr));
233       return TRUE;
234     }
235   else
236     {
237       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
238                            _("Unsupported socket address"));
239       return FALSE;
240     }
241 }
242
243 static void
244 g_inet_socket_address_class_init (GInetSocketAddressClass *klass)
245 {
246   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
247   GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass);
248
249   g_type_class_add_private (klass, sizeof (GInetSocketAddressPrivate));
250
251   gobject_class->finalize = g_inet_socket_address_finalize;
252   gobject_class->dispose = g_inet_socket_address_dispose;
253   gobject_class->set_property = g_inet_socket_address_set_property;
254   gobject_class->get_property = g_inet_socket_address_get_property;
255
256   gsocketaddress_class->get_family = g_inet_socket_address_get_family;
257   gsocketaddress_class->to_native = g_inet_socket_address_to_native;
258   gsocketaddress_class->get_native_size = g_inet_socket_address_get_native_size;
259
260   g_object_class_install_property (gobject_class, PROP_ADDRESS,
261                                    g_param_spec_object ("address",
262                                                         P_("Address"),
263                                                         P_("The address"),
264                                                         G_TYPE_INET_ADDRESS,
265                                                         G_PARAM_CONSTRUCT_ONLY |
266                                                         G_PARAM_READWRITE |
267                                                         G_PARAM_STATIC_STRINGS));
268
269   g_object_class_install_property (gobject_class, PROP_PORT,
270                                    g_param_spec_uint ("port",
271                                                       P_("Port"),
272                                                       P_("The port"),
273                                                       0,
274                                                       65535,
275                                                       0,
276                                                       G_PARAM_CONSTRUCT_ONLY |
277                                                       G_PARAM_READWRITE |
278                                                       G_PARAM_STATIC_STRINGS));
279
280   /**
281    * GInetSocketAddress:flowinfo:
282    *
283    * The <literal>sin6_flowinfo</literal> field, for IPv6 addresses.
284    *
285    * Since: 2.32
286    */
287   g_object_class_install_property (gobject_class, PROP_FLOWINFO,
288                                    g_param_spec_uint ("flowinfo",
289                                                       P_("Flow info"),
290                                                       P_("IPv6 flow info"),
291                                                       0,
292                                                       G_MAXUINT32,
293                                                       0,
294                                                       G_PARAM_CONSTRUCT_ONLY |
295                                                       G_PARAM_READWRITE |
296                                                       G_PARAM_STATIC_STRINGS));
297
298   /**
299    * GInetSocketAddress:scope_id:
300    *
301    * The <literal>sin6_scope_id</literal> field, for IPv6 addresses.
302    *
303    * Since: 2.32
304    */
305   g_object_class_install_property (gobject_class, PROP_SCOPE_ID,
306                                    g_param_spec_uint ("scope-id",
307                                                       P_("Scope ID"),
308                                                       P_("IPv6 scope ID"),
309                                                       0,
310                                                       G_MAXUINT32,
311                                                       0,
312                                                       G_PARAM_CONSTRUCT_ONLY |
313                                                       G_PARAM_READWRITE |
314                                                       G_PARAM_STATIC_STRINGS));
315 }
316
317 static void
318 g_inet_socket_address_init (GInetSocketAddress *address)
319 {
320   address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
321                                                G_TYPE_INET_SOCKET_ADDRESS,
322                                                GInetSocketAddressPrivate);
323 }
324
325 /**
326  * g_inet_socket_address_new:
327  * @address: a #GInetAddress
328  * @port: a port number
329  *
330  * Creates a new #GInetSocketAddress for @address and @port.
331  *
332  * Returns: a new #GInetSocketAddress
333  *
334  * Since: 2.22
335  */
336 GSocketAddress *
337 g_inet_socket_address_new (GInetAddress *address,
338                            guint16       port)
339 {
340   return g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
341                        "address", address,
342                        "port", port,
343                        NULL);
344 }
345
346 /**
347  * g_inet_socket_address_get_address:
348  * @address: a #GInetSocketAddress
349  *
350  * Gets @address's #GInetAddress.
351  *
352  * Returns: (transfer none): the #GInetAddress for @address, which must be
353  * g_object_ref()'d if it will be stored
354  *
355  * Since: 2.22
356  */
357 GInetAddress *
358 g_inet_socket_address_get_address (GInetSocketAddress *address)
359 {
360   g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), NULL);
361
362   return address->priv->address;
363 }
364
365 /**
366  * g_inet_socket_address_get_port:
367  * @address: a #GInetSocketAddress
368  *
369  * Gets @address's port.
370  *
371  * Returns: the port for @address
372  *
373  * Since: 2.22
374  */
375 guint16
376 g_inet_socket_address_get_port (GInetSocketAddress *address)
377 {
378   g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
379
380   return address->priv->port;
381 }
382
383
384 /**
385  * g_inet_socket_address_get_flowinfo:
386  * @address: a %G_SOCKET_FAMILY_IPV6 #GInetSocketAddress
387  *
388  * Gets the <literal>sin6_flowinfo</literal> field from @address,
389  * which must be an IPv6 address.
390  *
391  * Return value: the flowinfo field
392  *
393  * Since: 2.32
394  */
395 guint32
396 g_inet_socket_address_get_flowinfo (GInetSocketAddress *address)
397 {
398   g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
399   g_return_val_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6, 0);
400
401   return address->priv->flowinfo;
402 }
403
404 /**
405  * g_inet_socket_address_get_scope_id:
406  * @address: a %G_SOCKET_FAMILY_IPV6 #GInetAddress
407  *
408  * Gets the <literal>sin6_scope_id</literal> field from @address,
409  * which must be an IPv6 address.
410  *
411  * Return value: the scope id field
412  *
413  * Since: 2.32
414  */
415 guint32
416 g_inet_socket_address_get_scope_id (GInetSocketAddress *address)
417 {
418   g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
419   g_return_val_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6, 0);
420
421   return address->priv->scope_id;
422 }