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