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 "config.h" /* for HAVE_IFADDRS_H */
12 #include "conv.h" /* for strlcpy */
16 #include <sys/socket.h>
25 # ifdef HAVE_SYS_SOCKIO_H
26 # include <sys/sockio.h> /* for SIOCGIFADDR, especially on Solaris */
28 # include <sys/ioctl.h>
31 static const char *iface
= NULL
;
32 struct addr localip4
, localip6
;
33 static struct addr last_localip4
, last_localip6
;
36 localip_init(const char *interface
)
46 localip4
.family
= IPv4
;
49 localip6
.family
= IPv6
;
50 memset(&(localip6
.ip
.v6
), 0, sizeof(localip6
.ip
.v6
));
53 /* not reading from capfile */
55 int got_v4
= 0, got_v6
= 0;
56 struct ifaddrs
*ifas
, *ifa
;
58 if (getifaddrs(&ifas
) < 0)
59 err(1, "can't get own IP address on interface \"%s\"", iface
);
61 for (ifa
= ifas
; ifa
; ifa
= ifa
->ifa_next
) {
63 break; /* Task is already complete. */
65 if (strncmp(ifa
->ifa_name
, iface
, IFNAMSIZ
))
66 continue; /* Wrong interface. */
68 /* The first IPv4 name is always functional. */
69 if ((ifa
->ifa_addr
->sa_family
== AF_INET
) && !got_v4
)
71 /* Good IPv4 address. */
73 ((struct sockaddr_in
*)ifa
->ifa_addr
)->sin_addr
.s_addr
;
78 /* IPv6 needs some obvious exceptions. */
79 if ( ifa
->ifa_addr
->sa_family
== AF_INET6
) {
80 struct sockaddr_in6
*sa6
= (struct sockaddr_in6
*) ifa
->ifa_addr
;
82 if ( IN6_IS_ADDR_LINKLOCAL(&(sa6
->sin6_addr
))
83 || IN6_IS_ADDR_SITELOCAL(&(sa6
->sin6_addr
)) )
86 /* Only standard IPv6 can reach this point. */
87 memcpy(&(localip6
.ip
.v6
), &sa6
->sin6_addr
, sizeof(localip6
.ip
.v6
));
94 /* Report an error if IPv4 address could not be found. */
96 err(1, "can't get own IPv4 address on interface \"%s\"", iface
);
98 #else /* don't HAVE_IFADDRS_H */
100 int tmp
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
104 strlcpy(ifr
.ifr_name
, iface
, IFNAMSIZ
);
105 ifr
.ifr_addr
.sa_family
= AF_INET
;
106 if (ioctl(tmp
, SIOCGIFADDR
, &ifr
) == -1) {
107 if (errno
== EADDRNOTAVAIL
) {
108 verbosef("lost local IP");
110 err(1, "can't get own IP address on interface \"%s\"", iface
);
114 localip4
.ip
.v4
= ((struct sockaddr_in
*)&sa
)->sin_addr
.s_addr
;
121 if (!addr_equal(&last_localip4
, &localip4
)) {
122 verbosef("localip4 update(%s) = %s", iface
, addr_to_str(&localip4
));
123 last_localip4
= localip4
;
125 if (!addr_equal(&last_localip6
, &localip6
)) {
126 verbosef("localip6 update(%s) = %s", iface
, addr_to_str(&localip6
));
127 last_localip6
= localip6
;
131 /* vim:set ts=3 sw=3 tw=78 expandtab: */