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