1: /* $Id: getifaddr.c,v 1.1.1.3 2013/07/22 00:32:35 misho 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 */
7:
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
21:
22: #include "config.h"
23: #include "getifaddr.h"
24: #if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6)
25: #include <ifaddrs.h>
26: #endif
27:
28: int
29: getifaddr(const char * ifname, char * buf, int len)
30: {
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);
39:
40: if(!ifname || ifname[0]=='\0')
41: return -1;
42: s = socket(PF_INET, SOCK_DGRAM, 0);
43: if(s < 0)
44: {
45: syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m");
46: return -1;
47: }
48: strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
49: if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0)
50: {
51: syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
52: close(s);
53: return -1;
54: }
55: addr = (struct sockaddr_in *)&ifr.ifr_addr;
56: if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len))
57: {
58: syslog(LOG_ERR, "inet_ntop(): %m");
59: close(s);
60: return -1;
61: }
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;
67:
68: if(!ifname || ifname[0]=='\0')
69: return -1;
70: if(getifaddrs(&ifap)<0)
71: {
72: syslog(LOG_ERR, "getifaddrs: %m");
73: return -1;
74: }
75: for(ife = ifap; ife; ife = ife->ifa_next)
76: {
77: /* skip other interfaces if one was specified */
78: if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
79: continue;
80: if(ife->ifa_addr == NULL)
81: continue;
82: switch(ife->ifa_addr->sa_family)
83: {
84: case AF_INET:
85: inet_ntop(ife->ifa_addr->sa_family,
86: &((struct sockaddr_in *)ife->ifa_addr)->sin_addr,
87: buf, len);
88: break;
89: /*
90: case AF_INET6:
91: inet_ntop(ife->ifa_addr->sa_family,
92: &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr,
93: buf, len);
94: */
95: }
96: }
97: freeifaddrs(ifap);
98: #endif
99: return 0;
100: }
101:
102: #ifdef ENABLE_IPV6
103: int
104: find_ipv6_addr(const char * ifname,
105: char * dst, int n)
106: {
107: struct ifaddrs * ifap;
108: struct ifaddrs * ife;
109: const struct sockaddr_in6 * addr;
110: char buf[64];
111: int r = 0;
112:
113: if(!dst)
114: return -1;
115:
116: if(getifaddrs(&ifap)<0)
117: {
118: syslog(LOG_ERR, "getifaddrs: %m");
119: return -1;
120: }
121: for(ife = ifap; ife; ife = ife->ifa_next)
122: {
123: /* skip other interfaces if one was specified */
124: if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
125: continue;
126: if(ife->ifa_addr == NULL)
127: continue;
128: if(ife->ifa_addr->sa_family == AF_INET6)
129: {
130: addr = (const struct sockaddr_in6 *)ife->ifa_addr;
131: if(!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr)
132: && !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))
133: {
134: inet_ntop(ife->ifa_addr->sa_family,
135: &addr->sin6_addr,
136: buf, sizeof(buf));
137: /* add brackets */
138: snprintf(dst, n, "[%s]", buf);
139: r = 1;
140: }
141: }
142: }
143: freeifaddrs(ifap);
144: return r;
145: }
146: #endif
147:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>