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