2 * copyright (c) 2001-2008 Emil Mikulic.
4 * localip.c: determine local IP of our capture interface
6 * You may use, modify and redistribute this file under the terms of the
7 * GNU General Public License version 2. (see COPYING.GPL)
11 #include "conv.h" /* for strlcpy */
12 #include "decode.h" /* for ip_to_str */
16 #include <sys/socket.h>
23 static const char *iface
= NULL
;
25 struct in_addr localip
= { 0 };
26 static struct in_addr last_localip
= { 0 };
28 struct in6_addr localip6
;
29 static struct in6_addr last_localip6
;
32 localip_init(const char *interface
)
41 struct ifaddrs
*ifas
, *ifa
;
48 /* reading from capfile */
49 memset(&localip
, 0, sizeof(localip
));
50 memset(&localip6
, 0, sizeof(localip6
));
54 if (getifaddrs(&ifas
) < 0)
55 err(1, "can't get own IP address on interface \"%s\"", iface
);
57 for (ifa
= ifas
; ifa
; ifa
= ifa
->ifa_next
) {
58 if (flags
== (HAS_IPV4
| HAS_IPV6
))
59 break; /* Task is already complete. */
61 if (strncmp(ifa
->ifa_name
, iface
, IFNAMSIZ
))
62 continue; /* Wrong interface. */
64 /* The first IPv4 name is always functional. */
65 if ( (ifa
->ifa_addr
->sa_family
== AF_INET
)
66 && ! (flags
& HAS_IPV4
) ) {
67 /* Good IPv4 address. */
68 localip
.s_addr
= ((struct sockaddr_in
*) ifa
->ifa_addr
)->sin_addr
.s_addr
;
73 /* IPv6 needs some obvious exceptions. */
74 if ( ifa
->ifa_addr
->sa_family
== AF_INET6
) {
75 struct sockaddr_in6
*sa6
= (struct sockaddr_in6
*) ifa
->ifa_addr
;
77 if ( IN6_IS_ADDR_LINKLOCAL(&(sa6
->sin6_addr
))
78 || IN6_IS_ADDR_SITELOCAL(&(sa6
->sin6_addr
)) )
81 /* Only standard IPv6 can reach this point. */
82 memcpy(&localip6
, &sa6
->sin6_addr
, sizeof(localip6
));
89 /* Repport an error if IPv4 address could not be found. */
90 if ( !(flags
& HAS_IPV4
) )
91 err(1, "can't get own IPv4 address on interface \"%s\"", iface
);
94 * sa_family_t sa_family; * address family, AF_xxx
95 * char sa_data[14]; * 14 bytes of protocol address
97 * struct sockaddr_in {
98 * sa_family_t sin_family; * Address family
99 * unsigned short int sin_port; * Port number
100 * struct in_addr sin_addr; * Internet address
106 if (last_localip
.s_addr
!= localip
.s_addr
) {
107 verbosef("local_ip update(%s) = %s", iface
,
108 ip_to_str_af(&localip
, AF_INET
));
109 memcpy(&last_localip
, &localip
, sizeof(last_localip
));
111 if (memcmp(&last_localip6
, &localip6
, sizeof(localip6
))) {
112 verbosef("local_ip6 update(%s) = %s", iface
,
113 ip_to_str_af(&localip6
, AF_INET6
));
114 memcpy(&last_localip6
, &localip6
, sizeof(localip6
));
118 /* vim:set ts=3 sw=3 tw=78 expandtab: */