Bug Summary

File:root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c
Warning:line 2283, column 12
Value stored to 'md_af' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_c_external_nspr_pr2.c -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/nspr/pr -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/nspr/pr -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D _NSPR_BUILD_ -D LINUX -D HAVE_FCNTL_FILE_LOCKING -D HAVE_POINTER_LOCALTIME_R -D _GNU_SOURCE -D _PR_PTHREADS -I /root/firefox-clang/config/external/nspr/pr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/nspr/pr -I /root/firefox-clang/config/external/nspr -I /root/firefox-clang/nsprpub/pr/include -I /root/firefox-clang/nsprpub/pr/include/private -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c Unified_c_external_nspr_pr2.c
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6#include "primpl.h"
7
8#include <string.h>
9
10#if defined(LINUX1)
11# include <sys/un.h>
12#endif
13
14/*
15 * On Unix, the error code for gethostbyname() and gethostbyaddr()
16 * is returned in the global variable h_errno, instead of the usual
17 * errno.
18 */
19#if defined(XP_UNIX1)
20# if defined(_PR_NEED_H_ERRNO)
21extern int h_errno(*__h_errno_location ());
22# endif
23# define _MD_GETHOST_ERRNO()(*__h_errno_location ()) h_errno(*__h_errno_location ())
24#else
25# define _MD_GETHOST_ERRNO()(*__h_errno_location ()) _MD_ERRNO()((*__errno_location ()))
26#endif
27
28/*
29 * The meaning of the macros related to gethostbyname, gethostbyaddr,
30 * and gethostbyname2 is defined below.
31 * - _PR_HAVE_THREADSAFE_GETHOST: the gethostbyXXX functions return
32 * the result in thread specific storage. For example, AIX, HP-UX.
33 * - _PR_HAVE_GETHOST_R: have the gethostbyXXX_r functions. See next
34 * two macros.
35 * - _PR_HAVE_GETHOST_R_INT: the gethostbyXXX_r functions return an
36 * int. For example, Linux glibc.
37 * - _PR_HAVE_GETHOST_R_POINTER: the gethostbyXXX_r functions return
38 * a struct hostent* pointer. For example, Solaris.
39 */
40#if defined(_PR_NO_PREEMPT) || defined(_PR_HAVE_GETHOST_R) || \
41 defined(_PR_HAVE_THREADSAFE_GETHOST)
42# define _PR_NO_DNS_LOCK
43#endif
44
45#if defined(_PR_NO_DNS_LOCK)
46# define LOCK_DNS()
47# define UNLOCK_DNS()
48#else
49PRLock* _pr_dnsLock = NULL((void*)0);
50# define LOCK_DNS() PR_Lock(_pr_dnsLock)
51# define UNLOCK_DNS() PR_Unlock(_pr_dnsLock)
52#endif /* defined(_PR_NO_DNS_LOCK) */
53
54/*
55 * Some platforms have the reentrant getprotobyname_r() and
56 * getprotobynumber_r(). However, they come in three flavors.
57 * Some return a pointer to struct protoent, others return
58 * an int, and glibc's flavor takes five arguments.
59 */
60
61#if defined(SOLARIS) \
62|| (defined(LINUX1) && defined(_REENTRANT) && defined(__GLIBC__2) && \
63 __GLIBC__2 < 2)
64# define _PR_HAVE_GETPROTO_R
65# define _PR_HAVE_GETPROTO_R_POINTER
66#endif
67
68#if defined(AIX4_3_PLUS) || (defined(AIX) && defined(_THREAD_SAFE)) || \
69 (defined(HPUX10_10) && defined(_REENTRANT)) || \
70 (defined(HPUX10_20) && defined(_REENTRANT)) || defined(OPENBSD)
71# define _PR_HAVE_GETPROTO_R
72# define _PR_HAVE_GETPROTO_R_INT
73#endif
74
75#if __FreeBSD_version >= 602000
76# define _PR_HAVE_GETPROTO_R
77# define _PR_HAVE_5_ARG_GETPROTO_R
78#endif
79
80/* BeOS has glibc but not the glibc-style getprotobyxxx_r functions. */
81#if (defined(__GLIBC__2) && __GLIBC__2 >= 2)
82# define _PR_HAVE_GETPROTO_R
83# define _PR_HAVE_5_ARG_GETPROTO_R
84#endif
85
86#if !defined(_PR_HAVE_GETPROTO_R)
87 PRLock* _getproto_lock = NULL((void*)0);
88#endif
89
90#if defined(_PR_INET6_PROBE)
91extern PRBool _pr_ipv6_is_present(void);
92#endif
93
94#define _PR_IN6_IS_ADDR_UNSPECIFIED(a)(((a)->_S6_un._S6_u32[0] == 0) && ((a)->_S6_un.
_S6_u32[1] == 0) && ((a)->_S6_un._S6_u32[2] == 0) &&
((a)->_S6_un._S6_u32[3] == 0))
\
95 (((a)->pr_s6_addr32_S6_un._S6_u32[0] == 0) && ((a)->pr_s6_addr32_S6_un._S6_u32[1] == 0) && \
96 ((a)->pr_s6_addr32_S6_un._S6_u32[2] == 0) && ((a)->pr_s6_addr32_S6_un._S6_u32[3] == 0))
97
98#define _PR_IN6_IS_ADDR_LOOPBACK(a)(((a)->_S6_un._S6_u32[0] == 0) && ((a)->_S6_un.
_S6_u32[1] == 0) && ((a)->_S6_un._S6_u32[2] == 0) &&
((a)->_S6_un._S6_u8[12] == 0) && ((a)->_S6_un.
_S6_u8[13] == 0) && ((a)->_S6_un._S6_u8[14] == 0) &&
((a)->_S6_un._S6_u8[15] == 0x1U))
\
99 (((a)->pr_s6_addr32_S6_un._S6_u32[0] == 0) && ((a)->pr_s6_addr32_S6_un._S6_u32[1] == 0) && \
100 ((a)->pr_s6_addr32_S6_un._S6_u32[2] == 0) && ((a)->pr_s6_addr_S6_un._S6_u8[12] == 0) && \
101 ((a)->pr_s6_addr_S6_un._S6_u8[13] == 0) && ((a)->pr_s6_addr_S6_un._S6_u8[14] == 0) && \
102 ((a)->pr_s6_addr_S6_un._S6_u8[15] == 0x1U))
103
104const PRIPv6Addr _pr_in6addr_any = {
105 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
106
107const PRIPv6Addr _pr_in6addr_loopback = {
108 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1U}}};
109/*
110 * The values at bytes 10 and 11 are compared using pointers to
111 * 8-bit fields, and not 32-bit fields, to make the comparison work on
112 * both big-endian and little-endian systems
113 */
114
115#define _PR_IN6_IS_ADDR_V4MAPPED(a)(((a)->_S6_un._S6_u32[0] == 0) && ((a)->_S6_un.
_S6_u32[1] == 0) && ((a)->_S6_un._S6_u8[8] == 0) &&
((a)->_S6_un._S6_u8[9] == 0) && ((a)->_S6_un._S6_u8
[10] == 0xff) && ((a)->_S6_un._S6_u8[11] == 0xff))
\
116 (((a)->pr_s6_addr32_S6_un._S6_u32[0] == 0) && ((a)->pr_s6_addr32_S6_un._S6_u32[1] == 0) && \
117 ((a)->pr_s6_addr_S6_un._S6_u8[8] == 0) && ((a)->pr_s6_addr_S6_un._S6_u8[9] == 0) && \
118 ((a)->pr_s6_addr_S6_un._S6_u8[10] == 0xff) && ((a)->pr_s6_addr_S6_un._S6_u8[11] == 0xff))
119
120#define _PR_IN6_IS_ADDR_V4COMPAT(a)(((a)->_S6_un._S6_u32[0] == 0) && ((a)->_S6_un.
_S6_u32[1] == 0) && ((a)->_S6_un._S6_u32[2] == 0))
\
121 (((a)->pr_s6_addr32_S6_un._S6_u32[0] == 0) && ((a)->pr_s6_addr32_S6_un._S6_u32[1] == 0) && \
122 ((a)->pr_s6_addr32_S6_un._S6_u32[2] == 0))
123
124#define _PR_IN6_V4MAPPED_TO_IPADDR(a)((a)->_S6_un._S6_u32[3]) ((a)->pr_s6_addr32_S6_un._S6_u32[3])
125
126#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
127
128/*
129 * The _pr_QueryNetIfs() function finds out if the system has
130 * IPv4 or IPv6 source addresses configured and sets _pr_have_inet_if
131 * and _pr_have_inet6_if accordingly.
132 *
133 * We have an implementation using SIOCGIFCONF ioctl and a
134 * default implementation that simply sets _pr_have_inet_if
135 * and _pr_have_inet6_if to true. A better implementation
136 * would be to use the routing sockets (see Chapter 17 of
137 * W. Richard Stevens' Unix Network Programming, Vol. 1, 2nd. Ed.)
138 */
139
140static PRLock* _pr_query_ifs_lock = NULL((void*)0);
141static PRBool _pr_have_inet_if = PR_FALSE0;
142static PRBool _pr_have_inet6_if = PR_FALSE0;
143
144# undef DEBUG_QUERY_IFS
145
146# if defined(AIX) || (defined(DARWIN) && !defined(HAVE_GETIFADDRS))
147
148/*
149 * Use SIOCGIFCONF ioctl on platforms that don't have routing
150 * sockets. Warning: whether SIOCGIFCONF ioctl returns AF_INET6
151 * network interfaces is not portable.
152 *
153 * The _pr_QueryNetIfs() function is derived from the code in
154 * src/lib/libc/net/getifaddrs.c in BSD Unix and the code in
155 * Section 16.6 of W. Richard Stevens' Unix Network Programming,
156 * Vol. 1, 2nd. Ed.
157 */
158
159# include <sys/ioctl.h>
160# include <sys/socket.h>
161# include <netinet/in.h>
162# include <net/if.h>
163
164# ifdef DEBUG_QUERY_IFS
165static void _pr_PrintIfreq(struct ifreq* ifr) {
166 PRNetAddr addr;
167 struct sockaddr* sa;
168 const char* family;
169 char addrstr[64];
170
171 sa = &ifr->ifr_addr;
172 if (sa->sa_family == AF_INET2) {
173 struct sockaddr_in* sin = (struct sockaddr_in*)sa;
174 family = "inet";
175 memcpy(&addr.inet.ip, &sin->sin_addr, sizeof(sin->sin_addr));
176 } else if (sa->sa_family == AF_INET610) {
177 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
178 family = "inet6";
179 memcpy(&addr.ipv6.ip, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
180 } else {
181 return; /* skip if not AF_INET or AF_INET6 */
182 }
183 addr.raw.family = sa->sa_family;
184 PR_NetAddrToString(&addr, addrstr, sizeof(addrstr));
185 printf("%s: %s %s\n", ifr->ifr_name, family, addrstr);
186}
187# endif
188
189static void _pr_QueryNetIfs(void) {
190 int sock;
191 int rv;
192 struct ifconf ifc;
193 struct ifreq* ifr;
194 struct ifreq* lifr;
195 PRUint32 len, lastlen;
196 char* buf;
197
198 if ((sock = socket(AF_INET2, SOCK_STREAMSOCK_STREAM, 0)) == -1) {
199 return;
200 }
201
202 /* Issue SIOCGIFCONF request in a loop. */
203 lastlen = 0;
204 len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
205 for (;;) {
206 buf = (char*)PR_Malloc(len);
207 if (NULL((void*)0) == buf) {
208 close(sock);
209 return;
210 }
211 ifc.ifc_buf = buf;
212 ifc.ifc_len = len;
213 rv = ioctl(sock, SIOCGIFCONF0x8912, &ifc);
214 if (rv < 0) {
215 if (errno(*__errno_location ()) != EINVAL22 || lastlen != 0) {
216 close(sock);
217 PR_Free(buf);
218 return;
219 }
220 } else {
221 if (ifc.ifc_len == lastlen) {
222 break; /* success, len has not changed */
223 }
224 lastlen = ifc.ifc_len;
225 }
226 len += 10 * sizeof(struct ifreq); /* increment */
227 PR_Free(buf);
228 }
229 close(sock);
230
231 ifr = ifc.ifc_req;
232 lifr = (struct ifreq*)&ifc.ifc_buf[ifc.ifc_len];
233
234 while (ifr < lifr) {
235 struct sockaddr* sa;
236 int sa_len;
237
238# ifdef DEBUG_QUERY_IFS
239 _pr_PrintIfreq(ifr);
240# endif
241 sa = &ifr->ifr_addr;
242 if (sa->sa_family == AF_INET2) {
243 struct sockaddr_in* sin = (struct sockaddr_in*)sa;
244 if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)__bswap_32 (((in_addr_t) 0x7f000001))) {
245 _pr_have_inet_if = PR_TRUE1;
246 }
247 } else if (sa->sa_family == AF_INET610) {
248 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
249 if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&sin6->sin6_addr); __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] == __bswap_32 (1); }))
&&
250 !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&sin6->sin6_addr); (__a->__in6_u.__u6_addr32[0
] & __bswap_32 (0xffc00000)) == __bswap_32 (0xfe800000); }
))
) {
251 _pr_have_inet6_if = PR_TRUE1;
252 }
253 }
254
255# ifdef _PR_HAVE_SOCKADDR_LEN
256 sa_len = PR_MAX(sa->sa_len, sizeof(struct sockaddr))((sa->sa_len)>(sizeof(struct sockaddr))?(sa->sa_len)
:(sizeof(struct sockaddr)))
;
257# else
258 switch (sa->sa_family) {
259# ifdef AF_LINK
260 case AF_LINK:
261 sa_len = sizeof(struct sockaddr_dl);
262 break;
263# endif
264 case AF_INET610:
265 sa_len = sizeof(struct sockaddr_in6);
266 break;
267 default:
268 sa_len = sizeof(struct sockaddr);
269 break;
270 }
271# endif
272 ifr = (struct ifreq*)(((char*)sa) + sa_len);
273 }
274 PR_Free(buf);
275}
276
277# elif (defined(DARWIN) && defined(HAVE_GETIFADDRS)) || defined(FREEBSD) || \
278 defined(NETBSD) || defined(OPENBSD)
279
280/*
281 * Use the BSD getifaddrs function.
282 */
283
284# include <sys/types.h>
285# include <sys/socket.h>
286# include <ifaddrs.h>
287# include <netinet/in.h>
288
289# ifdef DEBUG_QUERY_IFS
290static void _pr_PrintIfaddrs(struct ifaddrs* ifa) {
291 struct sockaddr* sa;
292 const char* family;
293 void* addrp;
294 char addrstr[64];
295
296 sa = ifa->ifa_addr;
297 if (sa->sa_family == AF_INET2) {
298 struct sockaddr_in* sin = (struct sockaddr_in*)sa;
299 family = "inet";
300 addrp = &sin->sin_addr;
301 } else if (sa->sa_family == AF_INET610) {
302 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
303 family = "inet6";
304 addrp = &sin6->sin6_addr;
305 } else {
306 return; /* skip if not AF_INET or AF_INET6 */
307 }
308 inet_ntop(sa->sa_family, addrp, addrstr, sizeof(addrstr));
309 printf("%s: %s %s\n", ifa->ifa_name, family, addrstr);
310}
311# endif
312
313static void _pr_QueryNetIfs(void) {
314 struct ifaddrs* ifp;
315 struct ifaddrs* ifa;
316
317 if (getifaddrs(&ifp) == -1) {
318 return;
319 }
320 for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
321 struct sockaddr* sa;
322
323# ifdef DEBUG_QUERY_IFS
324 _pr_PrintIfaddrs(ifa);
325# endif
326 sa = ifa->ifa_addr;
327 if (sa->sa_family == AF_INET2) {
328 struct sockaddr_in* sin = (struct sockaddr_in*)sa;
329 if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)__bswap_32 (((in_addr_t) 0x7f000001))) {
330 _pr_have_inet_if = 1;
331 }
332 } else if (sa->sa_family == AF_INET610) {
333 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
334 if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&sin6->sin6_addr); __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] == __bswap_32 (1); }))
&&
335 !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&sin6->sin6_addr); (__a->__in6_u.__u6_addr32[0
] & __bswap_32 (0xffc00000)) == __bswap_32 (0xfe800000); }
))
) {
336 _pr_have_inet6_if = 1;
337 }
338 }
339 }
340 freeifaddrs(ifp);
341}
342
343# else /* default */
344
345/*
346 * Emulate the code in NSPR 4.2 or older. PR_GetIPNodeByName behaves
347 * as if the system had both IPv4 and IPv6 source addresses configured.
348 */
349static void _pr_QueryNetIfs(void) {
350 _pr_have_inet_if = PR_TRUE1;
351 _pr_have_inet6_if = PR_TRUE1;
352}
353
354# endif
355
356#endif /* _PR_INET6 && _PR_HAVE_GETHOSTBYNAME2 */
357
358void _PR_InitNet(void) {
359#if defined(XP_UNIX1)
360# ifdef HAVE_NETCONFIG
361 /*
362 * This one-liner prevents the endless re-open's and re-read's of
363 * /etc/netconfig on EACH and EVERY call to accept(), connect(), etc.
364 */
365 (void)setnetconfig();
366# endif
367#endif
368#if !defined(_PR_NO_DNS_LOCK)
369 _pr_dnsLock = PR_NewLock();
370#endif
371#if !defined(_PR_HAVE_GETPROTO_R)
372 _getproto_lock = PR_NewLock();
373#endif
374#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
375 _pr_query_ifs_lock = PR_NewLock();
376#endif
377}
378
379void _PR_CleanupNet(void) {
380#if !defined(_PR_NO_DNS_LOCK)
381 if (_pr_dnsLock) {
382 PR_DestroyLock(_pr_dnsLock);
383 _pr_dnsLock = NULL((void*)0);
384 }
385#endif
386#if !defined(_PR_HAVE_GETPROTO_R)
387 if (_getproto_lock) {
388 PR_DestroyLock(_getproto_lock);
389 _getproto_lock = NULL((void*)0);
390 }
391#endif
392#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
393 if (_pr_query_ifs_lock) {
394 PR_DestroyLock(_pr_query_ifs_lock);
395 _pr_query_ifs_lock = NULL((void*)0);
396 }
397#endif
398}
399
400/*
401** Allocate space from the buffer, aligning it to "align" before doing
402** the allocation. "align" must be a power of 2.
403*/
404static char* Alloc(PRIntn amount, char** bufp, PRIntn* buflenp, PRIntn align) {
405 char* buf = *bufp;
406 PRIntn buflen = *buflenp;
407
408 if (align && ((long)buf & (align - 1))) {
409 PRIntn skip = align - ((ptrdiff_t)buf & (align - 1));
410 if (buflen < skip) {
411 return 0;
412 }
413 buf += skip;
414 buflen -= skip;
415 }
416 if (buflen < amount) {
417 return 0;
418 }
419 *bufp = buf + amount;
420 *buflenp = buflen - amount;
421 return buf;
422}
423
424typedef enum _PRIPAddrConversion {
425 _PRIPAddrNoConversion,
426 _PRIPAddrIPv4Mapped,
427 _PRIPAddrIPv4Compat
428} _PRIPAddrConversion;
429
430/*
431** Convert an IPv4 address (v4) to an IPv4-mapped IPv6 address (v6).
432*/
433static void MakeIPv4MappedAddr(const char* v4, char* v6) {
434 memset(v6, 0, 10);
435 memset(v6 + 10, 0xff, 2);
436 memcpy(v6 + 12, v4, 4);
437}
438
439/*
440** Convert an IPv4 address (v4) to an IPv4-compatible IPv6 address (v6).
441*/
442static void MakeIPv4CompatAddr(const char* v4, char* v6) {
443 memset(v6, 0, 12);
444 memcpy(v6 + 12, v4, 4);
445}
446
447/*
448** Copy a hostent, and all of the memory that it refers to into
449** (hopefully) stacked buffers.
450*/
451static PRStatus CopyHostent(struct hostent* from, char** buf, PRIntn* bufsize,
452 _PRIPAddrConversion conversion, PRHostEnt* to) {
453 PRIntn len, na;
454 char** ap;
455
456 if (conversion != _PRIPAddrNoConversion && from->h_addrtype == AF_INET2) {
457 PR_ASSERT(from->h_length == 4)((from->h_length == 4)?((void)0):PR_Assert("from->h_length == 4"
,"/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c",457))
;
458 to->h_addrtype = PR_AF_INET610;
459 to->h_length = 16;
460 } else {
461#if defined(_PR_INET6) || defined(_PR_INET6_PROBE)
462 if (AF_INET610 == from->h_addrtype) {
463 to->h_addrtype = PR_AF_INET610;
464 } else
465#endif
466 to->h_addrtype = from->h_addrtype;
467 to->h_length = from->h_length;
468 }
469
470 /* Copy the official name */
471 if (!from->h_name) {
472 return PR_FAILURE;
473 }
474 len = strlen(from->h_name) + 1;
475 to->h_name = Alloc(len, buf, bufsize, 0);
476 if (!to->h_name) {
477 return PR_FAILURE;
478 }
479 memcpy(to->h_name, from->h_name, len);
480
481 /* Count the aliases, then allocate storage for the pointers */
482 if (!from->h_aliases) {
483 na = 1;
484 } else {
485 for (na = 1, ap = from->h_aliases; *ap != 0; na++, ap++) {
486 ;
487 } /* nothing to execute */
488 }
489 to->h_aliases =
490 (char**)Alloc(na * sizeof(char*), buf, bufsize, sizeof(char**));
491 if (!to->h_aliases) {
492 return PR_FAILURE;
493 }
494
495 /* Copy the aliases, one at a time */
496 if (!from->h_aliases) {
497 to->h_aliases[0] = 0;
498 } else {
499 for (na = 0, ap = from->h_aliases; *ap != 0; na++, ap++) {
500 len = strlen(*ap) + 1;
501 to->h_aliases[na] = Alloc(len, buf, bufsize, 0);
502 if (!to->h_aliases[na]) {
503 return PR_FAILURE;
504 }
505 memcpy(to->h_aliases[na], *ap, len);
506 }
507 to->h_aliases[na] = 0;
508 }
509
510 /* Count the addresses, then allocate storage for the pointers */
511 for (na = 1, ap = from->h_addr_list; *ap != 0; na++, ap++) {
512 ;
513 } /* nothing to execute */
514 to->h_addr_list =
515 (char**)Alloc(na * sizeof(char*), buf, bufsize, sizeof(char**));
516 if (!to->h_addr_list) {
517 return PR_FAILURE;
518 }
519
520 /* Copy the addresses, one at a time */
521 for (na = 0, ap = from->h_addr_list; *ap != 0; na++, ap++) {
522 to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0);
523 if (!to->h_addr_list[na]) {
524 return PR_FAILURE;
525 }
526 if (conversion != _PRIPAddrNoConversion && from->h_addrtype == AF_INET2) {
527 if (conversion == _PRIPAddrIPv4Mapped) {
528 MakeIPv4MappedAddr(*ap, to->h_addr_list[na]);
529 } else {
530 PR_ASSERT(conversion == _PRIPAddrIPv4Compat)((conversion == _PRIPAddrIPv4Compat)?((void)0):PR_Assert("conversion == _PRIPAddrIPv4Compat"
,"/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c",530))
;
531 MakeIPv4CompatAddr(*ap, to->h_addr_list[na]);
532 }
533 } else {
534 memcpy(to->h_addr_list[na], *ap, to->h_length);
535 }
536 }
537 to->h_addr_list[na] = 0;
538 return PR_SUCCESS;
539}
540
541#if !defined(_PR_HAVE_GETPROTO_R)
542/*
543** Copy a protoent, and all of the memory that it refers to into
544** (hopefully) stacked buffers.
545*/
546static PRStatus CopyProtoent(struct protoent* from, char* buf, PRIntn bufsize,
547 PRProtoEnt* to) {
548 PRIntn len, na;
549 char** ap;
550
551 /* Do the easy stuff */
552 to->p_num = from->p_proto;
553
554 /* Copy the official name */
555 if (!from->p_name) {
556 return PR_FAILURE;
557 }
558 len = strlen(from->p_name) + 1;
559 to->p_name = Alloc(len, &buf, &bufsize, 0);
560 if (!to->p_name) {
561 return PR_FAILURE;
562 }
563 memcpy(to->p_name, from->p_name, len);
564
565 /* Count the aliases, then allocate storage for the pointers */
566 for (na = 1, ap = from->p_aliases; *ap != 0; na++, ap++) {
567 ;
568 } /* nothing to execute */
569 to->p_aliases =
570 (char**)Alloc(na * sizeof(char*), &buf, &bufsize, sizeof(char**));
571 if (!to->p_aliases) {
572 return PR_FAILURE;
573 }
574
575 /* Copy the aliases, one at a time */
576 for (na = 0, ap = from->p_aliases; *ap != 0; na++, ap++) {
577 len = strlen(*ap) + 1;
578 to->p_aliases[na] = Alloc(len, &buf, &bufsize, 0);
579 if (!to->p_aliases[na]) {
580 return PR_FAILURE;
581 }
582 memcpy(to->p_aliases[na], *ap, len);
583 }
584 to->p_aliases[na] = 0;
585
586 return PR_SUCCESS;
587}
588#endif /* !defined(_PR_HAVE_GETPROTO_R) */
589
590/*
591 * #################################################################
592 * NOTE: tmphe, tmpbuf, bufsize, h, and h_err are local variables
593 * or arguments of PR_GetHostByName, PR_GetIPNodeByName, and
594 * PR_GetHostByAddr. DO NOT CHANGE THE NAMES OF THESE LOCAL
595 * VARIABLES OR ARGUMENTS.
596 * #################################################################
597 */
598#if defined(_PR_HAVE_GETHOST_R_INT)
599
600# define GETHOSTBYNAME(name)(gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &
h_err), h)
\
601 (gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &h_err), h)
602# define GETHOSTBYNAME2(name, af)(gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &
h, &h_err), h)
\
603 (gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h, &h_err), h)
604# define GETHOSTBYADDR(addr, addrlen, af)(gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize
, &h, &h_err), h)
\
605 (gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize, &h, &h_err), h)
606
607#elif defined(_PR_HAVE_GETHOST_R_POINTER)
608
609# define GETHOSTBYNAME(name)(gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &
h_err), h)
\
610 gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h_err)
611# define GETHOSTBYNAME2(name, af)(gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &
h, &h_err), h)
\
612 gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h_err)
613# define GETHOSTBYADDR(addr, addrlen, af)(gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize
, &h, &h_err), h)
\
614 gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize, &h_err)
615
616#else
617
618# define GETHOSTBYNAME(name)(gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &
h_err), h)
gethostbyname(name)
619# define GETHOSTBYNAME2(name, af)(gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &
h, &h_err), h)
gethostbyname2(name, af)
620# define GETHOSTBYADDR(addr, addrlen, af)(gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize
, &h, &h_err), h)
gethostbyaddr(addr, addrlen, af)
621
622#endif /* definition of GETHOSTBYXXX */
623
624PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
625PR_GetHostByName(const char* name, char* buf, PRIntn bufsize, PRHostEnt* hp) {
626 struct hostent* h;
627 PRStatus rv = PR_FAILURE;
628#if defined(_PR_HAVE_GETHOST_R)
629 char localbuf[PR_NETDB_BUF_SIZE2048];
630 char* tmpbuf;
631 struct hostent tmphe;
632 int h_err;
633#endif
634
635 if (!_pr_initialized) {
636 _PR_ImplicitInitialization();
637 }
638
639#if defined(_PR_HAVE_GETHOST_R)
640 tmpbuf = localbuf;
641 if (bufsize > sizeof(localbuf)) {
642 tmpbuf = (char*)PR_Malloc(bufsize);
643 if (NULL((void*)0) == tmpbuf) {
644 PR_SetError(PR_OUT_OF_MEMORY_ERROR(-6000L), 0);
645 return rv;
646 }
647 }
648#endif
649
650 LOCK_DNS();
651
652 h = GETHOSTBYNAME(name)(gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &
h_err), h)
;
653
654 if (NULL((void*)0) == h) {
655 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_GETHOST_ERRNO()(*__h_errno_location ()));
656 } else {
657 _PRIPAddrConversion conversion = _PRIPAddrNoConversion;
658 rv = CopyHostent(h, &buf, &bufsize, conversion, hp);
659 if (PR_SUCCESS != rv) {
660 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR(-5974L), 0);
661 }
662 }
663 UNLOCK_DNS();
664#if defined(_PR_HAVE_GETHOST_R)
665 if (tmpbuf != localbuf) {
666 PR_Free(tmpbuf);
667 }
668#endif
669 return rv;
670}
671
672#if !defined(_PR_INET6) && defined(_PR_INET6_PROBE) && \
673 defined(_PR_HAVE_GETIPNODEBYNAME)
674typedef struct hostent* (*_pr_getipnodebyname_t)(const char*, int, int, int*);
675typedef struct hostent* (*_pr_getipnodebyaddr_t)(const void*, size_t, int,
676 int*);
677typedef void (*_pr_freehostent_t)(struct hostent*);
678static void* _pr_getipnodebyname_fp;
679static void* _pr_getipnodebyaddr_fp;
680static void* _pr_freehostent_fp;
681
682/*
683 * Look up the addresses of getipnodebyname, getipnodebyaddr,
684 * and freehostent.
685 */
686PRStatus _pr_find_getipnodebyname(void) {
687 PRLibrary* lib;
688 PRStatus rv;
689# define GETIPNODEBYNAME "getipnodebyname"
690# define GETIPNODEBYADDR "getipnodebyaddr"
691# define FREEHOSTENT "freehostent"
692
693 _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary(GETIPNODEBYNAME, &lib);
694 if (NULL((void*)0) != _pr_getipnodebyname_fp) {
695 _pr_freehostent_fp = PR_FindSymbol(lib, FREEHOSTENT);
696 if (NULL((void*)0) != _pr_freehostent_fp) {
697 _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, GETIPNODEBYADDR);
698 if (NULL((void*)0) != _pr_getipnodebyaddr_fp) {
699 rv = PR_SUCCESS;
700 } else {
701 rv = PR_FAILURE;
702 }
703 } else {
704 rv = PR_FAILURE;
705 }
706 (void)PR_UnloadLibrary(lib);
707 } else {
708 rv = PR_FAILURE;
709 }
710 return rv;
711}
712#endif
713
714#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
715/*
716** Append the V4 addresses to the end of the list
717*/
718static PRStatus AppendV4AddrsToHostent(struct hostent* from, char** buf,
719 PRIntn* bufsize, PRHostEnt* to) {
720 PRIntn na, na_old;
721 char** ap;
722 char** new_addr_list;
723
724 /* Count the addresses, then grow storage for the pointers */
725 for (na_old = 0, ap = to->h_addr_list; *ap != 0; na_old++, ap++) {
726 ;
727 } /* nothing to execute */
728 for (na = na_old + 1, ap = from->h_addr_list; *ap != 0; na++, ap++) {
729 ;
730 } /* nothing to execute */
731 new_addr_list =
732 (char**)Alloc(na * sizeof(char*), buf, bufsize, sizeof(char**));
733 if (!new_addr_list) {
734 return PR_FAILURE;
735 }
736
737 /* Copy the V6 addresses, one at a time */
738 for (na = 0, ap = to->h_addr_list; *ap != 0; na++, ap++) {
739 new_addr_list[na] = to->h_addr_list[na];
740 }
741 to->h_addr_list = new_addr_list;
742
743 /* Copy the V4 addresses, one at a time */
744 for (ap = from->h_addr_list; *ap != 0; na++, ap++) {
745 to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0);
746 if (!to->h_addr_list[na]) {
747 return PR_FAILURE;
748 }
749 MakeIPv4MappedAddr(*ap, to->h_addr_list[na]);
750 }
751 to->h_addr_list[na] = 0;
752 return PR_SUCCESS;
753}
754#endif
755
756PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
757PR_GetIPNodeByName(const char* name, PRUint16 af, PRIntn flags, char* buf,
758 PRIntn bufsize, PRHostEnt* hp) {
759 struct hostent* h = 0;
760 PRStatus rv = PR_FAILURE;
761#if defined(_PR_HAVE_GETHOST_R)
762 char localbuf[PR_NETDB_BUF_SIZE2048];
763 char* tmpbuf;
764 struct hostent tmphe;
765 int h_err;
766#endif
767#if defined(_PR_HAVE_GETIPNODEBYNAME)
768 PRUint16 md_af = af;
769 int error_num;
770 int tmp_flags = 0;
771#endif
772#if defined(_PR_HAVE_GETHOSTBYNAME2)
773 PRBool did_af_inet = PR_FALSE0;
774#endif
775
776 if (!_pr_initialized) {
777 _PR_ImplicitInitialization();
778 }
779
780 if (af != PR_AF_INET2 && af != PR_AF_INET610) {
781 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
782 return PR_FAILURE;
783 }
784
785#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
786 PR_Lock(_pr_query_ifs_lock);
787 /*
788 * Keep querying the presence of IPv4 and IPv6 interfaces until
789 * at least one is up. This allows us to detect the local
790 * machine going from offline to online.
791 */
792 if (!_pr_have_inet_if && !_pr_have_inet6_if) {
793 _pr_QueryNetIfs();
794# ifdef DEBUG_QUERY_IFS
795 if (_pr_have_inet_if) {
796 printf("Have IPv4 source address\n");
797 }
798 if (_pr_have_inet6_if) {
799 printf("Have IPv6 source address\n");
800 }
801# endif
802 }
803 PR_Unlock(_pr_query_ifs_lock);
804#endif
805
806#if defined(_PR_HAVE_GETIPNODEBYNAME)
807 if (flags & PR_AI_V4MAPPED0x10) {
808 tmp_flags |= AI_V4MAPPED0x0008;
809 }
810 if (flags & PR_AI_ADDRCONFIG0x20) {
811 tmp_flags |= AI_ADDRCONFIG0x0020;
812 }
813 if (flags & PR_AI_ALL0x08) {
814 tmp_flags |= AI_ALL0x0010;
815 }
816 if (af == PR_AF_INET610) {
817 md_af = AF_INET610;
818 } else {
819 md_af = af;
820 }
821#endif
822
823#if defined(_PR_HAVE_GETHOST_R)
824 tmpbuf = localbuf;
825 if (bufsize > sizeof(localbuf)) {
826 tmpbuf = (char*)PR_Malloc(bufsize);
827 if (NULL((void*)0) == tmpbuf) {
828 PR_SetError(PR_OUT_OF_MEMORY_ERROR(-6000L), 0);
829 return rv;
830 }
831 }
832#endif
833
834 /* Do not need to lock the DNS lock if getipnodebyname() is called */
835#ifdef _PR_INET6
836# ifdef _PR_HAVE_GETHOSTBYNAME2
837 LOCK_DNS();
838 if (af == PR_AF_INET610) {
839 if ((flags & PR_AI_ADDRCONFIG0x20) == 0 || _pr_have_inet6_if) {
840# ifdef _PR_INET6_PROBE
841 if (_pr_ipv6_is_present())
842# endif
843 h = GETHOSTBYNAME2(name, AF_INET6)(gethostbyname2_r(name, 10, &tmphe, tmpbuf, bufsize, &
h, &h_err), h)
;
844 }
845 if ((NULL((void*)0) == h) && (flags & PR_AI_V4MAPPED0x10) &&
846 ((flags & PR_AI_ADDRCONFIG0x20) == 0 || _pr_have_inet_if)) {
847 did_af_inet = PR_TRUE1;
848 h = GETHOSTBYNAME2(name, AF_INET)(gethostbyname2_r(name, 2, &tmphe, tmpbuf, bufsize, &
h, &h_err), h)
;
849 }
850 } else {
851 if ((flags & PR_AI_ADDRCONFIG0x20) == 0 || _pr_have_inet_if) {
852 did_af_inet = PR_TRUE1;
853 h = GETHOSTBYNAME2(name, af)(gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &
h, &h_err), h)
;
854 }
855 }
856# elif defined(_PR_HAVE_GETIPNODEBYNAME)
857 h = getipnodebyname(name, md_af, tmp_flags, &error_num);
858# else
859# error "Unknown name-to-address translation function"
860# endif /* _PR_HAVE_GETHOSTBYNAME2 */
861#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
862 if (_pr_ipv6_is_present()) {
863# ifdef PR_GETIPNODE_NOT_THREADSAFE
864 LOCK_DNS();
865# endif
866 h = (*((_pr_getipnodebyname_t)_pr_getipnodebyname_fp))(
867 name, md_af, tmp_flags, &error_num);
868 } else {
869 LOCK_DNS();
870 h = GETHOSTBYNAME(name)(gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &
h_err), h)
;
871 }
872#else /* _PR_INET6 */
873 LOCK_DNS();
874 h = GETHOSTBYNAME(name)(gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &
h_err), h)
;
875#endif /* _PR_INET6 */
876
877 if (NULL((void*)0) == h) {
878#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
879 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), error_num);
880#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
881 if (_pr_ipv6_is_present()) {
882 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), error_num);
883 } else {
884 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_GETHOST_ERRNO()(*__h_errno_location ()));
885 }
886#else
887 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_GETHOST_ERRNO()(*__h_errno_location ()));
888#endif
889 } else {
890 _PRIPAddrConversion conversion = _PRIPAddrNoConversion;
891
892 if (af == PR_AF_INET610) {
893 conversion = _PRIPAddrIPv4Mapped;
894 }
895 rv = CopyHostent(h, &buf, &bufsize, conversion, hp);
896 if (PR_SUCCESS != rv) {
897 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR(-5974L), 0);
898 }
899#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
900 freehostent(h);
901#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
902 if (_pr_ipv6_is_present()) {
903 (*((_pr_freehostent_t)_pr_freehostent_fp))(h);
904 }
905#endif
906#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
907 if ((PR_SUCCESS == rv) && (flags & PR_AI_V4MAPPED0x10) &&
908 ((flags & PR_AI_ALL0x08) ||
909 ((flags & PR_AI_ADDRCONFIG0x20) && _pr_have_inet_if)) &&
910 !did_af_inet && (h = GETHOSTBYNAME2(name, AF_INET)(gethostbyname2_r(name, 2, &tmphe, tmpbuf, bufsize, &
h, &h_err), h)
) != 0) {
911 rv = AppendV4AddrsToHostent(h, &buf, &bufsize, hp);
912 if (PR_SUCCESS != rv) {
913 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR(-5974L), 0);
914 }
915 }
916#endif
917 }
918
919 /* Must match the convoluted logic above for LOCK_DNS() */
920#ifdef _PR_INET6
921# ifdef _PR_HAVE_GETHOSTBYNAME2
922 UNLOCK_DNS();
923# endif /* _PR_HAVE_GETHOSTBYNAME2 */
924#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
925# ifdef PR_GETIPNODE_NOT_THREADSAFE
926 UNLOCK_DNS();
927# else
928 if (!_pr_ipv6_is_present()) {
929 UNLOCK_DNS();
930 }
931# endif
932#else /* _PR_INET6 */
933 UNLOCK_DNS();
934#endif /* _PR_INET6 */
935
936#if defined(_PR_HAVE_GETHOST_R)
937 if (tmpbuf != localbuf) {
938 PR_Free(tmpbuf);
939 }
940#endif
941
942 return rv;
943}
944
945PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
946PR_GetHostByAddr(const PRNetAddr* hostaddr, char* buf, PRIntn bufsize,
947 PRHostEnt* hostentry) {
948 struct hostent* h;
949 PRStatus rv = PR_FAILURE;
950 const void* addr;
951 PRUint32 tmp_ip;
952 int addrlen;
953 PRInt32 af;
954#if defined(_PR_HAVE_GETHOST_R)
955 char localbuf[PR_NETDB_BUF_SIZE2048];
956 char* tmpbuf;
957 struct hostent tmphe;
958 int h_err;
959#endif
960#if defined(_PR_HAVE_GETIPNODEBYADDR)
961 int error_num;
962#endif
963
964 if (!_pr_initialized) {
965 _PR_ImplicitInitialization();
966 }
967
968 if (hostaddr->raw.family == PR_AF_INET610) {
969#if defined(_PR_INET6_PROBE)
970 af = _pr_ipv6_is_present() ? AF_INET610 : AF_INET2;
971#elif defined(_PR_INET6)
972 af = AF_INET610;
973#else
974 af = AF_INET2;
975#endif
976#if defined(_PR_GHBA_DISALLOW_V4MAPPED)
977 if (_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)(((&hostaddr->ipv6.ip)->_S6_un._S6_u32[0] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u32[1] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[8] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[9] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[10] == 0xff) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[11] == 0xff))
) {
978 af = AF_INET2;
979 }
980#endif
981 } else {
982 PR_ASSERT(hostaddr->raw.family == AF_INET)((hostaddr->raw.family == 2)?((void)0):PR_Assert("hostaddr->raw.family == AF_INET"
,"/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c",982))
;
983 af = AF_INET2;
984 }
985 if (hostaddr->raw.family == PR_AF_INET610) {
986#if defined(_PR_INET6) || defined(_PR_INET6_PROBE)
987 if (af == AF_INET610) {
988 addr = &hostaddr->ipv6.ip;
989 addrlen = sizeof(hostaddr->ipv6.ip);
990 } else
991#endif
992 {
993 PR_ASSERT(af == AF_INET)((af == 2)?((void)0):PR_Assert("af == AF_INET","/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c"
,993))
;
994 if (!_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)(((&hostaddr->ipv6.ip)->_S6_un._S6_u32[0] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u32[1] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[8] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[9] == 0) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[10] == 0xff) &&
((&hostaddr->ipv6.ip)->_S6_un._S6_u8[11] == 0xff))
) {
995 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
996 return rv;
997 }
998 tmp_ip = _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr*)&hostaddr->ipv6.ip)(((PRIPv6Addr*)&hostaddr->ipv6.ip)->_S6_un._S6_u32[
3])
;
999 addr = &tmp_ip;
1000 addrlen = sizeof(tmp_ip);
1001 }
1002 } else {
1003 PR_ASSERT(hostaddr->raw.family == AF_INET)((hostaddr->raw.family == 2)?((void)0):PR_Assert("hostaddr->raw.family == AF_INET"
,"/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c",1003))
;
1004 PR_ASSERT(af == AF_INET)((af == 2)?((void)0):PR_Assert("af == AF_INET","/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c"
,1004))
;
1005 addr = &hostaddr->inet.ip;
1006 addrlen = sizeof(hostaddr->inet.ip);
1007 }
1008
1009#if defined(_PR_HAVE_GETHOST_R)
1010 tmpbuf = localbuf;
1011 if (bufsize > sizeof(localbuf)) {
1012 tmpbuf = (char*)PR_Malloc(bufsize);
1013 if (NULL((void*)0) == tmpbuf) {
1014 PR_SetError(PR_OUT_OF_MEMORY_ERROR(-6000L), 0);
1015 return rv;
1016 }
1017 }
1018#endif
1019
1020 /* Do not need to lock the DNS lock if getipnodebyaddr() is called */
1021#if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6)
1022 h = getipnodebyaddr(addr, addrlen, af, &error_num);
1023#elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE)
1024 if (_pr_ipv6_is_present()) {
1025# ifdef PR_GETIPNODE_NOT_THREADSAFE
1026 LOCK_DNS();
1027# endif
1028 h = (*((_pr_getipnodebyaddr_t)_pr_getipnodebyaddr_fp))(addr, addrlen, af,
1029 &error_num);
1030 } else {
1031 LOCK_DNS();
1032 h = GETHOSTBYADDR(addr, addrlen, af)(gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize
, &h, &h_err), h)
;
1033 }
1034#else /* _PR_HAVE_GETIPNODEBYADDR */
1035 LOCK_DNS();
1036 h = GETHOSTBYADDR(addr, addrlen, af)(gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize
, &h, &h_err), h)
;
1037#endif /* _PR_HAVE_GETIPNODEBYADDR */
1038 if (NULL((void*)0) == h) {
1039#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
1040 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), error_num);
1041#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR)
1042 if (_pr_ipv6_is_present()) {
1043 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), error_num);
1044 } else {
1045 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_GETHOST_ERRNO()(*__h_errno_location ()));
1046 }
1047#else
1048 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_GETHOST_ERRNO()(*__h_errno_location ()));
1049#endif
1050 } else {
1051 _PRIPAddrConversion conversion = _PRIPAddrNoConversion;
1052 if (hostaddr->raw.family == PR_AF_INET610) {
1053 if (af == AF_INET2) {
1054 if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr*)&hostaddr->ipv6.ip)((((PRIPv6Addr*)&hostaddr->ipv6.ip)->_S6_un._S6_u32
[0] == 0) && (((PRIPv6Addr*)&hostaddr->ipv6.ip
)->_S6_un._S6_u32[1] == 0) && (((PRIPv6Addr*)&
hostaddr->ipv6.ip)->_S6_un._S6_u8[8] == 0) && (
((PRIPv6Addr*)&hostaddr->ipv6.ip)->_S6_un._S6_u8[9]
== 0) && (((PRIPv6Addr*)&hostaddr->ipv6.ip)->
_S6_un._S6_u8[10] == 0xff) && (((PRIPv6Addr*)&hostaddr
->ipv6.ip)->_S6_un._S6_u8[11] == 0xff))
) {
1055 conversion = _PRIPAddrIPv4Mapped;
1056 } else if (_PR_IN6_IS_ADDR_V4COMPAT((PRIPv6Addr*)&hostaddr->ipv6.ip)((((PRIPv6Addr*)&hostaddr->ipv6.ip)->_S6_un._S6_u32
[0] == 0) && (((PRIPv6Addr*)&hostaddr->ipv6.ip
)->_S6_un._S6_u32[1] == 0) && (((PRIPv6Addr*)&
hostaddr->ipv6.ip)->_S6_un._S6_u32[2] == 0))
) {
1057 conversion = _PRIPAddrIPv4Compat;
1058 }
1059 }
1060 }
1061 rv = CopyHostent(h, &buf, &bufsize, conversion, hostentry);
1062 if (PR_SUCCESS != rv) {
1063 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR(-5974L), 0);
1064 }
1065#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
1066 freehostent(h);
1067#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR)
1068 if (_pr_ipv6_is_present()) {
1069 (*((_pr_freehostent_t)_pr_freehostent_fp))(h);
1070 }
1071#endif
1072 }
1073
1074 /* Must match the convoluted logic above for LOCK_DNS() */
1075#if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6)
1076#elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE)
1077# ifdef PR_GETIPNODE_NOT_THREADSAFE
1078 UNLOCK_DNS();
1079# else
1080 if (!_pr_ipv6_is_present()) {
1081 UNLOCK_DNS();
1082 }
1083# endif
1084#else /* _PR_HAVE_GETIPNODEBYADDR */
1085 UNLOCK_DNS();
1086#endif /* _PR_HAVE_GETIPNODEBYADDR */
1087
1088#if defined(_PR_HAVE_GETHOST_R)
1089 if (tmpbuf != localbuf) {
1090 PR_Free(tmpbuf);
1091 }
1092#endif
1093
1094 return rv;
1095}
1096
1097/******************************************************************************/
1098/*
1099 * Some systems define a reentrant version of getprotobyname(). Too bad
1100 * the signature isn't always the same. But hey, they tried. If there
1101 * is such a definition, use it. Otherwise, grab a lock and do it here.
1102 */
1103/******************************************************************************/
1104
1105#if !defined(_PR_HAVE_GETPROTO_R)
1106/*
1107 * This may seem like a silly thing to do, but the compiler SHOULD
1108 * complain if getprotobyname_r() is implemented on some system and
1109 * we're not using it. For sure these signatures are different than
1110 * any usable implementation.
1111 */
1112
1113# if defined(ANDROID)
1114/* Android's Bionic libc system includes prototypes for these in netdb.h,
1115 * but doesn't actually include implementations. It uses the 5-arg form,
1116 * so these functions end up not matching the prototype. So just rename
1117 * them if not found.
1118 */
1119# define getprotobyname_r _pr_getprotobyname_r
1120# define getprotobynumber_r _pr_getprotobynumber_r
1121# endif
1122
1123static struct protoent* getprotobyname_r(const char* name) {
1124 return getprotobyname(name);
1125} /* getprotobyname_r */
1126
1127static struct protoent* getprotobynumber_r(PRInt32 number) {
1128 return getprotobynumber(number);
1129} /* getprotobynumber_r */
1130
1131#endif /* !defined(_PR_HAVE_GETPROTO_R) */
1132
1133PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
1134PR_GetProtoByName(const char* name, char* buffer, PRInt32 buflen,
1135 PRProtoEnt* result) {
1136 PRStatus rv = PR_SUCCESS;
1137#if defined(_PR_HAVE_GETPROTO_R)
1138 struct protoent* res = (struct protoent*)result;
1139#endif
1140
1141 if (!_pr_initialized) {
1142 _PR_ImplicitInitialization();
1143 }
1144
1145#if defined(_PR_HAVE_GETPROTO_R_INT)
1146 {
1147 /*
1148 ** The protoent_data has a pointer as the first field.
1149 ** That implies the buffer better be aligned, and char*
1150 ** doesn't promise much.
1151 */
1152 PRUptrdiff aligned = (PRUptrdiff)buffer;
1153 if (0 != (aligned & (sizeof(struct protoent_data*) - 1))) {
1154 aligned += sizeof(struct protoent_data*) - 1;
1155 aligned &= ~(sizeof(struct protoent_data*) - 1);
1156 buflen -= (aligned - (PRUptrdiff)buffer);
1157 buffer = (char*)aligned;
1158 }
1159 }
1160#endif /* defined(_PR_HAVE_GETPROTO_R_INT) */
1161
1162 if (PR_MIN_NETDB_BUF_SIZE1024 > buflen) {
1163 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
1164 return PR_FAILURE;
1165 }
1166
1167#if defined(_PR_HAVE_GETPROTO_R_POINTER)
1168 if (NULL((void*)0) == getprotobyname_r(name, res, buffer, buflen)) {
1169 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1170 return PR_FAILURE;
1171 }
1172#elif defined(_PR_HAVE_GETPROTO_R_INT)
1173 /*
1174 ** The buffer needs to be zero'd, and it should be
1175 ** at least the size of a struct protoent_data.
1176 */
1177 memset(buffer, 0, buflen);
1178 if (-1 == getprotobyname_r(name, res, (struct protoent_data*)buffer)) {
1179 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1180 return PR_FAILURE;
1181 }
1182#elif defined(_PR_HAVE_5_ARG_GETPROTO_R)
1183 /* The 5th argument for getprotobyname_r() cannot be NULL */
1184 if (-1 == getprotobyname_r(name, res, buffer, buflen, &res)) {
1185 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1186 return PR_FAILURE;
1187 }
1188#else /* do it the hard way */
1189 {
1190 struct protoent* staticBuf;
1191 PR_Lock(_getproto_lock);
1192 staticBuf = getprotobyname_r(name);
1193 if (NULL((void*)0) == staticBuf) {
1194 rv = PR_FAILURE;
1195 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1196 } else {
1197 rv = CopyProtoent(staticBuf, buffer, buflen, result);
1198 if (PR_FAILURE == rv) {
1199 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR(-5974L), 0);
1200 }
1201 }
1202 PR_Unlock(_getproto_lock);
1203 }
1204#endif /* all that */
1205 return rv;
1206}
1207
1208PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
1209PR_GetProtoByNumber(PRInt32 number, char* buffer, PRInt32 buflen,
1210 PRProtoEnt* result) {
1211 PRStatus rv = PR_SUCCESS;
1212#if defined(_PR_HAVE_GETPROTO_R)
1213 struct protoent* res = (struct protoent*)result;
1214#endif
1215
1216 if (!_pr_initialized) {
1217 _PR_ImplicitInitialization();
1218 }
1219
1220#if defined(_PR_HAVE_GETPROTO_R_INT)
1221 {
1222 /*
1223 ** The protoent_data has a pointer as the first field.
1224 ** That implies the buffer better be aligned, and char*
1225 ** doesn't promise much.
1226 */
1227 PRUptrdiff aligned = (PRUptrdiff)buffer;
1228 if (0 != (aligned & (sizeof(struct protoent_data*) - 1))) {
1229 aligned += sizeof(struct protoent_data*) - 1;
1230 aligned &= ~(sizeof(struct protoent_data*) - 1);
1231 buflen -= (aligned - (PRUptrdiff)buffer);
1232 buffer = (char*)aligned;
1233 }
1234 }
1235#endif /* defined(_PR_HAVE_GETPROTO_R_INT) */
1236
1237 if (PR_MIN_NETDB_BUF_SIZE1024 > buflen) {
1238 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
1239 return PR_FAILURE;
1240 }
1241
1242#if defined(_PR_HAVE_GETPROTO_R_POINTER)
1243 if (NULL((void*)0) == getprotobynumber_r(number, res, buffer, buflen)) {
1244 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1245 return PR_FAILURE;
1246 }
1247
1248#elif defined(_PR_HAVE_GETPROTO_R_INT)
1249 /*
1250 ** The buffer needs to be zero'd for these OS's.
1251 */
1252 memset(buffer, 0, buflen);
1253 if (-1 == getprotobynumber_r(number, res, (struct protoent_data*)buffer)) {
1254 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1255 return PR_FAILURE;
1256 }
1257#elif defined(_PR_HAVE_5_ARG_GETPROTO_R)
1258 /* The 5th argument for getprotobynumber_r() cannot be NULL */
1259 if (-1 == getprotobynumber_r(number, res, buffer, buflen, &res)) {
1260 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1261 return PR_FAILURE;
1262 }
1263#else /* do it the hard way */
1264 {
1265 struct protoent* staticBuf;
1266 PR_Lock(_getproto_lock);
1267 staticBuf = getprotobynumber_r(number);
1268 if (NULL((void*)0) == staticBuf) {
1269 rv = PR_FAILURE;
1270 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), _MD_ERRNO()((*__errno_location ())));
1271 } else {
1272 rv = CopyProtoent(staticBuf, buffer, buflen, result);
1273 if (PR_FAILURE == rv) {
1274 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR(-5974L), 0);
1275 }
1276 }
1277 PR_Unlock(_getproto_lock);
1278 }
1279#endif /* all that crap */
1280 return rv;
1281}
1282
1283PRUintn _PR_NetAddrSize(const PRNetAddr* addr) {
1284 PRUintn addrsize;
1285
1286 /*
1287 * RFC 2553 added a new field (sin6_scope_id) to
1288 * struct sockaddr_in6. PRNetAddr's ipv6 member has a
1289 * scope_id field to match the new field. In order to
1290 * work with older implementations supporting RFC 2133,
1291 * we take the size of struct sockaddr_in6 instead of
1292 * addr->ipv6.
1293 */
1294 if (AF_INET2 == addr->raw.family) {
1295 addrsize = sizeof(addr->inet);
1296 } else if (PR_AF_INET610 == addr->raw.family)
1297#if defined(_PR_INET6)
1298 addrsize = sizeof(struct sockaddr_in6);
1299#else
1300 addrsize = sizeof(addr->ipv6);
1301#endif
1302#if defined(XP_UNIX1)
1303 else if (AF_UNIX1 == addr->raw.family) {
1304# if defined(LINUX1)
1305 if (addr->local.path[0] == 0)
1306 /* abstract socket address is supported on Linux only */
1307 addrsize = strnlen(addr->local.path + 1, sizeof(addr->local.path)) +
1308 offsetof(struct sockaddr_un, sun_path)__builtin_offsetof(struct sockaddr_un, sun_path) + 1;
1309 else
1310# endif
1311 addrsize = sizeof(addr->local);
1312 }
1313#endif
1314 else {
1315 addrsize = 0;
1316 }
1317
1318 return addrsize;
1319} /* _PR_NetAddrSize */
1320
1321PR_IMPLEMENT(PRIntn)__attribute__((visibility("default"))) PRIntn
1322PR_EnumerateHostEnt(PRIntn enumIndex, const PRHostEnt* hostEnt, PRUint16 port,
1323 PRNetAddr* address) {
1324 void* addr = hostEnt->h_addr_list[enumIndex++];
1325 memset(address, 0, sizeof(PRNetAddr));
1326 if (NULL((void*)0) == addr) {
1327 enumIndex = 0;
1328 } else {
1329 address->raw.family = hostEnt->h_addrtype;
1330 if (PR_AF_INET610 == hostEnt->h_addrtype) {
1331 address->ipv6.port = htons(port)__bswap_16 (port);
1332 address->ipv6.flowinfo = 0;
1333 address->ipv6.scope_id = 0;
1334 memcpy(&address->ipv6.ip, addr, hostEnt->h_length);
1335 } else {
1336 PR_ASSERT(AF_INET == hostEnt->h_addrtype)((2 == hostEnt->h_addrtype)?((void)0):PR_Assert("AF_INET == hostEnt->h_addrtype"
,"/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c",1336))
;
1337 address->inet.port = htons(port)__bswap_16 (port);
1338 memcpy(&address->inet.ip, addr, hostEnt->h_length);
1339 }
1340 }
1341 return enumIndex;
1342} /* PR_EnumerateHostEnt */
1343
1344PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
1345PR_InitializeNetAddr(PRNetAddrValue val, PRUint16 port, PRNetAddr* addr) {
1346 PRStatus rv = PR_SUCCESS;
1347 if (!_pr_initialized) {
1348 _PR_ImplicitInitialization();
1349 }
1350
1351 if (val != PR_IpAddrNull) {
1352 memset(addr, 0, sizeof(*addr));
1353 }
1354 addr->inet.family = AF_INET2;
1355 addr->inet.port = htons(port)__bswap_16 (port);
1356 switch (val) {
1357 case PR_IpAddrNull:
1358 break; /* don't overwrite the address */
1359 case PR_IpAddrAny:
1360 addr->inet.ip = htonl(INADDR_ANY)__bswap_32 (((in_addr_t) 0x00000000));
1361 break;
1362 case PR_IpAddrLoopback:
1363 addr->inet.ip = htonl(INADDR_LOOPBACK)__bswap_32 (((in_addr_t) 0x7f000001));
1364 break;
1365 default:
1366 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
1367 rv = PR_FAILURE;
1368 }
1369 return rv;
1370} /* PR_InitializeNetAddr */
1371
1372PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
1373PR_SetNetAddr(PRNetAddrValue val, PRUint16 af, PRUint16 port, PRNetAddr* addr) {
1374 PRStatus rv = PR_SUCCESS;
1375 if (!_pr_initialized) {
1376 _PR_ImplicitInitialization();
1377 }
1378
1379 if (af == PR_AF_INET610) {
1380 if (val != PR_IpAddrNull) {
1381 memset(addr, 0, sizeof(addr->ipv6));
1382 }
1383 addr->ipv6.family = af;
1384 addr->ipv6.port = htons(port)__bswap_16 (port);
1385 addr->ipv6.flowinfo = 0;
1386 addr->ipv6.scope_id = 0;
1387 switch (val) {
1388 case PR_IpAddrNull:
1389 break; /* don't overwrite the address */
1390 case PR_IpAddrAny:
1391 addr->ipv6.ip = _pr_in6addr_any;
1392 break;
1393 case PR_IpAddrLoopback:
1394 addr->ipv6.ip = _pr_in6addr_loopback;
1395 break;
1396 default:
1397 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
1398 rv = PR_FAILURE;
1399 }
1400 } else {
1401 if (val != PR_IpAddrNull) {
1402 memset(addr, 0, sizeof(addr->inet));
1403 }
1404 addr->inet.family = af;
1405 addr->inet.port = htons(port)__bswap_16 (port);
1406 switch (val) {
1407 case PR_IpAddrNull:
1408 break; /* don't overwrite the address */
1409 case PR_IpAddrAny:
1410 addr->inet.ip = htonl(INADDR_ANY)__bswap_32 (((in_addr_t) 0x00000000));
1411 break;
1412 case PR_IpAddrLoopback:
1413 addr->inet.ip = htonl(INADDR_LOOPBACK)__bswap_32 (((in_addr_t) 0x7f000001));
1414 break;
1415 default:
1416 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
1417 rv = PR_FAILURE;
1418 }
1419 }
1420 return rv;
1421} /* PR_SetNetAddr */
1422
1423PR_IMPLEMENT(PRBool)__attribute__((visibility("default"))) PRBool
1424PR_IsNetAddrType(const PRNetAddr* addr, PRNetAddrValue val) {
1425 if (addr->raw.family == PR_AF_INET610) {
1426 if (val == PR_IpAddrAny) {
1427 if (_PR_IN6_IS_ADDR_UNSPECIFIED((PRIPv6Addr*)&addr->ipv6.ip)((((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u32[0] ==
0) && (((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un
._S6_u32[1] == 0) && (((PRIPv6Addr*)&addr->ipv6
.ip)->_S6_un._S6_u32[2] == 0) && (((PRIPv6Addr*)&
addr->ipv6.ip)->_S6_un._S6_u32[3] == 0))
) {
1428 return PR_TRUE1;
1429 }
1430 if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr*)&addr->ipv6.ip)((((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u32[0] ==
0) && (((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un
._S6_u32[1] == 0) && (((PRIPv6Addr*)&addr->ipv6
.ip)->_S6_un._S6_u8[8] == 0) && (((PRIPv6Addr*)&
addr->ipv6.ip)->_S6_un._S6_u8[9] == 0) && (((PRIPv6Addr
*)&addr->ipv6.ip)->_S6_un._S6_u8[10] == 0xff) &&
(((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u8[11] ==
0xff))
&&
1431 _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr*)&addr->ipv6.ip)(((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u32[3]) ==
1432 htonl(INADDR_ANY)__bswap_32 (((in_addr_t) 0x00000000))) {
1433 return PR_TRUE1;
1434 }
1435 } else if (val == PR_IpAddrLoopback) {
1436 if (_PR_IN6_IS_ADDR_LOOPBACK((PRIPv6Addr*)&addr->ipv6.ip)((((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u32[0] ==
0) && (((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un
._S6_u32[1] == 0) && (((PRIPv6Addr*)&addr->ipv6
.ip)->_S6_un._S6_u32[2] == 0) && (((PRIPv6Addr*)&
addr->ipv6.ip)->_S6_un._S6_u8[12] == 0) && (((PRIPv6Addr
*)&addr->ipv6.ip)->_S6_un._S6_u8[13] == 0) &&
(((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u8[14] ==
0) && (((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un
._S6_u8[15] == 0x1U))
) {
1437 return PR_TRUE1;
1438 }
1439 if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr*)&addr->ipv6.ip)((((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u32[0] ==
0) && (((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un
._S6_u32[1] == 0) && (((PRIPv6Addr*)&addr->ipv6
.ip)->_S6_un._S6_u8[8] == 0) && (((PRIPv6Addr*)&
addr->ipv6.ip)->_S6_un._S6_u8[9] == 0) && (((PRIPv6Addr
*)&addr->ipv6.ip)->_S6_un._S6_u8[10] == 0xff) &&
(((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u8[11] ==
0xff))
&&
1440 _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr*)&addr->ipv6.ip)(((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u32[3]) ==
1441 htonl(INADDR_LOOPBACK)__bswap_32 (((in_addr_t) 0x7f000001))) {
1442 return PR_TRUE1;
1443 }
1444 } else if (val == PR_IpAddrV4Mapped &&
1445 _PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr*)&addr->ipv6.ip)((((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u32[0] ==
0) && (((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un
._S6_u32[1] == 0) && (((PRIPv6Addr*)&addr->ipv6
.ip)->_S6_un._S6_u8[8] == 0) && (((PRIPv6Addr*)&
addr->ipv6.ip)->_S6_un._S6_u8[9] == 0) && (((PRIPv6Addr
*)&addr->ipv6.ip)->_S6_un._S6_u8[10] == 0xff) &&
(((PRIPv6Addr*)&addr->ipv6.ip)->_S6_un._S6_u8[11] ==
0xff))
) {
1446 return PR_TRUE1;
1447 }
1448 } else {
1449 if (addr->raw.family == AF_INET2) {
1450 if (val == PR_IpAddrAny && addr->inet.ip == htonl(INADDR_ANY)__bswap_32 (((in_addr_t) 0x00000000))) {
1451 return PR_TRUE1;
1452 }
1453 if (val == PR_IpAddrLoopback && addr->inet.ip == htonl(INADDR_LOOPBACK)__bswap_32 (((in_addr_t) 0x7f000001))) {
1454 return PR_TRUE1;
1455 }
1456 }
1457 }
1458 return PR_FALSE0;
1459}
1460
1461extern int pr_inet_aton(const char* cp, PRUint32* addr);
1462
1463#define XX 127
1464static const unsigned char index_hex[256] = {
1465 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1466 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1467 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, 0, 1, 2, 3, 4, 5, 6, 7, 8,
1468 9, XX, XX, XX, XX, XX, XX, XX, 10, 11, 12, 13, 14, 15, XX, XX, XX, XX, XX,
1469 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1470 XX, XX, 10, 11, 12, 13, 14, 15, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1471 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1472 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1473 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1474 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1475 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1476 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1477 XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
1478 XX, XX, XX, XX, XX, XX, XX, XX, XX,
1479};
1480
1481/*
1482 * StringToV6Addr() returns 1 if the conversion succeeds,
1483 * or 0 if the input is not a valid IPv6 address string.
1484 * (Same as inet_pton(AF_INET6, string, addr).)
1485 */
1486static int StringToV6Addr(const char* string, PRIPv6Addr* addr) {
1487 const unsigned char* s = (const unsigned char*)string;
1488 int section = 0; /* index of the current section (a 16-bit
1489 * piece of the address */
1490 int double_colon = -1; /* index of the section after the first
1491 * 16-bit group of zeros represented by
1492 * the double colon */
1493 unsigned int val;
1494 int len;
1495
1496 /* Handle initial (double) colon */
1497 if (*s == ':') {
1498 if (s[1] != ':') {
1499 return 0;
1500 }
1501 s += 2;
1502 addr->pr_s6_addr16_S6_un._S6_u16[0] = 0;
1503 section = double_colon = 1;
1504 }
1505
1506 while (*s) {
1507 if (section == 8) {
1508 return 0; /* too long */
1509 }
1510 if (*s == ':') {
1511 if (double_colon != -1) {
1512 return 0; /* two double colons */
1513 }
1514 addr->pr_s6_addr16_S6_un._S6_u16[section++] = 0;
1515 double_colon = section;
1516 s++;
1517 continue;
1518 }
1519 for (len = val = 0; len < 4 && index_hex[*s] != XX; len++) {
1520 val = (val << 4) + index_hex[*s++];
1521 }
1522 if (*s == '.') {
1523 if (len == 0) {
1524 return 0; /* nothing between : and . */
1525 }
1526 break;
1527 }
1528 if (*s == ':') {
1529 s++;
1530 if (!*s) {
1531 return 0; /* cannot end with single colon */
1532 }
1533 } else if (*s) {
1534 return 0; /* bad character */
1535 }
1536 addr->pr_s6_addr16_S6_un._S6_u16[section++] = htons((unsigned short)val)__bswap_16 ((unsigned short)val);
1537 }
1538
1539 if (*s == '.') {
1540 /* Have a trailing v4 format address */
1541 if (section > 6) {
1542 return 0; /* not enough room */
1543 }
1544
1545 /*
1546 * The number before the '.' is decimal, but we parsed it
1547 * as hex. That means it is in BCD. Check it for validity
1548 * and convert it to binary.
1549 */
1550 if (val > 0x0255 || (val & 0xf0) > 0x90 || (val & 0xf) > 9) {
1551 return 0;
1552 }
1553 val = (val >> 8) * 100 + ((val >> 4) & 0xf) * 10 + (val & 0xf);
1554 addr->pr_s6_addr_S6_un._S6_u8[2 * section] = val;
1555
1556 s++;
1557 val = index_hex[*s++];
1558 if (val > 9) {
1559 return 0;
1560 }
1561 while (*s >= '0' && *s <= '9') {
1562 val = val * 10 + *s++ - '0';
1563 if (val > 255) {
1564 return 0;
1565 }
1566 }
1567 if (*s != '.') {
1568 return 0; /* must have exactly 4 decimal numbers */
1569 }
1570 addr->pr_s6_addr_S6_un._S6_u8[2 * section + 1] = val;
1571 section++;
1572
1573 s++;
1574 val = index_hex[*s++];
1575 if (val > 9) {
1576 return 0;
1577 }
1578 while (*s >= '0' && *s <= '9') {
1579 val = val * 10 + *s++ - '0';
1580 if (val > 255) {
1581 return 0;
1582 }
1583 }
1584 if (*s != '.') {
1585 return 0; /* must have exactly 4 decimal numbers */
1586 }
1587 addr->pr_s6_addr_S6_un._S6_u8[2 * section] = val;
1588
1589 s++;
1590 val = index_hex[*s++];
1591 if (val > 9) {
1592 return 0;
1593 }
1594 while (*s >= '0' && *s <= '9') {
1595 val = val * 10 + *s++ - '0';
1596 if (val > 255) {
1597 return 0;
1598 }
1599 }
1600 if (*s) {
1601 return 0; /* must have exactly 4 decimal numbers */
1602 }
1603 addr->pr_s6_addr_S6_un._S6_u8[2 * section + 1] = val;
1604 section++;
1605 }
1606
1607 if (double_colon != -1) {
1608 /* Stretch the double colon */
1609 int tosection;
1610 int ncopy = section - double_colon;
1611 for (tosection = 7; ncopy--; tosection--) {
1612 addr->pr_s6_addr16_S6_un._S6_u16[tosection] = addr->pr_s6_addr16_S6_un._S6_u16[double_colon + ncopy];
1613 }
1614 while (tosection >= double_colon) {
1615 addr->pr_s6_addr16_S6_un._S6_u16[tosection--] = 0;
1616 }
1617 } else if (section != 8) {
1618 return 0; /* too short */
1619 }
1620 return 1;
1621}
1622#undef XX
1623
1624#ifndef _PR_HAVE_INET_NTOP
1625static const char* basis_hex = "0123456789abcdef";
1626
1627/*
1628 * V6AddrToString() returns a pointer to the buffer containing
1629 * the text string if the conversion succeeds, and NULL otherwise.
1630 * (Same as inet_ntop(AF_INET6, addr, buf, size), except that errno
1631 * is not set on failure.)
1632 */
1633static const char* V6AddrToString(const PRIPv6Addr* addr, char* buf,
1634 PRUint32 size) {
1635# define STUFF(c) \
1636 do { \
1637 if (!size--) return NULL((void*)0); \
1638 *buf++ = (c); \
1639 } while (0)
1640
1641 int double_colon = -1; /* index of the first 16-bit
1642 * group of zeros represented
1643 * by the double colon */
1644 int double_colon_length = 1; /* use double colon only if
1645 * there are two or more 16-bit
1646 * groups of zeros */
1647 int zero_length;
1648 int section;
1649 unsigned int val;
1650 const char* bufcopy = buf;
1651
1652 /* Scan to find the placement of the double colon */
1653 for (section = 0; section < 8; section++) {
1654 if (addr->pr_s6_addr16_S6_un._S6_u16[section] == 0) {
1655 zero_length = 1;
1656 section++;
1657 while (section < 8 && addr->pr_s6_addr16_S6_un._S6_u16[section] == 0) {
1658 zero_length++;
1659 section++;
1660 }
1661 /* Select the longest sequence of zeros */
1662 if (zero_length > double_colon_length) {
1663 double_colon = section - zero_length;
1664 double_colon_length = zero_length;
1665 }
1666 }
1667 }
1668
1669 /* Now start converting to a string */
1670 section = 0;
1671
1672 if (double_colon == 0) {
1673 if (double_colon_length == 6 ||
1674 (double_colon_length == 5 && addr->pr_s6_addr16_S6_un._S6_u16[5] == 0xffff)) {
1675 /* ipv4 format address */
1676 STUFF(':');
1677 STUFF(':');
1678 if (double_colon_length == 5) {
1679 STUFF('f');
1680 STUFF('f');
1681 STUFF('f');
1682 STUFF('f');
1683 STUFF(':');
1684 }
1685 if (addr->pr_s6_addr_S6_un._S6_u8[12] > 99) {
1686 STUFF(addr->pr_s6_addr_S6_un._S6_u8[12] / 100 + '0');
1687 }
1688 if (addr->pr_s6_addr_S6_un._S6_u8[12] > 9) {
1689 STUFF((addr->pr_s6_addr_S6_un._S6_u8[12] % 100) / 10 + '0');
1690 }
1691 STUFF(addr->pr_s6_addr_S6_un._S6_u8[12] % 10 + '0');
1692 STUFF('.');
1693 if (addr->pr_s6_addr_S6_un._S6_u8[13] > 99) {
1694 STUFF(addr->pr_s6_addr_S6_un._S6_u8[13] / 100 + '0');
1695 }
1696 if (addr->pr_s6_addr_S6_un._S6_u8[13] > 9) {
1697 STUFF((addr->pr_s6_addr_S6_un._S6_u8[13] % 100) / 10 + '0');
1698 }
1699 STUFF(addr->pr_s6_addr_S6_un._S6_u8[13] % 10 + '0');
1700 STUFF('.');
1701 if (addr->pr_s6_addr_S6_un._S6_u8[14] > 99) {
1702 STUFF(addr->pr_s6_addr_S6_un._S6_u8[14] / 100 + '0');
1703 }
1704 if (addr->pr_s6_addr_S6_un._S6_u8[14] > 9) {
1705 STUFF((addr->pr_s6_addr_S6_un._S6_u8[14] % 100) / 10 + '0');
1706 }
1707 STUFF(addr->pr_s6_addr_S6_un._S6_u8[14] % 10 + '0');
1708 STUFF('.');
1709 if (addr->pr_s6_addr_S6_un._S6_u8[15] > 99) {
1710 STUFF(addr->pr_s6_addr_S6_un._S6_u8[15] / 100 + '0');
1711 }
1712 if (addr->pr_s6_addr_S6_un._S6_u8[15] > 9) {
1713 STUFF((addr->pr_s6_addr_S6_un._S6_u8[15] % 100) / 10 + '0');
1714 }
1715 STUFF(addr->pr_s6_addr_S6_un._S6_u8[15] % 10 + '0');
1716 STUFF('\0');
1717 return bufcopy;
1718 }
1719 }
1720
1721 while (section < 8) {
1722 if (section == double_colon) {
1723 STUFF(':');
1724 STUFF(':');
1725 section += double_colon_length;
1726 continue;
1727 }
1728 val = ntohs(addr->pr_s6_addr16[section])__bswap_16 (addr->_S6_un._S6_u16[section]);
1729 if (val > 0xfff) {
1730 STUFF(basis_hex[val >> 12]);
1731 }
1732 if (val > 0xff) {
1733 STUFF(basis_hex[(val >> 8) & 0xf]);
1734 }
1735 if (val > 0xf) {
1736 STUFF(basis_hex[(val >> 4) & 0xf]);
1737 }
1738 STUFF(basis_hex[val & 0xf]);
1739 section++;
1740 if (section < 8 && section != double_colon) {
1741 STUFF(':');
1742 }
1743 }
1744 STUFF('\0');
1745 return bufcopy;
1746# undef STUFF
1747}
1748#endif /* !_PR_HAVE_INET_NTOP */
1749
1750/*
1751 * Convert an IPv4 addr to an (IPv4-mapped) IPv6 addr
1752 */
1753PR_IMPLEMENT(void)__attribute__((visibility("default"))) void
1754PR_ConvertIPv4AddrToIPv6(PRUint32 v4addr, PRIPv6Addr* v6addr) {
1755 PRUint8* dstp;
1756 dstp = v6addr->pr_s6_addr_S6_un._S6_u8;
1757 memset(dstp, 0, 10);
1758 memset(dstp + 10, 0xff, 2);
1759 memcpy(dstp + 12, (char*)&v4addr, 4);
1760}
1761
1762PR_IMPLEMENT(PRUint16)__attribute__((visibility("default"))) PRUint16 PR_ntohs(PRUint16 n) { return ntohs(n)__bswap_16 (n); }
1763PR_IMPLEMENT(PRUint32)__attribute__((visibility("default"))) PRUint32 PR_ntohl(PRUint32 n) { return ntohl(n)__bswap_32 (n); }
1764PR_IMPLEMENT(PRUint16)__attribute__((visibility("default"))) PRUint16 PR_htons(PRUint16 n) { return htons(n)__bswap_16 (n); }
1765PR_IMPLEMENT(PRUint32)__attribute__((visibility("default"))) PRUint32 PR_htonl(PRUint32 n) { return htonl(n)__bswap_32 (n); }
1766PR_IMPLEMENT(PRUint64)__attribute__((visibility("default"))) PRUint64 PR_ntohll(PRUint64 n) {
1767#ifdef IS_BIG_ENDIAN
1768 return n;
1769#else
1770 PRUint32 hi, lo;
1771 lo = (PRUint32)n;
1772 hi = (PRUint32)(n >> 32);
1773 hi = PR_ntohl(hi);
1774 lo = PR_ntohl(lo);
1775 return ((PRUint64)lo << 32) + (PRUint64)hi;
1776#endif
1777} /* ntohll */
1778
1779PR_IMPLEMENT(PRUint64)__attribute__((visibility("default"))) PRUint64 PR_htonll(PRUint64 n) {
1780#ifdef IS_BIG_ENDIAN
1781 return n;
1782#else
1783 PRUint32 hi, lo;
1784 lo = (PRUint32)n;
1785 hi = (PRUint32)(n >> 32);
1786 hi = htonl(hi)__bswap_32 (hi);
1787 lo = htonl(lo)__bswap_32 (lo);
1788 return ((PRUint64)lo << 32) + (PRUint64)hi;
1789#endif
1790} /* htonll */
1791
1792/*
1793 * Implementation of PR_GetAddrInfoByName and friends
1794 *
1795 * Compile-time options:
1796 *
1797 * _PR_HAVE_GETADDRINFO Define this macro if the target system provides
1798 * getaddrinfo. With this defined, NSPR will require
1799 * getaddrinfo at run time. If this if not defined,
1800 * then NSPR will attempt to dynamically resolve
1801 * getaddrinfo, falling back to PR_GetHostByName if
1802 * getaddrinfo does not exist on the target system.
1803 *
1804 * Since getaddrinfo is a relatively new system call on many systems,
1805 * we are forced to dynamically resolve it at run time in most cases.
1806 * The exception includes any system (such as Mac OS X) that is known to
1807 * provide getaddrinfo in all versions that NSPR cares to support.
1808 */
1809
1810#if defined(_PR_HAVE_GETADDRINFO)
1811
1812# if defined(_PR_INET6)
1813
1814typedef struct addrinfo PRADDRINFO;
1815# define GETADDRINFOgetaddrinfo getaddrinfo
1816# define FREEADDRINFOfreeaddrinfo freeaddrinfo
1817# define GETNAMEINFOgetnameinfo getnameinfo
1818
1819# elif defined(_PR_INET6_PROBE)
1820
1821typedef struct addrinfo PRADDRINFO;
1822
1823/* getaddrinfo/freeaddrinfo/getnameinfo prototypes */
1824# if defined(WIN32)
1825# define FUNC_MODIFIER __stdcall
1826# else
1827# define FUNC_MODIFIER
1828# endif
1829typedef int(FUNC_MODIFIER* FN_GETADDRINFO)(const char* nodename,
1830 const char* servname,
1831 const PRADDRINFO* hints,
1832 PRADDRINFO** res);
1833typedef int(FUNC_MODIFIER* FN_FREEADDRINFO)(PRADDRINFO* ai);
1834typedef int(FUNC_MODIFIER* FN_GETNAMEINFO)(const struct sockaddr* addr,
1835 int addrlen, char* host, int hostlen,
1836 char* serv, int servlen, int flags);
1837
1838/* global state */
1839static FN_GETADDRINFO _pr_getaddrinfo = NULL((void*)0);
1840static FN_FREEADDRINFO _pr_freeaddrinfo = NULL((void*)0);
1841static FN_GETNAMEINFO _pr_getnameinfo = NULL((void*)0);
1842
1843# define GETADDRINFO_SYMBOL "getaddrinfo"
1844# define FREEADDRINFO_SYMBOL "freeaddrinfo"
1845# define GETNAMEINFO_SYMBOL "getnameinfo"
1846
1847PRStatus _pr_find_getaddrinfo(void) {
1848 PRLibrary* lib;
1849# ifdef WIN32
1850 /*
1851 * On windows, we need to search ws2_32.dll or wship6.dll
1852 * (Microsoft IPv6 Technology Preview for Windows 2000) for
1853 * getaddrinfo and freeaddrinfo. These libraries might not
1854 * be loaded yet.
1855 */
1856 const char* libname[] = {"ws2_32.dll", "wship6.dll"};
1857 int i;
1858
1859 for (i = 0; i < sizeof(libname) / sizeof(libname[0]); i++) {
1860 lib = PR_LoadLibrary(libname[i]);
1861 if (!lib) {
1862 continue;
1863 }
1864 _pr_getaddrinfo =
1865 (FN_GETADDRINFO)PR_FindFunctionSymbol(lib, GETADDRINFO_SYMBOL);
1866 if (!_pr_getaddrinfo) {
1867 PR_UnloadLibrary(lib);
1868 continue;
1869 }
1870 _pr_freeaddrinfo =
1871 (FN_FREEADDRINFO)PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL);
1872 _pr_getnameinfo =
1873 (FN_GETNAMEINFO)PR_FindFunctionSymbol(lib, GETNAMEINFO_SYMBOL);
1874 if (!_pr_freeaddrinfo || !_pr_getnameinfo) {
1875 PR_UnloadLibrary(lib);
1876 continue;
1877 }
1878 /* Keep the library loaded. */
1879 return PR_SUCCESS;
1880 }
1881 return PR_FAILURE;
1882# else
1883 /*
1884 * Resolve getaddrinfo by searching all loaded libraries. Then
1885 * search library containing getaddrinfo for freeaddrinfo.
1886 */
1887 _pr_getaddrinfo =
1888 (FN_GETADDRINFO)PR_FindFunctionSymbolAndLibrary(GETADDRINFO_SYMBOL, &lib);
1889 if (!_pr_getaddrinfo) {
1890 return PR_FAILURE;
1891 }
1892 _pr_freeaddrinfo =
1893 (FN_FREEADDRINFO)PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL);
1894 _pr_getnameinfo =
1895 (FN_GETNAMEINFO)PR_FindFunctionSymbol(lib, GETNAMEINFO_SYMBOL);
1896 PR_UnloadLibrary(lib);
1897 if (!_pr_freeaddrinfo || !_pr_getnameinfo) {
1898 return PR_FAILURE;
1899 }
1900 return PR_SUCCESS;
1901# endif
1902}
1903
1904# define GETADDRINFOgetaddrinfo (*_pr_getaddrinfo)
1905# define FREEADDRINFOfreeaddrinfo (*_pr_freeaddrinfo)
1906# define GETNAMEINFOgetnameinfo (*_pr_getnameinfo)
1907
1908# endif /* _PR_INET6 */
1909
1910#endif /* _PR_HAVE_GETADDRINFO */
1911
1912#if !defined(_PR_HAVE_GETADDRINFO) || defined(_PR_INET6_PROBE)
1913/*
1914 * If getaddrinfo does not exist, then we will fall back on
1915 * PR_GetHostByName, which requires that we allocate a buffer for the
1916 * PRHostEnt data structure and its members.
1917 */
1918typedef struct PRAddrInfoFB {
1919 char buf[PR_NETDB_BUF_SIZE2048];
1920 PRHostEnt hostent;
1921 PRBool has_cname;
1922} PRAddrInfoFB;
1923
1924static PRAddrInfo* pr_GetAddrInfoByNameFB(const char* hostname, PRUint16 af,
1925 PRIntn flags) {
1926 PRStatus rv;
1927 PRAddrInfoFB* ai;
1928 /* fallback on PR_GetHostByName */
1929 ai = PR_NEW(PRAddrInfoFB)((PRAddrInfoFB *) (PR_Malloc((sizeof(PRAddrInfoFB)))));
1930 if (!ai) {
1931 PR_SetError(PR_OUT_OF_MEMORY_ERROR(-6000L), 0);
1932 return NULL((void*)0);
1933 }
1934 rv = PR_GetHostByName(hostname, ai->buf, sizeof ai->buf, &ai->hostent);
1935 if (rv == PR_FAILURE) {
1936 PR_Free(ai);
1937 return NULL((void*)0);
1938 }
1939 ai->has_cname = !(flags & PR_AI_NOCANONNAME0x8000);
1940
1941 return (PRAddrInfo*)ai;
1942}
1943#endif /* !_PR_HAVE_GETADDRINFO || _PR_INET6_PROBE */
1944
1945PR_IMPLEMENT(PRAddrInfo*)__attribute__((visibility("default"))) PRAddrInfo*
1946PR_GetAddrInfoByName(const char* hostname, PRUint16 af, PRIntn flags) {
1947 /* restrict input to supported values */
1948 if ((af != PR_AF_INET2 && af != PR_AF_UNSPEC0) ||
1949 (flags & ~PR_AI_NOCANONNAME0x8000) != PR_AI_ADDRCONFIG0x20) {
1950 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
1951 return NULL((void*)0);
1952 }
1953
1954 if (!_pr_initialized) {
1955 _PR_ImplicitInitialization();
1956 }
1957
1958#if !defined(_PR_HAVE_GETADDRINFO)
1959 return pr_GetAddrInfoByNameFB(hostname, af, flags);
1960#else
1961# if defined(_PR_INET6_PROBE)
1962 if (!_pr_ipv6_is_present()) {
1963 return pr_GetAddrInfoByNameFB(hostname, af, flags);
1964 }
1965# endif
1966 {
1967 PRADDRINFO *res, hints;
1968 int rv;
1969
1970 /*
1971 * we assume a RFC 2553 compliant getaddrinfo. this may at some
1972 * point need to be customized as platforms begin to adopt the
1973 * RFC 3493.
1974 */
1975
1976 memset(&hints, 0, sizeof(hints));
1977 if (!(flags & PR_AI_NOCANONNAME0x8000)) {
1978 hints.ai_flags |= AI_CANONNAME0x0002;
1979 }
1980# ifdef AI_ADDRCONFIG0x0020
1981 /*
1982 * Propagate AI_ADDRCONFIG to the GETADDRINFO call if PR_AI_ADDRCONFIG
1983 * is set.
1984 *
1985 * Need a workaround for loopback host addresses:
1986 * The problem is that in glibc and Windows, AI_ADDRCONFIG applies the
1987 * existence of an outgoing network interface to IP addresses of the
1988 * loopback interface, due to a strict interpretation of the
1989 * specification. For example, if a computer does not have any
1990 * outgoing IPv6 network interface, but its loopback network interface
1991 * supports IPv6, a getaddrinfo call on "localhost" with AI_ADDRCONFIG
1992 * won't return the IPv6 loopback address "::1", because getaddrinfo
1993 * thinks the computer cannot connect to any IPv6 destination,
1994 * ignoring the remote vs. local/loopback distinction.
1995 */
1996 if ((flags & PR_AI_ADDRCONFIG0x20) && strcmp(hostname, "localhost") != 0 &&
1997 strcmp(hostname, "localhost.localdomain") != 0 &&
1998 strcmp(hostname, "localhost6") != 0 &&
1999 strcmp(hostname, "localhost6.localdomain6") != 0) {
2000 hints.ai_flags |= AI_ADDRCONFIG0x0020;
2001 }
2002# endif
2003 hints.ai_family = (af == PR_AF_INET2) ? AF_INET2 : AF_UNSPEC0;
2004
2005 /*
2006 * it is important to select a socket type in the hints, otherwise we
2007 * will get back repetitive entries: one for each socket type. since
2008 * we do not expose ai_socktype through our API, it is okay to do this
2009 * here. the application may still choose to create a socket of some
2010 * other type.
2011 */
2012 hints.ai_socktype = SOCK_STREAMSOCK_STREAM;
2013
2014 rv = GETADDRINFOgetaddrinfo(hostname, NULL((void*)0), &hints, &res);
2015# ifdef AI_ADDRCONFIG0x0020
2016 if (rv == EAI_BADFLAGS-1 && (hints.ai_flags & AI_ADDRCONFIG0x0020)) {
2017 hints.ai_flags &= ~AI_ADDRCONFIG0x0020;
2018 rv = GETADDRINFOgetaddrinfo(hostname, NULL((void*)0), &hints, &res);
2019 }
2020# endif
2021 if (rv == 0) {
2022 return (PRAddrInfo*)res;
2023 }
2024
2025 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), rv);
2026 }
2027 return NULL((void*)0);
2028#endif
2029}
2030
2031PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
2032PR_GetPrefLoopbackAddrInfo(PRNetAddr* result, PRUint16 port) {
2033 char tmpBuf[40];
2034 const int tmpBufSize = sizeof(tmpBuf);
2035
2036 if (!result) {
2037 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
2038 return PR_FAILURE;
2039 }
2040
2041 if (!_pr_initialized) _PR_ImplicitInitialization();
2042
2043 PR_snprintf(tmpBuf, tmpBufSize, "%u", port);
2044
2045#if !defined(_PR_HAVE_GETADDRINFO) || !defined(AI_PASSIVE0x0001)
2046 PR_SetError(PR_NOT_IMPLEMENTED_ERROR(-5992L), 0);
2047 return PR_FAILURE;
2048#else
2049
2050 PRADDRINFO *res, hints;
2051 PRStatus rv;
2052
2053 memset(&hints, 0, sizeof(hints));
2054
2055 rv = GETADDRINFOgetaddrinfo(NULL((void*)0), tmpBuf, &hints, &res);
2056 if (rv == 0) {
2057 PRBool result_still_empty = PR_TRUE1;
2058 PRADDRINFO* ai = res;
2059 do {
2060 PRNetAddr aNetAddr;
2061
2062 while (ai && ai->ai_addrlen > sizeof(PRNetAddr)) ai = ai->ai_next;
2063
2064 if (ai) {
2065 /* copy sockaddr to PRNetAddr */
2066 memcpy(&aNetAddr, ai->ai_addr, ai->ai_addrlen);
2067 aNetAddr.raw.family = ai->ai_addr->sa_family;
2068# ifdef _PR_INET6
2069 if (AF_INET610 == aNetAddr.raw.family) aNetAddr.raw.family = PR_AF_INET610;
2070# endif
2071 if (ai->ai_addrlen < sizeof(PRNetAddr))
2072 memset(((char*)result) + ai->ai_addrlen, 0,
2073 sizeof(PRNetAddr) - ai->ai_addrlen);
2074 }
2075
2076 /* If we obtain more than one result, prefer IPv6. */
2077 if (result_still_empty || aNetAddr.raw.family == PR_AF_INET610) {
2078 memcpy(result, &aNetAddr, sizeof(PRNetAddr));
2079 }
2080 result_still_empty = PR_FALSE0;
2081 ai = ai->ai_next;
2082 } while (ai);
2083
2084 FREEADDRINFOfreeaddrinfo(res);
2085 return PR_SUCCESS;
2086 }
2087
2088 PR_SetError(PR_DIRECTORY_LOOKUP_ERROR(-5973L), rv);
2089 return PR_FAILURE;
2090#endif
2091}
2092
2093PR_IMPLEMENT(void)__attribute__((visibility("default"))) void PR_FreeAddrInfo(PRAddrInfo* ai) {
2094#if defined(_PR_HAVE_GETADDRINFO)
2095# if defined(_PR_INET6_PROBE)
2096 if (!_pr_ipv6_is_present()) {
2097 PR_Free((PRAddrInfoFB*)ai);
2098 } else
2099# endif
2100 FREEADDRINFOfreeaddrinfo((PRADDRINFO*)ai);
2101#else
2102 PR_Free((PRAddrInfoFB*)ai);
2103#endif
2104}
2105
2106PR_IMPLEMENT(void*)__attribute__((visibility("default"))) void*
2107PR_EnumerateAddrInfo(void* iterPtr, const PRAddrInfo* base, PRUint16 port,
2108 PRNetAddr* result) {
2109#if defined(_PR_HAVE_GETADDRINFO)
2110 PRADDRINFO* ai;
2111# if defined(_PR_INET6_PROBE)
2112 if (!_pr_ipv6_is_present()) {
2113 /* using PRAddrInfoFB */
2114 PRIntn iter = (PRIntn)(PRPtrdiff)iterPtr;
2115 iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB*)base)->hostent, port,
2116 result);
2117 if (iter < 0) {
2118 iter = 0;
2119 }
2120 return (void*)(PRPtrdiff)iter;
2121 }
2122# endif
2123
2124 if (iterPtr) {
2125 ai = ((PRADDRINFO*)iterPtr)->ai_next;
2126 } else {
2127 ai = (PRADDRINFO*)base;
2128 }
2129
2130 while (ai && ai->ai_addrlen > sizeof(PRNetAddr)) {
2131 ai = ai->ai_next;
2132 }
2133
2134 if (ai) {
2135 /* copy sockaddr to PRNetAddr */
2136 memcpy(result, ai->ai_addr, ai->ai_addrlen);
2137 result->raw.family = ai->ai_addr->sa_family;
2138# ifdef _PR_INET6
2139 if (AF_INET610 == result->raw.family) {
2140 result->raw.family = PR_AF_INET610;
2141 }
2142# endif
2143 if (ai->ai_addrlen < sizeof(PRNetAddr)) {
2144 memset(((char*)result) + ai->ai_addrlen, 0,
2145 sizeof(PRNetAddr) - ai->ai_addrlen);
2146 }
2147
2148 if (result->raw.family == PR_AF_INET2) {
2149 result->inet.port = htons(port)__bswap_16 (port);
2150 } else {
2151 result->ipv6.port = htons(port)__bswap_16 (port);
2152 }
2153 }
2154
2155 return ai;
2156#else
2157 /* using PRAddrInfoFB */
2158 PRIntn iter = (PRIntn)iterPtr;
2159 iter =
2160 PR_EnumerateHostEnt(iter, &((PRAddrInfoFB*)base)->hostent, port, result);
2161 if (iter < 0) {
2162 iter = 0;
2163 }
2164 return (void*)iter;
2165#endif
2166}
2167
2168PR_IMPLEMENT(const char*)__attribute__((visibility("default"))) const char* PR_GetCanonNameFromAddrInfo(const PRAddrInfo* ai) {
2169#if defined(_PR_HAVE_GETADDRINFO)
2170# if defined(_PR_INET6_PROBE)
2171 if (!_pr_ipv6_is_present()) {
2172 const PRAddrInfoFB* fb = (const PRAddrInfoFB*)ai;
2173 return fb->has_cname ? fb->hostent.h_name : NULL((void*)0);
2174 }
2175# endif
2176 return ((const PRADDRINFO*)ai)->ai_canonname;
2177#else
2178 const PRAddrInfoFB* fb = (const PRAddrInfoFB*)ai;
2179 return fb->has_cname ? fb->hostent.h_name : NULL((void*)0);
2180#endif
2181}
2182
2183#if defined(_PR_HAVE_GETADDRINFO)
2184static PRStatus pr_StringToNetAddrGAI(const char* string, PRNetAddr* addr) {
2185 PRADDRINFO *res, hints;
2186 int rv; /* 0 for success, or the error code EAI_xxx */
2187 PRNetAddr laddr;
2188 PRStatus status = PR_SUCCESS;
2189
2190 memset(&hints, 0, sizeof(hints));
2191 hints.ai_flags = AI_NUMERICHOST0x0004;
2192 hints.ai_family = AF_UNSPEC0;
2193 hints.ai_socktype = SOCK_STREAMSOCK_STREAM;
2194
2195 rv = GETADDRINFOgetaddrinfo(string, NULL((void*)0), &hints, &res);
2196 if (rv != 0) {
2197 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), rv);
2198 return PR_FAILURE;
2199 }
2200
2201 /* pick up the first addr */
2202 memcpy(&laddr, res->ai_addr, res->ai_addrlen);
2203 if (AF_INET610 == res->ai_addr->sa_family) {
2204 addr->ipv6.family = PR_AF_INET610;
2205 addr->ipv6.ip = laddr.ipv6.ip;
2206 addr->ipv6.scope_id = laddr.ipv6.scope_id;
2207 } else if (AF_INET2 == res->ai_addr->sa_family) {
2208 addr->inet.family = PR_AF_INET2;
2209 addr->inet.ip = laddr.inet.ip;
2210 } else {
2211 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
2212 status = PR_FAILURE;
2213 }
2214
2215 FREEADDRINFOfreeaddrinfo(res);
2216 return status;
2217}
2218#endif /* _PR_HAVE_GETADDRINFO */
2219
2220static PRStatus pr_StringToNetAddrFB(const char* string, PRNetAddr* addr) {
2221 PRIntn rv;
2222
2223 rv = pr_inet_aton(string, &addr->inet.ip);
2224 if (1 == rv) {
2225 addr->raw.family = AF_INET2;
2226 return PR_SUCCESS;
2227 }
2228
2229 PR_ASSERT(0 == rv)((0 == rv)?((void)0):PR_Assert("0 == rv","/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c"
,2229))
;
2230 /* clean up after the failed call */
2231 memset(&addr->inet.ip, 0, sizeof(addr->inet.ip));
2232
2233 rv = StringToV6Addr(string, &addr->ipv6.ip);
2234 if (1 == rv) {
2235 addr->raw.family = PR_AF_INET610;
2236 return PR_SUCCESS;
2237 }
2238
2239 PR_ASSERT(0 == rv)((0 == rv)?((void)0):PR_Assert("0 == rv","/root/firefox-clang/nsprpub/pr/src/misc/prnetdb.c"
,2239))
;
2240 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
2241 return PR_FAILURE;
2242}
2243
2244PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus PR_StringToNetAddr(const char* string, PRNetAddr* addr) {
2245 if (!_pr_initialized) {
2246 _PR_ImplicitInitialization();
2247 }
2248
2249 if (!addr || !string || !*string) {
2250 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
2251 return PR_FAILURE;
2252 }
2253
2254#if !defined(_PR_HAVE_GETADDRINFO)
2255 return pr_StringToNetAddrFB(string, addr);
2256#else
2257 /*
2258 * getaddrinfo with AI_NUMERICHOST is much slower than pr_inet_aton on some
2259 * platforms, such as Mac OS X (bug 404399), Linux glibc 2.10 (bug 344809),
2260 * and most likely others. So we only use it to convert literal IP addresses
2261 * that contain IPv6 scope IDs, which pr_inet_aton cannot convert.
2262 */
2263 if (!strchr(string, '%')) {
2264 return pr_StringToNetAddrFB(string, addr);
2265 }
2266
2267# if defined(_PR_INET6_PROBE)
2268 if (!_pr_ipv6_is_present()) {
2269 return pr_StringToNetAddrFB(string, addr);
2270 }
2271# endif
2272
2273 return pr_StringToNetAddrGAI(string, addr);
2274#endif
2275}
2276
2277#if defined(_PR_HAVE_GETADDRINFO)
2278static PRStatus pr_NetAddrToStringGNI(const PRNetAddr* addr, char* string,
2279 PRUint32 size) {
2280 int addrlen;
2281 const PRNetAddr* addrp = addr;
2282# if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
2283 PRUint16 md_af = addr->raw.family;
Value stored to 'md_af' during its initialization is never read
2284 PRNetAddr addrcopy;
2285# endif
2286 int rv; /* 0 for success, or the error code EAI_xxx */
2287
2288# ifdef _PR_INET6
2289 if (addr->raw.family == PR_AF_INET610) {
2290 md_af = AF_INET610;
2291# ifndef _PR_HAVE_SOCKADDR_LEN
2292 addrcopy = *addr;
2293 addrcopy.raw.family = md_af;
2294 addrp = &addrcopy;
2295# endif
2296 }
2297# endif
2298
2299 addrlen = PR_NETADDR_SIZE(addr)_PR_NetAddrSize(addr);
2300# ifdef _PR_HAVE_SOCKADDR_LEN
2301 addrcopy = *addr;
2302 ((struct sockaddr*)&addrcopy)->sa_len = addrlen;
2303 ((struct sockaddr*)&addrcopy)->sa_family = md_af;
2304 addrp = &addrcopy;
2305# endif
2306 rv = GETNAMEINFOgetnameinfo((const struct sockaddr*)addrp, addrlen, string, size, NULL((void*)0),
2307 0, NI_NUMERICHOST1);
2308 if (rv != 0) {
2309 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), rv);
2310 return PR_FAILURE;
2311 }
2312 return PR_SUCCESS;
2313}
2314#endif /* _PR_HAVE_GETADDRINFO */
2315
2316#if !defined(_PR_HAVE_GETADDRINFO) || defined(_PR_INET6_PROBE)
2317static PRStatus pr_NetAddrToStringFB(const PRNetAddr* addr, char* string,
2318 PRUint32 size) {
2319 if (PR_AF_INET610 == addr->raw.family) {
2320# if defined(_PR_HAVE_INET_NTOP)
2321 if (NULL((void*)0) == inet_ntop(AF_INET610, &addr->ipv6.ip, string, size))
2322# else
2323 if (NULL((void*)0) == V6AddrToString(&addr->ipv6.ip, string, size))
2324# endif
2325 {
2326 /* the size of the result buffer is inadequate */
2327 PR_SetError(PR_BUFFER_OVERFLOW_ERROR(-5962L), 0);
2328 return PR_FAILURE;
2329 }
2330 } else {
2331 if (size < 16) {
2332 goto failed;
2333 }
2334 if (AF_INET2 != addr->raw.family) {
2335 goto failed;
2336 } else {
2337 unsigned char* byte = (unsigned char*)&addr->inet.ip;
2338 PR_snprintf(string, size, "%u.%u.%u.%u", byte[0], byte[1], byte[2],
2339 byte[3]);
2340 }
2341 }
2342
2343 return PR_SUCCESS;
2344
2345failed:
2346 PR_SetError(PR_INVALID_ARGUMENT_ERROR(-5987L), 0);
2347 return PR_FAILURE;
2348
2349} /* pr_NetAddrToStringFB */
2350#endif /* !_PR_HAVE_GETADDRINFO || _PR_INET6_PROBE */
2351
2352PR_IMPLEMENT(PRStatus)__attribute__((visibility("default"))) PRStatus
2353PR_NetAddrToString(const PRNetAddr* addr, char* string, PRUint32 size) {
2354 if (!_pr_initialized) {
2355 _PR_ImplicitInitialization();
2356 }
2357
2358#if !defined(_PR_HAVE_GETADDRINFO)
2359 return pr_NetAddrToStringFB(addr, string, size);
2360#else
2361# if defined(_PR_INET6_PROBE)
2362 if (!_pr_ipv6_is_present()) {
2363 return pr_NetAddrToStringFB(addr, string, size);
2364 }
2365# endif
2366 return pr_NetAddrToStringGNI(addr, string, size);
2367#endif
2368} /* PR_NetAddrToString */