1 /* $Id: getifaddr.c,v 1.17 2013/04/27 15:40:09 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2013 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
,
30 struct in_addr
* addr
, struct in_addr
* mask
)
32 #ifndef USE_GETIFADDRS
33 /* use ioctl SIOCGIFADDR. Works only for ip v4 */
34 /* SIOCGIFADDR struct ifreq * */
38 struct sockaddr_in
* ifaddr
;
41 if(!ifname
|| ifname
[0]=='\0')
43 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
46 syslog(LOG_ERR
, "socket(PF_INET, SOCK_DGRAM): %m");
49 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
50 if(ioctl(s
, SIOCGIFADDR
, &ifr
, &ifrlen
) < 0)
52 syslog(LOG_ERR
, "ioctl(s, SIOCGIFADDR, ...): %m");
56 ifaddr
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
57 if(addr
) *addr
= ifaddr
->sin_addr
;
58 if(!inet_ntop(AF_INET
, &ifaddr
->sin_addr
, buf
, len
))
60 syslog(LOG_ERR
, "inet_ntop(): %m");
66 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
67 if(ioctl(s
, SIOCGIFNETMASK
, &ifr
, &ifrlen
) < 0)
69 syslog(LOG_ERR
, "ioctl(s, SIOCGIFNETMASK, ...): %m");
74 *mask
= ((struct sockaddr_in
*)&ifr
.ifr_netmask
)->sin_addr
;
76 *mask
= ((struct sockaddr_in
*)&ifr
.ifr_addr
)->sin_addr
;
80 #else /* ifndef USE_GETIFADDRS */
81 /* Works for all address families (both ip v4 and ip v6) */
82 struct ifaddrs
* ifap
;
85 if(!ifname
|| ifname
[0]=='\0')
87 if(getifaddrs(&ifap
)<0)
89 syslog(LOG_ERR
, "getifaddrs: %m");
92 for(ife
= ifap
; ife
; ife
= ife
->ifa_next
)
94 /* skip other interfaces if one was specified */
95 if(ifname
&& (0 != strcmp(ifname
, ife
->ifa_name
)))
97 if(ife
->ifa_addr
== NULL
)
99 switch(ife
->ifa_addr
->sa_family
)
102 inet_ntop(ife
->ifa_addr
->sa_family
,
103 &((struct sockaddr_in
*)ife
->ifa_addr
)->sin_addr
,
105 if(addr
) *addr
= ((struct sockaddr_in
*)ife
->ifa_addr
)->sin_addr
;
106 if(mask
) *mask
= ((struct sockaddr_in
*)ife
->ifa_netmask
)->sin_addr
;
110 inet_ntop(ife->ifa_addr->sa_family,
111 &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr,
123 find_ipv6_addr(const char * ifname
,
126 struct ifaddrs
* ifap
;
127 struct ifaddrs
* ife
;
128 const struct sockaddr_in6
* addr
;
135 if(getifaddrs(&ifap
)<0)
137 syslog(LOG_ERR
, "getifaddrs: %m");
140 for(ife
= ifap
; ife
; ife
= ife
->ifa_next
)
142 /* skip other interfaces if one was specified */
143 if(ifname
&& (0 != strcmp(ifname
, ife
->ifa_name
)))
145 if(ife
->ifa_addr
== NULL
)
147 if(ife
->ifa_addr
== NULL
)
149 if(ife
->ifa_addr
->sa_family
== AF_INET6
)
151 addr
= (const struct sockaddr_in6
*)ife
->ifa_addr
;
152 if(!IN6_IS_ADDR_LOOPBACK(&addr
->sin6_addr
)
153 && !IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
))
155 inet_ntop(ife
->ifa_addr
->sa_family
,
159 snprintf(dst
, n
, "[%s]", buf
);