if (addrlen < min_addrlen) return -1;
getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,	     size_t hostlen, char *serv, size_t servlen, int flags){  int serrno = errno;  int tmpbuflen = 1024;  int herrno;  char *tmpbuf = alloca (tmpbuflen);  struct hostent th;  socklen_t min_addrlen = 0;  int ok = 0;  if (sa == NULL || addrlen < sizeof (sa_family_t))    return -1;  switch (sa->sa_family)    {    case AF_LOCAL:      min_addrlen = (socklen_t) (((struct sockaddr_un *) NULL)->sun_path);      break;    default:      min_addrlen = __libc_sa_len (sa->sa_family);    }  if (addrlen < min_addrlen)    return -1;  if (host != NULL && hostlen > 0)    switch(sa->sa_family)      {      case AF_INET:      case AF_INET6:	if (!(flags & NI_NUMERICHOST))	  {	    struct hostent *h = NULL;	    if (h == NULL)	      {		if (sa->sa_family == AF_INET6)		  {		    while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in6 *) sa)->sin6_addr),					      sizeof(struct in6_addr),					      AF_INET6, &th, tmpbuf, tmpbuflen,					      &h, &herrno))		      {			if (herrno == NETDB_INTERNAL)			  {			    if (errno == ERANGE)			      {				tmpbuflen *= 2;				tmpbuf = alloca (tmpbuflen);			      }			    else			      {				__set_h_errno (herrno);				__set_errno (serrno);				return -1;			      }			  }			else			  {			    break;			  }		      }		  }		else		  {		    while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in *)sa)->sin_addr),					      sizeof(struct in_addr), AF_INET,					      &th, tmpbuf, tmpbuflen,					      &h, &herrno))		      {			if (errno == ERANGE)			  {			    tmpbuflen *= 2;			    tmpbuf = alloca (tmpbuflen);			  }			else			  {			    break;			  }		      }		  }	      }	    if (h)	      {		if (flags & NI_NOFQDN)		  {		    char *c;		    if ((c = nrl_domainname ()) && (c = strstr(h->h_name, c))			&& (c != h->h_name) && (*(--c) == '.'))		      {			strncpy (host, h->h_name,				 min(hostlen, (size_t) (c - h->h_name)));			host[min(hostlen - 1, (size_t) (c - h->h_name))]			  = '\0';			ok = 1;		      }		    else		      {			strncpy (host, h->h_name, hostlen);			ok = 1;		      }		  }		strncpy (host, h->h_name, hostlen);		ok = 1;	      }	  }	if (!ok)	  {	    if (flags & NI_NAMEREQD)	      {		__set_errno (serrno);		return -1;	      }	    else	      {		const char *c;		if (sa->sa_family == AF_INET6)		  {		    struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) sa;		    uint32_t scopeid;		    c = inet_ntop (AF_INET6,				   (void *) &sin6p->sin6_addr, host, hostlen);		    if (addrlen > sizeof (struct sockaddr_in6)			&& (scopeid = sin6p->sin6_scope_id))		      {			/* Buffer is >= IFNAMSIZ+1.  */			char scopebuf[MAXHOSTNAMELEN + 1];			int ni_numericscope = 0;			if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)			    || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))			  {			    if (if_indextoname (scopeid, scopebuf) == NULL)			      ++ni_numericscope;			  }			else			  ++ni_numericscope;			if (ni_numericscope)			  {			    char *scopeptr = &scopebuf[1];			    size_t real_hostlen;			    size_t scopelen;			    scopebuf[0] = SCOPE_DELIMITER;			    scopelen = 1 + snprintf (scopeptr,						     (scopebuf						      + sizeof scopebuf						      - scopeptr),						     "%u", scopeid);			    real_hostlen = __strnlen (host, hostlen);			    if (real_hostlen + scopelen + 1 > hostlen)			      return -1;			    memcpy (host + real_hostlen, scopebuf, scopelen);			  }		      }		  }		else		  c = inet_ntop (AF_INET,				 (void *) &(((struct sockaddr_in *) sa)->sin_addr),				 host, hostlen);		if (c == NULL)		  {		    __set_errno (serrno);		    return -1;		  }	      }	    ok = 1;	  }	break;      case AF_LOCAL:	if (!(flags & NI_NUMERICHOST))	  {	    struct utsname utsname;	    if (!uname (&utsname))	      {		strncpy (host, utsname.nodename, hostlen);		break;	      };	  };	if (flags & NI_NAMEREQD)	   {	    __set_errno (serrno);	    return -1;	  }	strncpy (host, "localhost", hostlen);	break;      default:        return -1;    }  if (serv && (servlen > 0))    switch(sa->sa_family)      {      case AF_INET:      case AF_INET6:	if (!(flags & NI_NUMERICSERV))	  {	    struct servent *s, ts;	    while (__getservbyport_r (((struct sockaddr_in *) sa)->sin_port,				      ((flags & NI_DGRAM) ? "udp" : "tcp"),				      &ts, tmpbuf, tmpbuflen, &s))	      {		if (herrno == NETDB_INTERNAL)		  {		    if (errno == ERANGE)		      {			tmpbuflen *= 2;			tmpbuf = __alloca (tmpbuflen);		      }		    else		      {			__set_errno (serrno);			return -1;		      }		  }		else		  {		    break;		  }	      }	    if (s)	      {		strncpy (serv, s->s_name, servlen);		break;	      }	  }	__snprintf (serv, servlen, "%d",		    ntohs (((struct sockaddr_in *) sa)->sin_port));	break;      case AF_LOCAL:	strncpy (serv, ((struct sockaddr_un *) sa)->sun_path, servlen);	break;    }  if (host && (hostlen > 0))    host[hostlen-1] = 0;  if (serv && (servlen > 0))    serv[servlen-1] = 0;  errno = serrno;  return 0;}