BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src / router / miniupnpd / getifaddr.c
blobc0fe43a8045d4b10f6468a7c2eb9da79e2a486b2
1 /* $Id: getifaddr.c,v 1.17 2013/04/27 15:40:09 nanard Exp $ */
2 /* MiniUPnP project
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 */
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)
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, SIOCGIFADDR, &ifr, &ifrlen) < 0)
52 syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
53 close(s);
54 return -1;
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");
61 close(s);
62 return -1;
64 if(mask)
66 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
67 if(ioctl(s, SIOCGIFNETMASK, &ifr, &ifrlen) < 0)
69 syslog(LOG_ERR, "ioctl(s, SIOCGIFNETMASK, ...): %m");
70 close(s);
71 return -1;
73 #ifdef ifr_netmask
74 *mask = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr;
75 #else
76 *mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
77 #endif
79 close(s);
80 #else /* ifndef USE_GETIFADDRS */
81 /* Works for all address families (both ip v4 and ip v6) */
82 struct ifaddrs * ifap;
83 struct ifaddrs * ife;
85 if(!ifname || ifname[0]=='\0')
86 return -1;
87 if(getifaddrs(&ifap)<0)
89 syslog(LOG_ERR, "getifaddrs: %m");
90 return -1;
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)))
96 continue;
97 if(ife->ifa_addr == NULL)
98 continue;
99 switch(ife->ifa_addr->sa_family)
101 case AF_INET:
102 inet_ntop(ife->ifa_addr->sa_family,
103 &((struct sockaddr_in *)ife->ifa_addr)->sin_addr,
104 buf, len);
105 if(addr) *addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr;
106 if(mask) *mask = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr;
107 break;
109 case AF_INET6:
110 inet_ntop(ife->ifa_addr->sa_family,
111 &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr,
112 buf, len);
116 freeifaddrs(ifap);
117 #endif
118 return 0;
121 #ifdef ENABLE_IPV6
123 find_ipv6_addr(const char * ifname,
124 char * dst, int n)
126 struct ifaddrs * ifap;
127 struct ifaddrs * ife;
128 const struct sockaddr_in6 * addr;
129 char buf[64];
130 int r = 0;
132 if(!dst)
133 return -1;
135 if(getifaddrs(&ifap)<0)
137 syslog(LOG_ERR, "getifaddrs: %m");
138 return -1;
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)))
144 continue;
145 if(ife->ifa_addr == NULL)
146 continue;
147 if(ife->ifa_addr == NULL)
148 continue;
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,
156 &addr->sin6_addr,
157 buf, sizeof(buf));
158 /* add brackets */
159 snprintf(dst, n, "[%s]", buf);
160 r = 1;
164 freeifaddrs(ifap);
165 return r;
167 #endif