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

📄 getaddrinfo.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $	*//* * Copyright (C) 1995, 1996, 1997, and 1998 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. *//* * Issues to be discussed: * - Thread safe-ness must be checked. * - Return values.  There are nonstandard return values defined and used *   in the source code.  This is because RFC2553 is silent about which error *   code must be returned for which situation. * - IPv4 classful (shortened) form.  RFC2553 is silent about it.  XNET 5.2 *   says to use inet_aton() to convert IPv4 numeric to binary (allows *   classful form as a result). *   current code - disallow classful form for IPv4 (due to use of inet_pton). * - freeaddrinfo(NULL).  RFC2553 is silent about it.  XNET 5.2 says it is *   invalid. *   current code - SEGV on freeaddrinfo(NULL) * Note: * - We use getipnodebyname() just for thread-safeness.  There's no intent *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to *   getipnodebyname(). * - The code filters out AFs that are not supported by the kernel, *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG *   in ai_flags? * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. *   (1) what should we do against numeric hostname (2) what should we do *   against NULL hostname (3) what is AI_ADDRCONFIG itself.  AF not ready? *   non-loopback address configured?  global address configured? * - To avoid search order issue, we have a big amount of code duplicate *   from gethnamaddr.c and some other places.  The issues that there's no *   lower layer function to lookup "IPv4 or IPv6" record.  Calling *   gethostbyname2 from getaddrinfo will end up in wrong search order, as *   follows: *	- The code makes use of following calls when asked to resolver with *	  ai_family  = PF_UNSPEC: *		getipnodebyname(host, AF_INET6); *		getipnodebyname(host, AF_INET); *	  This will result in the following queries if the node is configure to *	  prefer /etc/hosts than DNS: *		lookup /etc/hosts for IPv6 address *		lookup DNS for IPv6 address *		lookup /etc/hosts for IPv4 address *		lookup DNS for IPv4 address *	  which may not meet people's requirement. *	  The right thing to happen is to have underlying layer which does *	  PF_UNSPEC lookup (lookup both) and return chain of addrinfos. *	  This would result in a bit of code duplicate with _dns_ghbyname() and *	  friends. */#include "port_before.h"#include <sys/types.h>#include <sys/param.h>#include <sys/socket.h>#include <net/if.h>#include <netinet/in.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include <netdb.h>#include <resolv.h>#include <string.h>#include <stdlib.h>#include <stddef.h>#include <ctype.h>#include <unistd.h>#include <stdio.h>#include <errno.h>#include <stdarg.h>#include <irs.h>#include <isc/assertions.h>#include "port_after.h"#include "irs_data.h"#define SUCCESS 0#define ANY 0#define YES 1#define NO  0static const char in_addrany[] = { 0, 0, 0, 0 };static const char in6_addrany[] = {	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};static const char in_loopback[] = { 127, 0, 0, 1 };static const char in6_loopback[] = {	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};static const struct afd {	int a_af;	int a_addrlen;	int a_socklen;	int a_off;	const char *a_addrany;	const char *a_loopback;	int a_scoped;} afdl [] = {	{PF_INET6, sizeof(struct in6_addr),	 sizeof(struct sockaddr_in6),	 offsetof(struct sockaddr_in6, sin6_addr),	 in6_addrany, in6_loopback, 1},	{PF_INET, sizeof(struct in_addr),	 sizeof(struct sockaddr_in),	 offsetof(struct sockaddr_in, sin_addr),	 in_addrany, in_loopback, 0},	{0, 0, 0, 0, NULL, NULL, 0},};struct explore {	int e_af;	int e_socktype;	int e_protocol;	const char *e_protostr;	int e_wild;#define WILD_AF(ex)		((ex)->e_wild & 0x01)#define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)#define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)};static const struct explore explore[] = {#if 0	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },#endif	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },	{ -1, 0, 0, NULL, 0 },};#define PTON_MAX	16static int str_isnumber __P((const char *));static int explore_fqdn __P((const struct addrinfo *, const char *,	const char *, struct addrinfo **));static int explore_copy __P((const struct addrinfo *, const struct addrinfo *,	struct addrinfo **));static int explore_null __P((const struct addrinfo *,	const char *, struct addrinfo **));static int explore_numeric __P((const struct addrinfo *, const char *,	const char *, struct addrinfo **));static int explore_numeric_scope __P((const struct addrinfo *, const char *,	const char *, struct addrinfo **));static int get_canonname __P((const struct addrinfo *,	struct addrinfo *, const char *));static struct addrinfo *get_ai __P((const struct addrinfo *,	const struct afd *, const char *));static struct addrinfo *copy_ai __P((const struct addrinfo *));static int get_portmatch __P((const struct addrinfo *, const char *));static int get_port __P((const struct addrinfo *, const char *, int));static const struct afd *find_afd __P((int));static int addrconfig __P((int));static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *,				u_int32_t *scopeidp));static struct net_data *init __P((void));struct addrinfo *hostent2addrinfo __P((struct hostent *,				       const struct addrinfo *));struct addrinfo *addr2addrinfo __P((const struct addrinfo *,				    const char *));#if 0static const char *ai_errlist[] = {	"Success",	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */	"Temporary failure in name resolution",		/* EAI_AGAIN      */	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */	"ai_family not supported",			/* EAI_FAMILY     */	"Memory allocation failure", 			/* EAI_MEMORY     */	"No address associated with hostname", 		/* EAI_NODATA     */	"hostname nor servname provided, or not known",	/* EAI_NONAME     */	"servname not supported for ai_socktype",	/* EAI_SERVICE    */	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */	"System error returned in errno", 		/* EAI_SYSTEM     */	"Invalid value for hints",			/* EAI_BADHINTS	  */	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */	"Unknown error", 				/* EAI_MAX        */};#endif/* XXX macros that make external reference is BAD. */#define GET_AI(ai, afd, addr) \do { \	/* external reference: pai, error, and label free */ \	(ai) = get_ai(pai, (afd), (addr)); \	if ((ai) == NULL) { \		error = EAI_MEMORY; \		goto free; \	} \} while (/*CONSTCOND*/0)#define GET_PORT(ai, serv) \do { \	/* external reference: error and label free */ \	error = get_port((ai), (serv), 0); \	if (error != 0) \		goto free; \} while (/*CONSTCOND*/0)#define GET_CANONNAME(ai, str) \do { \	/* external reference: pai, error and label free */ \	error = get_canonname(pai, (ai), (str)); \	if (error != 0) \		goto free; \} while (/*CONSTCOND*/0)#define ERR(err) \do { \	/* external reference: error, and label bad */ \	error = (err); \	goto bad; \	/*NOTREACHED*/ \} while (/*CONSTCOND*/0)#define MATCH_FAMILY(x, y, w) \	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))#define MATCH(x, y, w) \	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))#if 0				/* bind8 has its own version */char *gai_strerror(ecode)	int ecode;{	if (ecode < 0 || ecode > EAI_MAX)		ecode = EAI_MAX;	return ai_errlist[ecode];}#endifvoidfreeaddrinfo(ai)	struct addrinfo *ai;{	struct addrinfo *next;	do {		next = ai->ai_next;		if (ai->ai_canonname)			free(ai->ai_canonname);		/* no need to free(ai->ai_addr) */		free(ai);		ai = next;	} while (ai);}static intstr_isnumber(p)	const char *p;{	char *ep;	if (*p == '\0')		return NO;	ep = NULL;	errno = 0;	(void)strtoul(p, &ep, 10);	if (errno == 0 && ep && *ep == '\0')		return YES;	else		return NO;}intgetaddrinfo(hostname, servname, hints, res)	const char *hostname, *servname;	const struct addrinfo *hints;	struct addrinfo **res;{	struct addrinfo sentinel;	struct addrinfo *cur;	int error = 0;	struct addrinfo ai, ai0, *afai = NULL;	struct addrinfo *pai;	const struct explore *ex;	memset(&sentinel, 0, sizeof(sentinel));	cur = &sentinel;	pai = &ai;	pai->ai_flags = 0;	pai->ai_family = PF_UNSPEC;	pai->ai_socktype = ANY;	pai->ai_protocol = ANY;	pai->ai_addrlen = 0;	pai->ai_canonname = NULL;	pai->ai_addr = NULL;	pai->ai_next = NULL;	if (hostname == NULL && servname == NULL)		return EAI_NONAME;	if (hints) {		/* error check for hints */		if (hints->ai_addrlen || hints->ai_canonname ||		    hints->ai_addr || hints->ai_next)			ERR(EAI_BADHINTS); /* xxx */		if (hints->ai_flags & ~AI_MASK)			ERR(EAI_BADFLAGS);		switch (hints->ai_family) {		case PF_UNSPEC:		case PF_INET:		case PF_INET6:			break;		default:			ERR(EAI_FAMILY);		}		memcpy(pai, hints, sizeof(*pai));		/*		 * if both socktype/protocol are specified, check if they		 * are meaningful combination.		 */		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {			for (ex = explore; ex->e_af >= 0; ex++) {				if (pai->ai_family != ex->e_af)					continue;				if (ex->e_socktype == ANY)					continue;				if (ex->e_protocol == ANY)					continue;				if (pai->ai_socktype == ex->e_socktype &&				    pai->ai_protocol != ex->e_protocol) {					ERR(EAI_BADHINTS);				}			}		}	}	/*	 * post-2553: AI_ALL and AI_V4MAPPED are effective only against	 * AF_INET6 query.  They needs to be ignored if specified in other	 * occassions.	 */	switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {	case AI_V4MAPPED:	case AI_ALL | AI_V4MAPPED:		if (pai->ai_family != AF_INET6)			pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);		break;	case AI_ALL:#if 1		/* illegal */		ERR(EAI_BADFLAGS);#else		pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);		break;#endif	}	/*	 * check for special cases.  (1) numeric servname is disallowed if	 * socktype/protocol are left unspecified. (2) servname is disallowed	 * for raw and other inet{,6} sockets.	 */	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)#ifdef PF_INET6	 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)#endif	    ) {		ai0 = *pai;	/* backup *pai */		if (pai->ai_family == PF_UNSPEC) {#ifdef PF_INET6			pai->ai_family = PF_INET6;#else			pai->ai_family = PF_INET;#endif		}		error = get_portmatch(pai, servname);		if (error)			ERR(error);		*pai = ai0;	}	ai0 = *pai;	/* NULL hostname, or numeric hostname */	for (ex = explore; ex->e_af >= 0; ex++) {		*pai = ai0;		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))			continue;		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))			continue;		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))			continue;		if (pai->ai_family == PF_UNSPEC)			pai->ai_family = ex->e_af;		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)			pai->ai_socktype = ex->e_socktype;		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)			pai->ai_protocol = ex->e_protocol;		/*		 * if the servname does not match socktype/protocol, ignore it.		 */		if (get_portmatch(pai, servname) != 0)			continue;		if (hostname == NULL) {			/*			 * filter out AFs that are not supported by the kernel			 * XXX errno?			 */			if (!addrconfig(pai->ai_family))				continue;			error = explore_null(pai, servname, &cur->ai_next);		} else			error = explore_numeric_scope(pai, hostname, servname,			    &cur->ai_next);		if (error)			goto free;		while (cur && cur->ai_next)			cur = cur->ai_next;	}	/*	 * XXX	 * If numreic representation of AF1 can be interpreted as FQDN	 * representation of AF2, we need to think again about the code below.	 */	if (sentinel.ai_next)		goto good;	if (pai->ai_flags & AI_NUMERICHOST)		ERR(EAI_NONAME);	if (hostname == NULL)		ERR(EAI_NONAME);	/*	 * hostname as alphabetical name.	 * We'll make sure that	 * - if returning addrinfo list is empty, return non-zero error	 *   value (already known one or EAI_NONAME).	 * - otherwise, 	 *   + if we haven't had any errors, return 0 (i.e. success).	 *   + if we've had an error, free the list and return the error.	 * without any assumption on the behavior of explore_fqdn().	 */	/* first, try to query DNS for all possible address families. */	*pai = ai0;	error = explore_fqdn(pai, hostname, servname, &afai);	if (error) {		if (afai != NULL)			freeaddrinfo(afai);		goto free;	}	if (afai == NULL) {		error = EAI_NONAME; /* we've had no errors. */		goto free;	}	/*	 * we would like to prefer AF_INET6 than AF_INET, so we'll make an	 * outer loop by AFs.	 */	for (ex = explore; ex->e_af >= 0; ex++) {		*pai = ai0;		if (pai->ai_family == PF_UNSPEC)			pai->ai_family = ex->e_af;		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))			continue;		if (!MATCH(pai->ai_socktype, ex->e_socktype,			   WILD_SOCKTYPE(ex))) {			continue;		}		if (!MATCH(pai->ai_protocol, ex->e_protocol,			   WILD_PROTOCOL(ex))) {			continue;		}#ifdef AI_ADDRCONFIG		/*		 * If AI_ADDRCONFIG is specified, check if we are		 * expected to return the address family or not.		 */		if ((pai->ai_flags & AI_ADDRCONFIG) != 0 &&		    !addrconfig(pai->ai_family))			continue;#endif		if (pai->ai_family == PF_UNSPEC)			pai->ai_family = ex->e_af;		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)			pai->ai_socktype = ex->e_socktype;		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)			pai->ai_protocol = ex->e_protocol;		/*		 * if the servname does not match socktype/protocol, ignore it.		 */		if (get_portmatch(pai, servname) != 0)			continue;		if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) {			freeaddrinfo(afai);			goto free;		}		while (cur && cur->ai_next)			cur = cur->ai_next;	}	freeaddrinfo(afai);	/* afai must not be NULL at this point. */	/* we must not have got any errors. */	if (error != 0) /* just for diagnosis */		abort();	if (sentinel.ai_next) {good:		*res = sentinel.ai_next;		return(SUCCESS);	} else {		/*		 * All the process succeeded, but we've had an empty list. 		 * This can happen if the given hints do not match our		 * candidates.		 */		error = EAI_NONAME;	}free:bad:	if (sentinel.ai_next)		freeaddrinfo(sentinel.ai_next);	*res = NULL;	return(error);}/* * FQDN hostname, DNS lookup */static intexplore_fqdn(pai, hostname, servname, res)	const struct addrinfo *pai;	const char *hostname;	const char *servname;	struct addrinfo **res;{	struct addrinfo *result;	struct addrinfo *cur;	struct net_data *net_data = init();	struct irs_ho *ho;	int error = 0;	char tmp[NS_MAXDNAME];	const char *cp;	INSIST(res != NULL && *res == NULL);	/*	 * if the servname does not match socktype/protocol, ignore it.	 */	if (get_portmatch(pai, servname) != 0)		return(0);	if (!net_data || !(ho = net_data->ho))		return(0);#if 0				/* XXX (notyet) */	if (net_data->ho_stayopen && net_data->ho_last &&	    net_data->ho_last->h_addrtype == af) {		if (ns_samename(name, net_data->ho_last->h_name) == 1)			return (net_data->ho_last);		for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++)			if (ns_samename(name, *hap) == 1)				return (net_data->ho_last);	}#endif

⌨️ 快捷键说明

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