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

📄 su_addrinfo.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
get_name(addr, gai_afd, res, numaddr, pai, port0)	const char *addr;	struct gai_afd *gai_afd;	struct addrinfo **res;	char *numaddr;	struct addrinfo *pai;	int port0;{	u_short port = port0 & 0xffff;	struct hostent *hp;	struct addrinfo *cur;	int error = 0, h_error;	#if SU_HAVE_IN6	hp = getipnodebyaddr(addr, gai_afd->a_addrlen, gai_afd->a_af, &h_error);#else	hp = gethostbyaddr(addr, gai_afd->a_addrlen, AF_INET);#endif	if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {		GET_AI(cur, gai_afd, hp->h_addr_list[0], port);		GET_CANONNAME(cur, hp->h_name);	} else		GET_AI(cur, gai_afd, numaddr, port);	#if SU_HAVE_IN6	if (hp)		freehostent(hp);#endif	*res = cur;	return SUCCESS; free:	if (cur)		freeaddrinfo(cur);#if SU_HAVE_IN6	if (hp)		freehostent(hp);#endif /* bad: */	*res = NULL;	return error;}static intget_addr(hostname, af, res, pai, port0)	const char *hostname;	int af;	struct addrinfo **res;	struct addrinfo *pai;	int port0;{	u_short port = port0 & 0xffff;	struct addrinfo sentinel;	struct hostent *hp;	struct addrinfo *top, *cur;	struct gai_afd *gai_afd;	int i, error = 0, h_error;	char *ap;	top = NULL;	sentinel.ai_next = NULL;	cur = &sentinel;#if SU_HAVE_IN6	if (af == AF_UNSPEC) {		hp = getipnodebyname(hostname, AF_INET6,				AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);	} else		hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);#else	hp = gethostbyname(hostname);	h_error = h_errno;#endif	if (hp == NULL) {		switch (h_error) {		case HOST_NOT_FOUND:		case NO_DATA:			error = EAI_NODATA;			break;		case TRY_AGAIN:			error = EAI_AGAIN;			break;		case NO_RECOVERY:		default:			error = EAI_FAIL;			break;		}		goto bad;	}	if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||	    (hp->h_addr_list[0] == NULL))		ERR(EAI_FAIL);		for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {		switch (af) {#if SU_HAVE_IN6		case AF_INET6:			gai_afd = &gai_afdl[N_INET6];			break;#endif#ifndef INET6		default:	/* AF_UNSPEC */#endif		case AF_INET:			gai_afd = &gai_afdl[N_INET];			break;#if SU_HAVE_IN6		default:	/* AF_UNSPEC */			if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {				ap += sizeof(struct in6_addr) -					sizeof(struct in_addr);				gai_afd = &gai_afdl[N_INET];			} else				gai_afd = &gai_afdl[N_INET6];			break;#endif		}#ifdef FAITH		if (translate && gai_afd->a_af == AF_INET) {			struct in6_addr *in6;			GET_AI(cur->ai_next, &gai_afdl[N_INET6], ap, port);			in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;			memcpy(&in6->s6_addr32[0], &faith_prefix,			    sizeof(struct in6_addr) - sizeof(struct in_addr));			memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));		} else#endif /* FAITH */		GET_AI(cur->ai_next, gai_afd, ap, port);		if (cur == &sentinel) {			top = cur->ai_next;			GET_CANONNAME(top, hp->h_name);		}		cur = cur->ai_next;	}#if SU_HAVE_IN6	freehostent(hp);#endif	*res = top;	return SUCCESS; free:	if (top)		freeaddrinfo(top);#if SU_HAVE_IN6	if (hp)		freehostent(hp);#endif bad:	*res = NULL;	return error;}/* * Issues to be discussed: * - Thread safe-ness must be checked * - Return values.  There seems to be no standard for return value (RFC2133) *   but INRIA implementation returns EAI_xxx defined for getaddrinfo(). */#define SUCCESS 0#define YES 1#define NO  0static struct gni_afd {	int a_af;	int a_addrlen;	int a_socklen;	int a_off;} gni_afdl [] = {#if SU_HAVE_IN6	{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),		offsetof(struct sockaddr_in6, sin6_addr)},#endif	{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),		offsetof(struct sockaddr_in, sin_addr)},	{0, 0, 0},};struct gni_sockinet {	u_char	si_len;	u_char	si_family;	u_short	si_port;};#define ENI_NOSOCKET 	EAI_FAIL#define ENI_NOSERVNAME	EAI_NONAME#define ENI_NOHOSTNAME	EAI_NONAME#define ENI_MEMORY	EAI_MEMORY#define ENI_SYSTEM	EAI_SYSTEM#define ENI_FAMILY	EAI_FAMILY#define ENI_SALEN	EAI_MEMORYstaticintgetnameinfo(sa, salen, host, hostlen, serv, servlen, flags)	const struct sockaddr *sa;	size_t salen;	char *host;	size_t hostlen;	char *serv;	size_t servlen;	int flags;{	struct gni_afd *gni_afd;	struct servent *sp;	struct hostent *hp;	u_short port;	int family, len, i;	char *addr, *p;	u_long v4a;	u_char pfx;	int h_error;	char numserv[512];	char numaddr[512];	if (sa == NULL)		return ENI_NOSOCKET;#if SU_HAVE_SOCKADDR_SA_LEN	len = sa->sa_len;	if (len != salen) return ENI_SALEN;#else	len = salen;#endif		family = sa->sa_family;	for (i = 0; gni_afdl[i].a_af; i++)		if (gni_afdl[i].a_af == family) {			gni_afd = &gni_afdl[i];			goto found;		}	return ENI_FAMILY;	 found:	if (len != gni_afd->a_socklen) return ENI_SALEN;		port = ((struct gni_sockinet *)sa)->si_port; /* network byte order */	addr = (char *)sa + gni_afd->a_off;	if (serv == NULL || servlen == 0) {		/* what we should do? */	} else if (flags & NI_NUMERICSERV) {		snprintf(numserv, sizeof(numserv), "%d", ntohs(port));		if (strlen(numserv) > servlen)			return ENI_MEMORY;		strcpy(serv, numserv);	} else {		sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");		if (sp) {			if (strlen(sp->s_name) > servlen)				return ENI_MEMORY;			strcpy(serv, sp->s_name);		} else			return ENI_NOSERVNAME;	}	switch (sa->sa_family) {	case AF_INET:		v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;		if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))			flags |= NI_NUMERICHOST;		v4a >>= IN_CLASSA_NSHIFT;		if (v4a == 0 || v4a == IN_LOOPBACKNET)			flags |= NI_NUMERICHOST;					break;#if SU_HAVE_IN6	case AF_INET6:		pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];		if (pfx == 0 || pfx == 0xfe || pfx == 0xff)			flags |= NI_NUMERICHOST;		break;#endif	}	if (host == NULL || hostlen == 0) {		/* what should we do? */	} else if (flags & NI_NUMERICHOST) {		if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))		    == NULL)			return ENI_SYSTEM;		if (strlen(numaddr) > hostlen)			return ENI_MEMORY;		strcpy(host, numaddr);	} else {#if SU_HAVE_IN6		hp = getipnodebyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af, &h_error);#else		hp = gethostbyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af);		h_error = h_errno;#endif		if (hp) {			if (flags & NI_NOFQDN) {				p = strchr(hp->h_name, '.');				if (p) *p = '\0';			}			if (strlen(hp->h_name) > hostlen) {#if SU_HAVE_IN6				freehostent(hp);#endif				return ENI_MEMORY;			}			strcpy(host, hp->h_name);#if SU_HAVE_IN6			freehostent(hp);#endif		} else {			if (flags & NI_NAMEREQD)				return ENI_NOHOSTNAME;			if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))			    == NULL)				return ENI_NOHOSTNAME;			if (strlen(numaddr) > hostlen)				return ENI_MEMORY;			strcpy(host, numaddr);		}	}	return SUCCESS;}#endif	/* !HAVE_GETNAMEINFO */#if !HAVE_FREEADDRINFOstatic voidfreeaddrinfo(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);	} while ((ai = next) != NULL);}#endif#if !HAVE_GAI_STRERRORstatic char *gai_strerror(ecode)	int ecode;{  switch (ecode) {  case 0:     return "success.";#if defined(EAI_ADDRFAMILY)  case EAI_ADDRFAMILY:    return "address family for hostname not supported.";#endif#if defined(EAI_AGAIN)  case EAI_AGAIN:    return "temporary failure in name resolution.";#endif#if defined(EAI_BADFLAGS)  case EAI_BADFLAGS:    return "invalid value for ai_flags.";#endif#if defined(EAI_FAIL)  case EAI_FAIL:    return "non-recoverable failure in name resolution.";#endif#if defined(EAI_FAMILY)  case EAI_FAMILY:    return "ai_family not supported.";#endif#if defined(EAI_MEMORY)  case EAI_MEMORY:    return "memory allocation failure.";#endif#if defined(EAI_NODATA)  case EAI_NODATA:    return "no address associated with hostname.";#endif#if defined(EAI_NONAME)  case EAI_NONAME:    return "hostname nor servname provided, or not known.";#endif#if defined(EAI_SERVICE)  case EAI_SERVICE:    return "servname not supported for ai_socktype.";#endif#if defined(EAI_SOCKTYPE)  case EAI_SOCKTYPE:    return "ai_socktype not supported.";#endif#if defined(EAI_SYSTEM)  case EAI_SYSTEM:    return "system error returned in errno.";#endif#if defined(EAI_BADHINTS)  case EAI_BADHINTS:    return "invalid value for hints.";#endif#if defined(EAI_PROTOCOL)  case EAI_PROTOCOL:    return "resolved protocol is unknown.";#endif  default:    return "unknown error.";  }}#endif/** Translate address and service. * * This is a getaddrinfo() supporting SCTP and other exotic protocols. */int su_getaddrinfo(char const *node, char const *service,		   su_addrinfo_t const *hints,		   su_addrinfo_t **res){#if HAVE_SCTP  if (res && hints && hints->ai_protocol == IPPROTO_SCTP) {    su_addrinfo_t *ai, system_hints[1];    int retval, socktype;    socktype = hints->ai_socktype;        if (!(socktype == 0 ||	  socktype == SOCK_SEQPACKET ||	  socktype == SOCK_STREAM ||	  socktype == SOCK_DGRAM))      return EAI_SOCKTYPE;    *system_hints = *hints;    system_hints->ai_protocol = IPPROTO_TCP;    system_hints->ai_socktype = SOCK_STREAM;    retval = getaddrinfo(node, service, system_hints, res);    if (retval)      return retval;    if (socktype == 0)      socktype = SOCK_STREAM;    for (ai = *res; ai; ai = ai->ai_next) {      ai->ai_protocol = IPPROTO_SCTP;      ai->ai_socktype = socktype;    }    return 0;  }#endif  return getaddrinfo(node, service, hints, res);}/** Free su_addrinfo_t structure allocated by su_getaddrinfo(). */void su_freeaddrinfo(su_addrinfo_t *res){  freeaddrinfo(res);}/** Return string describing address translation error. */char const *su_gai_strerror(int errcode){  return gai_strerror(errcode);}/** Resolve socket address into hostname and service name */intsu_getnameinfo(const su_sockaddr_t *su, size_t sulen,	       char *return_host, size_t hostlen,	       char *return_serv, size_t servlen,	       int flags){  return getnameinfo(&su->su_sa, sulen, 		     return_host, hostlen, 		     return_serv, servlen, 		     flags);}

⌨️ 快捷键说明

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