48 #include <sys/socket.h>
50 #include <netinet/in.h>
52 #include <sys/ioctl.h>
53 #include <arpa/inet.h>
55 #ifdef USE_SYS_SOCKIO_H
56 #include <sys/sockio.h>
64 #ifdef HAVE_GETIFADDRS
119 #ifndef HAVE_GETIFADDRS
123 static int ial_socket(
int af)
125 const char *myname =
"inet_addr_local[socket]";
137 if ((sock = socket(af, SOCK_DGRAM, 0)) < 0) {
139 if (af == AF_INET6) {
152 #ifdef HAVE_GETIFADDRS
167 const char *myname =
"inet_addr_local[getifaddrs]";
168 struct ifaddrs *ifap, *ifa;
169 struct sockaddr *sa, *sam;
171 if (getifaddrs(&ifap) < 0)
187 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
188 if (!(ifa->ifa_flags & IFF_UP) || ifa->ifa_addr == 0)
191 if (af != AF_UNSPEC && sa->sa_family != af)
193 sam = ifa->ifa_netmask;
196 msg_warn(
"ignoring interface with null netmask, address family %d",
200 switch (sa->sa_family) {
207 if (IN6_IS_ADDR_UNSPECIFIED(&SOCK_ADDR_IN6_ADDR(sa)))
216 if (mask_list != 0) {
224 sam->sa_len = sa->sa_family == AF_INET6 ?
225 sizeof(
struct sockaddr_in6) :
226 sizeof(struct sockaddr_in);
228 sam->sa_family = sa->sa_family;
236 #elif defined(HAS_SIOCGLIF)
244 #define NEXT_INTERFACE(lifr) (lifr + 1)
245 #define LIFREQ_SIZE(lifr) sizeof(lifr[0])
249 static
int ial_siocglif(INET_ADDR_LIST *addr_list,
250 INET_ADDR_LIST *mask_list,
253 const char *myname =
"inet_addr_local[siocglif]";
256 struct lifreq *lifr_mask;
257 struct lifreq *the_end;
265 if (af != AF_INET && af != AF_INET6)
266 msg_fatal(
"%s: address family was %d, must be AF_INET (%d) or "
267 "AF_INET6 (%d)", myname, af, AF_INET, AF_INET6);
268 sock = ial_socket(af);
273 memset(&lifc, 0,
sizeof(lifc));
274 lifc.lifc_family = AF_UNSPEC;
277 if (ioctl(sock, SIOCGLIFCONF, (
char *) &lifc) < 0) {
279 msg_fatal(
"%s: ioctl SIOCGLIFCONF: %m", myname);
285 the_end = (
struct lifreq *) (lifc.lifc_buf + lifc.lifc_len);
286 for (lifr = lifc.lifc_req; lifr < the_end;) {
287 sa = (
struct sockaddr *) &lifr->lifr_addr;
288 if (sa->sa_family != af) {
298 }
else if (af == AF_INET6) {
299 if (IN6_IS_ADDR_UNSPECIFIED(&SOCK_ADDR_IN6_ADDR(sa))) {
307 lifr_mask = (
struct lifreq *)
mymalloc(
sizeof(
struct lifreq));
308 memcpy((
void *) lifr_mask, (
void *) lifr,
sizeof(
struct lifreq));
309 if (ioctl(sock, SIOCGLIFNETMASK, lifr_mask) < 0)
310 msg_fatal(
"%s: ioctl(SIOCGLIFNETMASK): %m", myname);
313 (
struct sockaddr *) &lifr_mask->lifr_addr);
314 myfree((
void *) lifr_mask);
330 #if defined(_SIZEOF_ADDR_IFREQ)
331 #define NEXT_INTERFACE(ifr) ((struct ifreq *) \
332 ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr)))
333 #define IFREQ_SIZE(ifr) _SIZEOF_ADDR_IFREQ(*ifr)
334 #elif defined(HAS_SA_LEN)
335 #define NEXT_INTERFACE(ifr) ((struct ifreq *) \
336 ((char *) ifr + sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len))
337 #define IFREQ_SIZE(ifr) (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
339 #define NEXT_INTERFACE(ifr) (ifr + 1)
340 #define IFREQ_SIZE(ifr) sizeof(ifr[0])
349 const char *myname =
"inet_addr_local[siocgif]";
353 struct ifreq *ifr_mask;
354 struct ifreq *the_end;
373 sock = ial_socket(af);
380 if (ioctl(sock, SIOCGIFCONF, (
char *) &ifc) < 0) {
382 msg_fatal(
"%s: ioctl SIOCGIFCONF: %m", myname);
388 the_end = (
struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
389 for (ifr = ifc.ifc_req; ifr < the_end;) {
390 if (ifr->ifr_addr.sa_family != af) {
395 addr = ((
struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
396 if (addr.s_addr != INADDR_ANY) {
400 memcpy((
void *) ifr_mask, (
void *) ifr,
IFREQ_SIZE(ifr));
401 if (ioctl(sock, SIOCGIFNETMASK, ifr_mask) < 0)
402 msg_fatal(
"%s: ioctl SIOCGIFNETMASK: %m", myname);
409 ifr_mask->ifr_addr.sa_family = af;
411 ifr_mask->ifr_addr.sa_len =
sizeof(
struct sockaddr_in);
414 myfree((
void *) ifr_mask);
419 else if (af == AF_INET6) {
423 if (!(IN6_IS_ADDR_UNSPECIFIED(&SOCK_ADDR_IN6_ADDR(sa)))) {
427 struct sockaddr_in6 mask6;
429 mask6 = *SOCK_ADDR_IN6_PTR(sa);
430 memset((
void *) &mask6.sin6_addr, ~0,
431 sizeof(mask6.sin6_addr));
446 #ifdef HAS_PROCNET_IFINET6
461 const char *myname =
"inet_addr_local[procnet_ifinet6]";
466 struct sockaddr_in6 addr;
467 struct sockaddr_in6 mask;
478 if ((fp = fopen(_PATH_PROCNET_IFINET6,
"r")) != 0) {
480 memset((
void *) &addr, 0,
sizeof(addr));
481 addr.sin6_family = AF_INET6;
483 addr.sin6_len =
sizeof(addr);
486 while (fgets(buf,
sizeof(buf), fp) != 0) {
491 msg_warn(
"unexpected data in %s - skipping IPv6 configuration",
492 _PATH_PROCNET_IFINET6);
496 addr.sin6_addr = *(
struct in6_addr *)
vstring_str(addrbuf);
499 memset((
void *) &mask.sin6_addr, ~0,
sizeof(mask.sin6_addr));
500 mask_addr((
unsigned char *) &mask.sin6_addr,
501 sizeof(mask.sin6_addr), plen);
507 msg_warn(
"can't open %s (%m) - skipping IPv6 configuration",
508 _PATH_PROCNET_IFINET6);
518 unsigned *addr_family_list)
520 const char *myname =
"inet_addr_local";
521 int initial_count = addr_list->
used;
525 while ((family = *addr_family_list++) != 0) {
530 if (family == AF_INET) {
531 count = addr_list->
used;
532 #if defined(HAVE_GETIFADDRS)
533 ial_getifaddrs(addr_list, mask_list, AF_INET);
534 #elif defined (HAS_SIOCGLIF)
535 ial_siocglif(addr_list, mask_list, AF_INET);
537 ial_siocgif(addr_list, mask_list, AF_INET);
540 msg_info(
"%s: configured %d IPv4 addresses",
541 myname, addr_list->
used - count);
548 else if (family == AF_INET6) {
549 count = addr_list->
used;
550 #if defined(HAVE_GETIFADDRS)
551 ial_getifaddrs(addr_list, mask_list, AF_INET6);
552 #elif defined(HAS_PROCNET_IFINET6)
553 ial_procnet_ifinet6(addr_list, mask_list);
554 #elif defined(HAS_SIOCGLIF)
555 ial_siocglif(addr_list, mask_list, AF_INET6);
557 ial_siocgif(addr_list, mask_list, AF_INET6);
560 msg_info(
"%s: configured %d IPv6 addresses", myname,
561 addr_list->
used - count);
569 msg_panic(
"%s: unknown address family %d", myname, family);
571 return (addr_list->
used - initial_count);
581 int main(
int unused_argc,
char **argv)
600 if (addr_list.
used == 0)
601 msg_fatal(
"cannot find any active network interfaces");
603 if (addr_list.
used == 1)
604 msg_warn(
"found only one active network interface");
606 for (i = 0; i < addr_list.
used; i++) {
void mask_addr(unsigned char *addr_bytes, unsigned addr_byte_count, unsigned network_bits)
NORETURN msg_panic(const char *fmt,...)
void inet_addr_list_free(INET_ADDR_LIST *list)
int main(int argc, char **argv)
INET_PROTO_INFO * inet_proto_init(const char *context, const char *protocols)
struct sockaddr_storage * addrs
#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock)
#define INET_PROTO_NAME_ALL
int inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list, unsigned *addr_family_list)
unsigned int * ai_family_list
char buf[MAI_HOSTADDR_STRSIZE]
VSTREAM * vstream_printf(const char *fmt,...)
#define SOCK_ADDR_PTR(ptr)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define vstring_avail(vp)
void inet_addr_list_init(INET_ADDR_LIST *list)
NORETURN msg_fatal(const char *fmt,...)
int vstream_fflush(VSTREAM *stream)
void inet_addr_list_append(INET_ADDR_LIST *list, struct sockaddr *addr)
#define VSTRING_SPACE(vp, len)
#define NEXT_INTERFACE(ifr)
VSTRING * vstring_free(VSTRING *vp)
#define SOCK_ADDR_LEN(sa)
void msg_vstream_init(const char *name, VSTREAM *vp)
#define SOCK_ADDR_IN_ADDR(sa)
VSTRING * hex_decode(VSTRING *result, const char *in, ssize_t len)
void * mymalloc(ssize_t len)
void msg_info(const char *fmt,...)