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