📄 name6.c
字号:
/* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ *//* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * ++Copyright++ 1985, 1988, 1993 * - * Copyright (c) 1985, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- *//* * Atsushi Onoe <onoe@sm.sony.co.jp> *//* * TODO for thread safe * use mutex for _hostconf, _hostconf_init. * rewrite resolvers to be thread safe */#include <sys/cdefs.h>#include <sys/types.h>#include <machine/endian.h>#include <sys/types.h>#include <unistd.h>#include "namespace.h"#include <sys/param.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/queue.h>#include <netinet/in.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include <errno.h>#include <netdb.h>#include <resolv.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <nsswitch.h>#include <unistd.h>#include "un-namespace.h"#ifndef _PATH_HOSTS#define _PATH_HOSTS "/etc/hosts"#endif#ifndef MAXALIASES#define MAXALIASES 35#endif#ifndef MAXADDRS#define MAXADDRS 2#endif#ifndef MAXDNAME#define MAXDNAME 1025#endif#ifdef INET6#define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \ sizeof(struct in_addr))#else#define ADDRLEN(af) sizeof(struct in_addr)#endif#define MAPADDR(ab, ina) \do { \ memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \ memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \ memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \} while (0)#define MAPADDRENABLED(flags) \ (((flags) & AI_V4MAPPED) || \ (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled()))union inx_addr { struct in_addr in_addr;#ifdef INET6 struct in6_addr in6_addr;#endif struct { u_char mau_zero[10]; u_char mau_one[2]; struct in_addr mau_inaddr; } map_addr_un;#define map_zero map_addr_un.mau_zero#define map_one map_addr_un.mau_one#define map_inaddr map_addr_un.mau_inaddr};u_int16_t _getshort(const u_char *src);static struct hostent *_hpcopy(struct hostent *hp, int *errp);static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp);static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp);#ifdef INET6static struct hostent *_hpmapv6(struct hostent *hp, int *errp);#endifstatic struct hostent *_hpsort(struct hostent *hp);static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp);static char *_hgetword(char **pp);static int _mapped_addr_enabled(void);static FILE *_files_open(int *errp);static int _files_ghbyname(void *, void *, va_list);static int _files_ghbyaddr(void *, void *, va_list);#if 0 // keep gcc happystatic void _files_shent(int stayopen);static void _files_ehent(void);#endif#ifdef YPstatic int _nis_ghbyname(void *, void *, va_list);static int _nis_ghbyaddr(void *, void *, va_list);#endifstatic int _dns_ghbyname(void *, void *, va_list);static int _dns_ghbyaddr(void *, void *, va_list);#if 0 // keep gcc happystatic void _dns_shent(int stayopen);static void _dns_ehent(void);#endif#ifdef ICMPNLstatic int _icmp_ghbyaddr(void *, void *, va_list);#endif /* ICMPNL *//* Host lookup order if nsswitch.conf is broken or nonexistant */static const ns_src default_src[] = { { NSSRC_FILES, NS_SUCCESS }, { NSSRC_DNS, NS_SUCCESS },#ifdef ICMPNL#define NSSRC_ICMP "icmp" { NSSRC_ICMP, NS_SUCCESS },#endif { 0 }};/* * Check if kernel supports mapped address. * implementation dependent */#ifdef __KAME__#include <sys/sysctl.h>#endif /* __KAME__ */static int_mapped_addr_enabled(void){ /* implementation dependent check */#if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR) int mib[4]; size_t len; int val; mib[0] = CTL_NET; mib[1] = PF_INET6; mib[2] = IPPROTO_IPV6; mib[3] = IPV6CTL_MAPPED_ADDR; len = sizeof(val); if (__sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0) return 1;#endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */ return 0;}/* * Functions defined in RFC2553 * getipnodebyname, getipnodebyaddr, freehostent */static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp){ struct hostent *hp; int rval; static const ns_dtab dtab[] = { NS_FILES_CB(_files_ghbyname, NULL) { NSSRC_DNS, _dns_ghbyname, NULL }, NS_NIS_CB(_nis_ghbyname, NULL) { 0 } }; if (flags & AI_ADDRCONFIG) { int s; /* * TODO: * Note that implementation dependent test for address * configuration should be done everytime called * (or apropriate interval), * because addresses will be dynamically assigned or deleted. */ if (af == AF_UNSPEC) { if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) af = AF_INET; else { close(s); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) af = AF_INET6; else close(s); } } if (af != AF_UNSPEC) { if ((s = socket(af, SOCK_DGRAM, 0)) < 0) return NULL; close(s); } } rval = nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src, name, af, errp); return (rval == NS_SUCCESS) ? hp : NULL;}/* getipnodebyname() internal routine for multiple query(PF_UNSPEC) support. */struct hostent *_getipnodebyname_multi(const char *name, int af, int flags, int *errp){ struct hostent *hp; union inx_addr addrbuf; /* XXX: PF_UNSPEC is only supposed to be passed from getaddrinfo() */ if (af != AF_INET#ifdef INET6 && af != AF_INET6#endif && af != PF_UNSPEC ) { *errp = NO_RECOVERY; return NULL; }#ifdef INET6 /* special case for literal address */ if (inet_pton(AF_INET6, name, &addrbuf) == 1) { if (af != AF_INET6) { *errp = HOST_NOT_FOUND; return NULL; } return _hpaddr(af, name, &addrbuf, errp); }#endif if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) { if (af != AF_INET) { if (MAPADDRENABLED(flags)) { MAPADDR(&addrbuf, &addrbuf.in_addr); } else { *errp = HOST_NOT_FOUND; return NULL; } } return _hpaddr(af, name, &addrbuf, errp); } *errp = HOST_NOT_FOUND; hp = _ghbyname(name, af, flags, errp);#ifdef INET6 if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) && (MAPADDRENABLED(flags))) { struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp); if (hp == NULL) hp = _hpmapv6(hp2, errp); else { if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) { freehostent(hp2); hp2 = NULL; } hp = _hpmerge(hp, hp2, errp); } }#endif return _hpsort(hp);}struct hostent *getipnodebyname(const char *name, int af, int flags, int *errp){ if (af != AF_INET#ifdef INET6 && af != AF_INET6#endif ) { *errp = NO_RECOVERY; return NULL; } return(_getipnodebyname_multi(name, af ,flags, errp));}struct hostent *getipnodebyaddr(const void *src, size_t len, int af, int *errp){ struct hostent *hp; int rval;#ifdef INET6 struct in6_addr addrbuf;#else struct in_addr addrbuf;#endif static const ns_dtab dtab[] = { NS_FILES_CB(_files_ghbyaddr, NULL) { NSSRC_DNS, _dns_ghbyaddr, NULL }, NS_NIS_CB(_nis_ghbyaddr, NULL)#ifdef ICMPNL { NSSRC_ICMP, _icmp_ghbyaddr, NULL },#endif { 0 } }; *errp = HOST_NOT_FOUND; switch (af) { case AF_INET: if (len != sizeof(struct in_addr)) { *errp = NO_RECOVERY; return NULL; } if ((long)src & ~(sizeof(struct in_addr) - 1)) { memcpy(&addrbuf, src, len); src = &addrbuf; } if (((struct in_addr *)src)->s_addr == 0) return NULL; break;#ifdef INET6 case AF_INET6: if (len != sizeof(struct in6_addr)) { *errp = NO_RECOVERY; return NULL; } if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/ memcpy(&addrbuf, src, len); src = &addrbuf; } if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src)) return NULL; if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { src = (char *)src + (sizeof(struct in6_addr) - sizeof(struct in_addr)); af = AF_INET; len = sizeof(struct in_addr); } break;#endif default: *errp = NO_RECOVERY; return NULL; } rval = nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src, src, len, af, errp); return (rval == NS_SUCCESS) ? hp : NULL;}voidfreehostent(struct hostent *ptr){ free(ptr);}#if 0/* XXX: should be deprecated */struct hostent *getnodebyname(const char *name, int af, int flags){ return getipnodebyname(name, af, flags, &h_errno);}#ifdef __warn_references__warn_references(getnodebyname, "warning: getnodebyname() deprecated, " "should use getaddrinfo() or getipnodebyname()");#endifstruct hostent *getnodebyaddr(const void *src, size_t len, int af){ return getipnodebyaddr(src, len, af, &h_errno);}#ifdef __warn_references__warn_references(getnodebyaddr, "warning: getnodebyaddr() deprecated, " "should use getnameinfo() or getipnodebyaddr()");#endif#endif/* * Private utility functions *//* * _hpcopy: allocate and copy hostent structure */static struct hostent *_hpcopy(struct hostent *hp, int *errp){ struct hostent *nhp; char *cp, **pp; int size, addrsize; int nalias = 0, naddr = 0; int al_off; int i; if (hp == NULL) return hp; /* count size to be allocated */ size = sizeof(struct hostent); if (hp->h_name != NULL) size += strlen(hp->h_name) + 1; if ((pp = hp->h_aliases) != NULL) { for (i = 0; *pp != NULL; i++, pp++) { if (**pp != '\0') { size += strlen(*pp) + 1; nalias++; } } } /* adjust alignment */#ifdef ALIGN size = ALIGN(size);#endif al_off = size; size += sizeof(char *) * (nalias + 1);#ifdef ALIGN addrsize = ALIGN(hp->h_length);#else addrsize = hp->h_length;#endif if ((pp = hp->h_addr_list) != NULL) { while (*pp++ != NULL) naddr++; } size += addrsize * naddr; size += sizeof(char *) * (naddr + 1); /* copy */ if ((nhp = (struct hostent *)malloc(size)) == NULL) { *errp = TRY_AGAIN; return NULL; } cp = (char *)&nhp[1]; if (hp->h_name != NULL) { nhp->h_name = cp; strcpy(cp, hp->h_name); cp += strlen(cp) + 1; } else nhp->h_name = NULL; nhp->h_aliases = (char **)((char *)nhp + al_off); if ((pp = hp->h_aliases) != NULL) { for (i = 0; *pp != NULL; pp++) { if (**pp != '\0') { nhp->h_aliases[i++] = cp; strcpy(cp, *pp); cp += strlen(cp) + 1; } } } nhp->h_aliases[nalias] = NULL; cp = (char *)&nhp->h_aliases[nalias + 1]; nhp->h_addrtype = hp->h_addrtype; nhp->h_length = hp->h_length; nhp->h_addr_list = (char **)cp; if ((pp = hp->h_addr_list) != NULL) { cp = (char *)&nhp->h_addr_list[naddr + 1]; for (i = 0; *pp != NULL; pp++) { nhp->h_addr_list[i++] = cp; memcpy(cp, *pp, hp->h_length); cp += addrsize; } } nhp->h_addr_list[naddr] = NULL; return nhp;}/* * _hpaddr: construct hostent structure with one address */static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp){ struct hostent *hp, hpbuf; char *addrs[2]; hp = &hpbuf; hp->h_name = (char *)name; hp->h_aliases = NULL; hp->h_addrtype = af; hp->h_length = ADDRLEN(af); hp->h_addr_list = addrs; addrs[0] = (char *)addr; addrs[1] = NULL; return _hpcopy(hp, errp);}/* * _hpmerge: merge 2 hostent structure, arguments will be freed */static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp){ int i, j; int naddr, nalias; char **pp; struct hostent *hp, hpbuf; char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1]; union inx_addr addrbuf[MAXADDRS]; if (hp1 == NULL) return hp2; if (hp2 == NULL) return hp1;#define HP(i) (i == 1 ? hp1 : hp2) hp = &hpbuf; hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -