⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prnetdb.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "primpl.h"#include <string.h>/* * On Unix, the error code for gethostbyname() and gethostbyaddr() * is returned in the global variable h_errno, instead of the usual * errno. */#if defined(XP_UNIX)#if defined(_PR_NEED_H_ERRNO)extern int h_errno;#endif#define _MD_GETHOST_ERRNO() h_errno#else#define _MD_GETHOST_ERRNO() _MD_ERRNO()#endif/* * The meaning of the macros related to gethostbyname, gethostbyaddr, * and gethostbyname2 is defined below. * - _PR_HAVE_THREADSAFE_GETHOST: the gethostbyXXX functions return *   the result in thread specific storage.  For example, AIX, HP-UX, *   and OSF1. * -  _PR_HAVE_GETHOST_R: have the gethostbyXXX_r functions. See next *   two macros. * - _PR_HAVE_GETHOST_R_INT: the gethostbyXXX_r functions return an *   int.  For example, Linux glibc. * - _PR_HAVE_GETHOST_R_POINTER: the gethostbyXXX_r functions return *   a struct hostent* pointer.  For example, Solaris and IRIX. */#if defined(_PR_NO_PREEMPT) || defined(_PR_HAVE_GETHOST_R) \    || defined(_PR_HAVE_THREADSAFE_GETHOST)#define _PR_NO_DNS_LOCK#endif#if defined(_PR_NO_DNS_LOCK)#define LOCK_DNS()#define UNLOCK_DNS()#elsePRLock *_pr_dnsLock = NULL;#define LOCK_DNS() PR_Lock(_pr_dnsLock)#define UNLOCK_DNS() PR_Unlock(_pr_dnsLock)#endif  /* defined(_PR_NO_DNS_LOCK) *//* * Some platforms have the reentrant getprotobyname_r() and * getprotobynumber_r().  However, they come in two flavors. * Some return a pointer to struct protoent, others return * an int. */#if defined(XP_BEOS) && defined(BONE_VERSION)#include <arpa/inet.h>  /* pick up define for inet_addr */#include <sys/socket.h>#define _PR_HAVE_GETPROTO_R#define _PR_HAVE_GETPROTO_R_POINTER#endif#if defined(SOLARIS) || (defined(BSDI) && defined(_REENTRANT)) \	|| (defined(LINUX) && defined(_REENTRANT) \        && !(defined(__GLIBC__) && __GLIBC__ >= 2))#define _PR_HAVE_GETPROTO_R#define _PR_HAVE_GETPROTO_R_POINTER#endif#if defined(OSF1) \        || defined(AIX4_3) || (defined(AIX) && defined(_THREAD_SAFE)) \	|| (defined(HPUX10_10) && defined(_REENTRANT)) \        || (defined(HPUX10_20) && defined(_REENTRANT))#define _PR_HAVE_GETPROTO_R#define _PR_HAVE_GETPROTO_R_INT#endif#if (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2)#define _PR_HAVE_GETPROTO_R#define _PR_HAVE_5_ARG_GETPROTO_R#endif#if !defined(_PR_HAVE_GETPROTO_R)PRLock* _getproto_lock = NULL;#endif#if defined(_PR_INET6_PROBE)PR_EXTERN(PRBool) _pr_ipv6_is_present;#endif#define _PR_IN6_IS_ADDR_UNSPECIFIED(a)				\				(((a)->pr_s6_addr32[0] == 0) &&	\				((a)->pr_s6_addr32[1] == 0) &&		\				((a)->pr_s6_addr32[2] == 0) &&		\				((a)->pr_s6_addr32[3] == 0)) #define _PR_IN6_IS_ADDR_LOOPBACK(a)					\               (((a)->pr_s6_addr32[0] == 0)	&&	\               ((a)->pr_s6_addr32[1] == 0)		&&	\               ((a)->pr_s6_addr32[2] == 0)		&&	\               ((a)->pr_s6_addr[12] == 0)		&&	\               ((a)->pr_s6_addr[13] == 0)		&&	\               ((a)->pr_s6_addr[14] == 0)		&&	\               ((a)->pr_s6_addr[15] == 0x1U)) const PRIPv6Addr _pr_in6addr_any =	{{{ 0, 0, 0, 0,										0, 0, 0, 0,										0, 0, 0, 0,										0, 0, 0, 0 }}};const PRIPv6Addr _pr_in6addr_loopback = {{{ 0, 0, 0, 0,											0, 0, 0, 0,											0, 0, 0, 0,											0, 0, 0, 0x1U }}};/* * The values at bytes 10 and 11 are compared using pointers to * 8-bit fields, and not 32-bit fields, to make the comparison work on * both big-endian and little-endian systems */#define _PR_IN6_IS_ADDR_V4MAPPED(a)			\		(((a)->pr_s6_addr32[0] == 0) 	&&	\		((a)->pr_s6_addr32[1] == 0)	&&	\		((a)->pr_s6_addr[8] == 0)		&&	\		((a)->pr_s6_addr[9] == 0)		&&	\		((a)->pr_s6_addr[10] == 0xff)	&&	\		((a)->pr_s6_addr[11] == 0xff))#define _PR_IN6_IS_ADDR_V4COMPAT(a)			\		(((a)->pr_s6_addr32[0] == 0) &&	\		((a)->pr_s6_addr32[1] == 0) &&		\		((a)->pr_s6_addr32[2] == 0))#define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->pr_s6_addr32[3])#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)/* * The _pr_QueryNetIfs() function finds out if the system has * IPv4 or IPv6 source addresses configured and sets _pr_have_inet_if * and _pr_have_inet6_if accordingly. * * We have an implementation using SIOCGIFCONF ioctl and a * default implementation that simply sets _pr_have_inet_if * and _pr_have_inet6_if to true.  A better implementation * would be to use the routing sockets (see Chapter 17 of * W. Richard Stevens' Unix Network Programming, Vol. 1, 2nd. Ed.) */static PRBool _pr_have_inet_if = PR_FALSE;static PRBool _pr_have_inet6_if = PR_FALSE;#undef DEBUG_QUERY_IFS#if defined(AIX)/* * Use SIOCGIFCONF ioctl on platforms that don't have routing * sockets.  Warning: whether SIOCGIFCONF ioctl returns AF_INET6 * network interfaces is not portable. * * The _pr_QueryNetIfs() function is derived from the code in * src/lib/libc/net/getifaddrs.c in BSD Unix and the code in * Section 16.6 of W. Richard Stevens' Unix Network Programming, * Vol. 1, 2nd. Ed. */#include <sys/ioctl.h>#include <sys/socket.h>#include <netinet/in.h>#include <net/if.h>#ifdef DEBUG_QUERY_IFSstatic void_pr_PrintIfreq(struct ifreq *ifr){    PRNetAddr addr;    struct sockaddr *sa;    const char* family;    char addrstr[64];    sa = &ifr->ifr_addr;    if (sa->sa_family == AF_INET) {        struct sockaddr_in *sin = (struct sockaddr_in *)sa;        family = "inet";        memcpy(&addr.inet.ip, &sin->sin_addr, sizeof(sin->sin_addr));    } else if (sa->sa_family == AF_INET6) {        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;        family = "inet6";        memcpy(&addr.ipv6.ip, &sin6->sin6_addr, sizeof(sin6->sin6_addr));    } else {        return;  /* skip if not AF_INET or AF_INET6 */    }    addr.raw.family = sa->sa_family;    PR_NetAddrToString(&addr, addrstr, sizeof(addrstr));    printf("%s: %s %s\n", ifr->ifr_name, family, addrstr);}#endifstatic void_pr_QueryNetIfs(void){    int sock;    int rv;    struct ifconf ifc;    struct ifreq *ifr;    struct ifreq *lifr;    PRUint32 len, lastlen;    char *buf;    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        return;    }    /* Issue SIOCGIFCONF request in a loop. */    lastlen = 0;    len = 100 * sizeof(struct ifreq);  /* initial buffer size guess */    for (;;) {        buf = (char *)PR_Malloc(len);        if (NULL == buf) {            close(sock);            return;        }        ifc.ifc_buf = buf;        ifc.ifc_len = len;        rv = ioctl(sock, SIOCGIFCONF, &ifc);        if (rv < 0) {            if (errno != EINVAL || lastlen != 0) {                close(sock);                PR_Free(buf);                return;            }        } else {            if (ifc.ifc_len == lastlen)                break;  /* success, len has not changed */            lastlen = ifc.ifc_len;        }        len += 10 * sizeof(struct ifreq);  /* increment */        PR_Free(buf);    }    close(sock);    ifr = ifc.ifc_req;    lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];    while (ifr < lifr) {        struct sockaddr *sa;        int sa_len;#ifdef DEBUG_QUERY_IFS        _pr_PrintIfreq(ifr);#endif        sa = &ifr->ifr_addr;        if (sa->sa_family == AF_INET) {            struct sockaddr_in *sin = (struct sockaddr_in *) sa;            if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {                _pr_have_inet_if = PR_TRUE;            }         } else if (sa->sa_family == AF_INET6) {            struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;            if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) {                _pr_have_inet6_if = PR_TRUE;            }         }#ifdef _PR_HAVE_SOCKADDR_LEN        sa_len = PR_MAX(sa->sa_len, sizeof(struct sockaddr));#else        switch (sa->sa_family) {#ifdef AF_LINK        case AF_LINK:            sa_len = sizeof(struct sockaddr_dl);            break;#endif        case AF_INET6:            sa_len = sizeof(struct sockaddr_in6);            break;        default:            sa_len = sizeof(struct sockaddr);            break;        }#endif        ifr = (struct ifreq *)(((char *)sa) + sa_len);    }    PR_Free(buf);}#else  /* default *//* * Emulate the code in NSPR 4.2 or older.  PR_GetIPNodeByName behaves * as if the system had both IPv4 and IPv6 source addresses configured. */static void_pr_QueryNetIfs(void){    _pr_have_inet_if = PR_TRUE;    _pr_have_inet6_if = PR_TRUE;}#endif#endif  /* _PR_INET6 && _PR_HAVE_GETHOSTBYNAME2 */void _PR_InitNet(void){#if defined(XP_UNIX)#ifdef HAVE_NETCONFIG	/*	 * This one-liner prevents the endless re-open's and re-read's of	 * /etc/netconfig on EACH and EVERY call to accept(), connect(), etc.	 */	 (void)setnetconfig();#endif#endif#if !defined(_PR_NO_DNS_LOCK)	_pr_dnsLock = PR_NewLock();#endif#if !defined(_PR_HAVE_GETPROTO_R)	_getproto_lock = PR_NewLock();#endif#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)	_pr_QueryNetIfs();#ifdef DEBUG_QUERY_IFS	if (_pr_have_inet_if)		printf("Have IPv4 source address\n");	if (_pr_have_inet6_if)		printf("Have IPv6 source address\n");#endif#endif}void _PR_CleanupNet(void){#if !defined(_PR_NO_DNS_LOCK)    if (_pr_dnsLock) {        PR_DestroyLock(_pr_dnsLock);        _pr_dnsLock = NULL;    }#endif#if !defined(_PR_HAVE_GETPROTO_R)    if (_getproto_lock) {        PR_DestroyLock(_getproto_lock);        _getproto_lock = NULL;    }#endif}/*** Allocate space from the buffer, aligning it to "align" before doing** the allocation. "align" must be a power of 2.*/static char *Alloc(PRIntn amount, char **bufp, PRIntn *buflenp, PRIntn align){	char *buf = *bufp;	PRIntn buflen = *buflenp;	if (align && ((long)buf & (align - 1))) {		PRIntn skip = align - ((ptrdiff_t)buf & (align - 1));		if (buflen < skip) {			return 0;		}		buf += skip;		buflen -= skip;	}	if (buflen < amount) {		return 0;	}	*bufp = buf + amount;	*buflenp = buflen - amount;	return buf;}typedef enum _PRIPAddrConversion {    _PRIPAddrNoConversion,    _PRIPAddrIPv4Mapped,    _PRIPAddrIPv4Compat} _PRIPAddrConversion;/*** Convert an IPv4 address (v4) to an IPv4-mapped IPv6 address (v6).*/static void MakeIPv4MappedAddr(const char *v4, char *v6){    memset(v6, 0, 10);    memset(v6 + 10, 0xff, 2);    memcpy(v6 + 12, v4, 4);}/*** Convert an IPv4 address (v4) to an IPv4-compatible IPv6 address (v6).*/static void MakeIPv4CompatAddr(const char *v4, char *v6){    memset(v6, 0, 12);    memcpy(v6 + 12, v4, 4);}/*** Copy a hostent, and all of the memory that it refers to into** (hopefully) stacked buffers.*/static PRStatus CopyHostent(    struct hostent *from,    char **buf,    PRIntn *bufsize,    _PRIPAddrConversion conversion,    PRHostEnt *to){	PRIntn len, na;	char **ap;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -