0c15409906ab3dd8899be4122af33664b3d6ff1b
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 */
14 #include "bsd.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
)
41 localip4
.family
= IPv4
;
44 localip6
.family
= IPv6
;
45 memset(&(localip6
.ip
.v6
), 0, sizeof(localip6
.ip
.v6
));
47 last_localip4
= localip4
;
48 last_localip6
= localip6
;
55 localip_update_helper(void)
58 localip4
.family
= IPv4
;
61 localip6
.family
= IPv6
;
62 memset(&(localip6
.ip
.v6
), 0, sizeof(localip6
.ip
.v6
));
65 return; /* reading from capfile */
69 int got_v4
= 0, got_v6
= 0;
70 struct ifaddrs
*ifas
, *ifa
;
72 if (getifaddrs(&ifas
) < 0) {
73 warn("can't getifaddrs() on interface \"%s\"", iface
);
77 for (ifa
= ifas
; ifa
; ifa
= ifa
->ifa_next
) {
79 break; /* Task is already complete. */
81 if (strncmp(ifa
->ifa_name
, iface
, IFNAMSIZ
))
82 continue; /* Wrong interface. */
85 continue; /* This can be NULL, e.g. for ppp0. */
87 /* The first IPv4 name is always functional. */
88 if ((ifa
->ifa_addr
->sa_family
== AF_INET
) && !got_v4
)
90 /* Good IPv4 address. */
92 ((struct sockaddr_in
*)ifa
->ifa_addr
)->sin_addr
.s_addr
;
97 /* IPv6 needs some obvious exceptions. */
98 if ( ifa
->ifa_addr
->sa_family
== AF_INET6
) {
99 struct sockaddr_in6
*sa6
= (struct sockaddr_in6
*) ifa
->ifa_addr
;
101 if ( IN6_IS_ADDR_LINKLOCAL(&(sa6
->sin6_addr
))
102 || IN6_IS_ADDR_SITELOCAL(&(sa6
->sin6_addr
)) )
105 /* Only standard IPv6 can reach this point. */
106 memcpy(&(localip6
.ip
.v6
), &sa6
->sin6_addr
, sizeof(localip6
.ip
.v6
));
114 warnx("can't get own IPv4 address on interface \"%s\"", iface
);
116 #else /* don't HAVE_IFADDRS_H */
118 int tmp
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
122 strlcpy(ifr
.ifr_name
, iface
, IFNAMSIZ
);
123 ifr
.ifr_addr
.sa_family
= AF_INET
;
124 if (ioctl(tmp
, SIOCGIFADDR
, &ifr
) == -1) {
125 if (errno
== EADDRNOTAVAIL
) {
126 verbosef("lost local IP");
128 warn("can't get own IP address on interface \"%s\"", iface
);
132 localip4
.ip
.v4
= ((struct sockaddr_in
*)&sa
)->sin_addr
.s_addr
;
142 localip_update_helper();
144 if (!addr_equal(&last_localip4
, &localip4
)) {
145 verbosef("%s ip4 update: %s", iface
, addr_to_str(&localip4
));
146 last_localip4
= localip4
;
148 if (!addr_equal(&last_localip6
, &localip6
)) {
149 verbosef("%s ip6 update: %s", iface
, addr_to_str(&localip6
));
150 last_localip6
= localip6
;
154 /* vim:set ts=3 sw=3 tw=78 expandtab: */