1: /* $Id: getifaddr.c,v 1.1.1.2 2012/05/29 12:55:57 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 <arpa/inet.h>
17: #include <netinet/in.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 */
78: if(0 != strcmp(ifname, ife->ifa_name))
79: continue;
80: switch(ife->ifa_addr->sa_family)
81: {
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;
87: /*
88: case AF_INET6:
89: inet_ntop(ife->ifa_addr->sa_family,
90: &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr,
91: buf, len);
92: */
93: }
94: }
95: freeifaddrs(ifap);
96: #endif
97: return 0;
98: }
99:
100: #ifdef ENABLE_IPV6
101: int
102: find_ipv6_addr(const char * ifname,
103: char * dst, int n)
104: {
105: struct ifaddrs * ifap;
106: struct ifaddrs * ife;
107: const struct sockaddr_in6 * addr;
108: char buf[64];
109: int r = 0;
110:
111: if(!dst)
112: return -1;
113:
114: if(getifaddrs(&ifap)<0)
115: {
116: syslog(LOG_ERR, "getifaddrs: %m");
117: return -1;
118: }
119: for(ife = ifap; ife; ife = ife->ifa_next)
120: {
121: /* skip other interfaces if one was specified */
122: if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
123: continue;
124: if(ife->ifa_addr->sa_family == AF_INET6)
125: {
126: addr = (const struct sockaddr_in6 *)ife->ifa_addr;
127: if(!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr)
128: && !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))
129: {
130: inet_ntop(ife->ifa_addr->sa_family,
131: &addr->sin6_addr,
132: buf, sizeof(buf));
133: /* add brackets */
134: snprintf(dst, n, "[%s]", buf);
135: r = 1;
136: }
137: }
138: }
139: return r;
140: }
141: #endif
142:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>