X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/c9d84d15c5c4dc8eca7594101fe5026080ed641e..refs/pull/435/head:/missing/getnameinfo.c diff --git a/missing/getnameinfo.c b/missing/getnameinfo.c index 19545e58..63aba731 100644 --- a/missing/getnameinfo.c +++ b/missing/getnameinfo.c @@ -1,7 +1,7 @@ /* * 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: @@ -13,7 +13,7 @@ * 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 @@ -32,11 +32,14 @@ * - Thread safe-ness must be checked * - Return values. There seems to be no standard for return value (RFC2553) * but INRIA implementation returns EAI_xxx defined for getaddrinfo(). + * - RFC2553 says that we should raise error on short buffer. X/Open says + * we need to truncate the result. We obey RFC2553 (and X/Open should be + * modified). */ #ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#include +#endif #include #include @@ -48,12 +51,9 @@ #include #include #include +#include -#ifndef HAVE_PORTABLE_PROTOTYPE -#include "cdecl_ext.h" -#endif - -#ifndef HAVE_ADDRINFO +#ifdef NEED_ADDRINFO_H #include "addrinfo.h" #endif @@ -107,7 +107,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) u_short port; int family, i; char *addr, *p; - u_long v4a; + uint32_t v4a; int h_error; char numserv[512]; char numaddr[512]; @@ -119,7 +119,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) if (sa->sa_len != salen) return ENI_SALEN; #endif - + family = sa->sa_family; for (i = 0; afdl[i].a_af; i++) if (afdl[i].a_af == family) { @@ -127,16 +127,21 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) goto found; } return ENI_FAMILY; - + found: if (salen != afd->a_socklen) return ENI_SALEN; - + port = ((struct sockinet *)sa)->si_port; /* network byte order */ addr = (char *)sa + afd->a_off; if (serv == NULL || servlen == 0) { - /* what we should do? */ + /* + * 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; @@ -145,12 +150,12 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) (flags & NI_DGRAM) ? "udp" : "tcp"); } if (sp) { - if (strlen(sp->s_name) > servlen) + if (strlen(sp->s_name) + 1 > servlen) return ENI_MEMORY; strcpy(serv, sp->s_name); } else { snprintf(numserv, sizeof(numserv), "%d", ntohs(port)); - if (strlen(numserv) > servlen) + if (strlen(numserv) + 1 > servlen) return ENI_MEMORY; strcpy(serv, numserv); } @@ -158,12 +163,13 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) switch (sa->sa_family) { case AF_INET: - v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); + v4a = (uint32_t) + ntohl(((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; + if (v4a == 0) + flags |= NI_NUMERICHOST; break; #ifdef INET6 case AF_INET6: @@ -192,7 +198,12 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) #endif } if (host == NULL || hostlen == 0) { - /* what should we do? */ + /* + * 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) { /* NUMERICHOST and NAMEREQD conflicts with each other */ if (flags & NI_NAMEREQD) @@ -200,10 +211,10 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) == NULL) return ENI_SYSTEM; - if (strlen(numaddr) > hostlen) + if (strlen(numaddr) + 1 > hostlen) return ENI_MEMORY; strcpy(host, numaddr); -#ifdef INET6 +#if defined(INET6) && defined(NI_WITHSCOPEID) if (afd->a_af == AF_INET6 && (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) || IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) && @@ -228,7 +239,11 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); #else hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); +#ifdef HAVE_H_ERRNO h_error = h_errno; +#else + h_error = EINVAL; +#endif #endif if (hp) { @@ -236,7 +251,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) p = strchr(hp->h_name, '.'); if (p) *p = '\0'; } - if (strlen(hp->h_name) > hostlen) { + if (strlen(hp->h_name) + 1 > hostlen) { #ifdef USE_GETIPNODEBY freehostent(hp); #endif @@ -252,7 +267,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) == NULL) return ENI_NOHOSTNAME; - if (strlen(numaddr) > hostlen) + if (strlen(numaddr) + 1 > hostlen) return ENI_MEMORY; strcpy(host, numaddr); }