if (strlen(hp->h_name) > hostlen) {
if (strlen(hp->h_name) + 1 > hostlen) {
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)	const struct sockaddr *sa;	socklen_t salen;	char *host;	size_t hostlen;	char *serv;	size_t servlen;	int flags;{	struct afd *afd;	struct servent *sp;	struct hostent *hp;	u_short port;	int family, i;	const char *addr;	u_int32_t v4a;	int h_error;	char numserv[512];	char numaddr[512];	if (sa == NULL)		return ENI_NOSOCKET;	if (sa->sa_len != salen)		return ENI_SALEN;		family = sa->sa_family;	for (i = 0; afdl[i].a_af; i++)		if (afdl[i].a_af == family) {			afd = &afdl[i];			goto found;		}	return ENI_FAMILY;	 found:	if (salen != afd->a_socklen)		return ENI_SALEN;		/* network byte order */	port = ((const struct sockinet *)sa)->si_port;	addr = (const char *)sa + afd->a_off;	if (serv == NULL || servlen == 0) {		/*		 * do nothing in this case.		 * in case you are wondering if "&&" is more correct than		 * "||" here: RFC2553 says that serv == NULL OR servlen == 0		 * means that the caller does not want the result.		 */	} else {		if (flags & NI_NUMERICSERV)			sp = NULL;		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 {			snprintf(numserv, sizeof(numserv), "%d", ntohs(port));			if (strlen(numserv) > servlen)				return ENI_MEMORY;			strcpy(serv, numserv);		}	}	switch (sa->sa_family) {	case AF_INET:		v4a = (u_int32_t)		    ntohl(((const 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)			flags |= NI_NUMERICHOST;					break;#ifdef INET6	case AF_INET6:	    {		const struct sockaddr_in6 *sin6;		sin6 = (const struct sockaddr_in6 *)sa;		switch (sin6->sin6_addr.s6_addr[0]) {		case 0x00:			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))				;			else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))				;			else				flags |= NI_NUMERICHOST;			break;		default:			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {				flags |= NI_NUMERICHOST;			}			else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))				flags |= NI_NUMERICHOST;			break;		}	    }		break;#endif	}	if (host == NULL || hostlen == 0) {		/*		 * do nothing in this case.		 * in case you are wondering if "&&" is more correct than		 * "||" here: RFC2553 says that host == NULL OR hostlen == 0		 * means that the caller does not want the result.		 */	} else if (flags & NI_NUMERICHOST) {		int numaddrlen;		/* NUMERICHOST and NAMEREQD conflicts with each other */		if (flags & NI_NAMEREQD)			return ENI_NOHOSTNAME;		switch(afd->a_af) {#ifdef INET6		case AF_INET6:		{			int error;			if ((error = ip6_parsenumeric(sa, addr, host,						      hostlen, flags)) != 0)				return(error);			break;		}#endif		default:			if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))			    == NULL)				return ENI_SYSTEM;			numaddrlen = strlen(numaddr);			if (numaddrlen + 1 > hostlen) /* don't forget terminator */				return ENI_MEMORY;			strcpy(host, numaddr);			break;		}	} else {		hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);		h_error = h_errno;		if (hp) {#if 0			/*			 * commented out, since "for local host" is not			 * implemented here - see RFC2553 p30			 */			if (flags & NI_NOFQDN) {				char *p;				p = strchr(hp->h_name, '.');				if (p)					*p = '\0';			}#endif			if (strlen(hp->h_name) > hostlen) {				return ENI_MEMORY;			}			strcpy(host, hp->h_name);		} else {			if (flags & NI_NAMEREQD)				return ENI_NOHOSTNAME;			switch(afd->a_af) {#ifdef INET6			case AF_INET6:			{				int error;				if ((error = ip6_parsenumeric(sa, addr, host,							      hostlen,							      flags)) != 0)					return(error);				break;			}#endif			default:				if (inet_ntop(afd->a_af, addr, host,				    hostlen) == NULL)					return ENI_SYSTEM;				break;			}		}	}	return SUCCESS;}