1 /* $Id: getifaddr.c,v 1.15 2012/03/05 20:36:16 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2011 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
12 #include <sys/ioctl.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
19 #include <sys/sockio.h>
23 #include "getifaddr.h"
24 #if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6)
29 getifaddr(const char * ifname
, char * buf
, int len
)
31 #ifndef USE_GETIFADDRS
32 /* use ioctl SIOCGIFADDR. Works only for ip v4 */
33 /* SIOCGIFADDR struct ifreq * */
37 struct sockaddr_in
* addr
;
40 if(!ifname
|| ifname
[0]=='\0')
42 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
45 syslog(LOG_ERR
, "socket(PF_INET, SOCK_DGRAM): %m");
48 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
49 if(ioctl(s
, SIOCGIFADDR
, &ifr
, &ifrlen
) < 0)
51 syslog(LOG_ERR
, "ioctl(s, SIOCGIFADDR, ...): %m");
55 addr
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
56 if(!inet_ntop(AF_INET
, &addr
->sin_addr
, buf
, len
))
58 syslog(LOG_ERR
, "inet_ntop(): %m");
63 #else /* ifndef USE_GETIFADDRS */
64 /* Works for all address families (both ip v4 and ip v6) */
65 struct ifaddrs
* ifap
;
68 if(!ifname
|| ifname
[0]=='\0')
70 if(getifaddrs(&ifap
)<0)
72 syslog(LOG_ERR
, "getifaddrs: %m");
75 for(ife
= ifap
; ife
; ife
= ife
->ifa_next
)
77 /* skip other interfaces if one was specified */
78 if(ifname
&& (0 != strcmp(ifname
, ife
->ifa_name
)))
80 if(ife
->ifa_addr
== NULL
)
82 switch(ife
->ifa_addr
->sa_family
)
85 inet_ntop(ife
->ifa_addr
->sa_family
,
86 &((struct sockaddr_in
*)ife
->ifa_addr
)->sin_addr
,
91 inet_ntop(ife->ifa_addr->sa_family,
92 &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr,
104 find_ipv6_addr(const char * ifname
,
107 struct ifaddrs
* ifap
;
108 struct ifaddrs
* ife
;
109 const struct sockaddr_in6
* addr
;
116 if(getifaddrs(&ifap
)<0)
118 syslog(LOG_ERR
, "getifaddrs: %m");
121 for(ife
= ifap
; ife
; ife
= ife
->ifa_next
)
123 /* skip other interfaces if one was specified */
124 if(ifname
&& (0 != strcmp(ifname
, ife
->ifa_name
)))
126 if(ife
->ifa_addr
== NULL
)
128 if(ife
->ifa_addr
== NULL
)
130 if(ife
->ifa_addr
->sa_family
== AF_INET6
)
132 addr
= (const struct sockaddr_in6
*)ife
->ifa_addr
;
133 if(!IN6_IS_ADDR_LOOPBACK(&addr
->sin6_addr
)
134 && !IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
))
136 inet_ntop(ife
->ifa_addr
->sa_family
,
140 snprintf(dst
, n
, "[%s]", buf
);