2 * copyright (c) 2001-2011 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 */
15 #include <sys/socket.h>
22 static const char *iface
= NULL
;
23 struct addr localip4
, localip6
;
24 static struct addr last_localip4
, last_localip6
;
27 localip_init(const char *interface
)
36 struct ifaddrs
*ifas
, *ifa
;
37 int got_v4
= 0, got_v6
= 0;
39 localip4
.family
= IPv4
;
40 localip6
.family
= IPv6
;
43 /* reading from capfile */
45 memset(&(localip6
.ip
.v6
), 0, sizeof(localip6
.ip
.v6
));
49 if (getifaddrs(&ifas
) < 0)
50 err(1, "can't get own IP address on interface \"%s\"", iface
);
52 for (ifa
= ifas
; ifa
; ifa
= ifa
->ifa_next
) {
54 break; /* Task is already complete. */
56 if (strncmp(ifa
->ifa_name
, iface
, IFNAMSIZ
))
57 continue; /* Wrong interface. */
59 /* The first IPv4 name is always functional. */
60 if ((ifa
->ifa_addr
->sa_family
== AF_INET
) && !got_v4
)
62 /* Good IPv4 address. */
64 ((struct sockaddr_in
*)ifa
->ifa_addr
)->sin_addr
.s_addr
;
69 /* IPv6 needs some obvious exceptions. */
70 if ( ifa
->ifa_addr
->sa_family
== AF_INET6
) {
71 struct sockaddr_in6
*sa6
= (struct sockaddr_in6
*) ifa
->ifa_addr
;
73 if ( IN6_IS_ADDR_LINKLOCAL(&(sa6
->sin6_addr
))
74 || IN6_IS_ADDR_SITELOCAL(&(sa6
->sin6_addr
)) )
77 /* Only standard IPv6 can reach this point. */
78 memcpy(&(localip6
.ip
.v6
), &sa6
->sin6_addr
, sizeof(localip6
.ip
.v6
));
85 /* Report an error if IPv4 address could not be found. */
87 err(1, "can't get own IPv4 address on interface \"%s\"", iface
);
89 if (!addr_equal(&last_localip4
, &localip4
)) {
90 verbosef("localip4 update(%s) = %s", iface
, addr_to_str(&localip4
));
91 last_localip4
= localip4
;
93 if (!addr_equal(&last_localip6
, &localip6
)) {
94 verbosef("localip6 update(%s) = %s", iface
, addr_to_str(&localip6
));
95 last_localip6
= localip6
;
99 /* vim:set ts=3 sw=3 tw=78 expandtab: */