Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: nspr/pr/src/misc/prnetdb.c

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

Powered by Google App Engine
This is Rietveld 408576698