Bug Summary

File:libsofia-sip-ua/su/su_localinfo.c
Warning:line 224, column 13
Although the value stored to 'ip4' is used in the enclosing expression, the value is never actually read from 'ip4'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name su_localinfo.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-11/lib/clang/11.0.1 -D HAVE_CONFIG_H -I . -I ../.. -I ../../libsofia-sip-ua/su/sofia-sip -D SU_DEBUG=0 -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /drone/src/libsofia-sip-ua/su -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -o /drone/src/scan-build/2022-06-23-181620-12-1 -x c su_localinfo.c
1/*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2005 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25/**@ingroup su_socket
26 * @CFILE su_localinfo.c
27 *
28 * Obtain list of local addresses.
29 *
30 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
31 * @author Martti Mela <Martti.Mela@nokia.com>
32 *
33 * @date Created: Wed Oct 4 14:09:29 EET 2000 ppessi
34 */
35
36#include "config.h"
37
38#if HAVE_SYS_SOCKIO_H
39#include <sys/sockio.h>
40#endif
41
42#include <sofia-sip/su.h>
43#include <sofia-sip/su_localinfo.h>
44#include <sofia-sip/su_string.h>
45#include "su_module_debug.h"
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <assert.h>
51#include <stddef.h>
52#include <sys/types.h>
53
54#if HAVE_SYS_SOCKET_H1
55#include <sys/socket.h>
56#endif
57#if HAVE_NETINET_IN_H1
58#include <netinet/in.h>
59#endif
60#if HAVE_SYS_IOCTL_H1
61#include <sys/ioctl.h>
62#endif
63#if HAVE_NET_IF_H1
64#include <net/if.h>
65#endif
66#if HAVE_NET_IF_TYPES_H
67#include <net/if_types.h>
68#endif
69
70#if SU_LOCALINFO_TEST
71
72#undef USE_LOCALINFO01
73
74#elif HAVE_GETIFADDRS1
75
76#define USE_LOCALINFO01 1
77#define localinfo0bsd_localinfo bsd_localinfo
78static int bsd_localinfo(su_localinfo_t const *, su_localinfo_t **);
79
80#elif HAVE_IPHLPAPI_H
81
82#include <iphlpapi.h>
83#define USE_LOCALINFO01 1
84#define localinfo0bsd_localinfo win_localinfo
85static int win_localinfo(su_localinfo_t const *, su_localinfo_t **);
86
87#else
88/* No localinfo0(), use localinfo4() and localinfo6() */
89
90#undef USE_LOCALINFO01
91static int localinfo4(su_localinfo_t const *, su_localinfo_t **);
92# if SU_HAVE_IN61
93static int localinfo6(su_localinfo_t const *, su_localinfo_t **);
94# endif
95
96#endif
97
98static int li_scope4(uint32_t ip4);
99#if SU_HAVE_IN61
100static int li_scope6(struct in6_addr const *ip6);
101#endif
102
103#if !SU_LOCALINFO_TEST
104
105static int li_name(su_localinfo_t const*, int, su_sockaddr_t const*, char **);
106static void li_sort(su_localinfo_t *i, su_localinfo_t **rresult);
107
108/** @brief Request local address information.
109 *
110 * Gather the network interfaces and the addresses corresponding to them,
111 * check if they match to the search criteria specifed by @a hints and
112 * return a list of matching local address information in the @a
113 * return_localinfo. The local address information may include IPv4/IPv6
114 * addresses, interface name, interface index, address scope, and domain
115 * names corresponding to the local addresses.
116 *
117 * @param[in] hints specifies selection criteria
118 * @param[out] return_localinfo return list of local addresses
119 *
120 * @par Selection criteria - hints
121 *
122 * The selection criteria @a hints is used to select which addresses are
123 * returned and what kind of information is included in the @a res list.
124 *
125 * @par Selection by flags - hints->li_flags
126 *
127 * The @a hints->li_flags contain flags, which can be combined with bit-wise
128 * or. The currently defined flags are as follows:
129 *
130 * - #LI_V4MAPPED: when returning IPv4 addresses, map them as IPv6
131 * addresses. If this flag is specified, IPv4 addresses are returned even
132 * if @a hints->li_family is set to @c AF_INET6.
133 * - #LI_CANONNAME: return the domain name (DNS PTR) corresponding to the
134 * local address in @a li_canonname.
135 * - #LI_NAMEREQD: Do not return addresses not in DNS.
136 * - #LI_NUMERIC: instead of domain name, return the text presentation of
137 * the addresss in @a li_canonname.
138 * - #LI_DOWN: include interfaces and their addresses even if the interfaces
139 * are down. New in @VERSION_1_12_2.
140 * - #LI_IFNAME: return the interface name in @a li_ifname.
141 *
142 * @par Selection by address family - hints->li_family
143 *
144 * The address family can have three values: 0, AF_INET and AF_INET6. If
145 * address family @a hints->li_family, both IPv4 and IPv6 addresses are
146 * returned.
147 *
148 * @par Selection by interface index - hints->li_index
149 *
150 * If the field @a hints->li_index is non-zero, only the addresses assigned
151 * to the interface with given index are returned. The list of interface
152 * indices and names can be obtained by the function @c su_if_names().
153 *
154 * @par Selection by interface name - hints->li_ifname
155 *
156 * If the field @a hints->li_ifname is not NULL, only the addresses assigned
157 * to the named interface are returned. The list of interface names can be
158 * obtained by the function @c su_if_names().
159 *
160 * @par Selection by address scope - hints->li_scope
161 *
162 * If the field @a hints->li_scope is nonzero, only the addresses with
163 * matching scope are returned. The different address scopes can be combined
164 * with bitwise or. They are defined as follows
165 * - #LI_SCOPE_HOST: host-local address, valid within host (::1, 127.0.0.1/8)
166 * - #LI_SCOPE_LINK: link-local address, valid within link
167 * (IP6 addresses with prefix fe80::/10,
168 * IP4 addresses in net 169.254.0.0/16).
169 * - #LI_SCOPE_SITE: site-local address, addresses valid within organization
170 * (IPv6 addresses with prefix fec::/10,
171 * private IPv4 addresses in nets 10.0.0.0/8, 172.16.0.0/12,
172 * and 192.168.0.0/16 as defined in @RFC1918)
173 * - #LI_SCOPE_GLOBAL: global address.
174 *
175 * For instance, setting @a hints->li_scope to @c LI_SCOPE_GLOBAL | @c
176 * LI_SCOPE_SITE, both the @e global and @e site-local addresses are
177 * returned.
178 *
179 * @sa @RFC1918, @RFC4291, su_sockaddr_scope()
180 *
181 * @par Selection by domain name - hints->li_canonname
182 *
183 * If this field is non-null, the domain name (DNS PTR) corresponding to
184 * local IP addresses should match to the name given in this field.
185 *
186 * @return Zero (#ELI_NOERROR) when successful, or negative error code when
187 * failed.
188 *
189 * @par Diagnostics
190 * Use su_gli_strerror() in order to obtain a string describing the error
191 * code returned by su_getlocalinfo().
192 *
193 */
194int su_getlocalinfo(su_localinfo_t const *hints,
195 su_localinfo_t **return_localinfo)
196{
197 int error = 0, ip4 = 0;
198 int ip6 = 0;
199 su_localinfo_t *result = NULL((void*)0), **rr = &result;
200 su_localinfo_t hh[1] = {{ 0 }};
201
202 assert(return_localinfo)((void) sizeof ((return_localinfo) ? 1 : 0), __extension__ ({
if (return_localinfo) ; else __assert_fail ("return_localinfo"
, "su_localinfo.c", 202, __extension__ __PRETTY_FUNCTION__); }
))
;
203
204 *return_localinfo = NULL((void*)0);
205
206 if (hints) {
207 /* Copy hints so that it can be modified */
208 *hh = *hints;
209 if (hh->li_canonname)
210 hh->li_flags |= LI_CANONNAME;
211#if 0
212 /* hints->li_ifname is used to select by interface,
213 li_ifname is returned with LI_IFNAME flag
214 */
215 if ((hh->li_flags & LI_IFNAME) && hh->li_ifname == NULL((void*)0))
216 return ELI_BADHINTS;
217#endif
218 }
219
220 switch (hh->li_family) {
221#if SU_HAVE_IN61
222 case AF_INET610:
223 if (hh->li_flags & LI_V4MAPPED)
224 ip6 = ip4 = 1, hh->li_family = 0;
Although the value stored to 'ip4' is used in the enclosing expression, the value is never actually read from 'ip4'
225 else
226 ip6 = 1;
227 break;
228#endif
229
230 case AF_INET2:
231#ifndef USE_LOCALINFO01
232 ip4 = 1;
233#endif
234 break;
235
236 case 0:
237#ifndef USE_LOCALINFO01
238 ip4 = 1;
239#endif
240#if SU_HAVE_IN61
241 ip6 = 1;
242#endif
243
244 break;
245
246 default:
247 return -1;
248 }
249
250#if USE_LOCALINFO01
251 error = localinfo0bsd_localinfo(hh, rr);
252#else
253
254# if SU_HAVE_IN61
255 if (ip6) {
256 error = localinfo6(hh, rr);
257 if (error == ELI_NOADDRESS && ip4)
258 error = 0;
259
260 if (!error)
261 /* Search end of list */
262 for (; *rr; rr = &(*rr)->li_next)
263 ;
264 }
265# endif
266 if (ip4 && !error) {
267 /* Append IPv4 addresses */
268 error = localinfo4(hh, rr);
269 }
270#endif
271
272 if (ip6) {
273 /* Required to make compiler happy */
274 }
275 if (!result)
276 error = ELI_NOADDRESS;
277
278 if (!error)
279 li_sort(result, return_localinfo);
280 else
281 su_freelocalinfo(result);
282
283 return error;
284}
285
286#endif
287
288/** Free local address information.
289 *
290 * Free a list of su_localinfo_t structures obtained with su_getlocalinfo()
291 * or su_copylocalinfo() along with socket addresses and strings associated
292 * with them.
293 *
294 * @sa su_getlocalinfo(), su_copylocalinfo(), #su_localinfo_t
295 */
296void su_freelocalinfo(su_localinfo_t *tbf)
297{
298 su_localinfo_t *li;
299
300 for (li = tbf; li; li = tbf) {
301 tbf = li->li_next;
302 if (li->li_canonname)
303 free(li->li_canonname);
304 free(li);
305 }
306}
307
308/** Describe su_localinfo errors.
309 *
310 * The function su_gli_strerror() returns a string describing the error
311 * condition indicated by the code that was returned by the function
312 * su_getlocalinfo().
313 *
314 * @param error error code returned by su_getlocalinfo()
315 *
316 * @return
317 * A pointer to string describing the error condition.
318 */
319char const *su_gli_strerror(int error)
320{
321 switch (error) {
322 case ELI_NOERROR: return "No error";
323 case ELI_NOADDRESS: return "No matching address";
324 case ELI_MEMORY: return "Memory allocation error";
325 case ELI_FAMILY: return "Unknown address family";
326 case ELI_RESOLVER: return "Error when resolving address";
327 case ELI_SYSTEM: return "System error";
328 case ELI_BADHINTS: return "Invalid value for hints";
329 default: return "Unknown error";
330 }
331}
332
333/** Duplicate su_localinfo structure.
334 */
335su_localinfo_t *su_copylocalinfo(su_localinfo_t const *li0)
336{
337 size_t n;
338 su_localinfo_t *li, *retval = NULL((void*)0), **lli = &retval;
339
340# define SLEN(s)((s) ? strlen(s) + 1 : 0) ((s) ? strlen(s) + 1 : 0)
341
342 for (; li0 ; li0 = li0->li_next) {
343 n = sizeof(*li0) + li0->li_addrlen + SLEN(li0->li_ifname)((li0->li_ifname) ? strlen(li0->li_ifname) + 1 : 0);
344 if (!(li = calloc(1, n))) {
345 su_freelocalinfo(retval);
346 return NULL((void*)0);
347 }
348 *lli = li;
349 lli = &li->li_next;
350 li->li_flags = li0->li_flags;
351 li->li_family = li0->li_family;
352 li->li_index = li0->li_index;
353 li->li_scope = li0->li_scope;
354 li->li_addrlen = li0->li_addrlen;
355 li->li_addr = memcpy(li + 1, li0->li_addr, li0->li_addrlen);
356
357 if (li0->li_canonname) {
358 if (!(li->li_canonname = malloc(SLEN(li0->li_canonname)((li0->li_canonname) ? strlen(li0->li_canonname) + 1 : 0
)
))) {
359 su_freelocalinfo(retval);
360 return NULL((void*)0);
361 }
362 strcpy(li->li_canonname, li0->li_canonname);
363 }
364
365 if (li0->li_ifname)
366 li->li_ifname = strcpy(li->li_addrlen + (char *)li->li_addr,
367 li0->li_ifname);
368 }
369
370 return retval;
371}
372
373
374/** Return IPv4 address scope */
375static int
376li_scope4(uint32_t ip4)
377{
378 ip4 = ntohl(ip4);
379
380 if (0x7f000000 == (ip4 & 0xff000000))
381 return LI_SCOPE_HOST;
382 /* draft-ietf-zeroconf-ipv4-linklocal-02.txt - 169.254/16. */
383 else if (0xa9fe0000 == (ip4 & 0xffff0000))
384 return LI_SCOPE_LINK;
385 /* RFC1918 - 10/8, 172.16/12, 192.168/16. */
386 else if (0x0a000000 == (ip4 & 0xff000000) ||
387 0xac100000 == (ip4 & 0xfff00000) ||
388 0xc0a80000 == (ip4 & 0xffff0000))
389 return LI_SCOPE_SITE;
390 else
391 return LI_SCOPE_GLOBAL;
392}
393
394#if SU_HAVE_IN61
395
396#if HAVE_WINSOCK2_H
397#define IN6_IS_ADDR_LOOPBACK SU_IN6_IS_ADDR_LOOPBACK
398su_inlinestatic inline int
399IN6_IS_ADDR_LOOPBACK(void const *ip6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (void const *ip6); __a->__in6_u.__u6_addr32[0] == 0 &&
__a->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u
.__u6_addr32[2] == 0 && __a->__in6_u.__u6_addr32[3
] == htonl (1); }))
400{
401 uint8_t const *u = ip6;
402
403 return
404 u[0] == 0 && u[1] == 0 && u[2] == 0 && u[3] == 0 &&
405 u[4] == 0 && u[5] == 0 && u[6] == 0 && u[7] == 0 &&
406 u[8] == 0 && u[9] == 0 && u[10] == 0 && u[11] == 0 &&
407 u[12] == 0 && u[13] == 0 && u[14] == 0 && u[15] == 1;
408}
409#endif
410
411/** Return IPv6 address scope */
412static int
413li_scope6(struct in6_addr const *ip6)
414{
415 if (IN6_IS_ADDR_V4MAPPED(ip6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (ip6); __a->__in6_u.__u6_addr32[0] == 0 && __a
->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u.__u6_addr32
[2] == htonl (0xffff); }))
|| IN6_IS_ADDR_V4COMPAT(ip6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (ip6); __a->__in6_u.__u6_addr32[0] == 0 && __a
->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u.__u6_addr32
[2] == 0 && ntohl (__a->__in6_u.__u6_addr32[3]) >
1; }))
) {
416 uint32_t *u = (uint32_t *)(ip6->s6_addr__in6_u.__u6_addr8 + 12);
417
418 uint32_t ip4 = *u;
419 return li_scope4(ip4);
420 }
421 else if (IN6_IS_ADDR_LOOPBACK(ip6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (ip6); __a->__in6_u.__u6_addr32[0] == 0 && __a
->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u.__u6_addr32
[2] == 0 && __a->__in6_u.__u6_addr32[3] == htonl (
1); }))
)
422 return LI_SCOPE_HOST;
423 else if (IN6_IS_ADDR_LINKLOCAL(ip6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (ip6); (__a->__in6_u.__u6_addr32[0] & htonl (0xffc00000
)) == htonl (0xfe800000); }))
)
424 return LI_SCOPE_LINK;
425 else if (IN6_IS_ADDR_SITELOCAL(ip6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (ip6); (__a->__in6_u.__u6_addr32[0] & htonl (0xffc00000
)) == htonl (0xfec00000); }))
)
426 return LI_SCOPE_SITE;
427 else
428 return LI_SCOPE_GLOBAL;
429}
430#endif
431
432/** Return the scope of address in the sockaddr structure */
433int su_sockaddr_scope(su_sockaddr_t const *su, socklen_t sulen)
434{
435 if (sulen >= (sizeof su->su_sin) && su->su_familysu_sa.sa_family == AF_INET2)
436 return li_scope4(su->su_sin.sin_addr.s_addr);
437
438#if SU_HAVE_IN61
439 if (sulen >= (sizeof su->su_sin6) && su->su_familysu_sa.sa_family == AF_INET610)
440 return li_scope6(&su->su_sin6.sin6_addr);
441#endif
442
443 return 0;
444}
445
446#if HAVE_OPEN_C
447extern int su_get_local_ip_addr(su_sockaddr_t *su);
448#endif
449
450#if SU_LOCALINFO_TEST
451
452#elif USE_LOCALINFO01
453/* no localinfo4 */
454#elif HAVE_IFCONF1
455#if __APPLE_CC__
456/** Build a list of local IPv4 addresses and append it to *rresult. */
457static
458int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
459{
460 su_localinfo_t *li = NULL((void*)0);
461 su_sockaddr_t *su;
462 int error = ELI_NOADDRESS;
463 char *canonname = NULL((void*)0);
464 su_socket_t s;
465
466#if SU_HAVE_IN61
467 int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0;
468#else
469 int const su_xtra = 0;
470#endif
471
472 struct ifconf ifc;
473 int numifs;
474 char *buffer;
475 struct ifreq *ifr, *ifr_next;
476
477 su_sockaddr_t *sa;
478 socklen_t salen = sizeof(*sa);
479 int scope = 0, gni_flags = 0;
480
481 s = su_socket(AF_INET2, SOCK_DGRAMSOCK_DGRAM, 0);
482 if (s == -1) {
483 SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 484, "su_localinfo: su_socket failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
484 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 484, "su_localinfo: su_socket failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
485 return ELI_SYSTEM;
486 }
487
488
489 li = calloc(1, (sizeof *li) + (sizeof *sa));
490 sa = (void *)(li + 1);
491
492 error = getsockname(s, (struct sockaddr *) sa, &salen);
493 if (error < 0 && errno(*__errno_location ()) == SOCKET_ERRORSOCKET_ERROR) {
494 SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 495, "%s: getsockname() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
495 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 495, "%s: getsockname() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
;
496 }
497
498 error = bind(s, (struct sockaddr *) sa, salen);
499
500 if (error < 0) {
501 SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 502, "%s: bind() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
502 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 502, "%s: bind() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
;
503 goto err;
504 }
505
506 su_close(s);
507
508 scope = li_scope4(sa->su_sin.sin_addr.s_addr);
509
510 if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
511 gni_flags = NI_NUMERICHOST1;
512
513 if (su_xtra) {
514 /* Map IPv4 address to IPv6 address */
515 memset(sa, 0, sizeof(*sa));
516 sa->su_familysu_sa.sa_family = AF_INET610;
517 ((int32_t*)&sa->su_sin6.sin6_addr)[3] = sa->su_sin.sin_addr.s_addr;
518 ((int32_t*)&sa->su_sin6.sin6_addr)[2] = htonl(0xffff);
519 }
520
521 li->li_family = sa->su_familysu_sa.sa_family;
522 li->li_scope = scope;
523 li->li_index = 0;
524 li->li_addrlen = su_sockaddr_size(sa)((socklen_t)((sa)->su_sa.sa_family == 2 ? sizeof((sa)->
su_sin) : ((sa)->su_sa.sa_family == 10 ? sizeof((sa)->su_sin6
) : sizeof(*sa))))
;
525 li->li_addr = sa;
526
527 if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
528 goto err;
529
530 if (canonname) {
531 if (strchr(canonname, ':') ||
532 strspn(canonname, "0123456789.") == strlen(canonname))
533 li->li_flags |= LI_NUMERIC;
534 }
535 else
536 li->li_flags = 0;
537
538 li->li_canonname = canonname;
539
540 canonname = NULL((void*)0);
541
542 *rresult = li;
543 return 0;
544
545err:
546 if (canonname) free(canonname);
547 if (li) free(li);
548 su_close(s);
549
550 return error;
551}
552#else /* !__APPLE_CC__ */
553/** Build a list of local IPv4 addresses and append it to *rresult. */
554static
555int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
556{
557 su_localinfo_t *tbf = NULL((void*)0), **lli = &tbf;
558 su_localinfo_t *li = NULL((void*)0), *li_first = NULL((void*)0);
559 su_sockaddr_t *su;
560 int error = ELI_NOADDRESS;
561 char *canonname = NULL((void*)0);
562 su_socket_t s;
563
564#if SU_HAVE_IN61
565 int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0;
566#else
567 int const su_xtra = 0;
568#endif
569
570 struct ifconf ifc;
571 int numifs;
572 char *buffer;
573 struct ifreq *ifr, *ifr_next;
574
575#if HAVE_OPEN_C
576 su_sockaddr_t *sa;
577 socklen_t salen = sizeof(*sa);
578#endif
579
580 s = su_socket(AF_INET2, SOCK_DGRAMSOCK_DGRAM, 0);
581 if (s == -1) {
582 SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 583, "su_localinfo: su_socket failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
583 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 583, "su_localinfo: su_socket failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
584 return ELI_SYSTEM;
585 }
586
587# if HAVE_IFNUM
588 /* Get the list of known IP address from the kernel */
589 if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) {
590 /* can't get number of interfaces -- fall back */
591 SU_DEBUG_1(("su_localinfo: SIOCGIFNUM failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 592, "su_localinfo: SIOCGIFNUM failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
592 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 592, "su_localinfo: SIOCGIFNUM failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
593 error = ELI_SYSTEM;
594 goto err;
595 }
596
597 SU_DEBUG_9(("su_localinfo: %d active interfaces according to SIOCGIFNUM\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 9 ? (_su_llog((su_log_global
), 9, "su_localinfo.c", (const char *)__func__, 598, "su_localinfo: %d active interfaces according to SIOCGIFNUM\n"
, numifs)) : (void)0)
598 numifs))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 9 ? (_su_llog((su_log_global
), 9, "su_localinfo.c", (const char *)__func__, 598, "su_localinfo: %d active interfaces according to SIOCGIFNUM\n"
, numifs)) : (void)0)
;
599
600 if (numifs < 0)
601# endif
602 /* Default to 64 interfaces. Enough? */
603 numifs = 64;
604
605 if (numifs == 0)
606 return 0;
607
608 /*
609 * Allocate memory for SIOCGIFCONF ioctl buffer. This memory block is also
610 * used as li_first, first localinfo struct that is returned, so it can be
611 * freed by freelocalinfo() without any complications.
612 */
613 ifc.ifc_len = numifs * sizeof (struct ifreq);
614 buffer = malloc(sizeof(su_localinfo_t) + ifc.ifc_len + su_xtra);
615 if (!buffer) {
616 SU_DEBUG_1(("su_localinfo: memory exhausted\n" VA_NONE))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 616, "su_localinfo: memory exhausted\n"
"%s", "")) : (void)0)
;
617 error = ELI_MEMORY;
618 goto err;
619 }
620
621 li_first = (su_localinfo_t *)buffer;
622 memset(li_first, 0, sizeof(su_localinfo_t) + su_xtra);
623 ifc.ifc_bufifc_ifcu.ifcu_buf = buffer + sizeof(su_localinfo_t) + su_xtra;
624#if HAVE_OPEN_C
625 if (ioctl(s, SIOCGIFACTIVECONF, (char *)&ifc) < 0) {
626 SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 627, "su_localinfo: SIOCGIFCONF failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
627 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 627, "su_localinfo: SIOCGIFCONF failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
628 error = ELI_SYSTEM;
629 goto err;
630 }
631#else
632 if (ioctl(s, SIOCGIFCONF0x8912, (char *)&ifc) < 0) {
633 SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 634, "su_localinfo: SIOCGIFCONF failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
634 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 634, "su_localinfo: SIOCGIFCONF failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
635 error = ELI_SYSTEM;
636 goto err;
637 }
638#endif
639
640 buffer = ifc.ifc_bufifc_ifcu.ifcu_buf + ifc.ifc_len;
641
642 for (ifr = ifc.ifc_reqifc_ifcu.ifcu_req;
643 (void *)ifr < (void *)buffer;
644 ifr = ifr_next) {
645 struct ifreq ifreq[1];
646 int scope, if_index, flags = 0, gni_flags = 0;
647 char *if_name;
648#if SU_HAVE_IN61
649 su_sockaddr_t su2[1];
650#endif
651
652#if SA_LEN
653 if (ifr->ifr_addrifr_ifru.ifru_addr.sa_len > sizeof(ifr->ifr_addrifr_ifru.ifru_addr))
654 ifr_next = (struct ifreq *)
655 (ifr->ifr_addrifr_ifru.ifru_addr.sa_len + (char *)(&ifr->ifr_addrifr_ifru.ifru_addr));
656 else
657#else
658 ifr_next = ifr + 1;
659#endif
660
661 if_name = ifr->ifr_nameifr_ifrn.ifrn_name;
662
663#if defined(SIOCGIFINDEX0x8933)
664 ifreq[0] = *ifr;
665 if (ioctl(s, SIOCGIFINDEX0x8933, ifreq) < 0) {
666 SU_DEBUG_1(("su_localinfo: SIOCGIFINDEX failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 667, "su_localinfo: SIOCGIFINDEX failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
667 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 667, "su_localinfo: SIOCGIFINDEX failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
668 error = ELI_SYSTEM;
669 goto err;
670 }
671#if HAVE_IFR_INDEX
672 if_index = ifreq->ifr_index;
673#elif HAVE_IFR_IFINDEX1
674 if_index = ifreq->ifr_ifindexifr_ifru.ifru_ivalue;
675#else
676#error Unknown index field in struct ifreq
677#endif
678
679#else
680#warning su_localinfo() cannot map interface name to number
681 if_index = 0;
682#endif
683
684 SU_DEBUG_9(("su_localinfo: if %s with index %d\n", if_name, if_index))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 9 ? (_su_llog((su_log_global
), 9, "su_localinfo.c", (const char *)__func__, 684, "su_localinfo: if %s with index %d\n"
, if_name, if_index)) : (void)0)
;
685
686
687#if HAVE_OPEN_C
688 su_close(s);
689
690 li = calloc(1, sizeof(su_localinfo_t));
691 sa = calloc(1, sizeof(su_sockaddr_t));
692
693 if (su_get_local_ip_addr(sa) < 0)
694 goto err;
695
696 li->li_family = sa->su_familysu_sa.sa_family;
697 li->li_scope = LI_SCOPE_GLOBAL /* scope */;
698 li->li_index = if_index;
699 li->li_addrlen = su_sockaddr_size(sa)((socklen_t)((sa)->su_sa.sa_family == 2 ? sizeof((sa)->
su_sin) : ((sa)->su_sa.sa_family == 10 ? sizeof((sa)->su_sin6
) : sizeof(*sa))))
;
700 li->li_addr = sa;
701
702 if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
703 goto err;
704
705 if (canonname) {
706 if (strchr(canonname, ':') ||
707 strspn(canonname, "0123456789.") == strlen(canonname))
708 li->li_flags |= LI_NUMERIC;
709 }
710 else
711 li->li_flags = 0;
712
713 li->li_canonname = canonname;
714
715 canonname = NULL((void*)0);
716
717 *rresult = li;
718
719 return 0;
720#endif
721
722#if defined(SIOCGIFFLAGS0x8913)
723 ifreq[0] = *ifr;
724 if (ioctl(s, SIOCGIFFLAGS0x8913, ifreq) < 0) {
725 SU_DEBUG_1(("su_localinfo: SIOCGIFFLAGS failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 726, "su_localinfo: SIOCGIFFLAGS failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
726 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 726, "su_localinfo: SIOCGIFFLAGS failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
727 error = ELI_SYSTEM;
728 goto err;
729 }
730 /* Do not include interfaces that are down unless explicitly asked */
731 if ((ifreq->ifr_flagsifr_ifru.ifru_flags & IFF_UPIFF_UP) == 0 && (hints->li_flags & LI_DOWN) == 0) {
732 SU_DEBUG_9(("su_localinfo: if %s with index %d is down\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 9 ? (_su_llog((su_log_global
), 9, "su_localinfo.c", (const char *)__func__, 733, "su_localinfo: if %s with index %d is down\n"
, if_name, if_index)) : (void)0)
733 if_name, if_index))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 9 ? (_su_llog((su_log_global
), 9, "su_localinfo.c", (const char *)__func__, 733, "su_localinfo: if %s with index %d is down\n"
, if_name, if_index)) : (void)0)
;
734 continue;
735 }
736#elif defined(SIOCGIFACTIVECONF)
737/* Handled above in SIOCGIFACTIVECONF vs. SIOCGIFCONF*/
738#else
739#error su_localinfo() cannot determine interface status
740#endif
741
742#if 0
743 *ifreq = *ifr;
744 ifreq->ifr_addrifr_ifru.ifru_addr.sa_family = AF_INET2;
745 if (ioctl(s, SIOCGIFADDR0x8915, ifreq) < 0) {
746 SU_DEBUG_1(("su_localinfo: SIOCGIFADDR failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 747, "su_localinfo: SIOCGIFADDR failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
747 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 747, "su_localinfo: SIOCGIFADDR failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
748 error = ELI_SYSTEM;
749 goto err;
750 }
751 ifr->ifr_addrifr_ifru.ifru_addr = ifreq->ifr_addrifr_ifru.ifru_addr;
752#endif
753
754 su = (su_sockaddr_t *)&ifr->ifr_addrifr_ifru.ifru_addr;
755
756 if (SU_HAS_INADDR_ANY(su)((su)->su_sa.sa_family == 2 ? ((su)->su_sin.sin_addr.s_addr
== ((in_addr_t) 0x00000000)) : ((su)->su_sa.sa_family == 10
? (memcmp(&(su)->su_sin6.sin6_addr, (&in6addr_any
), sizeof(*(&in6addr_any))) == 0) : 0))
)
757 continue;
758
759 scope = li_scope4(su->su_sin.sin_addr.s_addr);
760
761 if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
762 (hints->li_ifname && strcmp(hints->li_ifname, if_name) != 0) ||
763 (hints->li_index && hints->li_index != if_index))
764 continue;
765
766#if SU_HAVE_IN61
767 if (su_xtra) {
768 /* Map IPv4 address to IPv6 address */
769 memset(su2, 0, sizeof(*su2));
770 su2->su_familysu_sa.sa_family = AF_INET610;
771 ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
772 ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
773 su = su2;
774 }
775#endif
776
777 if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
778 gni_flags = NI_NUMERICHOST1;
779
780 if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
781 goto err;
782 else if (error > 0)
783 continue;
784
785 if (canonname)
786 if (strchr(canonname, ':') ||
787 strspn(canonname, "0123456789.") == strlen(canonname))
788 flags |= LI_NUMERIC;
789
790 if (li_first)
791 li = li_first; /* Use li_first with all ifr structs to be freed */
792 else if (!(li = calloc(1, (sizeof *li) + su_xtra))) {
793 error = ELI_MEMORY;
794 goto err;
795 }
796 if (!tbf) tbf = li;
797 *lli = li; lli = &li->li_next;
798
799 if (su_xtra)
800 su = (su_sockaddr_t *)memcpy(li + 1, su, su_xtra);
801
802 li->li_flags = flags;
803 li->li_family = su->su_familysu_sa.sa_family;
804 li->li_scope = scope;
805 li->li_index = if_index;
806 li->li_addrlen = su_sockaddr_size(su)((socklen_t)((su)->su_sa.sa_family == 2 ? sizeof((su)->
su_sin) : ((su)->su_sa.sa_family == 10 ? sizeof((su)->su_sin6
) : sizeof(*su))))
;
807 li->li_addr = su;
808 li->li_canonname = canonname;
809 li->li_ifname = if_name;
810
811 canonname = NULL((void*)0);
812 li_first = NULL((void*)0);
813 }
814
815 if (canonname) free(canonname);
816 if (li_first) free(li_first);
817 su_close(s);
818
819 if (tbf) *rresult = tbf;
820 return 0;
821
822err:
823 if (canonname) free(canonname);
824 if (li_first) free(li_first);
825 su_freelocalinfo(tbf);
826 su_close(s);
827
828 return error;
829}
830#endif /* __APPLE_CC__ */
831#else
832static
833int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
834{
835 /* Kikka #3: resolve hostname */
836 char hostname[SU_MAXHOST(1025)] = "";
837 char *name, *ifname;
838 struct hostent *h;
839 int i, flags, error, gni_flags = 0;
840 su_localinfo_t *tbf = NULL((void*)0);
841 su_localinfo_t *li = NULL((void*)0), **lli = &tbf;
842 su_sockaddr_t *su;
843#if SU_HAVE_IN61
844 socklen_t su_sockaddr_sizeSU_SOCKADDR_SIZE =
845 (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : sizeof(struct sockaddr_in);
846 flags = hints->li_flags & (LI_V4MAPPED|LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
847#else
848 socklen_t su_sockaddr_sizeSU_SOCKADDR_SIZE = sizeof(struct sockaddr_in);
849 flags = hints->li_flags & (LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
850#endif
851
852 error = ELI_NOERROR;
853
854 if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {
855 if (hints->li_canonname)
856 name = hints->li_canonname;
857 else if (gethostname(name = hostname, sizeof(hostname)) != 0)
858 return ELI_SYSTEM;
859
860 h = gethostbyname(name);
861
862 if (name)
863 if (strchr(name, ':') ||
864 strspn(name, "0123456789.") == strlen(name))
865 flags |= LI_NUMERIC;
866
867 for (i = 0; h && h->h_addr_list[i]; i++) {
868 if ((li = calloc(1, sizeof(*li) + su_sockaddr_sizeSU_SOCKADDR_SIZE)) == NULL((void*)0)) {
869 error = ELI_MEMORY;
870 goto err;
871 }
872 li->li_flags = flags;
873
874 li->li_scope = li_scope4(*(uint32_t *)h->h_addr_list[i]);
875 if (li->li_scope == LI_SCOPE_HOST)
876 li->li_index = 1, ifname = "lo";
877 else
878 li->li_index = 2, ifname = "eth";
879
880 li->li_addrlen = su_sockaddr_sizeSU_SOCKADDR_SIZE;
881 li->li_addr = su = (su_sockaddr_t *)(li + 1);
882 su->su_familysu_sa.sa_family = li->li_family =
883 li->li_flags & LI_V4MAPPED ? AF_INET610 : AF_INET2;
884
885#if SU_HAVE_IN61
886 if (li->li_flags & LI_V4MAPPED) {
887 ((int32_t*)&su->su_sin6.sin6_addr)[2] = htonl(0xffff);
888 memcpy(&((int32_t*)&su->su_sin6.sin6_addr)[3],
889 h->h_addr_list[i], h->h_length);
890 }
891 else
892#endif
893 memcpy(&su->su_sin.sin_addr.s_addr, h->h_addr_list[i], h->h_length);
894 if (li->li_flags & LI_IFNAME)
895 li->li_ifname = ifname;
896 if (li->li_scope == LI_SCOPE_HOST || li->li_scope == LI_SCOPE_LINK)
897 gni_flags = NI_NUMERICHOST1;
898 if ((error = li_name(hints, gni_flags, su, &li->li_canonname)) < 0)
899 goto err;
900 else if (error > 0) {
901 free(li); li = NULL((void*)0); continue;
902 } else
903 error = ELI_NOADDRESS;
904 *lli = li; lli = &li->li_next; li = NULL((void*)0);
905 }
906 }
907
908 if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_HOST)) {
909 if ((li = calloc(1, sizeof(*li) + su_sockaddr_sizeSU_SOCKADDR_SIZE)) == NULL((void*)0)) {
910 error = ELI_MEMORY;
911 goto err;
912 }
913 li->li_flags = hints->li_flags &
914 (LI_V4MAPPED|LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
915 li->li_scope = LI_SCOPE_HOST, li->li_index = 1;
916 if (li->li_flags & LI_IFNAME)
917 li->li_ifname = "lo";
918 li->li_addrlen = su_sockaddr_sizeSU_SOCKADDR_SIZE;
919 li->li_addr = su = (su_sockaddr_t *)(li + 1);
920#if SU_HAVE_IN61
921 if (li->li_flags & LI_V4MAPPED) {
922 su->su_familysu_sa.sa_family = li->li_family = AF_INET610;
923 ((int32_t*)&su->su_sin6.sin6_addr)[2] = htonl(0xffff);
924 ((int32_t*)&su->su_sin6.sin6_addr)[3] = htonl(0x7f000001);
925 }
926 else
927#endif
928 su->su_familysu_sa.sa_family = li->li_family = AF_INET2,
929 su->su_sin.sin_addr.s_addr = htonl(0x7f000001);
930
931 if ((error = li_name(hints, NI_NUMERICHOST1, su, &li->li_canonname)) < 0) {
932 goto err;
933 } else if (error > 0) {
934 free(li); li = NULL((void*)0);
935 } else {
936 *lli = li; lli = &li->li_next; li = NULL((void*)0);
937 }
938 }
939
940 *rresult = tbf;
941
942 return 0;
943
944err:
945 if (li) su_freelocalinfo(li);
946 su_freelocalinfo(tbf);
947
948 return error;
949}
950
951#endif
952
953#if USE_LOCALINFO01 || !SU_HAVE_IN61 || SU_LOCALINFO_TEST
954/* No localinfo6() */
955#elif HAVE_PROC_NET_IF_INET61
956/** Build a list of local IPv6 addresses and append it to *return_result. */
957static
958int localinfo6(su_localinfo_t const *hints, su_localinfo_t **return_result)
959{
960 su_localinfo_t *li = NULL((void*)0);
961 su_sockaddr_t su[1] = {{ 0 }}, *addr;
962 int error = ELI_NOADDRESS;
963 char *canonname = NULL((void*)0);
964 char line[80];
965 FILE *f;
966
967 if ((f = fopen("/proc/net/if_inet6", "r"))) {
968 for (;error;) {
969 struct in6_addr in6;
970 unsigned if_index, prefix_len, scope, flags;
971 int addrlen, if_namelen;
972 char ifname[16];
973
974 if (!fgets(line, sizeof(line), f)) {
975 if (feof(f))
976 error = ELI_NOERROR;
977 break;
978 }
979
980 if (sscanf(line, "%08x%08x%08x%08x %2x %2x %2x %02x %016s\n",
981 &in6.s6_addr32__in6_u.__u6_addr32[0],
982 &in6.s6_addr32__in6_u.__u6_addr32[1],
983 &in6.s6_addr32__in6_u.__u6_addr32[2],
984 &in6.s6_addr32__in6_u.__u6_addr32[3],
985 &if_index, &prefix_len, &scope, &flags, ifname) != 9)
986 break;
987
988 flags = 0;
989
990 /* Fix global scope (it is 0) */
991 if (!scope) scope = LI_SCOPE_GLOBAL;
992
993 in6.s6_addr32__in6_u.__u6_addr32[0] = htonl(in6.s6_addr32__in6_u.__u6_addr32[0]);
994 in6.s6_addr32__in6_u.__u6_addr32[1] = htonl(in6.s6_addr32__in6_u.__u6_addr32[1]);
995 in6.s6_addr32__in6_u.__u6_addr32[2] = htonl(in6.s6_addr32__in6_u.__u6_addr32[2]);
996 in6.s6_addr32__in6_u.__u6_addr32[3] = htonl(in6.s6_addr32__in6_u.__u6_addr32[3]);
997
998 if (IN6_IS_ADDR_V4MAPPED(&in6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&in6); __a->__in6_u.__u6_addr32[0] == 0 &&
__a->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u
.__u6_addr32[2] == htonl (0xffff); }))
|| IN6_IS_ADDR_V4COMPAT(&in6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&in6); __a->__in6_u.__u6_addr32[0] == 0 &&
__a->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u
.__u6_addr32[2] == 0 && ntohl (__a->__in6_u.__u6_addr32
[3]) > 1; }))
) {
999 uint32_t ip4 = *(uint32_t *)(in6.s6_addr__in6_u.__u6_addr8 + 12);
1000 scope = li_scope4(ip4);
1001 }
1002
1003 if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
1004 (hints->li_index && hints->li_index != if_index) ||
1005 (hints->li_ifname && strcmp(hints->li_ifname, ifname) != 0))
1006 continue;
1007
1008 su->su_familysu_sa.sa_family = AF_INET610;
1009 su->su_sin6.sin6_addr = in6;
1010
1011 addrlen = su_sockaddr_size(su)((socklen_t)((su)->su_sa.sa_family == 2 ? sizeof((su)->
su_sin) : ((su)->su_sa.sa_family == 10 ? sizeof((su)->su_sin6
) : sizeof(*su))))
;
1012
1013 if ((error = li_name(hints, 0, su, &canonname)) < 0)
1014 break;
1015 else if (error > 0)
1016 continue;
1017 else
1018 error = ELI_NOADDRESS;
1019
1020 if (canonname &&
1021 (strchr(canonname, ':') ||
1022 strspn(canonname, "0123456789.") == strlen(canonname)))
1023 flags |= LI_NUMERIC;
1024
1025 if (hints->li_flags & LI_IFNAME)
1026 if_namelen = strlen(ifname) + 1;
1027 else
1028 if_namelen = 0;
1029
1030 if ((li = calloc(1, sizeof *li + addrlen + if_namelen)) == NULL((void*)0)) {
1031 error = ELI_MEMORY;
1032 break;
1033 }
1034 addr = (su_sockaddr_t*)memcpy((li + 1), su, addrlen);
1035 *return_result = li; return_result = &li->li_next;
1036
1037 li->li_flags = flags;
1038 li->li_family = AF_INET610;
1039 li->li_scope = scope;
1040 li->li_index = if_index;
1041 li->li_addr = addr;
1042 li->li_addrlen = addrlen;
1043 li->li_canonname = canonname;
1044 if (if_namelen)
1045 li->li_ifname = memcpy(addrlen + (char *)addr, ifname, if_namelen);
1046
1047 canonname = NULL((void*)0);
1048 }
1049
1050 fclose(f);
1051 }
1052
1053 if (canonname)
1054 free(canonname);
1055
1056 return error;
1057}
1058#else
1059/* Use HOSTADDR6 */
1060static
1061int localinfo6(su_localinfo_t const *hints, su_localinfo_t **rresult)
1062{
1063 char *addr, *ifname;
1064 int flags, error;
1065 su_localinfo_t *li = NULL((void*)0);
1066 su_sockaddr_t *su;
1067 int const su_sockaddr_sizeSU_SOCKADDR_SIZE = sizeof(*su);
1068
1069 error = ELI_NOADDRESS;
1070
1071#if defined(__APPLE_CC__)
1072 {
1073 su_sockaddr_t *sa;
1074 int salen = sizeof(*sa);
1075 int s;
1076
1077 if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {
1078 if ((addr = getenv("HOSTADDR6"))) {
1079
1080 li = calloc(1, sizeof(su_localinfo_t));
1081 sa = calloc(1, sizeof(su_sockaddr_t));
1082
1083 sa->su_familysu_sa.sa_family = AF_INET610;
1084 if (su_inet_ptoninet_pton(AF_INET610, addr, &sa->su_sin6.sin6_addr) <= 0)
1085 goto err;
1086
1087 s = su_socket(AF_INET610, SOCK_DGRAMSOCK_DGRAM, 0);
1088 if (s == -1) {
1089 SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1090, "su_localinfo: su_socket failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
1090 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1090, "su_localinfo: su_socket failed: %s\n"
, su_strerror(su_errno()))) : (void)0)
;
1091 return ELI_SYSTEM;
1092 }
1093
1094 error = getsockname(s, (struct sockaddr *) sa, &salen);
1095 if (error < 0 && errno(*__errno_location ()) == SOCKET_ERRORSOCKET_ERROR) {
1096 SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1097, "%s: getsockname() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
1097 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1097, "%s: getsockname() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
;
1098 }
1099
1100 error = bind(s, (struct sockaddr *) sa, salen);
1101
1102 if (error < 0) {
1103 SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1104, "%s: bind() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
1104 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1104, "%s: bind() failed: %s\n"
, __func__, su_strerror(su_errno()))) : (void)0)
;
1105 goto err;
1106 }
1107
1108 su_close(s);
1109
1110 li->li_family = sa->su_familysu_sa.sa_family;
1111 li->li_scope = LI_SCOPE_GLOBAL;
1112 li->li_index = 0;
1113 li->li_addrlen = su_sockaddr_size(sa)((socklen_t)((sa)->su_sa.sa_family == 2 ? sizeof((sa)->
su_sin) : ((sa)->su_sa.sa_family == 10 ? sizeof((sa)->su_sin6
) : sizeof(*sa))))
;
1114 li->li_addr = sa;
1115
1116 if ((error = li_name(hints, NI_NUMERICHOST1, sa, &li->li_canonname)) < 0)
1117 goto err;
1118
1119 li->li_flags = NI_NUMERICHOST1;
1120 }
1121 }
1122
1123 *rresult = li;
1124 return 0;
1125 }
1126#endif
1127
1128
1129 if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) {
1130 if ((addr = getenv("HOSTADDR6"))) {
1131 flags = hints->li_flags & (LI_CANONNAME|LI_NUMERIC|LI_IFNAME);
1132
1133 if ((li = calloc(1, sizeof(*li) + su_sockaddr_sizeSU_SOCKADDR_SIZE)) == NULL((void*)0)) {
1134 error = ELI_MEMORY;
1135 goto err;
1136 }
1137 li->li_flags = flags;
1138 li->li_scope = LI_SCOPE_GLOBAL, li->li_index = 2, ifname = "eth";
1139 li->li_addrlen = sizeof(*su);
1140 li->li_addr = su = (su_sockaddr_t *)(li + 1);
1141 su->su_familysu_sa.sa_family = li->li_family = AF_INET610;
1142 if (su_inet_ptoninet_pton(AF_INET610, addr, &su->su_sin6.sin6_addr) <= 0)
1143 goto err;
1144 if (li->li_flags & LI_IFNAME)
1145 li->li_ifname = ifname;
1146 if ((error = li_name(hints, NI_NUMERICHOST1, su, &li->li_canonname)) < 0)
1147 goto err;
1148 else if (error > 0) {
1149 free(li); li = NULL((void*)0);
1150 }
1151 }
1152 }
1153
1154 *rresult = li;
1155
1156 return 0;
1157
1158err:
1159 if (li) su_freelocalinfo(li);
1160 return error;
1161}
1162#endif
1163
1164#if !USE_LOCALINFO01
1165/* no localinfo0() or bsd_localinfo() */
1166#elif HAVE_GETIFADDRS1
1167
1168#include <ifaddrs.h>
1169
1170static
1171int bsd_localinfo(su_localinfo_t const hints[1],
1172 su_localinfo_t **return_result)
1173{
1174 struct ifaddrs *ifa, *results;
1175 int error = 0;
1176#if SU_HAVE_IN61
1177 int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
1178#endif
1179 char *canonname = NULL((void*)0);
1180
1181 if (getifaddrs(&results) < 0) {
1182 if (errno(*__errno_location ()) == ENOMEM12)
1183 return ELI_MEMORY;
1184 else
1185 return ELI_SYSTEM;
1186 }
1187
1188 for (ifa = results; ifa; ifa = ifa->ifa_next) {
1189 su_localinfo_t *li;
1190 su_sockaddr_t *su;
1191#if SU_HAVE_IN61
1192 su_sockaddr_t su2[1];
1193#endif
1194 socklen_t sulen;
1195 int scope, flags = 0, gni_flags = 0, if_index = 0;
1196 char const *ifname = 0;
1197 size_t ifnamelen = 0;
1198
1199 /* no ip address from if that is down */
1200 if ((ifa->ifa_flags & IFF_UPIFF_UP) == 0 && (hints->li_flags & LI_DOWN) == 0)
1201 continue;
1202
1203 su = (su_sockaddr_t *)ifa->ifa_addr;
1204
1205 if (!su)
1206 continue;
1207
1208 if (su->su_familysu_sa.sa_family == AF_INET2) {
1209 sulen = sizeof(su->su_sin);
1210 scope = li_scope4(su->su_sin.sin_addr.s_addr);
1211#if SU_HAVE_IN61
1212 if (v4_mapped)
1213 sulen = sizeof(su->su_sin6);
1214#endif
1215 }
1216#if SU_HAVE_IN61
1217 else if (su->su_familysu_sa.sa_family == AF_INET610) {
1218 if (IN6_IS_ADDR_MULTICAST(&su->su_sin6.sin6_addr)(((const uint8_t *) (&su->su_sin6.sin6_addr))[0] == 0xff
)
)
1219 continue;
1220 sulen = sizeof(su->su_sin6);
1221 scope = li_scope6(&su->su_sin6.sin6_addr);
1222 }
1223#endif
1224 else
1225 continue;
1226
1227 if (hints->li_flags & LI_IFNAME) {
1228 ifname = ifa->ifa_name;
1229 if (ifname)
1230 ifnamelen = strlen(ifname) + 1;
1231 }
1232
1233 if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
1234 (hints->li_family && hints->li_family != su->su_familysu_sa.sa_family) ||
1235 (hints->li_ifname && (!ifname || strcmp(hints->li_ifname, ifname))) ||
1236 (hints->li_index && hints->li_index != if_index))
1237 continue;
1238
1239 if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
1240 gni_flags = NI_NUMERICHOST1;
1241
1242#if SU_HAVE_IN61
1243 if (v4_mapped && su->su_familysu_sa.sa_family == AF_INET2) {
1244 /* Map IPv4 address to IPv6 address */
1245 memset(su2, 0, sizeof(*su2));
1246 su2->su_familysu_sa.sa_family = AF_INET610;
1247 ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
1248 ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
1249 su = su2;
1250 }
1251#endif
1252
1253 if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
1254 break;
1255
1256 if (error > 0) {
1257 error = 0;
1258 continue;
1259 }
1260
1261 if (canonname)
1262 if (strchr(canonname, ':') ||
1263 canonname[strspn(canonname, "0123456789.")] == '\0')
1264 flags |= LI_NUMERIC;
1265
1266 if (!(li = calloc(1, sizeof(*li) + sulen + ifnamelen))) {
1267 SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n" VA_NONE))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1267, "su_getlocalinfo: memory exhausted\n"
"%s", "")) : (void)0)
;
1268 error = ELI_MEMORY;
1269 break;
1270 }
1271 *return_result = li, return_result = &li->li_next;
1272
1273 li->li_flags = flags;
1274 li->li_family = su->su_familysu_sa.sa_family;
1275 li->li_scope = scope;
1276 li->li_index = if_index;
1277 li->li_addrlen = sulen;
1278 li->li_addr = memcpy(li + 1, su, sulen);
1279 li->li_canonname = canonname;
1280 if (ifnamelen) {
1281 li->li_ifname = strcpy((char *)(li + 1) + sulen, ifname);
1282 }
1283
1284 canonname = NULL((void*)0);
1285 }
1286
1287 if (canonname)
1288 free(canonname);
1289
1290 freeifaddrs(results);
1291
1292 return error;
1293}
1294
1295#elif USE_LOCALINFO01 && HAVE_IPHLPAPI_H && SU_HAVE_IN61
1296
1297static
1298char const *ws2ifname(DWORD iftype)
1299{
1300 switch (iftype) {
1301 case IF_TYPE_ETHERNET_CSMACD: return "eth";
1302 case IF_TYPE_IEEE80212: return "eth";
1303 case IF_TYPE_FASTETHER: return "eth";
1304 case IF_TYPE_GIGABITETHERNET: return "eth";
1305 case IF_TYPE_ISO88025_TOKENRING: return "token";
1306 case IF_TYPE_FDDI: return "fddi";
1307 case IF_TYPE_PPP: return "ppp";
1308 case IF_TYPE_SOFTWARE_LOOPBACK: return "lo";
1309 case IF_TYPE_SLIP: return "sl";
1310 case IF_TYPE_FRAMERELAY: return "fr";
1311 case IF_TYPE_ATM: return "atm";
1312 case IF_TYPE_HIPPI: return "hippi";
1313 case IF_TYPE_ISDN: return "isdn";
1314 case IF_TYPE_IEEE80211: return "wlan";
1315 case IF_TYPE_ADSL: return "adsl";
1316 case IF_TYPE_RADSL: return "radsl";
1317 case IF_TYPE_SDSL: return "sdsl";
1318 case IF_TYPE_VDSL: return "vdsl";
1319 case IF_TYPE_TUNNEL: return "tunnel";
1320 case IF_TYPE_IEEE1394: return "fw";
1321 case IF_TYPE_OTHER:
1322 default: return "other";
1323 }
1324}
1325
1326static
1327int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
1328{
1329 /* This is Windows XP code, for both IPv6 and IPv4. */
1330 ULONG iaa_size = 2048;
1331 IP_ADAPTER_ADDRESSES *iaa0, *iaa;
1332 int error, loopback_seen = 0;
1333 int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
1334 char *canonname = NULL((void*)0);
1335 su_localinfo_t *li, **next;
1336 int flags = GAA_FLAG_SKIP_MULTICAST;
1337 *rresult = NULL((void*)0); next = rresult;
1338
1339 iaa0 = malloc((size_t)iaa_size);
1340 if (!iaa0) {
1341 SU_DEBUG_1(("su_localinfo: memory exhausted\n"))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1341, "su_localinfo: memory exhausted\n"
, )) : (void)0)
;
1342 error = ELI_MEMORY;
1343 goto err;
1344 }
1345 error = GetAdaptersAddresses(hints->li_family, flags, NULL((void*)0), iaa0, &iaa_size);
1346 if (error == ERROR_BUFFER_OVERFLOW) {
1347 if ((iaa0 = realloc(iaa0, iaa_size)))
1348 error = GetAdaptersAddresses(hints->li_family, flags, NULL((void*)0), iaa0, &iaa_size);
1349 }
1350 if (error) {
1351 char const *empty = "";
1352 LPTSTR msg = empty;
1353
1354 if (error == ERROR_NO_DATA) {
1355 error = ELI_NOADDRESS;
1356 goto err;
1357 }
1358
1359 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1360 FORMAT_MESSAGE_FROM_SYSTEM |
1361 FORMAT_MESSAGE_IGNORE_INSERTS,
1362 NULL((void*)0),
1363 error,
1364 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1365 msg, 0, NULL((void*)0)))
1366 msg = empty;
1367
1368 SU_DEBUG_1(("su_localinfo: GetAdaptersAddresses: %s (%d)\n", msg, error))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1368, "su_localinfo: GetAdaptersAddresses: %s (%d)\n"
, msg, error)) : (void)0)
;
1369 if (msg != empty) LocalFree((LPVOID)msg);
1370 error = ELI_SYSTEM;
1371 goto err;
1372 }
1373
1374 for (iaa = iaa0; iaa; iaa = iaa->Next) {
1375 IP_ADAPTER_UNICAST_ADDRESS *ua;
1376 IP_ADAPTER_UNICAST_ADDRESS lua[1];
1377 int if_index = iaa->IfIndex;
1378 size_t ifnamelen = 0;
1379 char ifname[16];
1380
1381 for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) {
1382 su_sockaddr_t *su;
1383 socklen_t sulen;
1384 su_sockaddr_t su2[1];
1385 int scope, flags = 0, gni_flags = 0;
1386
1387 if (ua == NULL((void*)0)) {
1388 /* There is no loopback interface in windows */
1389 if (!loopback_seen && iaa->Next == NULL((void*)0)) {
1390 struct sockaddr_in loopback_sin = { AF_INET2, 0, {{ 127, 0, 0, 1 }}};
1391
1392 lua->Address.lpSockaddr = (struct sockaddr *)&loopback_sin;
1393 lua->Address.iSockaddrLength = sizeof(loopback_sin);
1394 lua->Next = NULL((void*)0);
1395
1396 iaa->IfType = IF_TYPE_SOFTWARE_LOOPBACK;
1397 if_index = 1;
1398
1399 ua = lua;
1400 }
1401 else
1402 break;
1403 }
1404
1405 su = (su_sockaddr_t *)ua->Address.lpSockaddr;
1406 sulen = ua->Address.iSockaddrLength;
1407
1408 if (su->su_familysu_sa.sa_family == AF_INET2) {
1409 scope = li_scope4(su->su_sin.sin_addr.s_addr);
1410 if (v4_mapped)
1411 sulen = sizeof(su->su_sin6);
1412 if (scope == LI_SCOPE_HOST)
1413 loopback_seen = 1;
1414 }
1415 else if (su->su_familysu_sa.sa_family == AF_INET610) {
1416 if (IN6_IS_ADDR_MULTICAST(&su->su_sin6.sin6_addr)(((const uint8_t *) (&su->su_sin6.sin6_addr))[0] == 0xff
)
)
1417 continue;
1418 scope = li_scope6(&su->su_sin6.sin6_addr);
1419 }
1420 else
1421 continue;
1422
1423 if (hints->li_flags & LI_IFNAME) {
1424 snprintf(ifname, sizeof(ifname), "%s%u",
1425 ws2ifname(iaa->IfType), if_index);
1426 ifnamelen = strlen(ifname) + 1;
1427 }
1428
1429 if ((hints->li_scope && (hints->li_scope & scope) == 0) ||
1430 (hints->li_family && hints->li_family != su->su_familysu_sa.sa_family) ||
1431 /* (hints->li_ifname && strcmp(hints->li_ifname, ifname) != 0) || */
1432 (hints->li_index && hints->li_index != if_index))
1433 continue;
1434
1435 if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
1436 gni_flags = NI_NUMERICHOST1;
1437
1438 if (v4_mapped && su->su_familysu_sa.sa_family == AF_INET2) {
1439 /* Map IPv4 address to IPv6 address */
1440 memset(su2, 0, sizeof(*su2));
1441 su2->su_familysu_sa.sa_family = AF_INET610;
1442 ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
1443 ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
1444 su = su2;
1445 }
1446
1447 if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
1448 goto err;
1449 else if (error > 0)
1450 continue;
1451
1452 if (canonname)
1453 if (strchr(canonname, ':') ||
1454 strspn(canonname, "0123456789.") == strlen(canonname))
1455 flags |= LI_NUMERIC;
1456
1457 if (!(li = calloc(1, sizeof(*li) + sulen + ifnamelen))) {
1458 SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n"))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1458, "su_getlocalinfo: memory exhausted\n"
, )) : (void)0)
;
1459 error = ELI_MEMORY; goto err;
1460 }
1461 *next = li, next = &li->li_next;
1462
1463 li->li_flags = flags;
1464 li->li_family = su->su_familysu_sa.sa_family;
1465 li->li_scope = scope;
1466 li->li_index = if_index;
1467 li->li_addrlen = sulen;
1468 li->li_addr = memcpy(li + 1, su, sulen);
1469 li->li_canonname = canonname;
1470 if (ifnamelen) {
1471 li->li_ifname = strcpy((char *)(li + 1) + sulen, ifname);
1472 /* WideCharToMultiByte(CP_ACP, 0,
1473 ifname, -1, (char *)(li + 1) + sulen, ifnamelen,
1474 NULL, NULL); */
1475 }
1476
1477 canonname = NULL((void*)0);
1478 }
1479 }
1480
1481 if (iaa0) free(iaa0);
1482 return 0;
1483
1484err:
1485 if (iaa0) free(iaa0);
1486 if (canonname) free(canonname);
1487 su_freelocalinfo(*rresult), *rresult = NULL((void*)0);
1488 return error;
1489}
1490
1491#elif HAVE_SIO_ADDRESS_LIST_QUERY
1492
1493static
1494int localinfo0bsd_localinfo(su_localinfo_t const *hints, su_localinfo_t **rresult)
1495{
1496 /* This is Windows IPv4 code */
1497 short family = AF_INET2;
1498 su_socket_t s;
1499 union {
1500 SOCKET_ADDRESS_LIST sal[1];
1501#if HAVE_INTERFACE_INFO_EX
1502 INTERFACE_INFO_EX ii[1];
1503#else
1504 INTERFACE_INFO ii[1];
1505#endif
1506 char buffer[2048];
1507 } b = {{ 1 }};
1508 DWORD salen = sizeof(b);
1509 int i, error = -1;
1510#if SU_HAVE_IN61
1511 int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
1512#endif
1513 su_localinfo_t *li, *head = NULL((void*)0), **next = &head;
1514 char *canonname = NULL((void*)0), *if_name = NULL((void*)0);
1515
1516 *rresult = NULL((void*)0);
1517
1518 s = su_socket(family, SOCK_DGRAMSOCK_DGRAM, 0);
1519 if (s == INVALID_SOCKET((su_socket_t)INVALID_SOCKET)) {
1520 SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "su_socket",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1521, "su_getlocalinfo: %s: %s\n"
, "su_socket", su_strerror(su_errno()))) : (void)0)
1521 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1521, "su_getlocalinfo: %s: %s\n"
, "su_socket", su_strerror(su_errno()))) : (void)0)
;
1522 return -1;
1523 }
1524
1525 /* get the list of known IP address (NT5 and up) */
1526 if (WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL((void*)0), 0,
1527 &b, sizeof(b), &salen, NULL((void*)0), NULL((void*)0)) == SOCKET_ERRORSOCKET_ERROR) {
1528 SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "SIO_ADDRESS_LIST_QUERY",((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1529, "su_getlocalinfo: %s: %s\n"
, "SIO_ADDRESS_LIST_QUERY", su_strerror(su_errno()))) : (void
)0)
1529 su_strerror(su_errno())))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1529, "su_getlocalinfo: %s: %s\n"
, "SIO_ADDRESS_LIST_QUERY", su_strerror(su_errno()))) : (void
)0)
;
1530 error = -1; goto err;
1531 }
1532 if (b.sal->iAddressCount < 1) {
1533 SU_DEBUG_1(("su_getlocalinfo: no local addresses\n"))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1533, "su_getlocalinfo: no local addresses\n"
, )) : (void)0)
;
1534 error = -1; goto err;
1535 }
1536
1537 for (i = 0; i < b.sal->iAddressCount; i++) {
1538 su_sockaddr_t *su = (su_sockaddr_t *)b.sal->Address[i].lpSockaddr;
1539#if SU_HAVE_IN61
1540 socklen_t sulen = v4_mapped ? sizeof(*su) : b.sal->Address[i].iSockaddrLength;
1541 su_sockaddr_t su2[1];
1542#else
1543 socklen_t sulen = b.sal->Address[i].iSockaddrLength;
1544#endif
1545 int scope, flags = 0, gni_flags = 0;
1546
1547 scope = li_scope4(su->su_sin.sin_addr.s_addr);
1548
1549 if (hints->li_scope && (hints->li_scope & scope) == 0)
1550 continue;
1551
1552 if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
1553 gni_flags = NI_NUMERICHOST1;
1554
1555 if (!(li = calloc(1, sizeof(*li) + sulen))) {
1556 SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n"))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 1 ? (_su_llog((su_log_global
), 1, "su_localinfo.c", (const char *)__func__, 1556, "su_getlocalinfo: memory exhausted\n"
, )) : (void)0)
;
1557 error = -1; goto err;
1558 }
1559 *next = li, next = &li->li_next;
1560
1561#if SU_HAVE_IN61
1562 if (v4_mapped) {
1563 /* Map IPv4 address to IPv6 address */
1564 memset(su2, 0, sizeof(*su2));
1565 su2->su_familysu_sa.sa_family = AF_INET610;
1566 ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff);
1567 ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr;
1568 su = su2;
1569 }
1570#endif
1571
1572 if ((error = li_name(hints, gni_flags, su, &canonname)) < 0)
1573 goto err;
1574 else if (error > 0)
1575 continue;
1576
1577 if (canonname)
1578 if (strchr(canonname, ':') ||
1579 strspn(canonname, "0123456789.") == strlen(canonname))
1580 flags |= LI_NUMERIC;
1581
1582 li->li_flags = flags;
1583 li->li_family = su->su_familysu_sa.sa_family;
1584 li->li_scope = scope;
1585 li->li_index = i;
1586 li->li_addrlen = su_sockaddr_size(su)((socklen_t)((su)->su_sa.sa_family == 2 ? sizeof((su)->
su_sin) : ((su)->su_sa.sa_family == 10 ? sizeof((su)->su_sin6
) : sizeof(*su))))
;
1587 li->li_addr = su;
1588 li->li_canonname = canonname, canonname = NULL((void*)0);
1589 if (hints->li_flags & LI_IFNAME)
1590 li->li_ifname = if_name;
1591 li->li_addr = (su_sockaddr_t *)(li + 1);
1592 li->li_addrlen = sulen;
1593 memcpy(li->li_addr, su, sulen);
1594 }
1595
1596 *rresult = head;
1597 su_close(s);
1598
1599 return 0;
1600
1601err:
1602 if (canonname) free(canonname);
1603 su_freelocalinfo(head);
1604 su_close(s);
1605
1606 return error;
1607}
1608#endif
1609
1610#if !SU_LOCALINFO_TEST
1611
1612static
1613int li_name(su_localinfo_t const *hints,
1614 int gni_flags,
1615 su_sockaddr_t const *su,
1616 char **ccanonname)
1617{
1618 char name[SU_MAXHOST(1025)];
1619 int error;
1620 int flags = hints->li_flags;
1621
1622 *ccanonname = NULL((void*)0);
1623
1624 if ((flags & LI_CANONNAME) || hints->li_canonname) {
1625 if ((flags & LI_NAMEREQD) == LI_NAMEREQD)
1626 gni_flags |= NI_NAMEREQD8;
1627 if (flags & LI_NUMERIC)
1628 gni_flags |= NI_NUMERICHOST1;
1629
1630 error = su_getnameinfo(su, su_sockaddr_size(su)((socklen_t)((su)->su_sa.sa_family == 2 ? sizeof((su)->
su_sin) : ((su)->su_sa.sa_family == 10 ? sizeof((su)->su_sin6
) : sizeof(*su))))
,
1631 name, sizeof(name), NULL((void*)0), 0,
1632 gni_flags);
1633 if (error) {
1634 if ((flags & LI_NAMEREQD) == LI_NAMEREQD)
1635 return 1;
1636 SU_DEBUG_7(("li_name: getnameinfo() failed\n" VA_NONE))((((su_log_global) != ((void*)0) && (su_log_global)->
log_init) == 0 ? 9 : (((su_log_global) != ((void*)0) &&
(su_log_global)->log_init > 1) ? (su_log_global)->log_level
: su_log_default->log_level)) >= 7 ? (_su_llog((su_log_global
), 7, "su_localinfo.c", (const char *)__func__, 1636, "li_name: getnameinfo() failed\n"
"%s", "")) : (void)0)
;
1637 if (!su_inet_ntopinet_ntop(su->su_familysu_sa.sa_family, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
, name, sizeof name))
1638 return ELI_RESOLVER;
1639 }
1640
1641 if (hints->li_canonname && !su_casematch(name, hints->li_canonname))
1642 return 1;
1643
1644 if (!(flags & LI_CANONNAME))
1645 return 0;
1646
1647 if (!(*ccanonname = strdup(name)))
1648 return ELI_MEMORY;
1649 }
1650 return 0;
1651}
1652
1653static
1654void li_sort(su_localinfo_t *i, su_localinfo_t **rresult)
1655{
1656 su_localinfo_t *li, **lli;
1657
1658#define LI_MAPPED(li)((li)->li_family == 10 && ((__extension__ ({ const
struct in6_addr *__a = (const struct in6_addr *) (&(li)->
li_addr->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32[0
] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == htonl (0xffff); })) || (__extension__
({ const struct in6_addr *__a = (const struct in6_addr *) (&
(li)->li_addr->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32
[0] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == 0 && ntohl (__a->
__in6_u.__u6_addr32[3]) > 1; }))))
\
1659 ((li)->li_family == AF_INET610 && \
1660 (IN6_IS_ADDR_V4MAPPED(&(li)->li_addr->su_sin6.sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&(li)->li_addr->su_sin6.sin6_addr); __a->__in6_u
.__u6_addr32[0] == 0 && __a->__in6_u.__u6_addr32[1
] == 0 && __a->__in6_u.__u6_addr32[2] == htonl (0xffff
); }))
|| \
1661 IN6_IS_ADDR_V4COMPAT(&(li)->li_addr->su_sin6.sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&(li)->li_addr->su_sin6.sin6_addr); __a->__in6_u
.__u6_addr32[0] == 0 && __a->__in6_u.__u6_addr32[1
] == 0 && __a->__in6_u.__u6_addr32[2] == 0 &&
ntohl (__a->__in6_u.__u6_addr32[3]) > 1; }))
))
1662
1663 /* Sort addresses according to scope (and mappedness) */
1664 for (li = i; li; li = i) {
1665 i = li->li_next;
1666 for (lli = rresult; *lli; lli = &(*lli)->li_next) {
1667 if ((*lli)->li_scope < li->li_scope)
1668 break;
1669#if SU_HAVE_IN61
1670 if (LI_MAPPED(*lli)((*lli)->li_family == 10 && ((__extension__ ({ const
struct in6_addr *__a = (const struct in6_addr *) (&(*lli
)->li_addr->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32
[0] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == htonl (0xffff); })) || (__extension__
({ const struct in6_addr *__a = (const struct in6_addr *) (&
(*lli)->li_addr->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32
[0] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == 0 && ntohl (__a->
__in6_u.__u6_addr32[3]) > 1; }))))
> LI_MAPPED(li)((li)->li_family == 10 && ((__extension__ ({ const
struct in6_addr *__a = (const struct in6_addr *) (&(li)->
li_addr->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32[0
] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == htonl (0xffff); })) || (__extension__
({ const struct in6_addr *__a = (const struct in6_addr *) (&
(li)->li_addr->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32
[0] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == 0 && ntohl (__a->
__in6_u.__u6_addr32[3]) > 1; }))))
)
1671 break;
1672#endif
1673 }
1674 li->li_next = *lli;
1675 *lli = li;
1676 }
1677}
1678
1679#endif
1680
1681/**Get local IP address.
1682 *
1683 * @deprecated
1684 * Use su_getlocalinfo() instead.
1685 */
1686int su_getlocalip(su_sockaddr_t *sa)
1687{
1688 su_localinfo_t *li = NULL((void*)0), hints[1] = {{ 0 }};
1689
1690 hints->li_family = sa->su_sa.sa_family ? sa->su_sa.sa_family : AF_INET2;
1691
1692 if (su_getlocalinfo(hints, &li) == 0) {
1693 memcpy(sa, li->li_addr, li->li_addrlen);
1694 su_freelocalinfo(li);
1695 return 0;
1696 }
1697 else
1698 return -1;
1699}