Add PPTP runtime and GUI
[tomato.git] / release / src / router / miniupnpd / getifaddr.c
blob0c1dd93cfcda8c2604dd826ba61fc2ebbc2fb4af
1 /* $Id: getifaddr.c,v 1.11 2011/05/15 08:59:27 nanard Exp $ */
2 /* MiniUPnP project
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 */
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 <arpa/inet.h>
17 #include <netinet/in.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)
31 #ifndef USE_GETIFADDRS
32 /* use ioctl SIOCGIFADDR. Works only for ip v4 */
33 /* SIOCGIFADDR struct ifreq * */
34 int s;
35 struct ifreq ifr;
36 int ifrlen;
37 struct sockaddr_in * addr;
38 ifrlen = sizeof(ifr);
40 if(!ifname || ifname[0]=='\0')
41 return -1;
42 s = socket(PF_INET, SOCK_DGRAM, 0);
43 if(s < 0)
45 syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m");
46 return -1;
48 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
49 if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0)
51 syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
52 close(s);
53 return -1;
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");
59 close(s);
60 return -1;
62 close(s);
63 #else /* ifndef USE_GETIFADDRS */
64 /* Works for all address families (both ip v4 and ip v6) */
65 struct ifaddrs * ifap;
66 struct ifaddrs * ife;
68 if(!ifname || ifname[0]=='\0')
69 return -1;
70 if(getifaddrs(&ifap)<0)
72 syslog(LOG_ERR, "getifaddrs: %m");
73 return -1;
75 for(ife = ifap; ife; ife = ife->ifa_next)
77 /* skip other interfaces */
78 if(0 != strcmp(ifname, ife->ifa_name))
79 continue;
80 switch(ife->ifa_addr->sa_family)
82 case AF_INET:
83 inet_ntop(ife->ifa_addr->sa_family,
84 &((struct sockaddr_in *)ife->ifa_addr)->sin_addr,
85 buf, len);
86 break;
88 case AF_INET6:
89 inet_ntop(ife->ifa_addr->sa_family,
90 &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr,
91 buf, len);
95 freeifaddrs(ifap);
96 #endif
97 return 0;
100 #ifdef ENABLE_IPV6
102 find_ipv6_addr(const char * ifname,
103 char * dst, int n)
105 struct ifaddrs * ifap;
106 struct ifaddrs * ife;
107 const struct sockaddr_in6 * addr;
108 char buf[64];
109 int r = 0;
111 if(!dst)
112 return -1;
114 if(getifaddrs(&ifap)<0)
116 syslog(LOG_ERR, "getifaddrs: %m");
117 return -1;
119 for(ife = ifap; ife; ife = ife->ifa_next)
121 /* skip other interfaces if one was specified */
122 if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
123 continue;
124 if(ife->ifa_addr == NULL)
125 continue;
126 if(ife->ifa_addr->sa_family == AF_INET6)
128 addr = (const struct sockaddr_in6 *)ife->ifa_addr;
129 if(!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr)
130 && !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))
132 inet_ntop(ife->ifa_addr->sa_family,
133 &addr->sin6_addr,
134 buf, sizeof(buf));
135 /* add brackets */
136 snprintf(dst, n, "[%s]", buf);
137 r = 1;
141 return r;
143 #endif