1 /*
2  * GNetwork Library: libgnetwork/gnetwork-interfaces.c
3  *
4  * Copyright (C) 2003 James M. Cape
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; version 2.1 of the
9  * License.
10  *
11  * This program 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
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif /* HAVE_CONFIG_H */
25 
26 #include "gnetwork-interfaces.h"
27 
28 #include "gnetwork-ip-address.h"
29 #include "gnetwork-utils.h"
30 #include "gnetwork-type-builtins.h"
31 
32 #include <sys/types.h>
33 
34 #include <unistd.h>
35 
36 /* Interfaces & Addresses */
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <net/if.h>
41 
42 #ifdef __linux__
43 # include <netpacket/packet.h>
44 # include <netinet/ether.h>
45 #else
46 # include <net/ethernet.h>
47 #endif
48 
49 #include <ifaddrs.h>
50 #include <arpa/inet.h>
51 
52 #include <stdio.h>
53 #include <string.h>
54 
55 
56 /* *************** *
57  *  Private Types  *
58  * *************** */
59 
60 struct _GNetworkInterfaceInfo
61 {
62   GTypeClass g_class;
63 
64   gint ref;
65 
66   guint64 index_;
67   gchar *name;
68 
69   GNetworkIpAddress ip4_address;
70   GNetworkIpAddress ip4_netmask;
71   GNetworkIpAddress ip4_broadcast_or_destination;
72   GSList *ip4_multicasts;
73 
74   GNetworkIpAddress ip6_address;
75   GNetworkIpAddress ip6_netmask;
76   GNetworkIpAddress ip6_destination;
77   GSList *ip6_multicasts;
78 
79   gchar *hw_address;
80   gchar *hw_broadcast_or_destination;
81 
82   GNetworkInterfaceFlags flags:16;
83   GNetworkProtocols protocols:3;
84 };
85 
86 
87 /* ******************* *
88  *  Utility Functions  *
89  * ******************* */
90 
91 static void
append_iface_info_from_interface(GNetworkInterfaceInfo * info,struct ifaddrs * data)92 append_iface_info_from_interface (GNetworkInterfaceInfo * info, struct ifaddrs *data)
93 {
94   GNetworkIpAddress addr = GNETWORK_IP_ADDRESS_INIT;
95 
96   switch (data->ifa_addr->sa_family)
97     {
98     case AF_INET:
99       info->protocols |= GNETWORK_PROTOCOL_IPv4;
100 
101       _gnetwork_ip_address_set_from_sockaddr (&addr, data->ifa_addr);
102 
103       if (gnetwork_ip_address_is_multicast (&addr))
104 	{
105 	  info->ip4_multicasts = g_slist_prepend (info->ip4_multicasts,
106 						  gnetwork_ip_address_dup (&addr));
107 	}
108       else
109 	{
110 	  memcpy (&(info->ip4_address), &addr, sizeof (GNetworkIpAddress));
111 	}
112 
113       _gnetwork_ip_address_set_from_sockaddr (&(info->ip4_address), data->ifa_addr);
114       _gnetwork_ip_address_set_from_sockaddr (&(info->ip4_netmask), data->ifa_netmask);
115       _gnetwork_ip_address_set_from_sockaddr (&(info->ip4_broadcast_or_destination),
116 					     data->ifa_dstaddr);
117       break;
118     case AF_INET6:
119       info->protocols |= GNETWORK_PROTOCOL_IPv6;
120 
121       _gnetwork_ip_address_set_from_sockaddr (&addr, data->ifa_addr);
122 
123       if (gnetwork_ip_address_is_multicast (&addr))
124 	{
125 	  info->ip6_multicasts = g_slist_prepend (info->ip6_multicasts,
126 						  gnetwork_ip_address_dup (&addr));
127 	}
128       else
129 	{
130 	  memcpy (&(info->ip6_address), &addr, sizeof (GNetworkIpAddress));
131 	}
132 
133       _gnetwork_ip_address_set_from_sockaddr (&(info->ip6_netmask), data->ifa_netmask);
134       _gnetwork_ip_address_set_from_sockaddr (&(info->ip6_destination), data->ifa_dstaddr);
135       break;
136 #ifdef AF_PACKET
137     case AF_PACKET:
138       info->protocols |= GNETWORK_PROTOCOL_PACKET;
139 
140       info->index_ = ((struct sockaddr_ll *) (data->ifa_addr))->sll_ifindex;
141 
142       info->hw_address = _gnetwork_sockaddr_get_address (data->ifa_addr);
143       info->hw_broadcast_or_destination = _gnetwork_sockaddr_get_address (data->ifa_dstaddr);
144       break;
145 #endif
146     }
147 }
148 
149 
150 static GNetworkInterfaceInfo *
create_info_from_interface(struct ifaddrs * data)151 create_info_from_interface (struct ifaddrs *data)
152 {
153   GNetworkInterfaceInfo *info = g_new0 (GNetworkInterfaceInfo, 1);
154 
155   info->g_class.g_type = GNETWORK_TYPE_INTERFACE_INFO;
156   info->ref = 1;
157 
158   info->name = g_strdup (data->ifa_name);
159   info->ip4_multicasts = NULL;
160   info->ip6_multicasts = NULL;
161 
162   info->flags = GNETWORK_INTERFACE_NONE;
163 
164   /* Flags */
165   if (data->ifa_flags & IFF_UP)
166     info->flags |= GNETWORK_INTERFACE_IS_UP;
167 
168   if (data->ifa_flags & IFF_RUNNING)
169     info->flags |= GNETWORK_INTERFACE_IS_RUNNING;
170 
171   if (data->ifa_flags & IFF_DEBUG)
172     info->flags |= GNETWORK_INTERFACE_IS_DEBUGGING;
173 
174   if (data->ifa_flags & IFF_LOOPBACK)
175     info->flags |= GNETWORK_INTERFACE_IS_LOOPBACK;
176 
177   if (data->ifa_flags & IFF_POINTOPOINT)
178     info->flags |= GNETWORK_INTERFACE_IS_POINT_TO_POINT;
179 
180 #ifdef IFF_MASTER
181   if (data->ifa_flags & IFF_MASTER)
182     info->flags |= GNETWORK_INTERFACE_IS_LOAD_MASTER;
183 #endif /* IFF_MASTER */
184 
185 #ifdef IFF_SLAVE
186   if (data->ifa_flags & IFF_SLAVE)
187     info->flags |= GNETWORK_INTERFACE_IS_LOAD_SLAVE;
188 #endif /* IFF_SLAVE */
189 
190   if (data->ifa_flags & IFF_BROADCAST)
191     info->flags |= GNETWORK_INTERFACE_CAN_BROADCAST;
192 
193   if (data->ifa_flags & IFF_MULTICAST)
194     info->flags |= GNETWORK_INTERFACE_CAN_MULTICAST;
195 
196 #ifdef IFF_NOTRAILERS
197   if (data->ifa_flags & IFF_NOTRAILERS)
198     info->flags |= GNETWORK_INTERFACE_NO_TRAILERS;
199 #endif /* IFF_NOTRAILERS */
200 
201   if (data->ifa_flags & IFF_NOARP)
202     info->flags |= GNETWORK_INTERFACE_NO_ARP;
203 
204 #ifdef IFF_PORTSEL
205   if (data->ifa_flags & IFF_PORTSEL)
206     info->flags |= GNETWORK_INTERFACE_CAN_SET_MEDIA;
207 #endif /* IFF_PORTSEL */
208 
209 #ifdef IFF_ALTPHYS
210   if (data->ifa_flags & IFF_ALTPHYS)
211     info->flags |= GNETWORK_INTERFACE_ALTERNATE_LINK;
212 #endif /* IFF_ALTPHYS */
213 
214 #ifdef IFF_AUTOMEDIA
215   if (data->ifa_flags & IFF_AUTOMEDIA)
216     info->flags |= GNETWORK_INTERFACE_AUTOSELECTED_MEDIA;
217 #endif /* IFF_AUTOMEDIA */
218 
219   if (data->ifa_flags & IFF_PROMISC)
220     info->flags |= GNETWORK_INTERFACE_RECV_ALL_PACKETS;
221 
222   if (data->ifa_flags & IFF_ALLMULTI)
223     info->flags |= GNETWORK_INTERFACE_RECV_ALL_MULTICAST;
224 
225   return info;
226 }
227 
228 
229 /* ************************************************************************** *
230  *  Public API                                                                *
231  * ************************************************************************** */
232 
233 GType
gnetwork_interface_info_get_type(void)234 gnetwork_interface_info_get_type (void)
235 {
236   static GType type = G_TYPE_INVALID;
237 
238   if (type == G_TYPE_INVALID)
239     {
240       type = g_boxed_type_register_static ("GNetworkInterfaceInfo",
241 					   (GBoxedCopyFunc) gnetwork_interface_info_ref,
242 					   (GBoxedFreeFunc) gnetwork_interface_info_unref);
243     }
244 
245   return type;
246 }
247 
248 
249 /**
250  * gnetwork_interface_get_info:
251  * @name: the name of the interface.
252  *
253  * Retrieves the information for the interface referred to by @name. The @name
254  * should be something like "%eth0", "%lo", etc.
255  *
256  * Returns: a structure describing a local interface.
257  *
258  * Since: 1.0
259  **/
260 GNetworkInterfaceInfo *
gnetwork_interface_get_info(const gchar * name)261 gnetwork_interface_get_info (const gchar * name)
262 {
263   struct ifaddrs *interfaces, *current;
264   GNetworkInterfaceInfo *retval;
265 
266   g_return_val_if_fail (name != NULL, NULL);
267   g_return_val_if_fail (strncmp (name, "sit", 3) != 0, NULL);
268 
269   interfaces = NULL;
270 
271   if (getifaddrs (&interfaces) < 0)
272     return NULL;
273 
274   retval = NULL;
275 
276   for (current = interfaces; current != NULL; current = current->ifa_next)
277     {
278       if (g_ascii_strcasecmp (current->ifa_name, name) == 0)
279 	{
280 	  if (retval == NULL)
281 	    {
282 	      retval = create_info_from_interface (current);
283 	    }
284 
285 	  append_iface_info_from_interface (retval, current);
286 	}
287     }
288 
289   freeifaddrs (interfaces);
290 
291   return retval;
292 }
293 
294 
295 typedef struct
296 {
297   gboolean is_ipaddr;
298   gconstpointer addr;
299   GNetworkInterfaceInfo *retval;
300 }
301 FindByAddrData;
302 
303 
304 static void
find_by_address(gpointer key,GNetworkInterfaceInfo * info,FindByAddrData * find_data)305 find_by_address (gpointer key, GNetworkInterfaceInfo *info, FindByAddrData *find_data)
306 {
307   if (find_data->is_ipaddr)
308     {
309       if (gnetwork_ip_address_is_ipv4 (find_data->addr))
310 	{
311 	  if (gnetwork_ip_address_equal (&(info->ip4_address), find_data->addr) ||
312 	      gnetwork_ip_address_equal (&(info->ip4_broadcast_or_destination), find_data->addr) ||
313 	      gnetwork_ip_address_equal (&(info->ip4_netmask), find_data->addr))
314 	    {
315 	      find_data->retval = gnetwork_interface_info_ref (info);
316 	    }
317 	}
318       else if (gnetwork_ip_address_equal (&(info->ip6_address), find_data->addr))
319 	{
320 	  find_data->retval = gnetwork_interface_info_ref (info);
321 	}
322     }
323   else if (g_ascii_strcasecmp (find_data->addr, info->hw_address) == 0)
324     {
325       find_data->retval = gnetwork_interface_info_ref (info);
326     }
327 }
328 
329 
330 /**
331  * gnetwork_interface_get_info_by_address:
332  * @address: a valid address string.
333  *
334  * Retrieves the #GNetworkInterfaceInfo which uses the address in @address.
335  *
336  * Returns: a list of local interfaces.
337  *
338  * Since: 1.0
339  **/
340 GNetworkInterfaceInfo *
gnetwork_interface_get_info_by_address(const gchar * address)341 gnetwork_interface_get_info_by_address (const gchar * address)
342 {
343   GNetworkIpAddress addr;
344   GHashTable *table;
345   struct ifaddrs *interfaces, *current;
346   guint i;
347   FindByAddrData find_data = {
348     FALSE, NULL, NULL
349   };
350 
351   interfaces = NULL;
352 
353   if (getifaddrs (&interfaces) < 0)
354     return NULL;
355 
356   /* Create the interface information. */
357   table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
358 				 (GDestroyNotify) gnetwork_interface_info_unref);
359 
360   for (i = 0, current = interfaces; current != NULL; current = current->ifa_next, i++)
361     {
362       if (strncmp (current->ifa_name, "sit", 3) != 0)
363 	{
364 	  GNetworkInterfaceInfo *data = g_hash_table_lookup (table, current->ifa_name);
365 
366 	  if (data == NULL)
367 	    {
368 	      data = create_info_from_interface (current);
369 	      g_hash_table_insert (table, data->name, data);
370 	    }
371 
372 	  append_iface_info_from_interface (data, current);
373 	}
374     }
375 
376   freeifaddrs (interfaces);
377 
378   find_data.is_ipaddr = gnetwork_ip_address_set_from_string (&addr, address);
379 
380   if (find_data.is_ipaddr)
381     find_data.addr = &addr;
382   else
383     find_data.addr = address;
384 
385   g_hash_table_foreach (table, (GHFunc) find_by_address, &find_data);
386   g_hash_table_destroy (table);
387 
388   return find_data.retval;
389 }
390 
391 
392 /**
393  * gnetwork_interface_get_all_interfaces:
394  *
395  * Retrieves a list of #GNetworkInterfaceInfo structures representing the local
396  * interfaces for this host. The returned list and list data should be freed
397  * using the following code:
398  *
399  * <informalexample><programlisting>g_slist_foreach (list, (GFunc) gnetwork_interface_info_unref, NULL);
400  * g_slist_free (list);
401  * </programlisting></informalexample>
402  *
403  * Returns: a list of local interfaces.
404  *
405  * Since: 1.0
406  **/
407 GSList *
gnetwork_interface_get_all_interfaces(void)408 gnetwork_interface_get_all_interfaces (void)
409 {
410   GHashTable *table;
411   struct ifaddrs *interfaces, *current;
412   GSList *retval;
413   guint i;
414 
415   interfaces = NULL;
416 
417   if (getifaddrs (&interfaces) < 0)
418     return NULL;
419 
420   table = g_hash_table_new (g_str_hash, g_str_equal);
421 
422   for (i = 0, current = interfaces; current != NULL; current = current->ifa_next, i++)
423     {
424       if (strncmp (current->ifa_name, "sit", 3) != 0)
425 	{
426 	  GNetworkInterfaceInfo *data = g_hash_table_lookup (table, current->ifa_name);
427 
428 	  if (data == NULL)
429 	    {
430 	      data = create_info_from_interface (current);
431 	      g_hash_table_insert (table, data->name, data);
432 	    }
433 
434 	  append_iface_info_from_interface (data, current);
435 	}
436     }
437 
438   freeifaddrs (interfaces);
439 
440   retval = NULL;
441   g_hash_table_foreach (table, _gnetwork_slist_from_hash_table, &retval);
442   g_hash_table_destroy (table);
443 
444   return g_slist_sort (retval, (GCompareFunc) gnetwork_interface_info_collate);
445 }
446 
447 
448 /**
449  * gnetwork_interface_info_get_name:
450  * @info: the interface information to examine.
451  *
452  * Retrieves the configured name of the interface described by @info (e.g.
453  * "eth0"). If @info is invalid, %NULL will be returned.
454  *
455  * Returns: the name of @info, or %NULL.
456  *
457  * Since: 1.0
458  **/
459 gchar *
gnetwork_interface_info_get_name(const GNetworkInterfaceInfo * info)460 gnetwork_interface_info_get_name (const GNetworkInterfaceInfo * info)
461 {
462   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), NULL);
463 
464   return g_strdup (info->name);
465 }
466 
467 
468 /**
469  * gnetwork_interface_info_get_protocols:
470  * @info: the interface information to examine.
471  *
472  * Retrieves the protocols used by the interface at @info. If @info is invalid,
473  * or the interface does not support any known protcols, %GNETWORK_PROTOCOL_NONE
474  * will be returned.
475  *
476  * Returns: the protocols used by @info.
477  *
478  * Since: 1.0
479  **/
480 GNetworkProtocols
gnetwork_interface_info_get_protocols(const GNetworkInterfaceInfo * info)481 gnetwork_interface_info_get_protocols (const GNetworkInterfaceInfo * info)
482 {
483   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), GNETWORK_PROTOCOL_NONE);
484 
485   return info->protocols;
486 }
487 
488 
489 /**
490  * gnetwork_interface_info_get_address:
491  * @info: the interface information to examine.
492  * @protocol: the protocol type to use.
493  *
494  * Retrieves the configured @protocol address of the interface described by
495  * @info (e.g. "127.0.0.1" for IPv4, "::1" for IPv6, or "00:00:00:00:00:00" for
496  * hardware). If @info is invalid, @protocol contains more than one flag, or if
497  * @info does not support @protocol, %NULL will be returned.
498  *
499  * Returns: the @protocol address of @info, or %NULL.
500  *
501  * Since: 1.0
502  **/
503 gconstpointer
gnetwork_interface_info_get_address(const GNetworkInterfaceInfo * info,GNetworkProtocols protocol)504 gnetwork_interface_info_get_address (const GNetworkInterfaceInfo * info, GNetworkProtocols protocol)
505 {
506   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), NULL);
507   g_return_val_if_fail (_gnetwork_flags_value_is_valid (GNETWORK_TYPE_PROTOCOLS, protocol), NULL);
508 
509   switch (protocol)
510     {
511     case GNETWORK_PROTOCOL_PACKET:
512       return info->hw_address;
513     case GNETWORK_PROTOCOL_IPv4:
514       return &(info->ip4_address);
515     case GNETWORK_PROTOCOL_IPv6:
516       return &(info->ip6_address);
517 
518     default:
519       break;
520     }
521 
522   g_return_val_if_reached (NULL);
523 }
524 
525 
526 /**
527  * gnetwork_interface_info_get_broadcast_address:
528  * @info: the interface information to examine.
529  * @protocol: the protocol type to use.
530  *
531  * Retrieves the broadcast address of the interface described by @info (e.g.
532  * "127.0.0.255" for IPv4 or "00:00:00:00:00:00" for hardware). If @info is
533  * invalid or is a "point-to-point" interface, or if @protocol does not support
534  * broadcasting (like IPv6), %NULL will be returned.
535  *
536  * Returns: the @protocol broadcast address of @info, or %NULL.
537  *
538  * Since: 1.0
539  **/
540 gconstpointer
gnetwork_interface_info_get_broadcast_address(const GNetworkInterfaceInfo * info,GNetworkProtocols protocol)541 gnetwork_interface_info_get_broadcast_address (const GNetworkInterfaceInfo * info,
542 					       GNetworkProtocols protocol)
543 {
544   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), NULL);
545   g_return_val_if_fail (_gnetwork_flags_value_is_valid (GNETWORK_TYPE_PROTOCOLS, protocol), NULL);
546 
547   switch (protocol)
548     {
549     case GNETWORK_PROTOCOL_PACKET:
550       return (!(info->flags & GNETWORK_INTERFACE_IS_POINT_TO_POINT) ?
551 	      info->hw_broadcast_or_destination : NULL);
552     case GNETWORK_PROTOCOL_IPv4:
553       return (!(info->flags & GNETWORK_INTERFACE_IS_POINT_TO_POINT) ?
554 	      &(info->ip4_broadcast_or_destination) : NULL);
555     case GNETWORK_PROTOCOL_IPv6:
556       return NULL;
557 
558     default:
559       break;
560     }
561 
562   g_return_val_if_reached (NULL);
563 }
564 
565 
566 /**
567  * gnetwork_interface_info_get_destination:
568  * @info: the interface information to examine.
569  * @protocol: the protocol type to use.
570  *
571  * Retrieves the destination address of the interface described by @info, (e.g.
572  * "127.0.0.1" for IPv4, "::1" for IPv6, or "00:00:00:00:00:00" for hardware).
573  * The returned data should not be modified or freed. If @info is invalid or
574  * is not a "point-to-point" interface, %NULL will be returned.
575  *
576  * See also: gnetwork_interface_info_get_flags().
577  *
578  * Returns: the @protocol destination address of @info, or %NULL.
579  *
580  * Since: 1.0
581  **/
582 gconstpointer
gnetwork_interface_info_get_destination(const GNetworkInterfaceInfo * info,GNetworkProtocols protocol)583 gnetwork_interface_info_get_destination (const GNetworkInterfaceInfo * info,
584 					 GNetworkProtocols protocol)
585 {
586   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), NULL);
587   g_return_val_if_fail (_gnetwork_flags_value_is_valid (GNETWORK_TYPE_PROTOCOLS, protocol), NULL);
588 
589   switch (protocol)
590     {
591     case GNETWORK_PROTOCOL_PACKET:
592       return (info->flags & GNETWORK_INTERFACE_IS_POINT_TO_POINT ?
593 	      info->hw_broadcast_or_destination : NULL);
594     case GNETWORK_PROTOCOL_IPv4:
595       return (info->flags & GNETWORK_INTERFACE_IS_POINT_TO_POINT ?
596 	      &(info->ip4_broadcast_or_destination) : NULL);
597     case GNETWORK_PROTOCOL_IPv6:
598       return (info->flags & GNETWORK_INTERFACE_IS_POINT_TO_POINT ?
599 	      &(info->ip6_destination) : NULL);
600 
601     default:
602       break;
603     }
604 
605   g_return_val_if_reached (NULL);
606 }
607 
608 
609 /**
610  * gnetwork_interface_info_get_netmask:
611  * @info: the interface information to examine.
612  * @protocol: the protocol to use.
613  *
614  * Retrieves the @protocol network mask of the interface described by @info
615  * (e.g. "255.255.255.255" for IPv4, or "ffff:ffff:ffff:ffff" for IPv6). If
616  * @info is invalid, %NULL will be returned.
617  *
618  * Returns: the network mask of @info, or %NULL.
619  *
620  * Since: 1.0
621  **/
622 gconstpointer
gnetwork_interface_info_get_netmask(const GNetworkInterfaceInfo * info,GNetworkProtocols protocol)623 gnetwork_interface_info_get_netmask (const GNetworkInterfaceInfo * info, GNetworkProtocols protocol)
624 {
625   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), NULL);
626   g_return_val_if_fail (_gnetwork_flags_value_is_valid (GNETWORK_TYPE_PROTOCOLS, protocol), NULL);
627 
628   switch (protocol)
629     {
630     case GNETWORK_PROTOCOL_IPv4:
631       return &(info->ip4_netmask);
632     case GNETWORK_PROTOCOL_IPv6:
633       return &(info->ip6_netmask);
634     case GNETWORK_PROTOCOL_PACKET:
635       return NULL;
636 
637     default:
638       break;
639     }
640 
641   g_return_val_if_reached (NULL);
642 }
643 
644 
645 /**
646  * gnetwork_interface_info_get_multicasts:
647  * @info: the interface information to examine.
648  * @protocol: the protocol to use.
649  *
650  * Retrieves a list of current multicast IP addresses for @protocol from the
651  * interface described by @info (e.g. "224.0.0.1" for IPv4, or "ff02::1" for
652  * IPv6). If @info or @protocol is invalid, or @protocol does not support
653  * multicasting (like the packet protocol), %NULL will be returned.
654  *
655  * Returns: the multicast addresses of @info, or %NULL.
656  *
657  * Since: 1.0
658  **/
659 G_CONST_RETURN GSList *
gnetwork_interface_info_get_multicasts(const GNetworkInterfaceInfo * info,GNetworkProtocols protocol)660 gnetwork_interface_info_get_multicasts (const GNetworkInterfaceInfo * info,
661 					GNetworkProtocols protocol)
662 {
663   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), NULL);
664   g_return_val_if_fail (_gnetwork_flags_value_is_valid (GNETWORK_TYPE_PROTOCOLS, protocol), NULL);
665 
666   switch (protocol)
667     {
668     case GNETWORK_PROTOCOL_IPv4:
669       return info->ip4_multicasts;
670     case GNETWORK_PROTOCOL_IPv6:
671       return info->ip6_multicasts;
672     case GNETWORK_PROTOCOL_PACKET:
673       return NULL;
674 
675     default:
676       break;
677     }
678 
679   g_return_val_if_reached (NULL);
680 }
681 
682 
683 /**
684  * gnetwork_interface_info_get_flags:
685  * @info: the interface information to examine.
686  *
687  * Retrieves the flags set on interface described by @info. If @info is invalid
688  * or no flags have been set, %GNETWORK_INTERFACE_NONE is returned.
689  *
690  * Returns: the flags set on @interface.
691  *
692  * Since: 1.0
693  **/
694 GNetworkInterfaceFlags
gnetwork_interface_info_get_flags(const GNetworkInterfaceInfo * info)695 gnetwork_interface_info_get_flags (const GNetworkInterfaceInfo * info)
696 {
697   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), GNETWORK_INTERFACE_NONE);
698 
699   return info->flags;
700 }
701 
702 
703 /**
704  * gnetwork_interface_info_get_index:
705  * @info: the interface information to examine.
706  *
707  * Retrieves the index of the interface described by @info. If @info is invalid
708  * or the index is unknown, %0 is returned.
709  *
710  * Returns: the index of @interface.
711  *
712  * Since: 1.0
713  **/
714 guint
gnetwork_interface_info_get_index(const GNetworkInterfaceInfo * info)715 gnetwork_interface_info_get_index (const GNetworkInterfaceInfo * info)
716 {
717   g_return_val_if_fail (GNETWORK_IS_INTERFACE_INFO (info), 0);
718 
719   return info->index_;
720 }
721 
722 
723 /**
724  * gnetwork_interface_info_ref:
725  * @info: the data to reference.
726  *
727  * Creates a reference to the data in @info. When no longer needed, this
728  * reference should be released with gnetwork_interface_info_unref().
729  *
730  * Returns: a reference to @info, or %NULL.
731  *
732  * Since: 1.0
733  **/
734 GNetworkInterfaceInfo *
gnetwork_interface_info_ref(GNetworkInterfaceInfo * info)735 gnetwork_interface_info_ref (GNetworkInterfaceInfo * info)
736 {
737   g_return_val_if_fail (info == NULL || GNETWORK_IS_INTERFACE_INFO (info), NULL);
738 
739   if (info != NULL && info->ref > 0)
740     {
741       info->ref++;
742     }
743 
744   return info;
745 }
746 
747 
748 /**
749  * gnetwork_interface_info_unref:
750  * @info: the local interface reference to release.
751  *
752  * Releases a reference to the data in @info. When all references have been
753  * released, the data in @info will be destroyed.
754  *
755  * Since: 1.0
756  **/
757 void
gnetwork_interface_info_unref(GNetworkInterfaceInfo * info)758 gnetwork_interface_info_unref (GNetworkInterfaceInfo * info)
759 {
760   g_return_if_fail (info == NULL || GNETWORK_IS_INTERFACE_INFO (info));
761 
762   if (info == NULL)
763     return;
764 
765   info->ref--;
766 
767   if (info->ref == 0)
768     {
769       g_free (info->name);
770 
771       g_slist_foreach (info->ip4_multicasts, (GFunc) g_free, NULL);
772       g_slist_free (info->ip4_multicasts);
773 
774       g_slist_foreach (info->ip6_multicasts, (GFunc) g_free, NULL);
775       g_slist_free (info->ip4_multicasts);
776 
777       g_free (info->hw_address);
778       g_free (info->hw_broadcast_or_destination);
779       g_free (info);
780     }
781 }
782 
783 
784 /**
785  * gnetwork_interface_info_collate:
786  * @info1: a structure describing a local interface.
787  * @info2: a structure describing a local interface.
788  *
789  * Determines which interface of the arguments is "greater" (should be sorted
790  * before) than the other, using the name.
791  *
792  * Returns: %-1 if @info1 should be sorted first, %1 if @info2 should be sorted first, or %0 if they are equal.
793  *
794  * Since: 1.0
795  **/
796 gint
gnetwork_interface_info_collate(const GNetworkInterfaceInfo * info1,const GNetworkInterfaceInfo * info2)797 gnetwork_interface_info_collate (const GNetworkInterfaceInfo * info1,
798 				 const GNetworkInterfaceInfo * info2)
799 {
800   gint retval;
801 
802   g_return_val_if_fail (info1 == NULL || GNETWORK_IS_INTERFACE_INFO (info1), 0);
803   g_return_val_if_fail (info2 == NULL || GNETWORK_IS_INTERFACE_INFO (info2), 0);
804 
805   if (info1 == NULL && info2 != NULL)
806     retval = 1;
807   else if (info1 != NULL && info2 == NULL)
808     retval = -1;
809   else if (info1 == info2)
810     retval = 0;
811   else if (info1->name == NULL && info2->name != NULL)
812     retval = 1;
813   else if (info1->name != NULL && info2->name == NULL)
814     retval = -1;
815   else if (info1->name == info2->name)
816     retval = 0;
817   else
818     retval = g_utf8_collate (info1->name, info2->name);
819 
820   return retval;
821 }
822 
823 
824 /* GNetworkProtocols
825 gnetwork_str_to_protocol (const gchar * address)
826 {
827   GNetworkProtocols retval;
828   gpointer ptr;
829 
830   if (address == NULL || address[0] == '\0')
831     return GNETWORK_PROTOCOL_NONE;
832 
833   ptr = g_malloc0 (MAX (sizeof (struct in_addr), sizeof (struct in6_addr)));
834   if (inet_pton (AF_INET6, address, ptr) > -1)
835     retval = GNETWORK_PROTOCOL_IPv6;
836   if (inet_pton (AF_INET, address, ptr) > -1)
837     retval = GNETWORK_PROTOCOL_IPv4;
838   else if (ether_aton (address) != NULL)
839     retval = GNETWORK_PROTOCOL_PACKET;
840   else
841     retval = GNETWORK_PROTOCOL_NONE;
842 
843   g_free (ptr);
844 
845   return retval;
846 } */
847