media/mtransport/third_party/nICEr/src/stun/addrs.c

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:929e9d0ca5ac
1 /*
2 Copyright (c) 2007, Adobe Systems, Incorporated
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 * Neither the name of Adobe Systems, Network Resonance nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 static char *RCSSTRING __UNUSED__="$Id: addrs.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
35
36 #include <csi_platform.h>
37 #include <assert.h>
38 #include <string.h>
39
40 #ifdef WIN32
41 #include <winsock2.h>
42 #include <iphlpapi.h>
43 #include <tchar.h>
44 #else /* UNIX */
45 #include <sys/param.h>
46 #include <sys/socket.h>
47 #ifndef ANDROID
48 #include <sys/sysctl.h>
49 #include <sys/syslog.h>
50 #else
51 #include <syslog.h>
52 /* Work around an Android NDK < r8c bug */
53 #undef __unused
54 #include <linux/sysctl.h>
55 #endif
56 #include <net/if.h>
57 #ifndef LINUX
58 #if !defined(__OpenBSD__) && !defined(__NetBSD__)
59 #include <net/if_var.h>
60 #endif
61 #include <net/if_dl.h>
62 #include <net/if_types.h>
63 #include <sys/sockio.h>
64 #else
65 #include <linux/sockios.h>
66 #include <linux/if.h>
67 #include <linux/kernel.h>
68 #include <linux/wireless.h>
69 #ifndef ANDROID
70 #include <linux/ethtool.h>
71 #endif
72 #endif
73 #include <net/route.h>
74
75 /* IP */
76 #include <netinet/in.h>
77 #ifdef LINUX
78 #include "sys/ioctl.h"
79 #else
80 #include <netinet/in_var.h>
81 #endif
82 #include <arpa/inet.h>
83 #include <netdb.h>
84 #endif /* UNIX */
85
86 #include "stun.h"
87 #include "addrs.h"
88
89
90
91 #if defined(BSD) || defined(DARWIN)
92 /*
93 * Copyright (c) 1983, 1993
94 * The Regents of the University of California. All rights reserved.
95 *
96 * Redistribution and use in source and binary forms, with or without
97 * modification, are permitted provided that the following conditions
98 * are met:
99 * 1. Redistributions of source code must retain the above copyright
100 * notice, this list of conditions and the following disclaimer.
101 * 2. Redistributions in binary form must reproduce the above copyright
102 * notice, this list of conditions and the following disclaimer in the
103 * documentation and/or other materials provided with the distribution.
104 *[3 Deleted as of 22nd July 1999; see
105 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
106 * for details]
107 * 4. Neither the name of the University nor the names of its contributors
108 * may be used to endorse or promote products derived from this software
109 * without specific prior written permission.
110 *
111 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
112 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
113 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
114 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
115 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
116 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
117 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
118 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
119 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
120 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
121 * SUCH DAMAGE.
122 */
123
124 #include <err.h>
125
126 static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
127 static int stun_grab_addrs(char *name, int addrcount,
128 struct ifa_msghdr *ifam,
129 nr_local_addr addrs[], int maxaddrs, int *count);
130 static int
131 nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr);
132
133
134 /*
135 * Expand the compacted form of addresses as returned via the
136 * configuration read via sysctl().
137 */
138 #define ROUNDUP(a) \
139 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
140 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
141
142 static void
143 stun_rt_xaddrs(cp, cplim, rtinfo)
144 caddr_t cp, cplim;
145 struct rt_addrinfo *rtinfo;
146 {
147 struct sockaddr *sa;
148 int i;
149
150 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
151 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
152 if ((rtinfo->rti_addrs & (1 << i)) == 0)
153 continue;
154 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
155 ADVANCE(cp, sa);
156 }
157 }
158
159 static int
160 stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_local_addr addrs[], int maxaddrs, int *count)
161 {
162 int r,_status;
163 int s = -1;
164 struct ifreq ifr;
165 struct rt_addrinfo info;
166 struct sockaddr_in *sin;
167
168 ifr.ifr_addr.sa_family = AF_INET;
169 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
170
171 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
172 r_log(NR_LOG_STUN, LOG_ERR, "unable to obtain addresses from socket");
173 ABORT(R_FAILED);
174 }
175
176 while (addrcount > 0) {
177 info.rti_addrs = ifam->ifam_addrs;
178
179 /* Expand the compacted addresses */
180 stun_rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info);
181 addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
182 addrs[*count].interface.estimated_speed = 0;
183 /* TODO (Bug 895790) Get interface properties for Darwin */
184
185 switch (info.rti_info[RTAX_IFA]->sa_family) {
186 case AF_INET:
187 sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
188
189 if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sin, sizeof(*sin), IPPROTO_UDP, 0, &(addrs[*count].addr))))
190 ABORT(r);
191
192 strlcpy(addrs[*count].addr.ifname, name, sizeof(addrs[*count].addr.ifname));
193
194 ++*count;
195 break;
196 case AF_INET6:
197 UNIMPLEMENTED;
198 break;
199 }
200
201 addrcount--;
202
203 if (*count >= maxaddrs) {
204 r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of %d entries", maxaddrs, maxaddrs+addrcount);
205 break;
206 }
207
208 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
209 }
210
211 _status = 0;
212 abort:
213 if (s != -1) close(s);
214 return _status;
215 }
216
217 static int
218 stun_get_mib_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
219 {
220 int _status;
221 char name[32];
222 int flags;
223 int addrcount;
224 struct if_msghdr *ifm, *nextifm;
225 struct ifa_msghdr *ifam;
226 struct sockaddr_dl *sdl;
227 char *buf = 0;
228 char *lim;
229 char *next;
230 size_t needed;
231 int mib[6];
232
233 *count = 0;
234
235 mib[0] = CTL_NET;
236 mib[1] = PF_ROUTE;
237 mib[2] = 0;
238 mib[3] = AF_INET;
239 mib[4] = NET_RT_IFLIST;
240 mib[5] = 0;
241
242 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
243 errx(1, "iflist-sysctl-estimate");
244 if ((buf = malloc(needed)) == NULL)
245 errx(1, "malloc");
246 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
247 errx(1, "actual retrieval of interface table");
248 lim = buf + needed;
249
250 next = buf;
251 while (next < lim) {
252 ifm = (struct if_msghdr *)next;
253
254 if (ifm->ifm_type == RTM_IFINFO) {
255 sdl = (struct sockaddr_dl *)(ifm + 1);
256 flags = ifm->ifm_flags;
257 } else {
258 r_log(NR_LOG_STUN, LOG_WARNING, "out of sync parsing NET_RT_IFLIST");
259 r_log(NR_LOG_STUN, LOG_DEBUG, "expected %d, got %d, msglen = %d, buf:%p, next:%p, lim:%p", RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen, buf, next, lim);
260 ABORT(R_FAILED);
261 }
262
263 next += ifm->ifm_msglen;
264 ifam = NULL;
265 addrcount = 0;
266 while (next < lim) {
267
268 nextifm = (struct if_msghdr *)next;
269
270 if (nextifm->ifm_type != RTM_NEWADDR)
271 break;
272
273 if (ifam == NULL)
274 ifam = (struct ifa_msghdr *)nextifm;
275
276 addrcount++;
277 next += nextifm->ifm_msglen;
278 }
279
280 if (sdl->sdl_nlen > sizeof(name) - 1) {
281 ABORT(R_INTERNAL);
282 }
283
284 memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
285 name[sdl->sdl_nlen] = '\0';
286
287 stun_grab_addrs(name, addrcount, ifam, addrs, maxaddrs, count);
288 }
289
290 _status = 0;
291 abort:
292 if (buf) free(buf);
293 return _status;
294 }
295
296 #elif defined(WIN32)
297
298 #define WIN32_MAX_NUM_INTERFACES 20
299
300
301 #define _NR_MAX_KEY_LENGTH 256
302 #define _NR_MAX_NAME_LENGTH 512
303
304 #define _ADAPTERS_BASE_REG "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
305
306 static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name)
307 {
308 int r,_status;
309 HKEY adapter_reg;
310 TCHAR adapter_key[_NR_MAX_KEY_LENGTH];
311 TCHAR keyval_buf[_NR_MAX_KEY_LENGTH];
312 TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH];
313 DWORD keyval_len, key_type;
314 size_t converted_chars, newlen;
315 char *my_fn = 0;
316
317 #ifdef _UNICODE
318 mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1,
319 adapter_GUID, _TRUNCATE);
320 #else
321 strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH);
322 #endif
323
324 _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG));
325 _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\"));
326 _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar);
327 _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection"));
328
329 r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg);
330
331 if (r != ERROR_SUCCESS) {
332 r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r);
333 ABORT(R_INTERNAL);
334 }
335
336 keyval_len = sizeof(keyval_buf);
337 r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type,
338 (BYTE *)keyval_buf, &keyval_len);
339
340 RegCloseKey(adapter_reg);
341
342 #ifdef UNICODE
343 newlen = wcslen(keyval_buf)+1;
344 my_fn = (char *) RCALLOC(newlen);
345 if (!my_fn) {
346 ABORT(R_NO_MEMORY);
347 }
348 wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE);
349 #else
350 my_fn = r_strdup(keyval_buf);
351 #endif
352
353 *friendly_name = my_fn;
354 _status=0;
355
356 abort:
357 if (_status) {
358 if (my_fn) free(my_fn);
359 }
360 return(_status);
361 }
362
363
364 static int
365 stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
366 {
367 int r,_status;
368 PIP_ADAPTER_INFO pAdapterInfo;
369 PIP_ADAPTER_INFO pAdapter = NULL;
370 PIP_ADDR_STRING pAddrString;
371 ULONG out_buf_len;
372 char *friendly_name=0;
373 char munged_ifname[IFNAMSIZ];
374 int n = 0;
375
376 *count = 0;
377
378 pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(sizeof(IP_ADAPTER_INFO));
379 out_buf_len = sizeof(IP_ADAPTER_INFO);
380
381 /* First call to GetAdaptersInfo is mainly to get length */
382
383 if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) {
384 RFREE(pAdapterInfo);
385 pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(out_buf_len);
386 if (pAdapterInfo == NULL) {
387 r_log(NR_LOG_STUN, LOG_ERR, "Error allocating memory for GetAdaptersInfo output");
388 ABORT(R_NO_MEMORY);
389 }
390 }
391 if ((r = GetAdaptersInfo(pAdapterInfo, &out_buf_len)) != NO_ERROR) {
392 r_log(NR_LOG_STUN, LOG_ERR, "Got error from GetAdaptersInfo");
393 ABORT(R_INTERNAL);
394 }
395 r_log(NR_LOG_STUN, LOG_DEBUG, "Got AdaptersInfo");
396
397 pAdapter = pAdapterInfo;
398
399 while (pAdapter) {
400 char *c;
401
402 r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Name (GUID) = %s", pAdapter->AdapterName);
403 r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Description = %s", pAdapter->Description);
404
405 if (nr_win32_get_adapter_friendly_name(pAdapter->AdapterName, &friendly_name)) {
406 friendly_name = 0;
407 }
408 if (friendly_name && *friendly_name) {
409 r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with friendly name: %s", friendly_name);
410 snprintf(munged_ifname, IFNAMSIZ, "%s%c", friendly_name, 0);
411 RFREE(friendly_name);
412 friendly_name = 0;
413 } else {
414 // Not all adapters follow the friendly name convention. Windows' PPTP
415 // VPN adapter puts "VPN Connection 2" in the Description field instead.
416 // Windows's renaming-logic appears to enforce uniqueness in spite of this.
417 r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with description: %s", pAdapter->Description);
418 snprintf(munged_ifname, IFNAMSIZ, "%s%c", pAdapter->Description, 0);
419 }
420 /* replace spaces with underscores */
421 c = strchr(munged_ifname, ' ');
422 while (c != NULL) {
423 *c = '_';
424 c = strchr(munged_ifname, ' ');
425 }
426 c = strchr(munged_ifname, '.');
427 while (c != NULL) {
428 *c = '+';
429 c = strchr(munged_ifname, '.');
430 }
431
432 r_log(NR_LOG_STUN, LOG_INFO, "Converted ifname: %s", munged_ifname);
433
434 for (pAddrString = &(pAdapter->IpAddressList); pAddrString != NULL; pAddrString = pAddrString->Next) {
435 unsigned long this_addr = inet_addr(pAddrString->IpAddress.String);
436 nr_transport_addr *addr = &(addrs[n].addr);
437
438 if (this_addr == 0)
439 continue;
440
441 r_log(NR_LOG_STUN, LOG_INFO, "Adapter %s address: %s", munged_ifname, pAddrString->IpAddress.String);
442
443 addr->ip_version=NR_IPV4;
444 addr->protocol = IPPROTO_UDP;
445
446 addr->u.addr4.sin_family=PF_INET;
447 addr->u.addr4.sin_port=0;
448 addr->u.addr4.sin_addr.s_addr=this_addr;
449 addr->addr=(struct sockaddr *)&(addr->u.addr4);
450 addr->addr_len=sizeof(struct sockaddr_in);
451
452 strlcpy(addr->ifname, munged_ifname, sizeof(addr->ifname));
453 snprintf(addr->as_string,40,"IP4:%s:%d",
454 inet_ntoa(addr->u.addr4.sin_addr),
455 ntohs(addr->u.addr4.sin_port));
456
457 /* TODO: (Bug 895793) Getting interface properties for Windows */
458 addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
459 addrs[n].interface.estimated_speed = 0;
460
461 if (++n >= maxaddrs)
462 goto done;
463 }
464
465 pAdapter = pAdapter->Next;
466 }
467
468 done:
469 *count = n;
470 _status = 0;
471
472 abort:
473 RFREE(pAdapterInfo);
474 RFREE(friendly_name);
475 return _status;
476 }
477
478 #ifdef GET_WIN32_ADDRS_NO_WIN2K
479 /* Here's a nice way to get adapter addresses and names, but it
480 * isn't supported on Win2000.
481 */
482 static int
483 stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
484 {
485 int r,_status;
486 PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL;
487 ULONG buflen;
488 char munged_ifname[IFNAMSIZ];
489 int n = 0;
490
491 *count = 0;
492
493 if (maxaddrs <= 0)
494 ABORT(R_INTERNAL);
495
496 /* Call GetAdaptersAddresses() twice. First, just to get the buf length */
497
498 buflen = 0;
499
500 r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen);
501 if (r != ERROR_BUFFER_OVERFLOW) {
502 r_log(NR_LOG_STUN, LOG_ERR, "Error getting buf len from GetAdaptersAddresses()");
503 ABORT(R_INTERNAL);
504 }
505
506 AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen);
507 if (AdapterAddresses == NULL) {
508 r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()");
509 ABORT(R_NO_MEMORY);
510 }
511
512 /* for real, this time */
513
514 r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen);
515 if (r != NO_ERROR) {
516 r_log(NR_LOG_STUN, LOG_ERR, "Error getting addresses from GetAdaptersAddresses()");
517 ABORT(R_INTERNAL);
518 }
519
520 /* Loop through the adapters */
521
522 for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) {
523 char *c;
524
525 if (tmpAddress->OperStatus != IfOperStatusUp)
526 continue;
527
528 snprintf(munged_ifname, IFNAMSIZ, "%S%c", tmpAddress->FriendlyName, 0);
529 /* replace spaces with underscores */
530 c = strchr(munged_ifname, ' ');
531 while (c != NULL) {
532 *c = '_';
533 c = strchr(munged_ifname, ' ');
534 }
535 c = strchr(munged_ifname, '.');
536 while (c != NULL) {
537 *c = '+';
538 c = strchr(munged_ifname, '+');
539 }
540
541 if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) {
542 IP_ADAPTER_UNICAST_ADDRESS *u = 0;
543
544 for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) {
545 SOCKET_ADDRESS *sa_addr = &u->Address;
546
547 if ((sa_addr->lpSockaddr->sa_family == AF_INET) ||
548 (sa_addr->lpSockaddr->sa_family == AF_INET6)) {
549 if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, sizeof(*sa_addr->lpSockaddr), IPPROTO_UDP, 0, &(addrs[n].addr))))
550 ABORT(r);
551 }
552 else {
553 r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for adapteraddress %s",munged_ifname);
554 continue;
555 }
556
557 strlcpy(addrs[n].addr.ifname, munged_ifname, sizeof(addrs[n].addr.ifname));
558 /* TODO: (Bug 895793) Getting interface properties for Windows */
559 addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
560 addrs[n].interface.estimated_speed = 0;
561 if (++n >= maxaddrs)
562 goto done;
563 }
564 }
565 }
566
567 done:
568 *count = n;
569 _status = 0;
570
571 abort:
572 RFREE(AdapterAddresses);
573 return _status;
574 }
575 #endif /* GET_WIN32_ADDRS_NO_WIN2K */
576
577 #elif defined(__sparc__)
578
579 static int
580 stun_get_sparc_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
581 {
582 *count = 0;
583 UNIMPLEMENTED; /*TODO !nn! - sparc */
584 return 0;
585 }
586
587 #else
588
589 static int
590 stun_get_siocgifconf_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
591 {
592 struct ifconf ifc;
593 int _status;
594 int s = socket( AF_INET, SOCK_DGRAM, 0 );
595 int len = 100 * sizeof(struct ifreq);
596 int r;
597 int e;
598 char *ptr;
599 int tl;
600 int n;
601 struct ifreq ifr2;
602
603 char buf[ len ];
604
605 ifc.ifc_len = len;
606 ifc.ifc_buf = buf;
607
608 e = ioctl(s,SIOCGIFCONF,&ifc);
609 ptr = buf;
610 tl = ifc.ifc_len;
611 n=0;
612
613 while ( (tl > 0) && ( n < maxaddrs) )
614 {
615 struct ifreq* ifr = (struct ifreq *)ptr;
616
617 #ifdef LINUX
618 int si = sizeof(struct ifreq);
619 #ifndef ANDROID
620 struct ethtool_cmd ecmd;
621 struct iwreq wrq;
622 #endif
623 #else
624 int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr));
625 #endif
626 tl -= si;
627 ptr += si;
628
629 ifr2 = *ifr;
630
631 e = ioctl(s,SIOCGIFADDR,&ifr2);
632 if ( e == -1 )
633 {
634 continue;
635 }
636
637 //r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e);
638
639 if ((r=nr_sockaddr_to_transport_addr(&ifr2.ifr_addr, sizeof(ifr2.ifr_addr), IPPROTO_UDP, 0, &(addrs[n].addr)))) {
640 r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address");
641 }
642 else {
643 addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
644 addrs[n].interface.estimated_speed = 0;
645 #if defined(LINUX) && !defined(ANDROID)
646 /* TODO (Bug 896851): interface property for Android */
647 /* Getting ethtool for ethernet information. */
648 ecmd.cmd = ETHTOOL_GSET;
649 ifr2.ifr_data = (void*)&ecmd;
650 e = ioctl(s, SIOCETHTOOL, &ifr2);
651 if (e == 0)
652 {
653 /* For wireless network, we won't get ethtool, it's a wired
654 connection */
655 addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED;
656 #ifdef DONT_HAVE_ETHTOOL_SPEED_HI
657 addrs[n].interface.estimated_speed = ecmd.speed;
658 #else
659 addrs[n].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000;
660 #endif
661 }
662
663 strncpy(wrq.ifr_name, ifr->ifr_name, sizeof(wrq.ifr_name));
664 e = ioctl(s, SIOCGIWRATE, &wrq);
665 if (e == 0)
666 {
667 addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI;
668 addrs[n].interface.estimated_speed = wrq.u.bitrate.value / 1000;
669 }
670
671 ifr2 = *ifr;
672 e = ioctl(s, SIOCGIFFLAGS, &ifr2);
673 if (e == 0)
674 {
675 if (ifr2.ifr_flags & IFF_POINTOPOINT)
676 {
677 addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN;
678 /* TODO (Bug 896913): find backend network type of this VPN */
679 }
680 }
681 #endif
682 strlcpy(addrs[n].addr.ifname, ifr->ifr_name, sizeof(addrs[n].addr.ifname));
683 ++n;
684 }
685 }
686
687 close(s);
688
689 *count = n;
690
691 _status = 0;
692 return _status;
693 }
694 #endif
695
696 static int
697 nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr)
698 {
699 int i;
700 int different;
701
702 for (i = 0; i < count; ++i) {
703 different = nr_transport_addr_cmp(&addrs[i].addr, &(addr->addr),
704 NR_TRANSPORT_ADDR_CMP_MODE_ALL);
705 if (!different)
706 return 1; /* duplicate */
707 }
708
709 return 0;
710 }
711
712 int
713 nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int *count)
714 {
715 int r, _status;
716 nr_local_addr *tmp = 0;
717 int i;
718 int n;
719
720 tmp = RMALLOC(*count * sizeof(*tmp));
721 if (!tmp)
722 ABORT(R_NO_MEMORY);
723
724 n = 0;
725 for (i = 0; i < *count; ++i) {
726 if (nr_stun_is_duplicate_addr(tmp, n, &addrs[i])) {
727 /* skip addrs[i], it's a duplicate */
728 }
729 else if (remove_loopback && nr_transport_addr_is_loopback(&addrs[i].addr)) {
730 /* skip addrs[i], it's a loopback */
731 }
732 else {
733 /* otherwise, copy it to the temporary array */
734 if ((r=nr_local_addr_copy(&tmp[n], &addrs[i])))
735 ABORT(r);
736 ++n;
737 }
738 }
739
740 *count = n;
741
742 /* copy temporary array into passed in/out array */
743 for (i = 0; i < *count; ++i) {
744 if ((r=nr_local_addr_copy(&addrs[i], &tmp[i])))
745 ABORT(r);
746 }
747
748 _status = 0;
749 abort:
750 RFREE(tmp);
751 return _status;
752 }
753
754 #ifndef USE_PLATFORM_NR_STUN_GET_ADDRS
755
756 int
757 nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int *count)
758 {
759 int _status=0;
760 int i;
761 char typestr[100];
762
763 #if defined(BSD) || defined(DARWIN)
764 _status = stun_get_mib_addrs(addrs, maxaddrs, count);
765 #elif defined(WIN32)
766 _status = stun_get_win32_addrs(addrs, maxaddrs, count);
767 #elif defined(__sparc__)
768 _status = stun_get_sparc_addrs(addrs, maxaddrs, count);
769 #else
770 _status = stun_get_siocgifconf_addrs(addrs, maxaddrs, count);
771 #endif
772
773 nr_stun_remove_duplicate_addrs(addrs, drop_loopback, count);
774
775 for (i = 0; i < *count; ++i) {
776 nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr));
777 r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n",
778 i,addrs[i].addr.as_string,addrs[i].addr.ifname,typestr);
779 }
780
781 return _status;
782 }
783
784 #endif

mercurial