From d8213bb5738ac778fcb5d696d1294b0f8ddae7f3 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 13 Feb 2013 09:49:33 -0800 Subject: [PATCH] Update getnameinfo.c, remove dead code, and fix error reporting. Also add a unit test for the salen size checking. Bug: 1889275 Change-Id: I8ec4107df9e2e9a8571e8915525249c6e44b98ad --- libc/netbsd/net/getnameinfo.c | 223 ++++++++---------------------- libc/netbsd/net/getservbyname_r.c | 76 ---------- libc/netbsd/net/getservbyport_r.c | 65 --------- libc/netbsd/net/getservent_r.c | 151 -------------------- tests/netdb_test.cpp | 31 ++++- 5 files changed, 89 insertions(+), 457 deletions(-) delete mode 100644 libc/netbsd/net/getservbyname_r.c delete mode 100644 libc/netbsd/net/getservbyport_r.c delete mode 100644 libc/netbsd/net/getservent_r.c diff --git a/libc/netbsd/net/getnameinfo.c b/libc/netbsd/net/getnameinfo.c index d8ac03743..4874da12d 100644 --- a/libc/netbsd/net/getnameinfo.c +++ b/libc/netbsd/net/getnameinfo.c @@ -1,4 +1,4 @@ -/* $NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $ */ +/* $NetBSD: getnameinfo.c,v 1.53 2012/09/26 23:13:00 christos Exp $ */ /* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */ /* @@ -47,30 +47,28 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $"); +__RCSID("$NetBSD: getnameinfo.c,v 1.53 2012/09/26 23:13:00 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #include #include +#include #include -#if defined(ANDROID_CHANGES) && defined(AF_LINK) -#include -#endif #include #include #include #include -#include "arpa_nameser.h" #include #include #include #ifdef ANDROID_CHANGES +#include "arpa_nameser.h" #include "resolv_private.h" #include #include #include -#include #include +#define MIN(x,y) ((x) < (y) ? (x) : (y)) #else #include #endif @@ -98,23 +96,15 @@ struct sockinet { u_short si_port; }; -static int getnameinfo_inet __P((const struct sockaddr *, socklen_t, char *, - socklen_t, char *, socklen_t, int)); +static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *, + socklen_t, char *, socklen_t, int); #ifdef INET6 -static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *, - socklen_t, int)); -static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, - int)); +static int ip6_parsenumeric(const struct sockaddr *, const char *, char *, + socklen_t, int); +static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int); #endif -#if defined(ANDROID_CHANGES) && defined(AF_LINK) -static int getnameinfo_link __P((const struct sockaddr *, socklen_t, char *, - socklen_t, char *, socklen_t, int)); -#endif -static int hexname __P((const u_int8_t *, size_t, char *, socklen_t)); - -// This should be synchronized to ResponseCode.h -static const int DnsProxyQueryResult = 222; - +static int getnameinfo_local(const struct sockaddr *, socklen_t, char *, + socklen_t, char *, socklen_t, int); /* * Top-level getnameinfo() code. Look at the address family, and pick an @@ -127,16 +117,41 @@ int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t h case AF_INET6: return getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags); -#if defined(ANDROID_CHANGES) && defined(AF_LINK) - case AF_LINK: - return getnameinfo_link(sa, salen, host, hostlen, + case AF_LOCAL: + return getnameinfo_local(sa, salen, host, hostlen, serv, servlen, flags); -#endif default: return EAI_FAMILY; } } +/* + * getnameinfo_local(): + * Format an local address into a printable format. + */ +/* ARGSUSED */ +static int +getnameinfo_local(const struct sockaddr *sa, socklen_t salen, + char *host, socklen_t hostlen, char *serv, socklen_t servlen, + int flags __attribute__((unused))) +{ + const struct sockaddr_un *sun = + (const struct sockaddr_un *)(const void *)sa; + + if (salen < (socklen_t) offsetof(struct sockaddr_un, sun_path)) { + return EAI_FAMILY; + } + + if (serv != NULL && servlen > 0) + serv[0] = '\0'; + + if (host && hostlen > 0) + strlcpy(host, sun->sun_path, + MIN((socklen_t) sizeof(sun->sun_path) + 1, hostlen)); + + return 0; +} + #ifdef ANDROID_CHANGES /* On success length of the host name is returned. A return * value of 0 means there's no host name associated with @@ -213,6 +228,8 @@ android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, int result_code = (int)strtol(msg_buf, NULL, 10); // verify the code itself + // This should be synchronized to ResponseCode.h + static const int DnsProxyQueryResult = 222; if (result_code != DnsProxyQueryResult) { goto exit; } @@ -241,19 +258,16 @@ android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, return result; } #endif + /* * getnameinfo_inet(): * Format an IPv4 or IPv6 sockaddr into a printable string. */ static int -getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) - const struct sockaddr *sa; - socklen_t salen; - char *host; - socklen_t hostlen; - char *serv; - socklen_t servlen; - int flags; +getnameinfo_inet(const struct sockaddr* sa, socklen_t salen, + char *host, socklen_t hostlen, + char *serv, socklen_t servlen, + int flags) { const struct afd *afd; struct servent *sp; @@ -261,7 +275,7 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) u_short port; int family, i; const char *addr; - u_int32_t v4a; + uint32_t v4a; char numserv[512]; char numaddr[512]; @@ -272,11 +286,6 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) if (sa == NULL) return EAI_FAIL; -#ifdef BSD4_4 - if (sa->sa_len != salen) - return EAI_FAIL; -#endif - family = sa->sa_family; for (i = 0; afdl[i].a_af; i++) if (afdl[i].a_af == family) { @@ -286,8 +295,11 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) return EAI_FAMILY; found: - if (salen != afd->a_socklen) - return EAI_FAIL; + // http://b/1889275: callers should be allowed to provide too much + // space, but not too little. + if (salen < afd->a_socklen) { + return EAI_FAMILY; + } /* network byte order */ port = ((const struct sockinet *)(const void *)sa)->si_port; @@ -321,7 +333,7 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) switch (sa->sa_family) { case AF_INET: - v4a = (u_int32_t) + v4a = (uint32_t) ntohl(((const struct sockaddr_in *) (const void *)sa)->sin_addr.s_addr); if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) @@ -412,7 +424,7 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) #endif if (hp) { -#if defined(ANDROID_CHANGES) && defined(AF_LINK) +#if 0 /* * commented out, since "for local host" is not * implemented here - see RFC2553 p30 @@ -457,12 +469,8 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) #ifdef INET6 static int -ip6_parsenumeric(sa, addr, host, hostlen, flags) - const struct sockaddr *sa; - const char *addr; - char *host; - socklen_t hostlen; - int flags; +ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host, + socklen_t hostlen, int flags) { size_t numaddrlen; char numaddr[512]; @@ -471,9 +479,6 @@ ip6_parsenumeric(sa, addr, host, hostlen, flags) assert(addr != NULL); assert(host != NULL); - if (hostlen < 0) - return EAI_OVERFLOW; - if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL) return EAI_SYSTEM; @@ -505,11 +510,7 @@ ip6_parsenumeric(sa, addr, host, hostlen, flags) /* ARGSUSED */ static int -ip6_sa2str(sa6, buf, bufsiz, flags) - const struct sockaddr_in6 *sa6; - char *buf; - size_t bufsiz; - int flags; +ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags) { unsigned int ifindex; const struct in6_addr *a6; @@ -548,109 +549,3 @@ ip6_sa2str(sa6, buf, bufsiz, flags) return n; } #endif /* INET6 */ - - -#if defined(ANDROID_CHANGES) && defined(AF_LINK) -/* - * getnameinfo_link(): - * Format a link-layer address into a printable format, paying attention to - * the interface type. - */ -/* ARGSUSED */ -static int -getnameinfo_link(const struct sockaddr *sa, socklen_t salen, - char *host, socklen_t hostlen, char *serv, socklen_t servlen, - int flags) -{ - const struct sockaddr_dl *sdl = - (const struct sockaddr_dl *)(const void *)sa; - const struct ieee1394_hwaddr *iha; - int n; - - if (serv != NULL && servlen > 0) - *serv = '\0'; - - if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { - n = snprintf(host, hostlen, "link#%u", sdl->sdl_index); - if (n < 0 || (socklen_t) n > hostlen) { - *host = '\0'; - return EAI_MEMORY; - } - return 0; - } - - switch (sdl->sdl_type) { -#ifdef IFT_ECONET - case IFT_ECONET: - if (sdl->sdl_alen < 2) - return EAI_FAMILY; - if (CLLADDR(sdl)[1] == 0) - n = snprintf(host, hostlen, "%u", CLLADDR(sdl)[0]); - else - n = snprintf(host, hostlen, "%u.%u", - CLLADDR(sdl)[1], CLLADDR(sdl)[0]); - if (n < 0 || (socklen_t) n >= hostlen) { - *host = '\0'; - return EAI_MEMORY; - } else - return 0; -#endif - case IFT_IEEE1394: - if (sdl->sdl_alen < sizeof(iha->iha_uid)) - return EAI_FAMILY; - iha = - (const struct ieee1394_hwaddr *)(const void *)CLLADDR(sdl); - return hexname(iha->iha_uid, sizeof(iha->iha_uid), - host, hostlen); - /* - * The following have zero-length addresses. - * IFT_ATM (net/if_atmsubr.c) - * IFT_FAITH (net/if_faith.c) - * IFT_GIF (net/if_gif.c) - * IFT_LOOP (net/if_loop.c) - * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c) - * IFT_SLIP (net/if_sl.c, net/if_strip.c) - * IFT_STF (net/if_stf.c) - * IFT_L2VLAN (net/if_vlan.c) - * IFT_PROPVIRTUAL (net/if_bridge.h> - */ - /* - * The following use IPv4 addresses as link-layer addresses: - * IFT_OTHER (net/if_gre.c) - */ - case IFT_ARCNET: /* default below is believed correct for all these. */ - case IFT_ETHER: - case IFT_FDDI: - case IFT_HIPPI: - case IFT_ISO88025: - default: - return hexname((const u_int8_t *)CLLADDR(sdl), - (size_t)sdl->sdl_alen, host, hostlen); - } -} -#endif - -static int -hexname(cp, len, host, hostlen) - const u_int8_t *cp; - char *host; - size_t len; - socklen_t hostlen; -{ - int n; - size_t i; - char *outp = host; - - *outp = '\0'; - for (i = 0; i < len; i++) { - n = snprintf(outp, hostlen, "%s%02x", - i ? ":" : "", cp[i]); - if (n < 0 || (socklen_t) n >= hostlen) { - *host = '\0'; - return EAI_MEMORY; - } - outp += n; - hostlen -= n; - } - return 0; -} diff --git a/libc/netbsd/net/getservbyname_r.c b/libc/netbsd/net/getservbyname_r.c deleted file mode 100644 index fb6dc5203..000000000 --- a/libc/netbsd/net/getservbyname_r.c +++ /dev/null @@ -1,76 +0,0 @@ -/* $NetBSD: getservbyname_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $ */ - -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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 -#include -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)getservbyname.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: getservbyname_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include - -#include "servent.h" - -struct servent * -getservbyname_r(const char *name, const char *proto, struct servent *sp, - struct servent_data *sd) -{ - struct servent *s; - char **cp; - - assert(name != NULL); - /* proto may be NULL */ - - setservent_r(sd->stayopen, sd); - while ((s = getservent_r(sp, sd)) != NULL) { - if (strcmp(name, s->s_name) == 0) - goto gotname; - for (cp = s->s_aliases; *cp; cp++) - if (strcmp(name, *cp) == 0) - goto gotname; - continue; -gotname: - if (proto == NULL || strcmp(s->s_proto, proto) == 0) - break; - } - if (!sd->stayopen) - if (sd->fp != NULL) { - (void)fclose(sd->fp); - sd->fp = NULL; - } - return s; -} diff --git a/libc/netbsd/net/getservbyport_r.c b/libc/netbsd/net/getservbyport_r.c deleted file mode 100644 index 6fe429311..000000000 --- a/libc/netbsd/net/getservbyport_r.c +++ /dev/null @@ -1,65 +0,0 @@ -/* $NetBSD: getservbyport_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $ */ - -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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 -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)getservbyport.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: getservbyport_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - -#include -#include - -#include "servent.h" - -struct servent * -getservbyport_r(int port, const char *proto, struct servent *sp, - struct servent_data *sd) -{ - struct servent *s; - - setservent_r(sd->stayopen, sd); - while ((s = getservent_r(sp, sd)) != NULL) { - if (s->s_port != port) - continue; - if (proto == NULL || strcmp(s->s_proto, proto) == 0) - break; - } - if (!sd->stayopen) - if (sd->fp != NULL) { - (void)fclose(sd->fp); - sd->fp = NULL; - } - return s; -} diff --git a/libc/netbsd/net/getservent_r.c b/libc/netbsd/net/getservent_r.c deleted file mode 100644 index 1668759b6..000000000 --- a/libc/netbsd/net/getservent_r.c +++ /dev/null @@ -1,151 +0,0 @@ -/* $NetBSD: getservent_r.c,v 1.5 2005/04/18 19:39:45 kleink Exp $ */ - -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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 -#include - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: getservent_r.c,v 1.5 2005/04/18 19:39:45 kleink Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include -#include - -#include "servent.h" - -void -setservent_r(int f, struct servent_data *sd) -{ - if (sd->fp == NULL) - sd->fp = fopen(_PATH_SERVICES, "r"); - else - rewind(sd->fp); - sd->stayopen |= f; -} - -void -endservent_r(struct servent_data *sd) -{ - if (sd->fp) { - (void)fclose(sd->fp); - sd->fp = NULL; - } - if (sd->aliases) { - free(sd->aliases); - sd->aliases = NULL; - sd->maxaliases = 0; - } - if (sd->line) { - free(sd->line); - sd->line = NULL; - } - sd->stayopen = 0; -} - -struct servent * -getservent_r(struct servent *sp, struct servent_data *sd) -{ - char *p, *cp, **q; - size_t i = 0; - int oerrno; - - if (sd->fp == NULL && (sd->fp = fopen(_PATH_SERVICES, "r")) == NULL) - return NULL; - - for (;;) { - if (sd->line) - free(sd->line); -// sd->line = fparseln(sd->fp, NULL, NULL, NULL, FPARSELN_UNESCALL); - fprintf(stderr, "*** FIX ME! getservent_r() is going to fail!!!\n"); - sd->line = NULL; - if (sd->line == NULL) - return NULL; - sp->s_name = p = sd->line; - p = strpbrk(p, " \t"); - if (p == NULL) - continue; - *p++ = '\0'; - while (*p == ' ' || *p == '\t') - p++; - cp = strpbrk(p, ",/"); - if (cp == NULL) - continue; - *cp++ = '\0'; - sp->s_port = htons((u_short)atoi(p)); - sp->s_proto = cp; - if (sd->aliases == NULL) { - sd->maxaliases = 10; - sd->aliases = malloc(sd->maxaliases * sizeof(char *)); - if (sd->aliases == NULL) { - oerrno = errno; - endservent_r(sd); - errno = oerrno; - return NULL; - } - } - q = sp->s_aliases = sd->aliases; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (i == sd->maxaliases - 2) { - sd->maxaliases *= 2; - q = realloc(q, - sd->maxaliases * sizeof(char *)); - if (q == NULL) { - oerrno = errno; - endservent_r(sd); - errno = oerrno; - return NULL; - } - sp->s_aliases = sd->aliases = q; - } - q[i++] = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - q[i] = NULL; - return sp; - } -} diff --git a/tests/netdb_test.cpp b/tests/netdb_test.cpp index 168f7c148..33f6c01d8 100644 --- a/tests/netdb_test.cpp +++ b/tests/netdb_test.cpp @@ -19,10 +19,39 @@ #include #include #include - +#include TEST(netdb, getaddrinfo_NULL_hints) { addrinfo* ai = NULL; ASSERT_EQ(0, getaddrinfo("localhost", "9999", NULL, &ai)); freeaddrinfo(ai); } + +TEST(netdb, getnameinfo_salen) { + sockaddr_storage ss; + memset(&ss, 0, sizeof(ss)); + sockaddr* sa = reinterpret_cast(&ss); + char tmp[16]; + + ss.ss_family = AF_INET; + socklen_t too_much = sizeof(ss); + socklen_t just_right = sizeof(sockaddr_in); + socklen_t too_little = sizeof(sockaddr_in) - 1; + + ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); + ASSERT_STREQ("0.0.0.0", tmp); + ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); + ASSERT_STREQ("0.0.0.0", tmp); + ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); + + ss.ss_family = AF_INET6; + just_right = sizeof(sockaddr_in6); + too_little = sizeof(sockaddr_in6) - 1; + too_much = just_right + 1; + + ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); + ASSERT_STREQ("::", tmp); + ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); + ASSERT_STREQ("::", tmp); + ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); +}