1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * Copyright (c) 2000 - 2001 Kungliga Tekniska H�gskolan
3*1c60b9acSAndroid Build Coastguard Worker * (Royal Institute of Technology, Stockholm, Sweden).
4*1c60b9acSAndroid Build Coastguard Worker * All rights reserved.
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
7*1c60b9acSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
8*1c60b9acSAndroid Build Coastguard Worker * are met:
9*1c60b9acSAndroid Build Coastguard Worker *
10*1c60b9acSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
11*1c60b9acSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
14*1c60b9acSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
15*1c60b9acSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
16*1c60b9acSAndroid Build Coastguard Worker *
17*1c60b9acSAndroid Build Coastguard Worker * 3. Neither the name of the Institute nor the names of its contributors
18*1c60b9acSAndroid Build Coastguard Worker * may be used to endorse or promote products derived from this software
19*1c60b9acSAndroid Build Coastguard Worker * without specific prior written permission.
20*1c60b9acSAndroid Build Coastguard Worker *
21*1c60b9acSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22*1c60b9acSAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*1c60b9acSAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*1c60b9acSAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25*1c60b9acSAndroid Build Coastguard Worker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*1c60b9acSAndroid Build Coastguard Worker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*1c60b9acSAndroid Build Coastguard Worker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*1c60b9acSAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*1c60b9acSAndroid Build Coastguard Worker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*1c60b9acSAndroid Build Coastguard Worker * SUCH DAMAGE.
32*1c60b9acSAndroid Build Coastguard Worker *
33*1c60b9acSAndroid Build Coastguard Worker * originally downloaded from
34*1c60b9acSAndroid Build Coastguard Worker *
35*1c60b9acSAndroid Build Coastguard Worker * http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c
36*1c60b9acSAndroid Build Coastguard Worker */
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker #include <errno.h>
39*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
40*1c60b9acSAndroid Build Coastguard Worker #include <sys/socket.h>
41*1c60b9acSAndroid Build Coastguard Worker #include <net/if.h>
42*1c60b9acSAndroid Build Coastguard Worker #include <stdlib.h>
43*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
44*1c60b9acSAndroid Build Coastguard Worker #include <sys/ioctl.h>
45*1c60b9acSAndroid Build Coastguard Worker #include <unistd.h>
46*1c60b9acSAndroid Build Coastguard Worker
47*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
48*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
49*1c60b9acSAndroid Build Coastguard Worker
50*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_HAVE_SYS_SOCKIO_H
51*1c60b9acSAndroid Build Coastguard Worker #include <sys/sockio.h>
52*1c60b9acSAndroid Build Coastguard Worker #endif
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_HAVE_NETINET_IN6_VAR_H
55*1c60b9acSAndroid Build Coastguard Worker #include <netinet/in6_var.h>
56*1c60b9acSAndroid Build Coastguard Worker #endif
57*1c60b9acSAndroid Build Coastguard Worker
58*1c60b9acSAndroid Build Coastguard Worker #ifndef max
59*1c60b9acSAndroid Build Coastguard Worker #define max(a, b) ((a) > (b) ? (a) : (b))
60*1c60b9acSAndroid Build Coastguard Worker #endif
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard Worker #include "getifaddrs.h"
63*1c60b9acSAndroid Build Coastguard Worker
64*1c60b9acSAndroid Build Coastguard Worker static int
getifaddrs2(struct ifaddrs ** ifap,int af,int siocgifconf,int siocgifflags,size_t ifreq_sz)65*1c60b9acSAndroid Build Coastguard Worker getifaddrs2(struct ifaddrs **ifap, int af, int siocgifconf, int siocgifflags,
66*1c60b9acSAndroid Build Coastguard Worker size_t ifreq_sz)
67*1c60b9acSAndroid Build Coastguard Worker {
68*1c60b9acSAndroid Build Coastguard Worker int ret;
69*1c60b9acSAndroid Build Coastguard Worker int fd;
70*1c60b9acSAndroid Build Coastguard Worker size_t buf_size;
71*1c60b9acSAndroid Build Coastguard Worker char *buf;
72*1c60b9acSAndroid Build Coastguard Worker struct ifconf ifconf;
73*1c60b9acSAndroid Build Coastguard Worker char *p;
74*1c60b9acSAndroid Build Coastguard Worker size_t sz;
75*1c60b9acSAndroid Build Coastguard Worker struct sockaddr sa_zero;
76*1c60b9acSAndroid Build Coastguard Worker struct ifreq *ifr;
77*1c60b9acSAndroid Build Coastguard Worker struct ifaddrs *start, **end = &start;
78*1c60b9acSAndroid Build Coastguard Worker
79*1c60b9acSAndroid Build Coastguard Worker buf = NULL;
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker memset(&sa_zero, 0, sizeof(sa_zero));
82*1c60b9acSAndroid Build Coastguard Worker fd = socket(af, SOCK_DGRAM, 0);
83*1c60b9acSAndroid Build Coastguard Worker if (fd < 0)
84*1c60b9acSAndroid Build Coastguard Worker return -1;
85*1c60b9acSAndroid Build Coastguard Worker
86*1c60b9acSAndroid Build Coastguard Worker buf_size = 8192;
87*1c60b9acSAndroid Build Coastguard Worker for (;;) {
88*1c60b9acSAndroid Build Coastguard Worker buf = lws_zalloc(buf_size, "getifaddrs2");
89*1c60b9acSAndroid Build Coastguard Worker if (buf == NULL) {
90*1c60b9acSAndroid Build Coastguard Worker ret = ENOMEM;
91*1c60b9acSAndroid Build Coastguard Worker goto error_out;
92*1c60b9acSAndroid Build Coastguard Worker }
93*1c60b9acSAndroid Build Coastguard Worker ifconf.ifc_len = (int)buf_size;
94*1c60b9acSAndroid Build Coastguard Worker ifconf.ifc_buf = buf;
95*1c60b9acSAndroid Build Coastguard Worker
96*1c60b9acSAndroid Build Coastguard Worker /*
97*1c60b9acSAndroid Build Coastguard Worker * Solaris returns EINVAL when the buffer is too small.
98*1c60b9acSAndroid Build Coastguard Worker */
99*1c60b9acSAndroid Build Coastguard Worker if (ioctl(fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
100*1c60b9acSAndroid Build Coastguard Worker ret = errno;
101*1c60b9acSAndroid Build Coastguard Worker goto error_out;
102*1c60b9acSAndroid Build Coastguard Worker }
103*1c60b9acSAndroid Build Coastguard Worker /*
104*1c60b9acSAndroid Build Coastguard Worker * Can the difference between a full and a overfull buf
105*1c60b9acSAndroid Build Coastguard Worker * be determined?
106*1c60b9acSAndroid Build Coastguard Worker */
107*1c60b9acSAndroid Build Coastguard Worker
108*1c60b9acSAndroid Build Coastguard Worker if (ifconf.ifc_len < (int)buf_size)
109*1c60b9acSAndroid Build Coastguard Worker break;
110*1c60b9acSAndroid Build Coastguard Worker lws_free(buf);
111*1c60b9acSAndroid Build Coastguard Worker buf_size *= 2;
112*1c60b9acSAndroid Build Coastguard Worker }
113*1c60b9acSAndroid Build Coastguard Worker
114*1c60b9acSAndroid Build Coastguard Worker for (p = ifconf.ifc_buf; p < ifconf.ifc_buf + ifconf.ifc_len; p += sz) {
115*1c60b9acSAndroid Build Coastguard Worker struct ifreq ifreq;
116*1c60b9acSAndroid Build Coastguard Worker struct sockaddr *sa;
117*1c60b9acSAndroid Build Coastguard Worker size_t salen;
118*1c60b9acSAndroid Build Coastguard Worker
119*1c60b9acSAndroid Build Coastguard Worker ifr = (struct ifreq *)p;
120*1c60b9acSAndroid Build Coastguard Worker sa = &ifr->ifr_addr;
121*1c60b9acSAndroid Build Coastguard Worker
122*1c60b9acSAndroid Build Coastguard Worker sz = ifreq_sz;
123*1c60b9acSAndroid Build Coastguard Worker salen = sizeof(struct sockaddr);
124*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN
125*1c60b9acSAndroid Build Coastguard Worker salen = sa->sa_len;
126*1c60b9acSAndroid Build Coastguard Worker sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
127*1c60b9acSAndroid Build Coastguard Worker #endif
128*1c60b9acSAndroid Build Coastguard Worker #ifdef SA_LEN
129*1c60b9acSAndroid Build Coastguard Worker salen = SA_LEN(sa);
130*1c60b9acSAndroid Build Coastguard Worker sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
131*1c60b9acSAndroid Build Coastguard Worker #endif
132*1c60b9acSAndroid Build Coastguard Worker memset(&ifreq, 0, sizeof(ifreq));
133*1c60b9acSAndroid Build Coastguard Worker memcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker if (ioctl(fd, siocgifflags, &ifreq) < 0) {
136*1c60b9acSAndroid Build Coastguard Worker ret = errno;
137*1c60b9acSAndroid Build Coastguard Worker goto error_out;
138*1c60b9acSAndroid Build Coastguard Worker }
139*1c60b9acSAndroid Build Coastguard Worker
140*1c60b9acSAndroid Build Coastguard Worker *end = lws_malloc(sizeof(**end), "getifaddrs");
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_next = NULL;
143*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_name = strdup(ifr->ifr_name);
144*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_flags = (unsigned int)ifreq.ifr_flags;
145*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_addr = lws_malloc(salen, "getifaddrs");
146*1c60b9acSAndroid Build Coastguard Worker memcpy((*end)->ifa_addr, sa, salen);
147*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_netmask = NULL;
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker #if 0
150*1c60b9acSAndroid Build Coastguard Worker /* fix these when we actually need them */
151*1c60b9acSAndroid Build Coastguard Worker if (ifreq.ifr_flags & IFF_BROADCAST) {
152*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_broadaddr =
153*1c60b9acSAndroid Build Coastguard Worker lws_malloc(sizeof(ifr->ifr_broadaddr), "getifaddrs");
154*1c60b9acSAndroid Build Coastguard Worker memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
155*1c60b9acSAndroid Build Coastguard Worker sizeof(ifr->ifr_broadaddr));
156*1c60b9acSAndroid Build Coastguard Worker } else if (ifreq.ifr_flags & IFF_POINTOPOINT) {
157*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_dstaddr =
158*1c60b9acSAndroid Build Coastguard Worker lws_malloc(sizeof(ifr->ifr_dstaddr), "getifaddrs");
159*1c60b9acSAndroid Build Coastguard Worker memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
160*1c60b9acSAndroid Build Coastguard Worker sizeof(ifr->ifr_dstaddr));
161*1c60b9acSAndroid Build Coastguard Worker } else
162*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_dstaddr = NULL;
163*1c60b9acSAndroid Build Coastguard Worker #else
164*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_dstaddr = NULL;
165*1c60b9acSAndroid Build Coastguard Worker #endif
166*1c60b9acSAndroid Build Coastguard Worker (*end)->ifa_data = NULL;
167*1c60b9acSAndroid Build Coastguard Worker
168*1c60b9acSAndroid Build Coastguard Worker end = &(*end)->ifa_next;
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker }
171*1c60b9acSAndroid Build Coastguard Worker *ifap = start;
172*1c60b9acSAndroid Build Coastguard Worker close(fd);
173*1c60b9acSAndroid Build Coastguard Worker lws_free(buf);
174*1c60b9acSAndroid Build Coastguard Worker return 0;
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker error_out:
177*1c60b9acSAndroid Build Coastguard Worker close(fd);
178*1c60b9acSAndroid Build Coastguard Worker lws_free(buf);
179*1c60b9acSAndroid Build Coastguard Worker errno = ret;
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker return -1;
182*1c60b9acSAndroid Build Coastguard Worker }
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker int
getifaddrs(struct ifaddrs ** ifap)185*1c60b9acSAndroid Build Coastguard Worker getifaddrs(struct ifaddrs **ifap)
186*1c60b9acSAndroid Build Coastguard Worker {
187*1c60b9acSAndroid Build Coastguard Worker int ret = -1;
188*1c60b9acSAndroid Build Coastguard Worker errno = ENXIO;
189*1c60b9acSAndroid Build Coastguard Worker #if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
190*1c60b9acSAndroid Build Coastguard Worker if (ret)
191*1c60b9acSAndroid Build Coastguard Worker ret = getifaddrs2(ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
192*1c60b9acSAndroid Build Coastguard Worker sizeof(struct in6_ifreq));
193*1c60b9acSAndroid Build Coastguard Worker #endif
194*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_IPV6) && defined(SIOCGIFCONF)
195*1c60b9acSAndroid Build Coastguard Worker if (ret)
196*1c60b9acSAndroid Build Coastguard Worker ret = getifaddrs2(ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
197*1c60b9acSAndroid Build Coastguard Worker sizeof(struct ifreq));
198*1c60b9acSAndroid Build Coastguard Worker #endif
199*1c60b9acSAndroid Build Coastguard Worker #if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
200*1c60b9acSAndroid Build Coastguard Worker if (ret)
201*1c60b9acSAndroid Build Coastguard Worker ret = getifaddrs2(ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
202*1c60b9acSAndroid Build Coastguard Worker sizeof(struct ifreq));
203*1c60b9acSAndroid Build Coastguard Worker #endif
204*1c60b9acSAndroid Build Coastguard Worker return ret;
205*1c60b9acSAndroid Build Coastguard Worker }
206*1c60b9acSAndroid Build Coastguard Worker
207*1c60b9acSAndroid Build Coastguard Worker void
freeifaddrs(struct ifaddrs * ifp)208*1c60b9acSAndroid Build Coastguard Worker freeifaddrs(struct ifaddrs *ifp)
209*1c60b9acSAndroid Build Coastguard Worker {
210*1c60b9acSAndroid Build Coastguard Worker struct ifaddrs *p, *q;
211*1c60b9acSAndroid Build Coastguard Worker
212*1c60b9acSAndroid Build Coastguard Worker for (p = ifp; p; ) {
213*1c60b9acSAndroid Build Coastguard Worker lws_free(p->ifa_name);
214*1c60b9acSAndroid Build Coastguard Worker lws_free(p->ifa_addr);
215*1c60b9acSAndroid Build Coastguard Worker lws_free(p->ifa_dstaddr);
216*1c60b9acSAndroid Build Coastguard Worker lws_free(p->ifa_netmask);
217*1c60b9acSAndroid Build Coastguard Worker lws_free(p->ifa_data);
218*1c60b9acSAndroid Build Coastguard Worker q = p;
219*1c60b9acSAndroid Build Coastguard Worker p = p->ifa_next;
220*1c60b9acSAndroid Build Coastguard Worker lws_free(q);
221*1c60b9acSAndroid Build Coastguard Worker }
222*1c60b9acSAndroid Build Coastguard Worker }
223*1c60b9acSAndroid Build Coastguard Worker
224*1c60b9acSAndroid Build Coastguard Worker #ifdef TEST
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker void
print_addr(const char * s,struct sockaddr * sa)227*1c60b9acSAndroid Build Coastguard Worker print_addr(const char *s, struct sockaddr *sa)
228*1c60b9acSAndroid Build Coastguard Worker {
229*1c60b9acSAndroid Build Coastguard Worker int i;
230*1c60b9acSAndroid Build Coastguard Worker printf(" %s=%d/", s, sa->sa_family);
231*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN
232*1c60b9acSAndroid Build Coastguard Worker for (i = 0;
233*1c60b9acSAndroid Build Coastguard Worker i < sa->sa_len - ((lws_intptr_t)sa->sa_data - (lws_intptr_t)&sa->sa_family); i++)
234*1c60b9acSAndroid Build Coastguard Worker printf("%02x", ((unsigned char *)sa->sa_data)[i]);
235*1c60b9acSAndroid Build Coastguard Worker #else
236*1c60b9acSAndroid Build Coastguard Worker for (i = 0; i < sizeof(sa->sa_data); i++)
237*1c60b9acSAndroid Build Coastguard Worker printf("%02x", ((unsigned char *)sa->sa_data)[i]);
238*1c60b9acSAndroid Build Coastguard Worker #endif
239*1c60b9acSAndroid Build Coastguard Worker printf("\n");
240*1c60b9acSAndroid Build Coastguard Worker }
241*1c60b9acSAndroid Build Coastguard Worker
242*1c60b9acSAndroid Build Coastguard Worker void
print_ifaddrs(struct ifaddrs * x)243*1c60b9acSAndroid Build Coastguard Worker print_ifaddrs(struct ifaddrs *x)
244*1c60b9acSAndroid Build Coastguard Worker {
245*1c60b9acSAndroid Build Coastguard Worker struct ifaddrs *p;
246*1c60b9acSAndroid Build Coastguard Worker
247*1c60b9acSAndroid Build Coastguard Worker for (p = x; p; p = p->ifa_next) {
248*1c60b9acSAndroid Build Coastguard Worker printf("%s\n", p->ifa_name);
249*1c60b9acSAndroid Build Coastguard Worker printf(" flags=%x\n", p->ifa_flags);
250*1c60b9acSAndroid Build Coastguard Worker if (p->ifa_addr)
251*1c60b9acSAndroid Build Coastguard Worker print_addr("addr", p->ifa_addr);
252*1c60b9acSAndroid Build Coastguard Worker if (p->ifa_dstaddr)
253*1c60b9acSAndroid Build Coastguard Worker print_addr("dstaddr", p->ifa_dstaddr);
254*1c60b9acSAndroid Build Coastguard Worker if (p->ifa_netmask)
255*1c60b9acSAndroid Build Coastguard Worker print_addr("netmask", p->ifa_netmask);
256*1c60b9acSAndroid Build Coastguard Worker printf(" %p\n", p->ifa_data);
257*1c60b9acSAndroid Build Coastguard Worker }
258*1c60b9acSAndroid Build Coastguard Worker }
259*1c60b9acSAndroid Build Coastguard Worker
260*1c60b9acSAndroid Build Coastguard Worker int
main()261*1c60b9acSAndroid Build Coastguard Worker main()
262*1c60b9acSAndroid Build Coastguard Worker {
263*1c60b9acSAndroid Build Coastguard Worker struct ifaddrs *a = NULL, *b;
264*1c60b9acSAndroid Build Coastguard Worker getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
265*1c60b9acSAndroid Build Coastguard Worker sizeof(struct ifreq));
266*1c60b9acSAndroid Build Coastguard Worker print_ifaddrs(a);
267*1c60b9acSAndroid Build Coastguard Worker printf("---\n");
268*1c60b9acSAndroid Build Coastguard Worker getifaddrs(&b);
269*1c60b9acSAndroid Build Coastguard Worker print_ifaddrs(b);
270*1c60b9acSAndroid Build Coastguard Worker return 0;
271*1c60b9acSAndroid Build Coastguard Worker }
272*1c60b9acSAndroid Build Coastguard Worker #endif
273