1 /* GNet - Networking library
2  * Copyright (C) 2000-2002  David Helder
3  * Copyright (C) 2000-2003  Andrew Lanoix
4  * Copyright (C) 2007       Tim-Philipp Müller <tim centricular net>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA  02111-1307, USA.
20  */
21 
22 #include "gnet-private.h"
23 #include "inetaddr.h"
24 
25 #ifdef HAVE_LINUX_NETLINK_H
26 #include <usagi_ifaddrs.h>
27 #endif
28 
29 #ifdef HAVE_IFADDRS_H
30 #include <ifaddrs.h>
31 #endif
32 
33 typedef struct _GInetAddrNewListState
34 {
35   GStaticMutex              mutex;
36   GList                    *ias;
37   gint                      port;
38   GInetAddrNewListAsyncFunc func;
39   gpointer                  data;
40   GDestroyNotify            notify;
41 
42   gboolean                  in_callback;
43   gboolean                  is_cancelled;
44   gboolean                  lookup_failed;
45   guint                     source;
46 
47   GMainContext             *context;  /* main context (we hold a reference) */
48   gint                      priority;
49 } GInetAddrNewListState;
50 
51 typedef struct _GInetAddrNewState
52 {
53   GInetAddrNewListAsyncID   list_id;
54   GInetAddrNewAsyncFunc     func;
55   gpointer                  data;
56   GDestroyNotify            notify;
57   gboolean                  in_callback;
58   GStaticMutex              mutex;
59   GMainContext             *context;  /* main context (we hold a reference) */
60   gint                      priority;
61 } GInetAddrNewState;
62 
63 typedef struct _GInetAddrReverseAsyncState
64 {
65   GStaticMutex               mutex;  /* protecting all of the below           */
66   GInetAddr                 *ia;     /* copy of GInetAddr to get the name for */
67   GInetAddrGetNameAsyncFunc  func;   /* user-provided callback function       */
68   gpointer                   data;   /* user data for callback function       */
69   GDestroyNotify             notify;
70   GMainContext              *context; /* main context (we hold a reference)   */
71   gint                       priority;
72   gchar                     *name;   /* result                                */
73   guint                      source; /* id of idle callback to marshal result
74                                       * from lookup thread into main thread   */
75   gboolean                   in_callback;
76   gboolean                   is_cancelled;
77 } GInetAddrReverseAsyncState;
78 
79 
80 #ifdef GNET_WIN32
81 #include <process.h>
82 
83 /* TODO: Use Window's inet_pton/inet_ntop if they ever implement it. */
84 static int
inet_pton(int af,const char * src,void * dst)85 inet_pton(int af, const char* src, void* dst)
86 {
87   int address_length;
88   struct sockaddr_storage sa;
89   struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
90   struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
91 
92   switch (af)
93     {
94     case AF_INET:
95       address_length = sizeof (struct sockaddr_in);
96       break;
97 
98     case AF_INET6:
99       address_length = sizeof (struct sockaddr_in6);
100       break;
101 
102     default:
103       return -1;
104     }
105 
106   if (WSAStringToAddress ((LPTSTR) src, af, NULL, (LPSOCKADDR) &sa, &address_length) == 0)
107     {
108       switch (af)
109 	{
110 	case AF_INET:
111 	  memcpy (dst, &sin->sin_addr, sizeof (struct in_addr));
112 	  break;
113 
114 	case AF_INET6:
115 	  memcpy (dst, &sin6->sin6_addr, sizeof (struct in6_addr));
116 	  break;
117 	}
118       return 1;
119     }
120 
121   return 0;
122 }
123 
124 static const char*
inet_ntop(int af,const void * src,char * dst,size_t size)125 inet_ntop(int af, const void* src, char* dst, size_t size)
126 {
127   int address_length;
128   DWORD string_length = size;
129   struct sockaddr_storage sa;
130   struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
131   struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
132 
133   memset (&sa, 0, sizeof (sa));
134   switch (af)
135     {
136     case AF_INET:
137       address_length = sizeof (struct sockaddr_in);
138       sin->sin_family = af;
139       memcpy (&sin->sin_addr, src, sizeof (struct in_addr));
140       break;
141 
142     case AF_INET6:
143       address_length = sizeof (struct sockaddr_in6);
144       sin6->sin6_family = af;
145       memcpy (&sin6->sin6_addr, src, sizeof (struct in6_addr));
146       break;
147 
148     default:
149       return NULL;
150     }
151 
152   if (WSAAddressToString ((LPSOCKADDR) &sa, address_length, NULL,
153 			  dst, &string_length) == 0)
154     return dst;
155 
156   return NULL;
157 }
158 #endif /* GNET_WIN32 */
159 
160 
161 /* **************************************** */
162 
163 static GList* gnet_gethostbyname(const char* hostname);
164 static gchar* gnet_gethostbyaddr(const struct sockaddr_storage* sa);
165 static void   ialist_free (GList* ialist);
166 
167 
168 #if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX) \
169    || defined(HAVE_GETADDRINFO_GLIB_MUTEX)
170 G_LOCK_DEFINE (dnslock);
171 #endif
172 
173 
174 #if !defined(HAVE_GETADDRINFO)
175 static GList* hostent2ialist (const struct hostent* he);
176 
177 static GList*
hostent2ialist(const struct hostent * he)178 hostent2ialist (const struct hostent* he)
179 {
180   GList* list = NULL;
181   int i;
182 
183   if (!he)
184     return NULL;
185 
186   for (i = 0; he->h_addr_list[i]; ++i)
187     {
188       GInetAddr* ia;
189 
190       ia = g_new0(GInetAddr, 1);
191       ia->ref_count = 1;
192       GNET_SOCKADDR_FAMILY(ia->sa) = he->h_addrtype;
193       GNET_INETADDR_SET_SS_LEN(ia);
194       memcpy (GNET_SOCKADDR_ADDRP(ia->sa), he->h_addr_list[i], he->h_length);
195       list = g_list_prepend(list, ia);
196     }
197 
198   /* list is returned backwards */
199   return list;
200 }
201 
202 #endif
203 
204 
205 
206 /* Thread safe gethostbyname.  Maps hostname to list of
207    sockaddr_storage pointers. */
208 
209 static GList*
gnet_gethostbyname(const char * hostname)210 gnet_gethostbyname(const char* hostname)
211 {
212   GList* list = NULL;
213 
214   /* **************************************** */
215   /* DNS lookup: getaddrinfo() */
216 
217 #ifdef HAVE_GETADDRINFO
218   {
219     struct addrinfo hints;
220     struct addrinfo* res = NULL;
221     int rv;
222     GIPv6Policy policy;
223 
224     policy = gnet_ipv6_get_policy();
225 
226     memset (&hints, 0, sizeof(hints));
227     hints.ai_socktype = SOCK_STREAM;
228     if (policy == GIPV6_POLICY_IPV4_ONLY)
229       hints.ai_family = AF_INET;
230     else if (policy == GIPV6_POLICY_IPV6_ONLY)
231       hints.ai_family = AF_INET6;
232 
233     /* If GLIB_MUTEX is not defined, either getaddrinfo() is
234        thread-safe, or we don't have mutexes. */
235 #   ifdef HAVE_GETADDRINFO_GLIB_MUTEX
236     G_LOCK (dnslock);
237 #   endif
238 
239     rv = getaddrinfo (hostname, NULL, &hints, &res);
240     if (rv == 0)
241       {
242 	struct addrinfo* i;
243 	GList* ipv4_list = NULL;
244 	GList* ipv6_list = NULL;
245 
246 	for (i = res; i != NULL; i = i->ai_next)
247 	  {
248 	    GInetAddr* ia;
249 
250 	    ia = g_new0(GInetAddr, 1);
251 	    ia->ref_count = 1;
252 	    memcpy (&ia->sa, i->ai_addr, i->ai_addrlen);
253 
254 	    if (i->ai_family == PF_INET)
255 	      ipv4_list = g_list_prepend (ipv4_list, ia);
256 	    else if (i->ai_family == PF_INET6)
257 	      ipv6_list = g_list_prepend (ipv6_list, ia);
258 	    else
259 	      g_free (ia);
260 	  }
261 
262 	if (policy == GIPV6_POLICY_IPV4_ONLY)
263 	  {
264 	    list = ipv4_list;
265 	    g_list_free (ipv6_list);
266 	  }
267 	else if (policy == GIPV6_POLICY_IPV4_THEN_IPV6)
268 	  {
269 	    list = g_list_concat (ipv6_list, ipv4_list);
270 	    /* list will be reversed below */
271 	  }
272 	else if (policy == GIPV6_POLICY_IPV6_ONLY)
273 	  {
274 	    list = ipv6_list;
275 	    g_list_free (ipv4_list);
276 	  }
277 	else if (policy == GIPV6_POLICY_IPV6_THEN_IPV4)
278 	  {
279 	    list = g_list_concat (ipv4_list, ipv6_list);
280 	    /* list will be reversed below */
281 	  }
282       }
283 
284     if (res)
285       freeaddrinfo (res);
286 
287 #   ifdef HAVE_GETADDRINFO_GLIB_MUTEX
288     G_UNLOCK (dnslock);
289 #   endif
290   }
291 #else
292 
293   /* **************************************** */
294   /* DNS lookup: gethostbyname() */
295 
296 #ifdef HAVE_GETHOSTBYNAME_THREADSAFE
297   {
298     struct hostent* he;
299 
300     he = gethostbyname(hostname);
301     list = hostent2ialist(he);
302   }
303 #else
304 #ifdef HAVE_GETHOSTBYNAME_R_GLIBC
305   {
306     struct hostent result_buf, *result;
307     size_t len;
308     char* buf;
309     int herr;
310     int rv;
311 
312     len = 1024;
313     buf = g_new(gchar, len);
314 
315     while ((rv = gethostbyname_r (hostname, &result_buf, buf, len,
316 				  &result, &herr))
317 	   == ERANGE)
318       {
319 	len *= 2;
320 	buf = g_renew (gchar, buf, len);
321       }
322 
323     if (!rv)
324       list = hostent2ialist(result);
325 
326     g_free(buf);
327   }
328 
329 #else
330 #ifdef HAVE_GETHOSTBYNAME_R_SOLARIS
331   {
332     size_t len = 8192; /* Stevens suggest this size should be adequate */
333     char * buf = NULL;
334     struct hostent result;
335     struct hostent* he;
336 
337     do
338       {
339 	buf = g_renew (gchar, buf, len);
340 	errno = 0;
341 	he = gethostbyname_r (hostname, &result, buf, len, &h_errno);
342 	len += 1024;
343       }
344     while (errno == ERANGE);
345 
346     if (he)
347       list = hostent2ialist(&result);
348 
349   done:
350     g_free(buf);
351   }
352 
353 #else
354 #ifdef HAVE_GETHOSTBYNAME_R_HPUX
355   {
356     struct hostent result;
357     struct hostent_data buf;
358     int rv;
359 
360     rv = gethostbyname_r (hostname, &result, &buf);
361     if (!rv)
362       list = hostent2ialist(&result);
363   }
364 
365 #else
366   {
367     struct hostent* he;
368 
369 #   ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
370     G_LOCK (dnslock);
371 #   endif
372 
373     he = gethostbyname(hostname);
374     list = hostent2ialist(he);
375 
376 #   ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
377     G_UNLOCK (dnslock);
378 #   endif
379   }
380 #endif
381 #endif
382 #endif
383 #endif
384 #endif
385 
386   if (list)
387     list = g_list_reverse (list);
388 
389   return list;
390 
391 }
392 
393 /* Free list of GInetAddr's.  We assume name hasn't been allocated. */
394 static void
ialist_free(GList * ialist)395 ialist_free (GList* ialist)
396 {
397   GList* i;
398 
399   if (!ialist)
400     return;
401 
402   for (i = ialist; i != NULL; i = i->next)
403     g_free ((GInetAddr*) i->data);
404   g_list_free (ialist);
405 }
406 
407 
408 
409 /*
410 
411    Thread safe gethostbyaddr (we assume that gethostbyaddr_r follows
412    the same pattern as gethostbyname_r, so we don't have special
413    checks for it in configure.in.
414 
415    Returns: the hostname; NULL on error.
416 */
417 
418 gchar*
gnet_gethostbyaddr(const struct sockaddr_storage * sa)419 gnet_gethostbyaddr(const struct sockaddr_storage* sa)
420 {
421   gchar* rv = NULL;
422 
423   /* We assume if there's getaddrinfo(), then there's getnameinfo(). */
424 #ifdef HAVE_GETADDRINFO
425   {
426     int gnirv;
427     char host[NI_MAXHOST];
428 
429 
430 #   ifdef HAVE_GETADDRINFO_GLIB_MUTEX
431       G_LOCK (dnslock);
432 #   endif
433 
434   again:
435     gnirv = getnameinfo((const struct sockaddr*) sa,
436 			GNET_SOCKADDR_LEN(*sa),
437 			host, sizeof(host),
438 			NULL, 0, NI_NAMEREQD);
439     if (gnirv == 0)
440       rv = g_strdup (host);
441     else if (gnirv == EAGAIN)
442       goto again;
443     else
444       rv = NULL;
445 
446 #   ifdef HAVE_GETADDRINFO_GLIB_MUTEX
447       G_UNLOCK (dnslock);
448 #   endif
449 
450   }
451 #else
452 #ifdef HAVE_GETHOSTBYNAME_THREADSAFE
453   {
454     const char* sa_addr   = GNET_SOCKADDR_ADDRP(*sa);
455     size_t      sa_len    = GNET_SOCKADDR_ADDRLEN(*sa);
456     int         sa_type   = GNET_SOCKADDR_FAMILY(*sa);
457 
458     struct hostent* he;
459 
460     he = gethostbyaddr(sa_addr, sa_len, sa_type);
461     if (he != NULL && he->h_name != NULL)
462       rv = g_strdup(he->h_name);
463   }
464 #else
465 #ifdef HAVE_GETHOSTBYNAME_R_GLIBC
466   {
467     const char* sa_addr   = GNET_SOCKADDR_ADDRP(*sa);
468     size_t      sa_len    = GNET_SOCKADDR_ADDRLEN(*sa);
469     int         sa_type   = GNET_SOCKADDR_FAMILY(*sa);
470 
471     struct hostent result_buf, *result;
472     size_t len;
473     char* buf;
474     int herr;
475     int res;
476 
477     len = 1024;
478     buf = g_new(gchar, len);
479 
480     while ((res = gethostbyaddr_r (sa_addr, sa_len, sa_type,
481 				   &result_buf, buf, len,
482 				   &result, &herr))
483 	   == ERANGE)
484       {
485 	len *= 2;
486 	buf = g_renew (gchar, buf, len);
487       }
488 
489     if (res || result == NULL || result->h_name == NULL)
490       goto done;
491 
492     rv = g_strdup(result->h_name);
493 
494   done:
495     g_free(buf);
496   }
497 
498 #else
499 #ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
500   {
501     const char* sa_addr   = GNET_SOCKADDR_ADDRP(*sa);
502     size_t      sa_len    = GNET_SOCKADDR_ADDRLEN(*sa);
503     int         sa_type   = GNET_SOCKADDR_FAMILY(*sa);
504 
505     struct hostent result;
506     size_t len;
507     char* buf;
508     int herr;
509     int res;
510 
511     len = 1024;
512     buf = g_new(gchar, len);
513 
514     while ((res = gethostbyaddr_r (sa_addr, sa_len, sa_type, &result, buf, len, &herr)) == ERANGE)
515       {
516 	len *= 2;
517 	buf = g_renew (gchar, buf, len);
518       }
519 
520     if (res || hp == NULL || hp->h_name == NULL)
521       goto done;
522 
523     rv = g_strdup(result->h_name);
524 
525   done:
526     g_free(buf);
527   }
528 
529 #else
530 #ifdef HAVE_GETHOSTBYNAME_R_HPUX
531   {
532     const char* sa_addr   = GNET_SOCKADDR_ADDRP(*sa);
533     size_t      sa_len    = GNET_SOCKADDR_ADDRLEN(*sa);
534     int         sa_type   = GNET_SOCKADDR_FAMILY(*sa);
535 
536     struct hostent result;
537     struct hostent_data buf;
538     int res;
539 
540     res = gethostbyaddr_r (sa_addr, sa_len, sa_type, &result, &buf);
541 
542     if (res == 0)
543       rv = g_strdup (result.h_name);
544   }
545 
546 #else
547 #ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
548   {
549     const char* sa_addr   = GNET_SOCKADDR_ADDRP(*sa);
550     size_t      sa_len    = GNET_SOCKADDR_ADDRLEN(*sa);
551     int         sa_type   = GNET_SOCKADDR_FAMILY(*sa);
552 
553     struct hostent* he;
554 
555     G_LOCK (dnslock);
556     he = gethostbyaddr(sa_addr, sa_len, sa_type);
557     if (he != NULL && he->h_name != NULL)
558       rv = g_strdup(he->h_name);
559     G_UNLOCK (dnslock);
560   }
561 #else
562   {
563     const char* sa_addr   = GNET_SOCKADDR_ADDRP(*sa);
564     size_t      sa_len    = GNET_SOCKADDR_ADDRLEN(*sa);
565     int         sa_type   = GNET_SOCKADDR_FAMILY(*sa);
566 
567     struct hostent* he;
568 
569     he = gethostbyaddr(sa_addr, sa_len, sa_type);
570     if (he != NULL && he->h_name != NULL)
571       rv = g_strdup(he->h_name);
572   }
573 #endif
574 #endif
575 #endif
576 #endif
577 #endif
578 #endif
579 
580   return rv;
581 }
582 
583 
584 
585 /* **************************************** */
586 
587 
588 /**
589  *  gnet_inetaddr_new
590  *  @hostname: host name
591  *  @port: port number (0 if the port doesn't matter)
592  *
593  *  Creates a #GInetAddr from a host name and port.  This function
594  *  makes a DNS lookup on the host name so it may block.  The host
595  *  name may resolve to multiple addresses.  If this occurs, the first
596  *  address in the list is returned.  Use gnet_inetaddr_new_list() to
597  *  get the complete list.
598  *
599  *  Returns: a new #GInetAddr; NULL on error.
600  *
601  **/
602 GInetAddr*
gnet_inetaddr_new(const gchar * hostname,gint port)603 gnet_inetaddr_new (const gchar* hostname, gint port)
604 {
605   GList* ialist;
606   GInetAddr* ia = NULL;
607 
608   /*
609    * First attempt nonblocking lookup
610    */
611   ia = gnet_inetaddr_new_nonblock (hostname, port);
612   if (ia)
613     return ia;
614 
615   ialist = gnet_gethostbyname (hostname);
616   if (!ialist)
617     return NULL;
618 
619   ia = (GInetAddr*) ialist->data;
620   ialist = g_list_remove (ialist, ia);
621 
622   GNET_INETADDR_PORT_SET(ia, g_htons(port));
623 
624   ialist_free (ialist);
625 
626   return ia;
627 }
628 
629 
630 /**
631  *  gnet_inetaddr_new_list:
632  *  @hostname: host name
633  *  @port: port number (0 if the port doesn't matter)
634  *
635  *  Creates a GList of #GInetAddr's from a host name and port.  This
636  *  function makes a DNS lookup on the host name so it may block.
637  *
638  *  Returns: a GList of #GInetAddr structures or NULL on error.
639  *
640  **/
641 GList*
gnet_inetaddr_new_list(const gchar * hostname,gint port)642 gnet_inetaddr_new_list (const gchar* hostname, gint port)
643 {
644   GInetAddr* ia;
645   GList* ialist;
646   GList* i;
647 
648   g_return_val_if_fail (hostname != NULL, NULL);
649 
650   /*
651    * First attempt nonblocking lookup
652    */
653   ia = gnet_inetaddr_new_nonblock (hostname, port);
654   if (ia)
655     return g_list_prepend (NULL, ia);
656 
657   /* Try to get the host by name (ie, DNS) */
658   ialist = gnet_gethostbyname(hostname);
659   if (!ialist)
660     return NULL;
661 
662   /* Set the port */
663   for (i = ialist; i != NULL; i = i->next)
664     {
665       GInetAddr* ia = (GInetAddr*) i->data;
666       GNET_INETADDR_PORT_SET(ia, g_htons(port));
667     }
668 
669   return ialist;
670 }
671 
672 
673 /**
674  *  gnet_inetaddr_delete_list
675  *  @list: GList of #GInetAddr's
676  *
677  *  Deletes a GList of #GInetAddr's.
678  *
679  **/
680 void
gnet_inetaddr_delete_list(GList * list)681 gnet_inetaddr_delete_list (GList* list)
682 {
683   GList* i;
684 
685   for (i = list; i != NULL; i = i->next)
686     gnet_inetaddr_delete ((GInetAddr*) i->data);
687   g_list_free (list);
688 }
689 
690 
691 
692 /* **************************************** */
693 /* gnet_inetaddr_new_async()		    */
694 
695 static void inetaddr_new_async_cb (GList* ialist, gpointer data);
696 
697 /**
698  *  gnet_inetaddr_new_async_full
699  *  @hostname: host name
700  *  @port: port number (0 if the port doesn't matter)
701  *  @func: callback function
702  *  @data: data to pass to @func on the callback, or NULL
703  *  @notify: function to call to free @data, or NULL
704  *  @context: the #GMainContext to use for notifications, or NULL for the
705  *      default GLib main context.  If in doubt, pass NULL.
706  *  @priority: the priority with which to schedule notifications in the
707  *      main context, e.g. #G_PRIORITY_DEFAULT or #G_PRIORITY_HIGH.
708  *
709  *  Asynchronously creates a #GInetAddr from a host name and port.
710  *  The callback is called once the #GInetAddr is created or an error
711  *  occurs during lookup.  The callback will not be called during the
712  *  call to this function.
713  *
714  *  See gnet_inetaddr_new_list_async() for implementation notes.
715  *
716  *  Returns: the ID of the lookup; NULL on failure.  The ID can be used
717  *  with gnet_inetaddr_new_async_cancel() to cancel the lookup.
718  *
719  *  Since: 2.0.8
720  **/
721 GInetAddrNewAsyncID
gnet_inetaddr_new_async_full(const gchar * hostname,gint port,GInetAddrNewAsyncFunc func,gpointer data,GDestroyNotify notify,GMainContext * context,gint priority)722 gnet_inetaddr_new_async_full (const gchar * hostname, gint port,
723     GInetAddrNewAsyncFunc func, gpointer data, GDestroyNotify notify,
724     GMainContext * context, gint priority)
725 {
726   GInetAddrNewListAsyncID list_id;
727   GInetAddrNewState *state;
728 
729   if (context == NULL)
730     context = g_main_context_default ();
731 
732   state = g_new0 (GInetAddrNewState, 1);
733 
734   g_static_mutex_init (&state->mutex);
735   g_static_mutex_lock (&state->mutex);
736 
737   state->func = func;
738   state->data = data;
739   state->notify = notify;
740   state->context = g_main_context_ref (context);
741   state->priority = priority;
742 
743   list_id = gnet_inetaddr_new_list_async_full (hostname, port,
744       inetaddr_new_async_cb, state, (GDestroyNotify) NULL, context, priority);
745 
746   state->list_id = list_id;
747 
748   g_static_mutex_unlock (&state->mutex);
749 
750   if (list_id == NULL) {
751     if (state->notify)
752       state->notify (state->data);
753     g_main_context_unref (state->context);
754     g_static_mutex_free (&state->mutex);
755     g_free (state);
756     return NULL;
757   }
758 
759   return state;
760 }
761 
762 /**
763  *  gnet_inetaddr_new_async
764  *  @hostname: host name
765  *  @port: port number (0 if the port doesn't matter)
766  *  @func: callback function
767  *  @data: data to pass to @func on the callback
768  *
769  *  Asynchronously creates a #GInetAddr from a host name and port.
770  *  The callback is called once the #GInetAddr is created or an error
771  *  occurs during lookup.  The callback will not be called during the
772  *  call to this function.
773  *
774  *  See gnet_inetaddr_new_list_async() for implementation notes.
775  *
776  *  Returns: the ID of the lookup; NULL on failure.  The ID can be used
777  *  with gnet_inetaddr_new_async_cancel() to cancel the lookup.
778  *
779  **/
780 GInetAddrNewAsyncID
gnet_inetaddr_new_async(const gchar * hostname,gint port,GInetAddrNewAsyncFunc func,gpointer data)781 gnet_inetaddr_new_async (const gchar* hostname, gint port,
782 			 GInetAddrNewAsyncFunc func, gpointer data)
783 {
784   GInetAddrNewAsyncID async_id;
785 
786   g_return_val_if_fail (hostname != NULL, NULL);
787   g_return_val_if_fail (func != NULL, NULL);
788 
789   async_id = gnet_inetaddr_new_async_full (hostname, port, func, data,
790       (GDestroyNotify) NULL, NULL, G_PRIORITY_DEFAULT);
791 
792   return async_id;
793 }
794 
795 
796 /**
797  *  gnet_inetaddr_new_async_cancel
798  *  @id: ID of the lookup
799  *
800  *  Cancels an asynchronous #GInetAddr creation that was started with
801  *  gnet_inetaddr_new_async().
802  *
803  **/
804 void
gnet_inetaddr_new_async_cancel(GInetAddrNewAsyncID async_id)805 gnet_inetaddr_new_async_cancel (GInetAddrNewAsyncID async_id)
806 {
807   GInetAddrNewState* state = (GInetAddrNewState*) async_id;
808 
809   g_return_if_fail (async_id != NULL);
810 
811   if (state->in_callback)
812     return;
813 
814   gnet_inetaddr_new_list_async_cancel (state->list_id);
815   if (state->notify)
816     state->notify (state->data);
817   g_main_context_unref (state->context);
818   g_free (state);
819 }
820 
821 
822 static void
inetaddr_new_async_cb(GList * ialist,gpointer data)823 inetaddr_new_async_cb (GList* ialist, gpointer data)
824 {
825   GInetAddrNewState* state = (GInetAddrNewState*) data;
826 
827   g_return_if_fail (state);
828 
829   state->in_callback = TRUE;
830 
831   /* make sure we don't proceed before gnet_inetaddr_new_async()
832    * has set state->list_id, which is needed by _async_cancel */
833   g_static_mutex_lock (&state->mutex);
834   g_static_mutex_unlock (&state->mutex);
835 
836   if (ialist)
837     {
838       GInetAddr* ia;
839 
840       ia = (GInetAddr*) ialist->data;	      /* Get address */
841       g_assert (ia);
842 
843       ialist = g_list_remove (ialist, ia);    /* Remove from list */
844       ialist_free (ialist);		      /* Delete list */
845 
846       (*state->func)(ia, state->data);
847     }
848   else
849     {
850       (*state->func)(NULL, state->data);
851     }
852 
853   state->in_callback = FALSE;
854 
855   /* abuse _cancel() to free the state */
856   gnet_inetaddr_new_async_cancel (state);
857 }
858 
859 
860 /* **************************************** */
861 /* gnet_inetaddr_new_list_async()	    */
862 
863 static gboolean inetaddr_new_list_async_nonblock_dispatch (gpointer data);
864 
865 static void* inetaddr_new_list_async_gthread (void* arg);
866 
867 /**
868  *  gnet_inetaddr_new_list_async_full
869  *  @hostname: host name
870  *  @port: port number (0 if the port doesn't matter)
871  *  @func: callback function
872  *  @data: data to pass to @func on the callback, or NULL
873  *  @notify: function to call to free @data, or NULL
874  *  @context: the #GMainContext to use for notifications, or NULL for the
875  *      default GLib main context.  If in doubt, pass NULL.
876  *  @priority: the priority with which to schedule notifications in the
877  *      main context, e.g. #G_PRIORITY_DEFAULT or #G_PRIORITY_HIGH.
878  *
879  *  Asynchronously creates a GList of #GInetAddr's from a host name
880  *  and port.  The callback is called once the list is created or an
881  *  error occurs during lookup.  The callback will not be called
882  *  during the call to gnet_inetaddr_new_list_async().  The list
883  *  passed in the callback is callee owned (meaning that it is your
884  *  responsibility to free the list and each #GInetAddr in the list).
885  *
886  *  If you need to lookup hundreds of addresses, we recommend calling
887  *  g_main_iteration(FALSE) between calls.  This will help prevent an
888  *  explosion of threads.
889  *
890  *  If you need a more robust library for Unix, look at <ulink
891  *  url="http://www.gnu.org/software/adns/adns.html">GNU ADNS</ulink>.
892  *  GNU ADNS is under the GNU GPL.  This library does not use threads
893  *  or processes.
894  *
895  *  The Windows version is molded after the Unix GThread version.
896  *
897  *  Returns: the ID of the lookup; NULL on failure.  The ID can be
898  *  used with gnet_inetaddr_new_list_async_cancel() to cancel the
899  *  lookup.
900  *
901  *  Since: 2.0.8
902  **/
903 GInetAddrNewListAsyncID
gnet_inetaddr_new_list_async_full(const gchar * hostname,gint port,GInetAddrNewListAsyncFunc func,gpointer data,GDestroyNotify notify,GMainContext * context,gint priority)904 gnet_inetaddr_new_list_async_full (const gchar * hostname, gint port,
905     GInetAddrNewListAsyncFunc func, gpointer data, GDestroyNotify notify,
906     GMainContext * context, gint priority)
907 {
908   GInetAddrNewListState *state = NULL;
909   GInetAddr *ia;
910 
911   g_return_val_if_fail (hostname != NULL, NULL);
912   g_return_val_if_fail (func != NULL, NULL);
913 
914   if (context == NULL)
915     context = g_main_context_default ();
916 
917   state = g_new0 (GInetAddrNewListState, 1);
918 
919   g_static_mutex_init (&state->mutex);
920 
921   /* set everything up (must be done before we create the thread) */
922   state->port = port;
923   state->func = func;
924   state->data = data;
925   state->notify = notify;
926   state->context = g_main_context_ref (context);
927   state->priority = priority;
928 
929   /* First attempt nonblocking lookup */
930   ia = gnet_inetaddr_new_nonblock (hostname, port);
931   if (ia) {
932     state->ias = g_list_prepend (NULL, ia);
933     state->source = _gnet_idle_add_full (state->context, state->priority,
934         inetaddr_new_list_async_nonblock_dispatch, state, NULL);
935   } else {
936     GError *err = NULL;
937     gpointer *args;
938 
939     args = g_new (gpointer, 2);
940     args[0] = g_strdup (hostname);
941     args[1] = state;
942 
943     if (!g_thread_create (inetaddr_new_list_async_gthread, args, FALSE, &err)) {
944       g_warning ("g_thread_create error: %s\n", err->message);
945       g_error_free (err);
946       if (state->notify)
947         state->notify (state->data);
948       g_main_context_unref (state->context);
949       g_static_mutex_free (&state->mutex);
950       g_free (args[0]);
951       g_free (state);
952       return NULL;
953     }
954   }
955 
956   return state;
957 }
958 
959 /**
960  *  gnet_inetaddr_new_list_async
961  *  @hostname: host name
962  *  @port: port number (0 if the port doesn't matter)
963  *  @func: callback function
964  *  @data: data to pass to @func on the callback
965  *
966  *  Asynchronously creates a GList of #GInetAddr's from a host name
967  *  and port.  The callback is called once the list is created or an
968  *  error occurs during lookup.  The callback will not be called
969  *  during the call to gnet_inetaddr_new_list_async().  The list
970  *  passed in the callback is callee owned (meaning that it is your
971  *  responsibility to free the list and each #GInetAddr in the list).
972  *
973  *  If you need to lookup hundreds of addresses, we recommend calling
974  *  g_main_iteration(FALSE) between calls.  This will help prevent an
975  *  explosion of threads.
976  *
977  *  If you need a more robust library for Unix, look at <ulink
978  *  url="http://www.gnu.org/software/adns/adns.html">GNU ADNS</ulink>.
979  *  GNU ADNS is under the GNU GPL.  This library does not use threads
980  *  or processes.
981  *
982  *  The Windows version is molded after the Unix GThread version.
983  *
984  *  Returns: the ID of the lookup; NULL on failure.  The ID can be
985  *  used with gnet_inetaddr_new_list_async_cancel() to cancel the
986  *  lookup.
987  *
988  **/
989 GInetAddrNewListAsyncID
gnet_inetaddr_new_list_async(const gchar * hostname,gint port,GInetAddrNewListAsyncFunc func,gpointer data)990 gnet_inetaddr_new_list_async (const gchar* hostname, gint port,
991     GInetAddrNewListAsyncFunc func, gpointer data)
992 {
993   GInetAddrNewListAsyncID async_id;
994 
995   g_return_val_if_fail (hostname != NULL, NULL);
996   g_return_val_if_fail (func != NULL, NULL);
997 
998   async_id = gnet_inetaddr_new_list_async_full (hostname, port, func, data,
999       (GDestroyNotify) NULL, NULL, G_PRIORITY_DEFAULT);
1000 
1001   return async_id;
1002 }
1003 
1004 /* TODO: we could merge this with inetaddr_new_list_async_gthread_dispatch()
1005  * if we used the same type of mutex for the structure ... */
1006 static gboolean
inetaddr_new_list_async_nonblock_dispatch(gpointer data)1007 inetaddr_new_list_async_nonblock_dispatch (gpointer data)
1008 {
1009   GInetAddrNewListState* state = (GInetAddrNewListState*) data;
1010 
1011   g_static_mutex_lock (&state->mutex);
1012 
1013   state->in_callback = TRUE;
1014 
1015   (*state->func) (state->ias, state->data);
1016 
1017   state->in_callback = FALSE;
1018 
1019   if (state->notify)
1020     state->notify (state->data);
1021   g_main_context_unref (state->context);
1022   g_static_mutex_unlock (&state->mutex);
1023   g_static_mutex_free (&state->mutex);
1024   g_free (state);
1025 
1026   return FALSE;
1027 }
1028 
1029 static gboolean inetaddr_new_list_async_gthread_dispatch (gpointer data);
1030 
1031 
1032 static void*
inetaddr_new_list_async_gthread(void * arg)1033 inetaddr_new_list_async_gthread (void* arg)
1034 {
1035   void** args = (void**) arg;
1036   gchar* name = (gchar*) args[0];
1037   GInetAddrNewListState* state = (GInetAddrNewListState*) args[1];
1038   GList* ialist = NULL;
1039 
1040   g_free (args);
1041 
1042   /* Avoid the blocking call in the unlikely case that we've already been
1043    * cancelled */
1044   g_static_mutex_lock (&state->mutex);
1045   if (state->is_cancelled)
1046     goto cancelled;
1047   g_static_mutex_unlock (&state->mutex);
1048 
1049   /* Do lookup (without holding the lock while we're blocking so the main
1050    * thread can cancel us without having to wait until we've finished our
1051    * blocking call) */
1052   ialist = gnet_gethostbyname (name);
1053 
1054   /* Lock again */
1055   g_static_mutex_lock (&state->mutex);
1056 
1057   /* If cancelled, destroy state and exit.  The main thread is no
1058    * longer using state. */
1059   if (state->is_cancelled)
1060     goto cancelled;
1061 
1062   g_free (name);
1063 
1064   if (ialist)
1065     {
1066       GList* i;
1067 
1068       /* Set the port */
1069       for (i = ialist; i != NULL; i = i->next)
1070 	{
1071 	  GInetAddr* ia = (GInetAddr*) i->data;
1072           GNET_INETADDR_PORT_SET(ia, g_htons(state->port));
1073 	}
1074 
1075       /* Save the list */
1076       state->ias = ialist;
1077     }
1078   else
1079     {
1080       /* Flag failure */
1081       state->lookup_failed = TRUE;
1082     }
1083 
1084   /* Add a source for reply */
1085   state->source = _gnet_idle_add_full (state->context, state->priority,
1086       inetaddr_new_list_async_gthread_dispatch, state, NULL);
1087 
1088   /* Unlock */
1089   g_static_mutex_unlock (&state->mutex);
1090 
1091  /* Thread exits... */
1092   return NULL;
1093 
1094 cancelled:
1095   {
1096     ialist_free (ialist);
1097     if (state->notify)
1098       state->notify (state->data);
1099     g_main_context_unref (state->context);
1100     g_static_mutex_unlock (&state->mutex);
1101     g_static_mutex_free (&state->mutex);
1102     g_free (state);
1103     g_free (name);
1104     return NULL;
1105   }
1106 
1107 }
1108 
1109 static gboolean
inetaddr_new_list_async_gthread_dispatch(gpointer data)1110 inetaddr_new_list_async_gthread_dispatch (gpointer data)
1111 {
1112   GInetAddrNewListState* state = (GInetAddrNewListState*) data;
1113 
1114   g_static_mutex_lock (&state->mutex);
1115 
1116   state->in_callback = TRUE;
1117 
1118   /* Upcall */
1119   if (!state->lookup_failed)
1120     (*state->func)(state->ias, state->data);
1121   else
1122     (*state->func)(NULL, state->data);
1123 
1124   state->in_callback = FALSE;
1125 
1126   /* Delete state */
1127   if (state->notify)
1128     state->notify (state->data);
1129   g_main_context_unref (state->context);
1130   g_static_mutex_unlock (&state->mutex);
1131   g_static_mutex_free (&state->mutex);
1132   g_free (state);
1133 
1134   return FALSE;
1135 }
1136 
1137 
1138 /**
1139  *  gnet_inetaddr_new_list_async_cancel
1140  *  @id: ID of the lookup
1141  *
1142  *  Cancels an asynchronous #GInetAddr list creation that was started
1143  *  with gnet_inetaddr_new_list_async().
1144  *
1145  **/
1146 void
gnet_inetaddr_new_list_async_cancel(GInetAddrNewListAsyncID id)1147 gnet_inetaddr_new_list_async_cancel (GInetAddrNewListAsyncID id)
1148 {
1149   GInetAddrNewListState* state = (GInetAddrNewListState*) id;
1150 
1151   g_return_if_fail (state);
1152 
1153   if (state->in_callback)
1154     return;
1155 
1156   /* We don't use in_callback because we'd have to get the mutex to
1157      access it and if we're in the callback we'd already have the
1158      mutex and deadlock.  in_callback was mostly meant to prevent
1159      programmer error.  */
1160 
1161   g_static_mutex_lock (&state->mutex);
1162 
1163   /* Check if the thread has finished and a reply is pending.  If a
1164    * reply is pending, cancel it and delete state. */
1165   if (state->source) {
1166     _gnet_source_remove (state->context, state->source);
1167 
1168     ialist_free (state->ias);
1169 
1170     if (state->notify)
1171       state->notify (state->data);
1172     g_main_context_unref (state->context);
1173     g_static_mutex_unlock (&state->mutex);
1174     g_static_mutex_free (&state->mutex);
1175     g_free (state);
1176   } else {
1177     /* Otherwise, the thread is still running.  Set the cancelled flag
1178      * and allow the thread to complete.  When the thread completes, it
1179      * will delete state.  We can't kill the thread because we'd loose
1180      * the resources allocated in gethostbyname_r. */
1181     state->is_cancelled = TRUE;
1182     g_static_mutex_unlock (&state->mutex);
1183   }
1184 }
1185 
1186 
1187 /**
1188  *  gnet_inetaddr_new_nonblock:
1189  *  @hostname: host name
1190  *  @port: port number (0 if the port doesn't matter)
1191  *
1192  *  Creates a #GInetAddr from a host name and port without blocking.
1193  *  This function does not make a DNS lookup and will fail if creating
1194  *  the address would require a DNS lookup.
1195  *
1196  *  Returns: a new #GInetAddr, or NULL if there was a failure or the
1197  *  function would block.
1198  *
1199  **/
1200 GInetAddr*
gnet_inetaddr_new_nonblock(const gchar * hostname,gint port)1201 gnet_inetaddr_new_nonblock (const gchar* hostname, gint port)
1202 {
1203   GInetAddr* ia = NULL;
1204   struct in_addr inaddr;
1205 #ifdef HAVE_IPV6
1206   struct in6_addr in6addr;
1207 #endif
1208 
1209   g_return_val_if_fail (hostname, NULL);
1210 
1211   if (inet_pton(AF_INET, hostname, &inaddr) > 0)
1212     {
1213       struct sockaddr_in* sa_inp;
1214 
1215       ia = g_new0(GInetAddr, 1);
1216       ia->ref_count = 1;
1217       sa_inp = (struct sockaddr_in*) &ia->sa;
1218 
1219       sa_inp->sin_family = AF_INET;
1220       GNET_INETADDR_SET_SS_LEN(ia);
1221       sa_inp->sin_addr = inaddr;
1222       sa_inp->sin_port = g_htons(port);
1223     }
1224 #ifdef HAVE_IPV6
1225   else if (inet_pton(AF_INET6, hostname, &in6addr) > 0)
1226     {
1227       struct sockaddr_in6* sa_inp;
1228 
1229       ia = g_new0(GInetAddr, 1);
1230       ia->ref_count = 1;
1231       sa_inp = (struct sockaddr_in6*) &ia->sa;
1232 
1233       sa_inp->sin6_family = AF_INET6;
1234       GNET_INETADDR_SET_SS_LEN(ia);
1235       sa_inp->sin6_addr = in6addr;
1236       sa_inp->sin6_port = g_htons(port);
1237     }
1238 #endif
1239   else
1240     return NULL;
1241 
1242   return ia;
1243 }
1244 
1245 
1246 
1247 /**
1248  *  gnet_inetaddr_new_bytes
1249  *  @bytes: address in raw bytes
1250  *  @length: length of @bytes (4 if IPv4, 16 if IPv6)
1251  *
1252  *  Creates a #GInetAddr from raw bytes.  The bytes should be in
1253  *  network byte order (big endian).  There should be 4 bytes if it's
1254  *  an IPv4 address and 16 bytees if it's an IPv6 address.  The port
1255  *  is set to 0.
1256  *
1257  *  Returns: a new #GInetAddr, or NULL if there was a failure.
1258  *
1259  **/
1260 GInetAddr*
gnet_inetaddr_new_bytes(const gchar * bytes,const guint length)1261 gnet_inetaddr_new_bytes (const gchar* bytes, const guint length)
1262 {
1263   GInetAddr* ia = NULL;
1264 
1265   g_return_val_if_fail (bytes, NULL);
1266 
1267   if (length != 4 && length != 16)
1268     return NULL;
1269 
1270   ia = g_new0 (GInetAddr, 1);
1271   ia->ref_count = 1;
1272   if (length == 4)
1273     GNET_INETADDR_FAMILY(ia) = AF_INET;
1274 #ifdef HAVE_IPV6
1275   else
1276     GNET_INETADDR_FAMILY(ia) = AF_INET6;
1277 #endif
1278   GNET_INETADDR_SET_SS_LEN(ia);
1279   memcpy(GNET_INETADDR_ADDRP(ia), bytes, length);
1280 
1281   return ia;
1282 }
1283 
1284 
1285 /**
1286  *   gnet_inetaddr_clone:
1287  *   @inetaddr: a #GInetAddr
1288  *
1289  *   Copies a #GInetAddr.
1290  *
1291  *   Returns: a copy of @inetaddr.
1292  *
1293  **/
1294 GInetAddr*
gnet_inetaddr_clone(const GInetAddr * inetaddr)1295 gnet_inetaddr_clone(const GInetAddr* inetaddr)
1296 {
1297   GInetAddr* cia;
1298 
1299   g_return_val_if_fail (inetaddr != NULL, NULL);
1300 
1301   cia = g_new0(GInetAddr, 1);
1302   cia->ref_count = 1;
1303   cia->sa = inetaddr->sa;
1304   if (inetaddr->name != NULL)
1305     cia->name = g_strdup(inetaddr->name);
1306 
1307   return cia;
1308 }
1309 
1310 
1311 /**
1312  *  gnet_inetaddr_delete
1313  *  @inetaddr: a #GInetAddr
1314  *
1315  *  Deletes a #GInetAddr.
1316  *
1317  **/
1318 void
gnet_inetaddr_delete(GInetAddr * inetaddr)1319 gnet_inetaddr_delete (GInetAddr* inetaddr)
1320 {
1321   if (inetaddr != NULL)
1322     gnet_inetaddr_unref (inetaddr);
1323 }
1324 
1325 
1326 /**
1327  *  gnet_inetaddr_ref
1328  *  @inetaddr: a #GInetAddr
1329  *
1330  *  Adds a reference to a #GInetAddr.
1331  *
1332  **/
1333 void
gnet_inetaddr_ref(GInetAddr * inetaddr)1334 gnet_inetaddr_ref (GInetAddr* inetaddr)
1335 {
1336   g_return_if_fail (inetaddr != NULL);
1337 
1338   g_atomic_int_inc (&inetaddr->ref_count);
1339 }
1340 
1341 
1342 /**
1343  *  gnet_inetaddr_unref
1344  *  @inetaddr: a #GInetAddr
1345  *
1346  *  Removes a reference from a #GInetAddr.  A #GInetAddr is deleted
1347  *  when the reference count reaches 0.
1348  *
1349  **/
1350 void
gnet_inetaddr_unref(GInetAddr * inetaddr)1351 gnet_inetaddr_unref (GInetAddr* inetaddr)
1352 {
1353   g_return_if_fail (inetaddr != NULL);
1354 
1355   if (g_atomic_int_dec_and_test (&inetaddr->ref_count)) {
1356     g_free (inetaddr->name);
1357     g_free (inetaddr);
1358   }
1359 }
1360 
1361 
1362 
1363 /**
1364  *  gnet_inetaddr_get_name:
1365  *  @inetaddr: a #GInetAddr
1366  *
1367  *  Gets the host name for a #GInetAddr.  This functions makes a
1368  *  reverse DNS lookup on the address so it may block.  The canonical
1369  *  name is returned if the address has no host name.
1370  *
1371  *  Returns: the host name for the @inetaddr; NULL on error.
1372  *
1373  **/
1374 gchar*
gnet_inetaddr_get_name(GInetAddr * inetaddr)1375 gnet_inetaddr_get_name (/* const */ GInetAddr* inetaddr)
1376 {
1377   g_return_val_if_fail (inetaddr != NULL, NULL);
1378 
1379   if (inetaddr->name == NULL)
1380     {
1381       gchar* name;
1382 
1383       if ((name = gnet_gethostbyaddr(&inetaddr->sa)) != NULL)
1384 	inetaddr->name = name;
1385       else
1386 	inetaddr->name = gnet_inetaddr_get_canonical_name(inetaddr);
1387     }
1388 
1389   g_return_val_if_fail (inetaddr->name, NULL);
1390   return g_strdup(inetaddr->name);
1391 }
1392 
1393 
1394 
1395 /**
1396  *  gnet_inetaddr_get_name_nonblock:
1397  *  @inetaddr: a #GInetAddr
1398  *
1399  *  Gets the host name for a #GInetAddr.  This function does not make
1400  *  a reverse DNS lookup and will fail if getting the name would
1401  *  require a reverse DNS lookup.
1402  *
1403  *  Returns: the host name for the @inetaddr, or NULL if there was an
1404  *  error or it would require blocking.
1405  *
1406  **/
1407 gchar*
gnet_inetaddr_get_name_nonblock(GInetAddr * inetaddr)1408 gnet_inetaddr_get_name_nonblock (GInetAddr* inetaddr)
1409 {
1410   if (inetaddr->name)
1411     return g_strdup(inetaddr->name);
1412 
1413   return NULL;
1414 }
1415 
1416 
1417 
1418 static void* inetaddr_get_name_async_gthread (void* arg);
1419 
1420 /**
1421  *  gnet_inetaddr_get_name_async_full:
1422  *  @inetaddr: a #GInetAddr
1423  *  @func: callback function
1424  *  @data: data to pass to @func on the callback
1425  *  @notify: function to call to free @data, or NULL
1426  *  @context: the #GMainContext to use for notifications, or NULL for the
1427  *      default GLib main context.  If in doubt, pass NULL.
1428  *  @priority: the priority with which to schedule notifications in the
1429  *      main context, e.g. #G_PRIORITY_DEFAULT or #G_PRIORITY_HIGH.
1430  *
1431  *  Asynchronously gets the host name for a #GInetAddr.  The callback
1432  *  is called once the reverse DNS lookup is complete.  The callback
1433  *  will not be called during the call to this function.
1434  *
1435  *  See gnet_inetaddr_new_list_async_full() for implementation notes.
1436  *
1437  *  Returns: the ID of the lookup; NULL on failure.  The ID can be
1438  *  used with gnet_inetaddr_get_name_async_cancel() to cancel the
1439  *  lookup.
1440  *
1441  *  Since: 2.0.8
1442  **/
1443 GInetAddrGetNameAsyncID
gnet_inetaddr_get_name_async_full(GInetAddr * inetaddr,GInetAddrGetNameAsyncFunc func,gpointer data,GDestroyNotify notify,GMainContext * context,gint priority)1444 gnet_inetaddr_get_name_async_full (GInetAddr * inetaddr,
1445     GInetAddrGetNameAsyncFunc func, gpointer data, GDestroyNotify notify,
1446     GMainContext * context, gint priority)
1447 {
1448   GInetAddrReverseAsyncState *state = NULL;
1449   GError *err = NULL;
1450 
1451   g_return_val_if_fail (inetaddr != NULL, NULL);
1452   g_return_val_if_fail (func != NULL, NULL);
1453 
1454   if (context == NULL)
1455     context = g_main_context_default ();
1456 
1457   state = g_new0 (GInetAddrReverseAsyncState, 1);
1458 
1459   /* Set up state for callback */
1460   g_static_mutex_init (&state->mutex);
1461 
1462   state->ia = gnet_inetaddr_clone (inetaddr);
1463   state->func = func;
1464   state->data = data;
1465   state->notify = notify;
1466   state->is_cancelled = FALSE;
1467   state->in_callback = FALSE;
1468   state->source = 0;
1469   state->name = NULL;
1470   state->context = g_main_context_ref (context);
1471   state->priority = priority;
1472 
1473   if (!g_thread_create (inetaddr_get_name_async_gthread, state, FALSE, &err)) {
1474     g_warning ("g_thread_create error: %s\n", err->message);
1475     g_error_free (err);
1476     gnet_inetaddr_delete (state->ia);
1477     if (state->notify)
1478       state->notify (state->data);
1479     g_main_context_unref (state->context);
1480     g_static_mutex_free (&state->mutex);
1481     g_free (state);
1482     return NULL;
1483   }
1484 
1485   return state;
1486 }
1487 
1488 /**
1489  *  gnet_inetaddr_get_name_async:
1490  *  @inetaddr: a #GInetAddr
1491  *  @func: callback function
1492  *  @data: data to pass to @func on the callback
1493  *
1494  *  Asynchronously gets the host name for a #GInetAddr.  The callback
1495  *  is called once the reverse DNS lookup is complete.  The call back
1496  *  will not be called during the call to this function.
1497  *
1498  *  See gnet_inetaddr_new_list_async() for implementation notes.
1499  *
1500  *  Returns: the ID of the lookup; NULL on failure.  The ID can be
1501  *  used with gnet_inetaddr_get_name_async_cancel() to cancel the
1502  *  lookup.
1503  *
1504  **/
1505 GInetAddrGetNameAsyncID
gnet_inetaddr_get_name_async(GInetAddr * inetaddr,GInetAddrGetNameAsyncFunc func,gpointer data)1506 gnet_inetaddr_get_name_async (GInetAddr * inetaddr,
1507     GInetAddrGetNameAsyncFunc func, gpointer data)
1508 {
1509   GInetAddrGetNameAsyncID async_id;
1510 
1511   async_id = gnet_inetaddr_get_name_async_full (inetaddr, func, data,
1512       (GDestroyNotify) NULL, NULL, G_PRIORITY_DEFAULT);
1513 
1514   return async_id;
1515 }
1516 
1517 /**
1518  *  gnet_inetaddr_get_name_async_cancel:
1519  *  @id: ID of the lookup
1520  *
1521  *  Cancels an asynchronous name lookup that was started with
1522  *  gnet_inetaddr_get_name_async().  This function should only be
1523  *  called from the application's main thread, ie. the thread in which
1524  *  context the callback delivering the result would be called (In a
1525  *  GTK+/GUI application this would be your normal GUI thread).
1526  *
1527  */
1528 void
gnet_inetaddr_get_name_async_cancel(GInetAddrGetNameAsyncID id)1529 gnet_inetaddr_get_name_async_cancel (GInetAddrGetNameAsyncID id)
1530 {
1531   GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) id;
1532 
1533   g_return_if_fail (id != NULL);
1534   g_return_if_fail (state->in_callback == FALSE);
1535 
1536   g_static_mutex_lock (&state->mutex);
1537 
1538   /* Check if the thread has finished and a reply is pending.  If a
1539    * reply is pending, cancel it and delete state. */
1540   if (state->source) {
1541     g_free (state->name);
1542     _gnet_source_remove (state->context, state->source);
1543     gnet_inetaddr_delete (state->ia);
1544     if (state->notify)
1545       state->notify (state->data);
1546     g_main_context_unref (state->context);
1547     g_static_mutex_unlock (&state->mutex);
1548     g_static_mutex_free (&state->mutex);
1549     memset (state, 0xaa, sizeof (*state));
1550     g_free (state);
1551   } else {
1552     /* Otherwise, the thread is still running.  Set the cancelled flag
1553      * and allow the thread to complete.  When the thread completes, it
1554      * will delete state.  We can't kill the thread because we'd loose
1555      * the resources allocated in gethostbyname_r. */
1556      state->is_cancelled = TRUE;
1557      g_static_mutex_unlock (&state->mutex);
1558   }
1559 }
1560 
1561 
1562 static gboolean
inetaddr_get_name_async_gthread_dispatch(gpointer data)1563 inetaddr_get_name_async_gthread_dispatch (gpointer data)
1564 {
1565   GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) data;
1566 
1567   g_static_mutex_lock (&state->mutex);
1568 
1569   /* make sure we don't deadlock if user tries to cancel us from callback */
1570   state->in_callback = TRUE;
1571 
1572   /* Upcall */
1573   (*state->func) (state->name, state->data);
1574 
1575   /* Delete state */
1576   gnet_inetaddr_delete (state->ia);
1577   if (state->notify)
1578     state->notify (state->data);
1579   g_main_context_unref (state->context);
1580   g_static_mutex_unlock (&state->mutex);
1581   g_static_mutex_free (&state->mutex);
1582   memset (state, 0, sizeof(*state));
1583   g_free (state);
1584 
1585   return FALSE;
1586 }
1587 
1588 
1589 static void*
inetaddr_get_name_async_gthread(void * arg)1590 inetaddr_get_name_async_gthread (void* arg)
1591 {
1592   GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) arg;
1593   gchar* name;
1594 
1595   g_assert (state->ia != NULL);
1596 
1597   /* Lock */
1598   g_static_mutex_lock (&state->mutex);
1599 
1600   /* Do lookup */
1601   if (state->ia->name) {
1602     name = g_strdup (state->ia->name);
1603   } else {
1604     /* Release lock while we block, so we can be cancelled from the main thread
1605      * without blocking it until we're done */
1606     g_static_mutex_unlock (&state->mutex);
1607     name = gnet_gethostbyaddr(&state->ia->sa);
1608     g_static_mutex_lock (&state->mutex);
1609   }
1610 
1611   /* If cancelled, destroy state and exit.  The main thread is no
1612      longer using state. */
1613   if (state->is_cancelled) {
1614     g_free (name);
1615     gnet_inetaddr_delete (state->ia);
1616     if (state->notify)
1617       state->notify (state->data);
1618     g_main_context_unref (state->context);
1619     g_static_mutex_unlock (&state->mutex);
1620     g_static_mutex_free (&state->mutex);
1621     g_free (state);
1622     return NULL;
1623   }
1624 
1625   /* Copy name to state */
1626   if (name) {
1627     state->name = name;
1628   } else {
1629     /* Lookup failed: name is canonical name */
1630     state->name = gnet_inetaddr_get_canonical_name (state->ia);
1631   }
1632 
1633   /* Add a source for reply */
1634   /* FIXME use context and priority once implemented! */
1635   state->source = _gnet_idle_add_full (state->context, state->priority,
1636       inetaddr_get_name_async_gthread_dispatch, state, NULL);
1637 
1638   /* Unlock */
1639   g_static_mutex_unlock (&state->mutex);
1640 
1641   /* Thread exits... */
1642   return NULL;
1643 }
1644 
1645 
1646 /**
1647  *  gnet_inetaddr_get_length
1648  *  @inetaddr: a #GInetAddr
1649  *
1650  *  Get the length of a #GInetAddr's address in bytes.  An IPv4
1651  *  address is 4 bytes long.  An IPv6 address is 16 bytes long.
1652  *
1653  *  Returns: the length in bytes.
1654  *
1655  **/
1656 gint
gnet_inetaddr_get_length(const GInetAddr * inetaddr)1657 gnet_inetaddr_get_length (const GInetAddr* inetaddr)
1658 {
1659   g_return_val_if_fail (inetaddr, 0);
1660 
1661   return GNET_INETADDR_ADDRLEN(inetaddr);
1662 }
1663 
1664 
1665 
1666 /**
1667  *  gnet_inetaddr_get_bytes
1668  *  @inetaddr: a #GInetAddr
1669  *  @buffer: buffer to store address in
1670  *
1671  *  Get a #GInetAddr's address as bytes.  @buffer should be 4 bytes
1672  *  long for an IPv4 address or 16 bytes long for an IPv6 address.
1673  *  Use %GNET_INETADDR_MAX_LEN when allocating a static buffer and
1674  *  gnet_inetaddr_get_length() when allocating a dynamic buffer.
1675  *
1676  **/
1677 void
gnet_inetaddr_get_bytes(const GInetAddr * inetaddr,gchar * buffer)1678 gnet_inetaddr_get_bytes (const GInetAddr* inetaddr, gchar* buffer)
1679 {
1680   g_return_if_fail (inetaddr);
1681   g_return_if_fail (buffer);
1682 
1683   memcpy (buffer, GNET_INETADDR_ADDRP(inetaddr),
1684 	  GNET_INETADDR_ADDRLEN(inetaddr));
1685 }
1686 
1687 
1688 /**
1689  *  gnet_inetaddr_set_bytes
1690  *  @inetaddr: a #GInetAddr
1691  *  @bytes: address in raw bytes
1692  *  @length: length of @bytes
1693  *
1694  *  Sets the address of a #GInetAddr from bytes.  @buffer will be
1695  *  4 bytes long for an IPv4 address and 16 bytes long for an IPv6
1696  *  address.
1697  *
1698  **/
1699 void
gnet_inetaddr_set_bytes(GInetAddr * inetaddr,const gchar * bytes,gint length)1700 gnet_inetaddr_set_bytes (GInetAddr* inetaddr,
1701 			 const gchar* bytes, gint length)
1702 {
1703   gint port;
1704 
1705   g_return_if_fail (inetaddr);
1706   g_return_if_fail (bytes);
1707   g_return_if_fail (length == 4 || length == 16);
1708 
1709   /* Save the port.  If the family changes and it's location moves, it
1710      could be trashed. */
1711   port = GNET_INETADDR_PORT(inetaddr);
1712 
1713   if (length == 4)
1714     GNET_INETADDR_FAMILY(inetaddr) = AF_INET;
1715 #ifdef HAVE_IPV6
1716   else if (length == 16)
1717     GNET_INETADDR_FAMILY(inetaddr) = AF_INET6;
1718 #endif
1719   GNET_INETADDR_SET_SS_LEN(inetaddr);
1720   memcpy (GNET_INETADDR_ADDRP(inetaddr), bytes, length);
1721   GNET_INETADDR_PORT_SET(inetaddr, port);
1722 }
1723 
1724 
1725 
1726 
1727 /**
1728  *  gnet_inetaddr_get_canonical_name:
1729  *  @inetaddr: a #GInetAddr
1730  *
1731  *  Gets the canonical name of a #GInetAddr.  An IPv4 canonical name
1732  *  is a dotted decimal name (e.g., 141.213.8.59).  An IPv6 canonical
1733  *  name is a semicoloned hexidecimal name (e.g., 23:de:ad:be:ef).
1734  *
1735  *  Returns: the canonical name; NULL on error.
1736  *
1737  **/
1738 gchar*
gnet_inetaddr_get_canonical_name(const GInetAddr * inetaddr)1739 gnet_inetaddr_get_canonical_name(const GInetAddr* inetaddr)
1740 {
1741   gchar buffer[INET6_ADDRSTRLEN];	/* defined in netinet/in.h */
1742 
1743   g_return_val_if_fail (inetaddr != NULL, NULL);
1744 
1745   if (inet_ntop(GNET_INETADDR_FAMILY(inetaddr),
1746 		GNET_INETADDR_ADDRP(inetaddr),
1747 		buffer, sizeof(buffer)) == NULL)
1748     return NULL;
1749   return g_strdup(buffer);
1750 }
1751 
1752 
1753 /**
1754  *  gnet_inetaddr_get_port:
1755  *  @inetaddr: a #GInetAddr
1756  *
1757  *  Gets the port number of a #GInetAddr.
1758  *
1759  *  Returns: the port number.
1760  */
1761 gint
gnet_inetaddr_get_port(const GInetAddr * inetaddr)1762 gnet_inetaddr_get_port(const GInetAddr* inetaddr)
1763 {
1764   g_return_val_if_fail(inetaddr != NULL, -1);
1765 
1766   return (gint) g_ntohs(GNET_INETADDR_PORT(inetaddr));
1767 }
1768 
1769 
1770 /**
1771  *  gnet_inetaddr_set_port:
1772  *  @inetaddr: a #GInetAddr
1773  *  @port: new port number
1774  *
1775  *  Set the port number of a #GInetAddr.
1776  *
1777  **/
1778 void
gnet_inetaddr_set_port(const GInetAddr * inetaddr,gint port)1779 gnet_inetaddr_set_port(const GInetAddr* inetaddr, gint port)
1780 {
1781   g_return_if_fail(inetaddr != NULL);
1782 
1783   GNET_INETADDR_PORT_SET(inetaddr, g_htons(port));
1784 }
1785 
1786 
1787 
1788 /* **************************************** */
1789 
1790 
1791 /**
1792  *  gnet_inetaddr_is_canonical
1793  *  @hostname: host name
1794  *
1795  *  Checks if the host name is in canonical form.
1796  *
1797  *  Returns: TRUE if @name is canonical; FALSE otherwise.
1798  *
1799  **/
1800 gboolean
gnet_inetaddr_is_canonical(const gchar * name)1801 gnet_inetaddr_is_canonical (const gchar* name)
1802 {
1803   char buf[16];
1804 
1805   g_return_val_if_fail (name, FALSE);
1806 
1807   if (inet_pton(AF_INET, name, buf) > 0)
1808     return TRUE;
1809 
1810 #ifdef HAVE_IPV6
1811  {
1812    if (inet_pton(AF_INET6, name, buf) > 0)
1813      return TRUE;
1814  }
1815 #endif
1816 
1817  return FALSE;
1818 }
1819 
1820 
1821 
1822 /**
1823  *  gnet_inetaddr_is_internet
1824  *  @inetaddr: a #GInetAddr
1825  *
1826  *  Checks if a #GInetAddr is a sensible internet address.  This mean
1827  *  it is not private, reserved, loopback, multicast, or broadcast.
1828  *
1829  *  Note that private and loopback address are often valid addresses,
1830  *  so this should only be used to check for general internet
1831  *  connectivity.  That is, if the address passes, it is reachable on
1832  *  the internet.
1833  *
1834  *  Returns: TRUE if the address is an internet address; FALSE
1835  *  otherwise.
1836  *
1837  **/
1838 gboolean
gnet_inetaddr_is_internet(const GInetAddr * inetaddr)1839 gnet_inetaddr_is_internet (const GInetAddr* inetaddr)
1840 {
1841   g_return_val_if_fail(inetaddr != NULL, FALSE);
1842 
1843   if (!gnet_inetaddr_is_private(inetaddr) 	&&
1844       !gnet_inetaddr_is_reserved(inetaddr) 	&&
1845       !gnet_inetaddr_is_loopback(inetaddr) 	&&
1846       !gnet_inetaddr_is_multicast(inetaddr) 	&&
1847       !gnet_inetaddr_is_broadcast(inetaddr))
1848     {
1849       return TRUE;
1850     }
1851 
1852   return FALSE;
1853 }
1854 
1855 
1856 
1857 /**
1858  *  gnet_inetaddr_is_private
1859  *  @inetaddr: a #GInetAddr
1860  *
1861  *  Checks if a #GInetAddr is an address reserved for private
1862  *  networks.  For IPv4, this includes:
1863  *
1864  *   10.0.0.0        -   10.255.255.255  (10/8 prefix)
1865  *   172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
1866  *   192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
1867  *
1868  *  (from RFC 1918.  See also draft-manning-dsua-02.txt)
1869  *
1870  *  For IPv6, this includes link local addresses (fe80::/64) and site
1871  *  local addresses (fec0::/64).
1872  *
1873  *  Returns: TRUE if @inetaddr is private; FALSE otherwise.
1874  *
1875  **/
1876 gboolean
gnet_inetaddr_is_private(const GInetAddr * inetaddr)1877 gnet_inetaddr_is_private (const GInetAddr* inetaddr)
1878 {
1879   g_return_val_if_fail (inetaddr != NULL, FALSE);
1880 
1881   if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET)
1882     {
1883       guint32 addr;
1884 
1885       addr = GNET_INETADDR_SA4(inetaddr).sin_addr.s_addr;
1886       addr = g_ntohl(addr);
1887 
1888       if ((addr & 0xFF000000) == (10 << 24))
1889 	return TRUE;
1890 
1891       if ((addr & 0xFFF00000) == 0xAC100000)
1892 	return TRUE;
1893 
1894       if ((addr & 0xFFFF0000) == 0xC0A80000)
1895 	return TRUE;
1896     }
1897 #ifdef HAVE_IPV6
1898   else if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET6)
1899     {
1900       if (IN6_IS_ADDR_LINKLOCAL(&GNET_INETADDR_SA6(inetaddr).sin6_addr) ||
1901 	  IN6_IS_ADDR_SITELOCAL(&GNET_INETADDR_SA6(inetaddr).sin6_addr))
1902 	return TRUE;
1903     }
1904 #endif
1905 
1906   return FALSE;
1907 }
1908 
1909 
1910 /**
1911  *  gnet_inetaddr_is_reserved:
1912  *  @inetaddr: a #GInetAddr
1913  *
1914  *  Checks if a #GInetAddr is reserved for some purpose.  This
1915  *  excludes addresses reserved for private networks.
1916  *
1917  *  For IPv4, we check for:
1918  *    0.0.0.0/16  (top 16 bits are 0's)
1919  *    Class E (top 5 bits are 11110)
1920  *
1921  *  For IPv6, we check for the 00000000 prefix.
1922  *
1923  *  Returns: TRUE if @inetaddr is reserved; FALSE otherwise.
1924  *
1925  **/
1926 gboolean
gnet_inetaddr_is_reserved(const GInetAddr * inetaddr)1927 gnet_inetaddr_is_reserved (const GInetAddr* inetaddr)
1928 {
1929   g_return_val_if_fail (inetaddr != NULL, FALSE);
1930 
1931   if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET)
1932     {
1933       guint32 addr;
1934 
1935       addr = GNET_INETADDR_SA4(inetaddr).sin_addr.s_addr;
1936       addr = g_ntohl(addr);
1937 
1938       if ((addr & 0xFFFF0000) == 0)
1939 	return TRUE;
1940 
1941       if ((addr & 0xF8000000) == 0xF0000000)
1942 	return TRUE;
1943     }
1944 #ifdef HAVE_IPV6
1945   else if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET6)
1946     {
1947       guint32 high_addr;
1948 
1949       high_addr = GNET_INETADDR_ADDR32(inetaddr, 0);
1950       high_addr = g_ntohl(high_addr);
1951 
1952       if ((high_addr & 0xFFFF0000) == 0)	/* 0000 0000 prefix */
1953 	return TRUE;
1954     }
1955 #endif
1956 
1957   return FALSE;
1958 }
1959 
1960 
1961 
1962 /**
1963  *  gnet_inetaddr_is_loopback:
1964  *  @inetaddr: a #GInetAddr
1965  *
1966  *  Checks if a #GInetAddr is a loopback address.  The IPv4 loopback
1967  *  addresses have the prefix 127.0.0.1/24.  The IPv6 loopback address
1968  *  is ::1.
1969  *
1970  *  Returns: TRUE if @inetaddr is a loopback address; FALSE otherwise.
1971  *
1972  **/
1973 gboolean
gnet_inetaddr_is_loopback(const GInetAddr * inetaddr)1974 gnet_inetaddr_is_loopback (const GInetAddr* inetaddr)
1975 {
1976   g_return_val_if_fail (inetaddr != NULL, FALSE);
1977 
1978   if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET)
1979     {
1980       guint32 addr;
1981 
1982       addr = GNET_INETADDR_SA4(inetaddr).sin_addr.s_addr;
1983       addr = g_ntohl(addr);
1984 
1985       if ((addr & 0xFF000000) == (IN_LOOPBACKNET << 24))
1986 	return TRUE;
1987     }
1988 #ifdef HAVE_IPV6
1989   else if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET6)
1990     {
1991       if (IN6_IS_ADDR_LOOPBACK(&GNET_INETADDR_SA6(inetaddr).sin6_addr))
1992 	return TRUE;
1993     }
1994 #endif
1995 
1996   return FALSE;
1997 }
1998 
1999 
2000 /**
2001  *  gnet_inetaddr_is_multicast
2002  *  @inetaddr: a #GInetAddr
2003  *
2004  *  Checks if a #GInetAddr is a multicast address.  IPv4 multicast
2005  *  addresses are in the range 224.0.0.0 to 239.255.255.255 (ie, the
2006  *  top four bits are 1110).  IPv6 multicast addresses have the prefix
2007  *  FF.
2008  *
2009  *  Returns: TRUE if @inetaddr is a multicast address; FALSE
2010  *  otherwise.
2011  *
2012  **/
2013 gboolean
gnet_inetaddr_is_multicast(const GInetAddr * inetaddr)2014 gnet_inetaddr_is_multicast (const GInetAddr* inetaddr)
2015 {
2016   g_return_val_if_fail (inetaddr != NULL, FALSE);
2017 
2018   if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET)
2019     {
2020       if (IN_MULTICAST(g_htonl(GNET_INETADDR_SA4(inetaddr).sin_addr.s_addr)))
2021 	return TRUE;
2022     }
2023 #ifdef HAVE_IPV6
2024   else if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET6)
2025     {
2026       if (IN6_IS_ADDR_MULTICAST(&GNET_INETADDR_SA6(inetaddr).sin6_addr))
2027 	return TRUE;
2028     }
2029 #endif
2030 
2031   return FALSE;
2032 }
2033 
2034 
2035 /**
2036  *  gnet_inetaddr_is_broadcast
2037  *  @inetaddr: a #GInetAddr
2038  *
2039  *  Checks if a #GInetAddr is a broadcast address.  The broadcast
2040  *  address is 255.255.255.255.  (Network broadcast addresses are
2041  *  network dependent.)
2042  *
2043  *  Returns: TRUE if @inetaddr is a broadcast address; FALSE
2044  *  otherwise.
2045  *
2046  **/
2047 gboolean
gnet_inetaddr_is_broadcast(const GInetAddr * inetaddr)2048 gnet_inetaddr_is_broadcast (const GInetAddr* inetaddr)
2049 {
2050   g_return_val_if_fail (inetaddr != NULL, FALSE);
2051 
2052   if (GNET_INETADDR_FAMILY(inetaddr) == AF_INET)
2053     {
2054       if (g_htonl(GNET_SOCKADDR_IN(inetaddr->sa).sin_addr.s_addr) == INADDR_BROADCAST)
2055 	return TRUE;
2056     }
2057   /* There is no IPv6 broadcast address */
2058 
2059   return FALSE;
2060 }
2061 
2062 
2063 /**
2064  *  gnet_inetaddr_is_ipv4:
2065  *  @inetaddr: a #GInetAddr
2066  *
2067  *  Checks if a #GInetAddr is an IPv4 address.
2068  *
2069  *  Returns: TRUE if @inetaddr is an IPv4 address; FALSE otherwise.
2070  *
2071  **/
2072 gboolean
gnet_inetaddr_is_ipv4(const GInetAddr * inetaddr)2073 gnet_inetaddr_is_ipv4 (const GInetAddr* inetaddr)
2074 {
2075   g_return_val_if_fail (inetaddr != NULL, FALSE);
2076 
2077   return GNET_INETADDR_FAMILY(inetaddr) == AF_INET;
2078 }
2079 
2080 
2081 /**
2082  *  gnet_inetaddr_is_ipv6:
2083  *  @inetaddr: a #GInetAddr
2084  *
2085  *  Check if a #GInetAddr is an IPv6 address.
2086  *
2087  *  Returns: TRUE if @inetaddr is an IPv6 address; FALSE otherwise.
2088  *
2089  **/
2090 gboolean
gnet_inetaddr_is_ipv6(const GInetAddr * inetaddr)2091 gnet_inetaddr_is_ipv6 (const GInetAddr* inetaddr)
2092 {
2093   g_return_val_if_fail (inetaddr != NULL, FALSE);
2094 
2095 #ifdef HAVE_IPV6
2096   return GNET_INETADDR_FAMILY(inetaddr) == AF_INET6;
2097 #else
2098   return FALSE;
2099 #endif
2100 }
2101 
2102 
2103 
2104 /* **************************************** */
2105 
2106 
2107 
2108 /**
2109  *  gnet_inetaddr_hash:
2110  *  @p: Pointer to an #GInetAddr.
2111  *
2112  *  Creates a hash code for a #GInetAddr for use with GHashTable.
2113  *
2114  *  Returns: the hash code for @p.
2115  *
2116  **/
2117 guint
gnet_inetaddr_hash(gconstpointer p)2118 gnet_inetaddr_hash (gconstpointer p)
2119 {
2120   const GInetAddr* ia;
2121   guint32 port;
2122   guint32 addr = 0;
2123 
2124   g_assert(p != NULL);
2125 
2126   ia = (const GInetAddr*) p;
2127 
2128   port = (guint32) g_ntohs(GNET_INETADDR_PORT(ia));
2129 
2130   /* We do pay attention to network byte order just in case the hash
2131      result is saved or sent to a different host.  */
2132 
2133   if (GNET_INETADDR_FAMILY(ia) == AF_INET)
2134     {
2135       struct sockaddr_in* sa_in = (struct sockaddr_in*) &ia->sa;
2136 
2137       addr = g_ntohl(sa_in->sin_addr.s_addr);
2138     }
2139 #ifdef HAVE_IPV6
2140   else if (GNET_INETADDR_FAMILY(ia) == AF_INET6)
2141     {
2142       addr = g_ntohl(GNET_INETADDR_ADDR32(ia, 0)) ^
2143 	g_ntohl(GNET_INETADDR_ADDR32(ia, 1)) ^
2144 	g_ntohl(GNET_INETADDR_ADDR32(ia, 2)) ^
2145 	g_ntohl(GNET_INETADDR_ADDR32(ia, 3));
2146     }
2147 #endif
2148   else
2149     g_assert_not_reached();
2150 
2151   return (port ^ addr);
2152 }
2153 
2154 
2155 
2156 /**
2157  *  gnet_inetaddr_equal:
2158  *  @p1: a #GInetAddr.
2159  *  @p2: another #GInetAddr.
2160  *
2161  *  Compares two #GInetAddr's for equality.  IPv4 and IPv6 addresses
2162  *  are always unequal.
2163  *
2164  *  Returns: TRUE if they are equal; FALSE otherwise.
2165  *
2166  **/
2167 gboolean
gnet_inetaddr_equal(gconstpointer p1,gconstpointer p2)2168 gnet_inetaddr_equal (gconstpointer p1, gconstpointer p2)
2169 {
2170   const GInetAddr* ia1 = (const GInetAddr*) p1;
2171   const GInetAddr* ia2 = (const GInetAddr*) p2;
2172 
2173   g_return_val_if_fail (p1, FALSE);
2174   g_return_val_if_fail (p2, FALSE);
2175 
2176   /* Note network byte order doesn't matter */
2177 
2178   if (GNET_INETADDR_FAMILY(ia1) != GNET_INETADDR_FAMILY(ia2))
2179     return FALSE;
2180 
2181   if (GNET_INETADDR_FAMILY(ia1) == AF_INET)
2182     {
2183       struct sockaddr_in* sa_in1 = (struct sockaddr_in*) &ia1->sa;
2184       struct sockaddr_in* sa_in2 = (struct sockaddr_in*) &ia2->sa;
2185 
2186       if ((sa_in1->sin_addr.s_addr == sa_in2->sin_addr.s_addr) &&
2187 	  (sa_in1->sin_port == sa_in2->sin_port))
2188 	return TRUE;
2189     }
2190 #ifdef HAVE_IPV6
2191   else if (GNET_INETADDR_FAMILY(ia1) == AF_INET6)
2192     {
2193       struct sockaddr_in6* sa_in1 = (struct sockaddr_in6*) &ia1->sa;
2194       struct sockaddr_in6* sa_in2 = (struct sockaddr_in6*) &ia2->sa;
2195 
2196       if (IN6_ARE_ADDR_EQUAL(&sa_in1->sin6_addr, &sa_in2->sin6_addr) &&
2197 	  (sa_in1->sin6_port == sa_in2->sin6_port))
2198 	return TRUE;
2199     }
2200 #endif
2201   else
2202     g_assert_not_reached();
2203 
2204   return FALSE;
2205 }
2206 
2207 
2208 /**
2209  *  gnet_inetaddr_noport_equal
2210  *  @p1: a #GInetAddr
2211  *  @p2: another #GInetAddr
2212  *
2213  *  Compares two #GInetAddr's for equality, but does not compare the
2214  *  port numbers.
2215  *
2216  *  Returns: TRUE if they are equal; FALSE otherwise.
2217  *
2218  **/
2219 gboolean
gnet_inetaddr_noport_equal(gconstpointer p1,gconstpointer p2)2220 gnet_inetaddr_noport_equal (gconstpointer p1, gconstpointer p2)
2221 {
2222   const GInetAddr* ia1 = (const GInetAddr*) p1;
2223   const GInetAddr* ia2 = (const GInetAddr*) p2;
2224 
2225   /* Note network byte order doesn't matter */
2226 
2227   if (GNET_INETADDR_FAMILY(ia1) != GNET_INETADDR_FAMILY(ia2))
2228     return FALSE;
2229 
2230   if (GNET_INETADDR_FAMILY(ia1) == AF_INET)
2231     {
2232       struct sockaddr_in* sa_in1 = (struct sockaddr_in*) &ia1->sa;
2233       struct sockaddr_in* sa_in2 = (struct sockaddr_in*) &ia2->sa;
2234 
2235       if (sa_in1->sin_addr.s_addr == sa_in2->sin_addr.s_addr)
2236 	return TRUE;
2237     }
2238 #ifdef HAVE_IPV6
2239   else if (GNET_INETADDR_FAMILY(ia1) == AF_INET6)
2240     {
2241       if ((GNET_INETADDR_ADDR32(ia1, 0) ==
2242 	   GNET_INETADDR_ADDR32(ia2, 0)) &&
2243 	  (GNET_INETADDR_ADDR32(ia1, 1) ==
2244 	   GNET_INETADDR_ADDR32(ia2, 1)) &&
2245 	  (GNET_INETADDR_ADDR32(ia1, 2) ==
2246 	   GNET_INETADDR_ADDR32(ia2, 2)) &&
2247 	  (GNET_INETADDR_ADDR32(ia1, 3) ==
2248 	   GNET_INETADDR_ADDR32(ia2, 3)))
2249 	return TRUE;
2250     }
2251 #endif
2252   else
2253     g_assert_not_reached();
2254 
2255   return FALSE;
2256 }
2257 
2258 
2259 
2260 /* **************************************** */
2261 
2262 /**
2263  *  gnet_inetaddr_get_host_name:
2264  *
2265  *  Gets the host's name.
2266  *
2267  *  Returns: the name of the host; NULL on error.
2268  *
2269  **/
2270 gchar*
gnet_inetaddr_get_host_name(void)2271 gnet_inetaddr_get_host_name (void)
2272 {
2273   gchar* name;
2274 #ifndef GNET_WIN32
2275   struct utsname myname;
2276   GInetAddr* addr;
2277 
2278   /* Get system name */
2279   if (uname(&myname) < 0)
2280     return NULL;
2281 
2282   /* Do forward lookup */
2283   addr = gnet_inetaddr_new (myname.nodename, 0);
2284   if (!addr)
2285     return NULL;
2286 
2287   /* Do backwards lookup */
2288   name = gnet_inetaddr_get_name (addr);
2289   if (!name)
2290     name = g_strdup (myname.nodename);
2291 
2292   gnet_inetaddr_delete (addr);
2293 #else
2294   name = g_new0(char, 256);
2295   if (gethostname(name, 256))
2296     {
2297       g_free(name);
2298       return NULL;
2299     }
2300 #endif
2301   return name;
2302 }
2303 
2304 
2305 /**
2306  *  gnet_inetaddr_get_host_addr:
2307  *
2308  *  Get the host's address.
2309  *
2310  *  Returns: the address of the host; NULL on error.
2311  *
2312  **/
2313 GInetAddr*
gnet_inetaddr_get_host_addr(void)2314 gnet_inetaddr_get_host_addr (void)
2315 {
2316   gchar* name;
2317   GInetAddr* ia = NULL;
2318 
2319   name = gnet_inetaddr_get_host_name();
2320   if (name != NULL)
2321     {
2322       ia = gnet_inetaddr_new(name, 0);
2323       g_free(name);
2324     }
2325 
2326   return ia;
2327 }
2328 
2329 
2330 /* **************************************** */
2331 
2332 static GInetAddr* autodetect_internet_interface_ipv4 (void);
2333 static GInetAddr* autodetect_internet_interface_ipv6 (void);
2334 
2335 
2336 /**
2337  *  gnet_inetaddr_autodetect_internet_interface
2338  *
2339  *  Finds an interface likely to be connected to the internet.  This
2340  *  function can be used to automatically configure peer-to-peer
2341  *  applications.  The function relies on heuristics and does not
2342  *  always work correctly, especially if the host is behind a NAT.
2343  *
2344  *  Returns: an address of an internet interface; NULL if it couldn't
2345  *  find one or on error.
2346  *
2347  **/
2348 GInetAddr*
gnet_inetaddr_autodetect_internet_interface(void)2349 gnet_inetaddr_autodetect_internet_interface (void)
2350 {
2351   GInetAddr* iface = NULL;
2352   GIPv6Policy policy;
2353   policy = gnet_ipv6_get_policy();
2354   switch (policy)
2355     {
2356     case GIPV6_POLICY_IPV4_THEN_IPV6:
2357       {
2358 	iface = autodetect_internet_interface_ipv4();
2359 	if (iface) break;
2360 	iface = autodetect_internet_interface_ipv6();
2361 	break;
2362       }
2363     case GIPV6_POLICY_IPV6_THEN_IPV4:
2364       {
2365 	iface = autodetect_internet_interface_ipv6();
2366 	if (iface) break;
2367 	iface = autodetect_internet_interface_ipv4();
2368 	break;
2369       }
2370     case GIPV6_POLICY_IPV4_ONLY:
2371       {
2372 	iface = autodetect_internet_interface_ipv4();
2373 	break;
2374       }
2375     case GIPV6_POLICY_IPV6_ONLY:
2376       {
2377 	iface = autodetect_internet_interface_ipv6();
2378 	break;
2379       }
2380     }
2381 
2382   /* If that didn't work, return the first Internet interface. */
2383   if (!iface)
2384     iface = gnet_inetaddr_get_internet_interface ();
2385 
2386   return iface;
2387 }
2388 
2389 
2390 static GInetAddr*
autodetect_internet_interface_ipv4(void)2391 autodetect_internet_interface_ipv4 (void)
2392 {
2393   GInetAddr* ia;
2394   GInetAddr* iface;
2395 
2396   /* First try to get the interface with a route to
2397      junglemonkey.net (141.213.11.223).  This uses the connected UDP
2398      socket method described by Stevens.  It does not work on all
2399      systems.  (see Stevens UNPv1 pp 231-3) */
2400   ia = gnet_inetaddr_new_nonblock ("141.213.11.223", 0);
2401   g_assert (ia);
2402 
2403   iface = gnet_inetaddr_get_interface_to (ia);
2404   gnet_inetaddr_delete (ia);
2405 
2406   /* We want an internet interface */
2407   if (iface && gnet_inetaddr_is_internet(iface))
2408     return iface;
2409   gnet_inetaddr_delete (iface);
2410 
2411   return NULL;
2412 }
2413 
2414 
2415 static GInetAddr*
autodetect_internet_interface_ipv6(void)2416 autodetect_internet_interface_ipv6 (void)
2417 {
2418   GInetAddr* ia;
2419   GInetAddr* iface;
2420 
2421   /* Try IPv6 using kame.net's address */
2422   ia = gnet_inetaddr_new_nonblock("3FFE:501:4819:2000:210:F3FF:FE03:4D0", 0);
2423   g_assert (ia);
2424 
2425   iface = gnet_inetaddr_get_interface_to (ia);
2426   gnet_inetaddr_delete (ia);
2427 
2428   /* We want an internet interface */
2429   if (iface && gnet_inetaddr_is_internet(iface))
2430     return iface;
2431   gnet_inetaddr_delete (iface);
2432 
2433   return NULL;
2434 }
2435 
2436 
2437 
2438 /**
2439  *  gnet_inetaddr_get_interface_to:
2440  *  @inetaddr: a #GInetAddr
2441  *
2442  *  Figures out which local interface would be used to send a packet
2443  *  to @inetaddr.  This works on some systems, but not others.  We
2444  *  recommend using gnet_inetaddr_autodetect_internet_interface() to
2445  *  find an Internet interface since it's more likely to work.
2446  *
2447  *  Returns: the address of an interface used to route packets to
2448  *  @inetaddr; NULL if there is no such interface or the system does
2449  *  not support this check.
2450  *
2451  **/
2452 GInetAddr*
gnet_inetaddr_get_interface_to(const GInetAddr * inetaddr)2453 gnet_inetaddr_get_interface_to (const GInetAddr* inetaddr)
2454 {
2455   SOCKET sockfd;
2456   struct sockaddr_storage myaddr;
2457   socklen_t len;
2458   GInetAddr* iface;
2459 
2460   g_return_val_if_fail (inetaddr, NULL);
2461 
2462   sockfd = socket (GNET_INETADDR_FAMILY(inetaddr), SOCK_DGRAM, 0);
2463   if (!GNET_IS_SOCKET_VALID(sockfd))
2464     {
2465       g_warning ("socket() failed");
2466       return NULL;
2467     }
2468 
2469   if (connect (sockfd, &GNET_INETADDR_SA(inetaddr), GNET_INETADDR_LEN(inetaddr)) == -1)
2470     {
2471       GNET_CLOSE_SOCKET(sockfd);
2472       return NULL;
2473     }
2474 
2475   len = sizeof (myaddr);
2476   if (getsockname (sockfd, (struct sockaddr*) &myaddr, &len) != 0)
2477     {
2478       GNET_CLOSE_SOCKET(sockfd);
2479       return NULL;
2480     }
2481 
2482   iface = g_new0 (GInetAddr, 1);
2483   iface->ref_count = 1;
2484   iface->sa = myaddr;
2485 
2486   return iface;
2487 }
2488 
2489 
2490 
2491 /**
2492  *  gnet_inetaddr_get_internet_interface
2493  *
2494  *  Finds an internet interface.  This function finds the first
2495  *  interface that is an internet address.  IPv6 policy is followed.
2496  *
2497  *  This function does not work on some systems.  We recommend using
2498  *  gnet_inetaddr_autodetect_internet_interface(), which performs
2499  *  additional checks.
2500  *
2501  *  Returns: the address of an internet interface; NULL if no internet
2502  *  interfaces or on error.
2503  *
2504  **/
2505 GInetAddr*
gnet_inetaddr_get_internet_interface(void)2506 gnet_inetaddr_get_internet_interface (void)
2507 {
2508   GList* interfaces;
2509   GList* i;
2510   GInetAddr* ipv4_addr = NULL;
2511   GInetAddr* ipv6_addr = NULL;
2512   GInetAddr* iface = NULL;
2513   GIPv6Policy policy;
2514 
2515   /* Get a list of interfaces */
2516   interfaces = gnet_inetaddr_list_interfaces ();
2517   if (interfaces == NULL)
2518     return NULL;
2519 
2520   /* Find the first IPv4 and IPv6 interfaces */
2521   for (i = interfaces; i != NULL; i = i->next)
2522     {
2523       GInetAddr* ia;
2524 
2525       ia = (GInetAddr*) i->data;
2526 
2527       if (gnet_inetaddr_is_internet (ia))
2528 	{
2529 	  if (ipv4_addr == NULL && gnet_inetaddr_is_ipv4 (ia))
2530 	    ipv4_addr = ia;
2531 	  else if (ipv6_addr == NULL && gnet_inetaddr_is_ipv6 (ia))
2532 	    ipv6_addr = ia;
2533 	}
2534     }
2535 
2536   /* Choose one based on policy */
2537   policy = gnet_ipv6_get_policy();
2538   switch (policy)
2539     {
2540     case GIPV6_POLICY_IPV4_THEN_IPV6:
2541       {
2542 	if (ipv4_addr)
2543 	  iface = ipv4_addr;
2544 	else
2545 	  iface = ipv6_addr;
2546 	break;
2547       }
2548     case GIPV6_POLICY_IPV6_THEN_IPV4:
2549       {
2550 	if (ipv6_addr)
2551 	  iface = ipv6_addr;
2552 	else
2553 	  iface = ipv4_addr;
2554 	break;
2555       }
2556     case GIPV6_POLICY_IPV4_ONLY:
2557       {
2558 	iface = ipv4_addr;
2559 	break;
2560       }
2561     case GIPV6_POLICY_IPV6_ONLY:
2562       {
2563 	iface = ipv6_addr;
2564 	break;
2565       }
2566     }
2567 
2568   /* Copy the interface */
2569   if (iface != NULL)
2570     iface = gnet_inetaddr_clone (iface);
2571 
2572   /* Delete the interface list */
2573   for (i = interfaces; i != NULL; i = i->next)
2574     gnet_inetaddr_delete ((GInetAddr*) i->data);
2575   g_list_free (interfaces);
2576 
2577   return iface;
2578 }
2579 
2580 
2581 /**
2582  *  gnet_inetaddr_is_internet_domainname:
2583  *  @name: name
2584  *
2585  *  Checks if a name is a sensible internet domain name.  This
2586  *  function uses heuristics. It does not use DNS and will not block.
2587  *  For example, "localhost" and "10.10.23.42" are not sensible
2588  *  internet domain names.  (10.10.23.42 is a network address, but not
2589  *  accessible to the internet at large.)
2590  *
2591  *  Returns: TRUE if @name is a sensible Internet domain name; FALSE
2592  *  otherwise.
2593  *
2594  **/
2595 gboolean
gnet_inetaddr_is_internet_domainname(const gchar * name)2596 gnet_inetaddr_is_internet_domainname (const gchar* name)
2597 {
2598   GInetAddr* addr;
2599 
2600   g_return_val_if_fail (name, FALSE);
2601 
2602   /* The name can't be localhost or localhost.localdomain */
2603   if (!strcmp(name, "localhost") ||
2604       !strcmp(name, "localhost.localdomain"))
2605     {
2606       return FALSE;
2607     }
2608 
2609   /* The name must have a dot in it */
2610   if (!strchr(name, '.'))
2611     {
2612       return FALSE;
2613     }
2614 
2615   /* If it's dotted decimal, make sure it's valid */
2616   addr = gnet_inetaddr_new_nonblock (name, 0);
2617   if (addr)
2618     {
2619       gboolean rv;
2620 
2621       rv = gnet_inetaddr_is_internet (addr);
2622       gnet_inetaddr_delete (addr);
2623 
2624       if (!rv)
2625 	return FALSE;
2626     }
2627 
2628   return TRUE;
2629 }
2630 
2631 
2632 /* **************************************** */
2633 
2634 
2635 
2636 
2637 #ifndef GNET_WIN32		/* Unix specific version */
2638 
2639 /**
2640  *  gnet_inetaddr_list_interfaces
2641  *
2642  *  Gets a list of #GInetAddr interfaces's on this host.  This list
2643  *  includes all "up" Internet interfaces and the loopback interface,
2644  *  if it exists.
2645  *
2646  *  On Windows if you do not have IPv6 installed then this function
2647  *  will return up to 10 interfaces.
2648  *
2649  *  This function may not work on some systems.
2650  *
2651  *  Returns: A list of #GInetAddr's representing available interfaces.
2652  *  The caller should delete the list and the addresses.
2653  *
2654  **/
2655 GList*
gnet_inetaddr_list_interfaces(void)2656 gnet_inetaddr_list_interfaces (void)
2657 {
2658   GList* list = NULL;
2659 
2660   /* Use USAGI project's getifaddr() if available. */
2661 #ifdef HAVE_LINUX_NETLINK_H
2662 #  define HAVE_GETIFADDRS 1
2663 #  define getifaddrs usagi_getifaddrs
2664 #  define freeifaddrs usagi_freeifaddrs
2665 #endif
2666 
2667 #ifdef HAVE_GETIFADDRS
2668 
2669   int rv;
2670   struct ifaddrs* ifs;
2671   struct ifaddrs* i;
2672 
2673   rv = getifaddrs (&ifs);
2674   if (rv != 0)
2675     return NULL;
2676 
2677   for (i = ifs; i != NULL; i = i->ifa_next)
2678     {
2679       struct sockaddr* sa;
2680       void*  src;
2681       size_t len;
2682       GInetAddr* ia;
2683 
2684       /* Skip if not up or is loopback */
2685       if (!(i->ifa_flags & IFF_UP) ||
2686 	  (i->ifa_flags & IFF_LOOPBACK))
2687 	continue;
2688 
2689       /* Skip if no address */
2690       if (!i->ifa_addr)
2691 	continue;
2692 
2693       /* Get address, or skip if not IPv4 or IPv6 */
2694       sa = (struct sockaddr*) i->ifa_addr;
2695       if (sa->sa_family == AF_INET)
2696 	{
2697 	  src = (void*) &((struct sockaddr_in*) sa)->sin_addr;
2698 	  len = sizeof(struct in_addr);
2699 	}
2700 #ifdef HAVE_IPV6
2701       else if (sa->sa_family == AF_INET6)
2702 	{
2703 	  src = (char*) &((struct sockaddr_in6*) sa)->sin6_addr;
2704 	  len = sizeof(struct in6_addr);
2705 	}
2706 #endif
2707       else
2708 	continue;
2709 
2710       ia = g_new0 (GInetAddr, 1);
2711       ia->ref_count = 1;
2712       GNET_INETADDR_FAMILY(ia) = sa->sa_family;
2713       GNET_INETADDR_SET_SS_LEN(ia);
2714       memcpy(GNET_INETADDR_ADDRP(ia), src, len);
2715       list = g_list_prepend (list, ia);
2716     }
2717 
2718   freeifaddrs (ifs);
2719 
2720 #else	/* Old-fashioned IPv4-only method */
2721 
2722   gint len, lastlen;
2723   gchar* buf;
2724   gchar* ptr;
2725   gint sockfd;
2726   struct ifconf ifc;
2727   struct ifreq* ifr;
2728 
2729 
2730   /* Create a dummy socket */
2731   sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2732   if (!GNET_IS_SOCKET_VALID(sockfd))
2733     return NULL;
2734 
2735   len = 8 * sizeof(struct ifreq);
2736   lastlen = 0;
2737 
2738   /* Get the list of interfaces.  We might have to try multiple times
2739      if there are a lot of interfaces. */
2740   while(1)
2741     {
2742       buf = g_new0(gchar, len);
2743 
2744       ifc.ifc_len = len;
2745       ifc.ifc_buf = buf;
2746       if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
2747 	{
2748 	  /* Might have failed because our buffer was too small */
2749 	  if (errno != EINVAL || lastlen != 0)
2750 	    {
2751 	      g_free(buf);
2752 	      return NULL;
2753 	    }
2754 	}
2755       else
2756 	{
2757 	  /* Break if we got all the interfaces */
2758 	  if (ifc.ifc_len == lastlen)
2759 	    break;
2760 
2761 	  lastlen = ifc.ifc_len;
2762 	}
2763 
2764       /* Did not allocate big enough buffer - try again */
2765       len += 8 * sizeof(struct ifreq);
2766       g_free(buf);
2767     }
2768 
2769   /* Create the list.  Stevens has a much more complex way of doing
2770      this, but his is probably much more correct portable.  */
2771   for (ptr = buf; ptr < (buf + ifc.ifc_len);
2772 #ifdef HAVE_SOCKADDR_SA_LEN
2773       ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len
2774 #else
2775       ptr += sizeof(struct ifreq)
2776 #endif
2777 )
2778     {
2779       struct sockaddr_storage addr;
2780       int rv;
2781       GInetAddr* ia;
2782 
2783       ifr = (struct ifreq*) ptr;
2784 
2785       /* Ignore non-AF_INET */
2786       if (ifr->ifr_addr.sa_family != AF_INET)
2787 	{
2788 #ifdef HAVE_IPV6
2789 	  if (ifr->ifr_addr.sa_family != AF_INET6)
2790 #endif
2791 	    continue;
2792 	}
2793 
2794       /* Save the address - the next call will clobber it */
2795       memcpy(&addr, &ifr->ifr_addr, sizeof(addr));
2796 
2797       /* Get the flags */
2798       rv = ioctl(sockfd, SIOCGIFFLAGS, ifr);
2799       if (rv == -1)
2800 	continue;
2801 
2802       /* Ignore entries that aren't up or loopback.  Someday we'll
2803 	 write an interface structure and include this stuff. */
2804       if (!(ifr->ifr_flags & IFF_UP) ||
2805 	  (ifr->ifr_flags & IFF_LOOPBACK))
2806 	continue;
2807 
2808       /* Create an InetAddr for this one and add it to our list */
2809       ia = g_new0 (GInetAddr, 1);
2810       ia->ref_count = 1;
2811       ia->sa = addr;
2812       list = g_list_prepend (list, ia);
2813     }
2814 
2815   g_free (buf);
2816 #endif
2817 
2818   list = g_list_reverse (list);
2819 
2820   return list;
2821 }
2822 
2823 
2824 #else /* GNET_WIN32 Windows specific version */
2825 
2826 GList*
gnet_inetaddr_list_interfaces(void)2827 gnet_inetaddr_list_interfaces (void)
2828 {
2829   GList* list;
2830   SOCKET s;
2831   int wsError;
2832   DWORD bytesReturned;
2833   SOCKADDR_IN* pAddrInet;
2834   u_long SetFlags;
2835   INTERFACE_INFO localAddr[10];  /* Assumes there will be no more than 10 IP interfaces */
2836   int numLocalAddr;
2837   int i;
2838   struct sockaddr_storage addr;
2839   GInetAddr *ia;
2840   /*SOCKADDR_IN* pAddrInet2; */	/* For testing */
2841 
2842   PIP_ADAPTER_ADDRESSES_GNET gaa_struct, p_aa;
2843   PIP_ADAPTER_UNICAST_ADDRESS_GNET p_ua;
2844   ULONG out_len;
2845   DWORD gaa_rv;
2846   void*  src;
2847   size_t len;
2848   struct sockaddr* sa;
2849 
2850   list = NULL;
2851 
2852   /* IPv6 codepath begin */
2853   if (pfn_getaddaptersaddresses)
2854   {
2855     /* first call fails but returns needed buffer size */
2856 	out_len = 0;
2857 	gaa_struct = NULL;
2858     pfn_getaddaptersaddresses(
2859 	AF_UNSPEC,
2860 	GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST,
2861 	NULL,
2862 	gaa_struct,
2863 	&out_len);
2864 
2865 	gaa_struct = (PIP_ADAPTER_ADDRESSES_GNET)malloc(out_len);
2866 	gaa_rv = pfn_getaddaptersaddresses(
2867 	AF_UNSPEC,
2868 	GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_FRIENDLY_NAME |GAA_FLAG_SKIP_MULTICAST,
2869 	NULL,
2870 	gaa_struct,
2871 	&out_len);
2872 
2873 	if (gaa_rv != ERROR_SUCCESS)
2874 		return NULL;
2875 
2876 	p_aa = gaa_struct;
2877 	while (p_aa)
2878 	{
2879 		p_ua = p_aa->FirstUnicastAddress;
2880 		while (p_ua)
2881 		{
2882 			if (p_ua->Address.lpSockaddr)
2883 			{
2884 				sa = (struct sockaddr*) p_ua->Address.lpSockaddr;
2885 				if (sa->sa_family == AF_INET)
2886 				{
2887 					src = (void*) &((struct sockaddr_in*) sa)->sin_addr;
2888 					len = sizeof(struct in_addr);
2889 				}
2890 				else if (sa->sa_family == AF_INET6)
2891 				{
2892 					src = (char*) &((struct sockaddr_in6*) sa)->sin6_addr;
2893 					len = sizeof(struct in6_addr);
2894 				}
2895 				else
2896 				{
2897 					p_ua = p_ua->Next;
2898 					continue;
2899 				}
2900 
2901 				ia = g_new0 (GInetAddr, 1);
2902 				ia->ref_count = 1;
2903 				GNET_INETADDR_FAMILY(ia) = sa->sa_family;
2904 				GNET_INETADDR_SET_SS_LEN(ia);
2905 				memcpy(GNET_INETADDR_ADDRP(ia), src, len);
2906 				if  (gnet_inetaddr_is_loopback(ia))
2907 				{
2908 					g_free(ia);
2909 				}
2910 				else
2911 				{
2912 					list = g_list_prepend (list, ia);
2913 				}
2914 			}
2915 			p_ua = p_ua->Next;
2916 		}
2917 		p_aa = p_aa->Next;
2918 	}
2919 
2920 	free(gaa_struct);
2921 	return list;
2922   } /* IPv6 codepath end */
2923 
2924 
2925   if((s = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0)) == INVALID_SOCKET)
2926     {
2927       return NULL;
2928     }
2929 
2930   /* Enumerate all IP interfaces */
2931   wsError = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, &localAddr,
2932 		     sizeof(localAddr), &bytesReturned, NULL, NULL);
2933   if (wsError == SOCKET_ERROR)
2934     {
2935       closesocket(s);
2936       return NULL;
2937     }
2938 
2939   closesocket(s);
2940 
2941   /* Display interface information */
2942   numLocalAddr = (bytesReturned/sizeof(INTERFACE_INFO));
2943   for (i=0; i<numLocalAddr; i++)
2944     {
2945       pAddrInet = (SOCKADDR_IN*)&localAddr[i].iiAddress;
2946       memcpy(&addr, pAddrInet, sizeof(addr));
2947       /* pAddrInet2 = (SOCKADDR_IN*)&addr; */	/*For testing */
2948 
2949       SetFlags = localAddr[i].iiFlags;
2950       if ((SetFlags & IFF_UP) || (SetFlags & IFF_LOOPBACK))
2951 	{
2952 	  /* Create an InetAddr for this one and add it to our list */
2953 	  ia = g_new0(GInetAddr, 1);
2954 	  memcpy(&ia->sa, &addr, sizeof(addr));
2955 	  ia->ref_count = 1;
2956 	  list = g_list_prepend(list, ia);
2957 	}
2958     }
2959   return list;
2960 }
2961 
2962 #endif /* end Windows specific gnet_inetaddr_list_interfaces */
2963 
2964