First set of changes for windows
[cascardo/gnio.git] / gnio / ginet4address.c
1 /* GNIO - GLib Network Layer of GIO
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
27 #ifndef G_OS_WIN32
28 # include <netinet/in.h>
29 # include <arpa/inet.h>
30 #else
31 # include <winsock2.h>
32 # define IN_LOOPBACKNET 127
33 #endif
34
35 #include "ginet4address.h"
36
37 G_DEFINE_TYPE (GInet4Address, g_inet4_address, G_TYPE_INET_ADDRESS);
38
39 struct _GInet4AddressPrivate {
40   union {
41     guint8  u4_addr8[4];
42     guint32 u4_addr32;
43   } addr;
44 };
45
46 static gboolean
47 g_inet4_address_is_any (GInetAddress *address)
48 {
49   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
50
51   return (g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32) == INADDR_ANY);
52 }
53
54 static gboolean
55 g_inet4_address_is_linklocal (GInetAddress *address)
56 {
57   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
58
59   return ((g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32) & 0xffff0000) == 0xa9fe0000);
60 }
61
62 static gboolean
63 g_inet4_address_is_loopback (GInetAddress *address)
64 {
65   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
66
67   return (G_INET4_ADDRESS (address)->priv->addr.u4_addr8[0] == IN_LOOPBACKNET);
68 }
69
70 static gboolean
71 g_inet4_address_is_sitelocal (GInetAddress *address)
72 {
73   guint32 addr;
74
75   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
76
77   addr = g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32);
78
79   return ((addr & 0xff000000) == (10 << 24)) || ((addr & 0xfff00000) == 0xac100000) || ((addr & 0xffff0000) == 0xc0a80000);
80 }
81
82 static gboolean
83 g_inet4_address_is_multicast (GInetAddress *address)
84 {
85   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
86
87   return IN_MULTICAST (g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32));
88 }
89
90 static gboolean
91 g_inet4_address_is_mc_global (GInetAddress *address)
92 {
93   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
94
95   return FALSE;
96 }
97
98 static gboolean
99 g_inet4_address_is_mc_linklocal (GInetAddress *address)
100 {
101   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
102
103   return FALSE;
104 }
105
106 static gboolean
107 g_inet4_address_is_mc_nodelocal (GInetAddress *address)
108 {
109   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
110
111   return FALSE;
112 }
113
114 static gboolean
115 g_inet4_address_is_mc_orglocal (GInetAddress *address)
116 {
117   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
118
119   return FALSE;
120 }
121
122 static gboolean
123 g_inet4_address_is_mc_sitelocal (GInetAddress *address)
124 {
125   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE);
126
127   return FALSE;
128 }
129
130 static void
131 g_inet4_address_finalize (GObject *object)
132 {
133   GInet4Address *address G_GNUC_UNUSED = G_INET4_ADDRESS (object);
134
135   if (G_OBJECT_CLASS (g_inet4_address_parent_class)->finalize)
136     (*G_OBJECT_CLASS (g_inet4_address_parent_class)->finalize) (object);
137 }
138
139 static void
140 g_inet4_address_dispose (GObject *object)
141 {
142   GInet4Address *address G_GNUC_UNUSED = G_INET4_ADDRESS (object);;
143
144   if (G_OBJECT_CLASS (g_inet4_address_parent_class)->dispose)
145     (*G_OBJECT_CLASS (g_inet4_address_parent_class)->dispose) (object);
146 }
147
148 static void
149 g_inet4_address_class_init (GInet4AddressClass *klass)
150 {
151   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
152   GInetAddressClass *ginetaddress_class = G_INET_ADDRESS_CLASS (klass);
153   
154   g_type_class_add_private (klass, sizeof (GInet4AddressPrivate));
155
156   gobject_class->finalize = g_inet4_address_finalize;
157   gobject_class->dispose = g_inet4_address_dispose;
158
159   ginetaddress_class->is_any = g_inet4_address_is_any;
160   ginetaddress_class->is_linklocal = g_inet4_address_is_linklocal;
161   ginetaddress_class->is_loopback = g_inet4_address_is_loopback;
162   ginetaddress_class->is_sitelocal = g_inet4_address_is_sitelocal;
163   ginetaddress_class->is_multicast = g_inet4_address_is_multicast;
164   ginetaddress_class->is_mc_global = g_inet4_address_is_mc_global;
165   ginetaddress_class->is_mc_linklocal = g_inet4_address_is_mc_linklocal;
166   ginetaddress_class->is_mc_nodelocal = g_inet4_address_is_mc_nodelocal;
167   ginetaddress_class->is_mc_orglocal = g_inet4_address_is_mc_orglocal;
168   ginetaddress_class->is_mc_sitelocal = g_inet4_address_is_mc_sitelocal;
169 }
170
171 static void
172 g_inet4_address_init (GInet4Address *address)
173 {
174   address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
175                                                G_TYPE_INET4_ADDRESS,
176                                                GInet4AddressPrivate);
177 }
178
179 /* ************************************************************************* */
180 /* Public Functions */
181
182 GInet4Address *
183 g_inet4_address_from_string (const gchar *string)
184 {
185   struct in_addr addr;
186
187 #ifndef G_OS_WIN32
188   if (!inet_aton (string, &addr))
189     {
190       g_warning ("Could not parse IP address %s", string);
191       return NULL;
192     }
193 #else
194   addr.s_addr = inet_addr (string);
195   if (addr.s_addr == INADDR_NONE)
196     {
197       g_warning ("Could not parse IP address %s", string);
198       return NULL;
199     }
200 #endif
201
202   return g_inet4_address_from_bytes ((guint8 *) &(addr.s_addr));
203 }
204
205 char *
206 g_inet4_address_to_string (GInet4Address *address)
207 {
208   guint8 *addr;
209
210   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), NULL);
211
212   addr = address->priv->addr.u4_addr8;
213
214   return g_strdup_printf ("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
215 }
216
217 GInet4Address *
218 g_inet4_address_from_bytes (guint8 bytes[])
219 {
220   GInet4Address *address = G_INET4_ADDRESS (g_object_new (G_TYPE_INET4_ADDRESS, NULL));
221
222   guint8 *addr = address->priv->addr.u4_addr8;
223
224   addr[0] = bytes[0];
225   addr[1] = bytes[1];
226   addr[2] = bytes[2];
227   addr[3] = bytes[3];
228
229   return address;
230 }
231
232 const guint8 *
233 g_inet4_address_to_bytes (GInet4Address *address)
234 {
235   g_return_val_if_fail (G_IS_INET4_ADDRESS (address), NULL);
236
237   return address->priv->addr.u4_addr8;
238 }
239
240 GInet4Address *
241 g_inet4_address_new_loopback (void)
242 {
243   guint8 addr[8] = {127, 0, 0, 1};
244
245   return g_inet4_address_from_bytes (addr);
246 }
247
248 GInet4Address *
249 g_inet4_address_new_any (void)
250 {
251   guint8 addr[8] = {0, 0, 0, 0};
252
253   return g_inet4_address_from_bytes (addr);
254 }