vsftpd 3.0.3
[tomato.git] / release / src-rt-6.x.4708 / router / miniupnpd / getifaddr.c
blob6bbbe78d83fd7b39bcdad1ea29aa167366955d84
1 /* $Id: getifaddr.c,v 1.23 2014/05/06 14:40:53 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2014 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
8 #include <stdio.h>
9 #include <string.h>
10 #include <syslog.h>
11 #include <unistd.h>
12 #include <sys/ioctl.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <net/if.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #if defined(sun)
19 #include <sys/sockio.h>
20 #endif
22 #include "config.h"
23 #include "getifaddr.h"
24 #if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6) || defined(ENABLE_PCP)
25 #include <ifaddrs.h>
26 #endif
28 int
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 * */
35 int s;
36 struct ifreq ifr;
37 int ifrlen;
38 struct sockaddr_in * ifaddr;
39 ifrlen = sizeof(ifr);
41 if(!ifname || ifname[0]=='\0')
42 return -1;
43 s = socket(PF_INET, SOCK_DGRAM, 0);
44 if(s < 0)
46 syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m");
47 return -1;
49 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
50 if(ioctl(s, SIOCGIFFLAGS, &ifr, &ifrlen) < 0)
52 syslog(LOG_DEBUG, "ioctl(s, SIOCGIFFLAGS, ...): %m");
53 close(s);
54 return -1;
56 if ((ifr.ifr_flags & IFF_UP) == 0)
58 syslog(LOG_DEBUG, "network interface %s is down", ifname);
59 close(s);
60 return -1;
62 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
63 if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0)
65 syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
66 close(s);
67 return -1;
69 ifaddr = (struct sockaddr_in *)&ifr.ifr_addr;
70 if(addr) *addr = ifaddr->sin_addr;
71 if(buf)
73 if(!inet_ntop(AF_INET, &ifaddr->sin_addr, buf, len))
75 syslog(LOG_ERR, "inet_ntop(): %m");
76 close(s);
77 return -1;
80 if(mask)
82 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
83 if(ioctl(s, SIOCGIFNETMASK, &ifr, &ifrlen) < 0)
85 syslog(LOG_ERR, "ioctl(s, SIOCGIFNETMASK, ...): %m");
86 close(s);
87 return -1;
89 #ifdef ifr_netmask
90 *mask = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr;
91 #else
92 *mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
93 #endif
95 close(s);
96 #else /* ifndef USE_GETIFADDRS */
97 /* Works for all address families (both ip v4 and ip v6) */
98 struct ifaddrs * ifap;
99 struct ifaddrs * ife;
101 if(!ifname || ifname[0]=='\0')
102 return -1;
103 if(getifaddrs(&ifap)<0)
105 syslog(LOG_ERR, "getifaddrs: %m");
106 return -1;
108 for(ife = ifap; ife; ife = ife->ifa_next)
110 /* skip other interfaces if one was specified */
111 if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
112 continue;
113 if(ife->ifa_addr == NULL)
114 continue;
115 switch(ife->ifa_addr->sa_family)
117 case AF_INET:
118 if(buf)
120 inet_ntop(ife->ifa_addr->sa_family,
121 &((struct sockaddr_in *)ife->ifa_addr)->sin_addr,
122 buf, len);
124 if(addr) *addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr;
125 if(mask) *mask = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr;
126 break;
128 case AF_INET6:
129 inet_ntop(ife->ifa_addr->sa_family,
130 &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr,
131 buf, len);
135 freeifaddrs(ifap);
136 #endif
137 return 0;
140 #ifdef ENABLE_PCP
142 int getifaddr_in6(const char * ifname, int af, struct in6_addr * addr)
144 #if defined(ENABLE_IPV6) || defined(USE_GETIFADDRS)
145 struct ifaddrs * ifap;
146 struct ifaddrs * ife;
147 #ifdef ENABLE_IPV6
148 const struct sockaddr_in6 * tmpaddr;
149 #endif /* ENABLE_IPV6 */
150 int found = 0;
152 if(!ifname || ifname[0]=='\0')
153 return -1;
154 if(getifaddrs(&ifap)<0)
156 syslog(LOG_ERR, "getifaddrs: %m");
157 return -1;
159 for(ife = ifap; ife && !found; ife = ife->ifa_next)
161 /* skip other interfaces if one was specified */
162 if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
163 continue;
164 if(ife->ifa_addr == NULL)
165 continue;
166 if (ife->ifa_addr->sa_family != af)
167 continue;
168 switch(ife->ifa_addr->sa_family)
170 case AF_INET:
171 /* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */
172 memset(addr->s6_addr, 0, 10);
173 addr->s6_addr[10] = 0xff;
174 addr->s6_addr[11] = 0xff;
175 memcpy(addr->s6_addr + 12,
176 &(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr),
178 found = 1;
179 break;
181 #ifdef ENABLE_IPV6
182 case AF_INET6:
183 tmpaddr = (const struct sockaddr_in6 *)ife->ifa_addr;
184 if(!IN6_IS_ADDR_LOOPBACK(&tmpaddr->sin6_addr)
185 && !IN6_IS_ADDR_LINKLOCAL(&tmpaddr->sin6_addr))
187 memcpy(addr->s6_addr,
188 &tmpaddr->sin6_addr,
189 16);
190 found = 1;
192 break;
193 #endif /* ENABLE_IPV6 */
196 freeifaddrs(ifap);
197 return (found ? 0 : -1);
198 #else /* defined(ENABLE_IPV6) || defined(USE_GETIFADDRS) */
199 /* IPv4 only */
200 struct in_addr addr4;
201 if(af != AF_INET)
202 return -1;
203 if(getifaddr(ifname, NULL, 0, &addr4, NULL) < 0)
204 return -1;
205 /* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */
206 memset(addr->s6_addr, 0, 10);
207 addr->s6_addr[10] = 0xff;
208 addr->s6_addr[11] = 0xff;
209 memcpy(addr->s6_addr + 12, &addr4.s_addr, 4);
210 return 0;
211 #endif
213 #endif /* ENABLE_PCP */
215 #ifdef ENABLE_IPV6
217 find_ipv6_addr(const char * ifname,
218 char * dst, int n)
220 struct ifaddrs * ifap;
221 struct ifaddrs * ife;
222 const struct sockaddr_in6 * addr;
223 char buf[64];
224 int r = 0;
226 if(!dst)
227 return -1;
229 if(getifaddrs(&ifap)<0)
231 syslog(LOG_ERR, "getifaddrs: %m");
232 return -1;
234 for(ife = ifap; ife; ife = ife->ifa_next)
236 /* skip other interfaces if one was specified */
237 if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
238 continue;
239 if(ife->ifa_addr == NULL)
240 continue;
241 if(ife->ifa_addr->sa_family == AF_INET6)
243 addr = (const struct sockaddr_in6 *)ife->ifa_addr;
244 if(!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr)
245 && !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))
247 inet_ntop(ife->ifa_addr->sa_family,
248 &addr->sin6_addr,
249 buf, sizeof(buf));
250 /* add brackets */
251 snprintf(dst, n, "[%s]", buf);
252 r = 1;
256 freeifaddrs(ifap);
257 return r;
259 #endif