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, ip6_to_str */
16 #include <sys/socket.h>
23 static const char *iface
= NULL
;
25 in_addr_t localip
= 0;
26 static in_addr_t 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 */
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
= ((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
;
78 if( IN6_IS_ADDR_LINKLOCAL(&(sa6
->sin6_addr
))
79 || IN6_IS_ADDR_SITELOCAL(&(sa6
->sin6_addr
)) )
81 if( IN6_IS_ADDR_LINKLOCAL(&(sa6
->sin6_addr
.s6_addr
))
82 || IN6_IS_ADDR_SITELOCAL(&(sa6
->sin6_addr
.s6_addr
)) )
86 /* Only standard IPv6 can reach this point. */
87 memcpy(&localip6
, &sa6
->sin6_addr
, sizeof(localip6
));
94 /* Repport an error if IPv4 address could not be found. */
95 if ( !(flags
& HAS_IPV4
) )
96 err(1, "can't get own IPv4 address on interface \"%s\"", iface
);
99 * sa_family_t sa_family; * address family, AF_xxx
100 * char sa_data[14]; * 14 bytes of protocol address
102 * struct sockaddr_in {
103 * sa_family_t sin_family; * Address family
104 * unsigned short int sin_port; * Port number
105 * struct in_addr sin_addr; * Internet address
111 if (last_localip
!= localip
) {
112 verbosef("local_ip update(%s) = %s", iface
, ip_to_str(localip
));
113 last_localip
= localip
;
115 if (memcmp(&last_localip6
, &localip6
, sizeof(localip6
))) {
116 verbosef("local_ip6 update(%s) = %s", iface
, ip6_to_str(&localip6
));
117 memcpy(&last_localip6
, &localip6
, sizeof(localip6
));
121 /* vim:set ts=3 sw=3 tw=78 expandtab: */