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

📄 su_addrinfo.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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. */#include "config.h"#include <sofia-sip/su_addrinfo.h>#include <sofia-sip/su.h>#ifndef IN_LOOPBACKNET#define IN_LOOPBACKNET          127#endif#ifndef IN_EXPERIMENTAL#define IN_EXPERIMENTAL(a)      ((((long int) (a)) & 0xf0000000) == 0xf0000000)#endif#if !HAVE_GETADDRINFO#include <string.h>#include <stddef.h>#include <stdlib.h>#include <ctype.h>/* * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. * * 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 RFC2133 is silent about which error *   code must be returned for which situation. * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag. */#if defined(__KAME__) && defined(INET6)# define FAITH#endif#define SUCCESS 0#define GAI_ANY 0#define YES 1#define NO  0#undef SU_HAVE_IN6#ifdef FAITHstatic int translate = NO;static struct in6_addr faith_prefix = IN6ADDR_GAI_ANY_INIT;#endifstatic 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};struct sockinet {	u_char	si_len;	u_char	si_family;	u_short	si_port;};static struct gai_afd {	int a_af;	int a_addrlen;	int a_socklen;	int a_off;	const char *a_addrany;	const char *a_loopback;	} gai_afdl [] = {#if SU_HAVE_IN6#define N_INET6 0	{PF_INET6, sizeof(struct in6_addr),	 sizeof(struct sockaddr_in6),	 offsetof(struct sockaddr_in6, sin6_addr),	 in6_addrany, in6_loopback},#define N_INET  1#else#define N_INET  0#endif	{PF_INET, sizeof(struct in_addr),	 sizeof(struct sockaddr_in),	 offsetof(struct sockaddr_in, sin_addr),	 in_addrany, in_loopback},	{0, 0, 0, 0, NULL, NULL},};#if SU_HAVE_IN6#define PTON_MAX	16#else#define PTON_MAX	4#endif#if SU_HAVE_IN6 && !defined(s6_addr8)#  define s6_addr8 s6_addr#endif#if !SU_HAVE_IN6#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)#elseextern int h_errno;#endif#endifstatic int get_name(const char *, struct gai_afd *,		    struct addrinfo **, char *, struct addrinfo *,		    int);static int get_addr(const char *, int, struct addrinfo **,		    struct addrinfo *, int);static int str_isnumber(const char *);	#define GET_CANONNAME(ai, str) \if (pai->ai_flags & AI_CANONNAME) {\	if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\		strcpy((ai)->ai_canonname, (str));\	} else {\		error = EAI_MEMORY;\		goto free;\	}\}#if SU_HAVE_SOCKADDR_SA_LEN#define GET_AI(ai, gai_afd, addr, port) {\	char *p;\	if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\					      ((gai_afd)->a_socklen)))\	    == NULL) goto free;\	memcpy(ai, pai, sizeof(struct addrinfo));\	(ai)->ai_addr = (struct sockaddr *)((ai) + 1);\	memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\	(ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\	(ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\	((struct sockinet *)(ai)->ai_addr)->si_port = port;\	p = (char *)((ai)->ai_addr);\	memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\}#else#define GET_AI(ai, gai_afd, addr, port) {\	char *p;\	if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\					      ((gai_afd)->a_socklen)))\	    == NULL) goto free;\	memcpy(ai, pai, sizeof(struct addrinfo));\	(ai)->ai_addr = (struct sockaddr *)((ai) + 1);\	memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\	(ai)->ai_addrlen = (gai_afd)->a_socklen; \	(ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\	((struct sockinet *)(ai)->ai_addr)->si_port = port;\	p = (char *)((ai)->ai_addr);\	memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\}#endif#define ERR(err) { error = (err); goto bad; }static intstr_isnumber(p)	const char *p;{	char *q = (char *)p;	while (*q) {		if (! isdigit(*q))			return NO;		q++;	}	return YES;}staticintgetaddrinfo(hostname, servname, hints, res)	const char *hostname, *servname;	const struct addrinfo *hints;	struct addrinfo **res;{	struct addrinfo sentinel;	struct addrinfo *top = NULL;	struct addrinfo *cur;	int i, error = 0;	char pton[PTON_MAX];	struct addrinfo ai;	struct addrinfo *pai;	u_short port;#ifdef FAITH	static int firsttime = 1;	if (firsttime) {		/* translator hack */		{			char *q = getenv("GAI");			if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)				translate = YES;		}		firsttime = 0;	}#endif	/* initialize file static vars */	sentinel.ai_next = NULL;	cur = &sentinel;	pai = &ai;	pai->ai_flags = 0;	pai->ai_family = PF_UNSPEC;	pai->ai_socktype = GAI_ANY;	pai->ai_protocol = GAI_ANY;	pai->ai_addrlen = 0;	pai->ai_canonname = NULL;	pai->ai_addr = NULL;	pai->ai_next = NULL;	port = GAI_ANY;		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:#if SU_HAVE_IN6		case PF_INET6:#endif			break;		default:			ERR(EAI_FAMILY);		}		memcpy(pai, hints, sizeof(*pai));		switch (pai->ai_socktype) {		case GAI_ANY:			switch (pai->ai_protocol) {			case GAI_ANY:				break;			case IPPROTO_UDP:				pai->ai_socktype = SOCK_DGRAM;				break;			case IPPROTO_TCP:				pai->ai_socktype = SOCK_STREAM;				break;#if HAVE_SCTP			case IPPROTO_SCTP:				pai->ai_socktype = SOCK_STREAM;				break;#endif			default:				pai->ai_socktype = SOCK_RAW;				break;			}			break;		case SOCK_RAW:			break;		case SOCK_DGRAM:			if (pai->ai_protocol != IPPROTO_UDP &&#if HAVE_SCTP			    pai->ai_protocol != IPPROTO_SCTP &&#endif			    pai->ai_protocol != GAI_ANY)				ERR(EAI_BADHINTS);	/*xxx*/			if (pai->ai_protocol == GAI_ANY)				pai->ai_protocol = IPPROTO_UDP;			break;		case SOCK_STREAM:			if (pai->ai_protocol != IPPROTO_TCP &&#if HAVE_SCTP			    pai->ai_protocol != IPPROTO_SCTP &&#endif			    pai->ai_protocol != GAI_ANY)				ERR(EAI_BADHINTS);	/*xxx*/			if (pai->ai_protocol == GAI_ANY)				pai->ai_protocol = IPPROTO_TCP;			break;#if HAVE_SCTP		case SOCK_SEQPACKET:			if (pai->ai_protocol != IPPROTO_SCTP &&			    pai->ai_protocol != GAI_ANY)				ERR(EAI_BADHINTS);	/*xxx*/			if (pai->ai_protocol == GAI_ANY)				pai->ai_protocol = IPPROTO_SCTP;			break;#endif		default:			ERR(EAI_SOCKTYPE);			break;		}	}	/*	 * service port	 */	if (servname) {		if (str_isnumber(servname)) {			if (pai->ai_socktype == GAI_ANY) {				/* caller accept *GAI_ANY* socktype */				pai->ai_socktype = SOCK_DGRAM;				pai->ai_protocol = IPPROTO_UDP;			}			port = htons(atoi(servname));		} else {			struct servent *sp;			char *proto;			proto = NULL;			switch (pai->ai_socktype) {			case GAI_ANY:				proto = NULL;				break;			case SOCK_DGRAM:				proto = "udp";				break;			case SOCK_STREAM:				proto = "tcp";				break;			default:				fprintf(stderr, "panic!\n");				break;			}			if ((sp = getservbyname(servname, proto)) == NULL)				ERR(EAI_SERVICE);			port = sp->s_port;			if (pai->ai_socktype == GAI_ANY) {				if (strcmp(sp->s_proto, "udp") == 0) {					pai->ai_socktype = SOCK_DGRAM;					pai->ai_protocol = IPPROTO_UDP;				} else if (strcmp(sp->s_proto, "tcp") == 0) {					pai->ai_socktype = SOCK_STREAM;					pai->ai_protocol = IPPROTO_TCP;#if HAVE_SCTP				} else if (strcmp(sp->s_proto, "sctp") == 0) {					pai->ai_socktype = SOCK_STREAM;					pai->ai_protocol = IPPROTO_SCTP;#endif				} else					ERR(EAI_PROTOCOL);	/*xxx*/			}		}	}		/*	 * hostname == NULL.	 * passive socket -> anyaddr (0.0.0.0 or ::)	 * non-passive socket -> localhost (127.0.0.1 or ::1)	 */	if (hostname == NULL) {		struct gai_afd *gai_afd;		for (gai_afd = &gai_afdl[0]; gai_afd->a_af; gai_afd++) {			if (!(pai->ai_family == PF_UNSPEC			   || pai->ai_family == gai_afd->a_af)) {				continue;			}			if (pai->ai_flags & AI_PASSIVE) {				GET_AI(cur->ai_next, gai_afd, gai_afd->a_addrany, port);				/* xxx meaningless?				 * GET_CANONNAME(cur->ai_next, "anyaddr");				 */			} else {				GET_AI(cur->ai_next, gai_afd, gai_afd->a_loopback,					port);				/* xxx meaningless?				 * GET_CANONNAME(cur->ai_next, "localhost");				 */			}			cur = cur->ai_next;		}		top = sentinel.ai_next;		if (top)			goto good;		else			ERR(EAI_FAMILY);	}		/* hostname as numeric name */	for (i = 0; gai_afdl[i].a_af; i++) {		if (inet_pton(gai_afdl[i].a_af, hostname, pton)) {			u_long v4a;			u_char pfx;			switch (gai_afdl[i].a_af) {			case AF_INET:				v4a = ((struct in_addr *)pton)->s_addr;				if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))					pai->ai_flags &= ~AI_CANONNAME;				v4a >>= IN_CLASSA_NSHIFT;				if (v4a == 0 || v4a == IN_LOOPBACKNET)					pai->ai_flags &= ~AI_CANONNAME;				break;#if SU_HAVE_IN6			case AF_INET6:				pfx = ((struct in6_addr *)pton)->s6_addr8[0];				if (pfx == 0 || pfx == 0xfe || pfx == 0xff)					pai->ai_flags &= ~AI_CANONNAME;				break;#endif			}						if (pai->ai_family == gai_afdl[i].a_af ||			    pai->ai_family == PF_UNSPEC) {				if (! (pai->ai_flags & AI_CANONNAME)) {					GET_AI(top, &gai_afdl[i], pton, port);					goto good;				}				/*				 * if AI_CANONNAME and if reverse lookup				 * fail, return ai anyway to pacify				 * calling application.				 *				 * XXX getaddrinfo() is a name->address				 * translation function, and it looks strange				 * that we do addr->name translation here.				 */				get_name(pton, &gai_afdl[i], &top, pton, pai, port);				goto good;			} else 				ERR(EAI_FAMILY);	/*xxx*/		}	}	if (pai->ai_flags & AI_NUMERICHOST)		ERR(EAI_NONAME);	/* hostname as alphabetical name */	error = get_addr(hostname, pai->ai_family, &top, pai, port);	if (error == 0) {		if (top) { good:			*res = top;			return SUCCESS;		} else			error = EAI_FAIL;	} free:	if (top)		freeaddrinfo(top); bad:	*res = NULL;	return error;}static int

⌨️ 快捷键说明

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