Index: include/asr.h =================================================================== RCS file: /cvs/src/include/asr.h,v retrieving revision 1.1 diff -u -p -r1.1 asr.h --- include/asr.h 26 Mar 2014 18:13:15 -0000 1.1 +++ include/asr.h 22 Oct 2019 04:41:08 -0000 @@ -84,5 +84,7 @@ struct asr_query *getnetbyaddr_async(in_ struct asr_query *getaddrinfo_async(const char *, const char *, const struct addrinfo *, void *); +struct asr_query *getprotonameinfo_async(const struct sockaddr *, socklen_t, + int, char *, size_t, char *, size_t, int, void *); struct asr_query *getnameinfo_async(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, void *); Index: include/netdb.h =================================================================== RCS file: /cvs/src/include/netdb.h,v retrieving revision 1.33 diff -u -p -r1.33 netdb.h --- include/netdb.h 18 Jan 2015 20:29:31 -0000 1.33 +++ include/netdb.h 22 Oct 2019 04:41:08 -0000 @@ -321,6 +321,8 @@ int getnameinfo(const struct sockaddr * const char *gai_strerror(int); #if __BSD_VISIBLE +int getprotonameinfo(const struct sockaddr *, socklen_t, int, + char *, size_t, char *, size_t, int); int getrrsetbyname(const char *, unsigned int, unsigned int, unsigned int, struct rrsetinfo **); void freerrset(struct rrsetinfo *); #endif Index: lib/libc/Symbols.list =================================================================== RCS file: /cvs/src/lib/libc/Symbols.list,v retrieving revision 1.72 diff -u -p -r1.72 Symbols.list --- lib/libc/Symbols.list 28 May 2019 14:49:38 -0000 1.72 +++ lib/libc/Symbols.list 22 Oct 2019 04:41:08 -0000 @@ -1055,6 +1055,8 @@ getnetbyaddr getnetbyaddr_async getnetbyname getnetbyname_async +getprotonameinfo +getprotonameinfo_async getrrsetbyname getrrsetbyname_async res_init Index: lib/libc/shlib_version =================================================================== RCS file: /cvs/src/lib/libc/shlib_version,v retrieving revision 1.208 diff -u -p -r1.208 shlib_version --- lib/libc/shlib_version 13 May 2019 22:25:27 -0000 1.208 +++ lib/libc/shlib_version 22 Oct 2019 04:41:08 -0000 @@ -1,4 +1,4 @@ major=95 -minor=1 +minor=2 # note: If changes were made to include/thread_private.h or if system calls # were added/changed then librthread/shlib_version must also be updated. Index: lib/libc/asr/asr_private.h =================================================================== RCS file: /cvs/src/lib/libc/asr/asr_private.h,v retrieving revision 1.47 diff -u -p -r1.47 asr_private.h --- lib/libc/asr/asr_private.h 28 Apr 2018 15:16:49 -0000 1.47 +++ lib/libc/asr/asr_private.h 22 Oct 2019 04:41:09 -0000 @@ -255,6 +255,7 @@ struct asr_query { struct sockaddr_in sain; struct sockaddr_in6 sain6; } sa; + int proto; int flags; } ni; #define MAXTOKEN 10 @@ -318,6 +319,9 @@ struct asr_query *_gethostbyaddr_async_c struct asr_ctx *); int _asr_iter_domain(struct asr_query *, const char *, char *, size_t); + +/* getnameinfo.c */ +int _asr_servname(const struct sockaddr *, int, char *, size_t, int); #ifdef DEBUG Index: lib/libc/asr/getnameinfo.c =================================================================== RCS file: /cvs/src/lib/libc/asr/getnameinfo.c,v retrieving revision 1.9 diff -u -p -r1.9 getnameinfo.c --- lib/libc/asr/getnameinfo.c 3 Jul 2019 03:24:03 -0000 1.9 +++ lib/libc/asr/getnameinfo.c 22 Oct 2019 04:41:09 -0000 @@ -28,7 +28,6 @@ #include static size_t asr_print_addr(const struct sockaddr *, char *, size_t); -static size_t asr_print_port(const struct sockaddr *, const char *, char *, size_t); #define SA_IN(sa) ((struct sockaddr_in*)(sa)) #define SA_IN6(sa) ((struct sockaddr_in6*)(sa)) @@ -94,25 +93,69 @@ asr_print_addr(const struct sockaddr *sa return (s); } +static int +asr_print_proto_port(int port, int proto, char *buf, size_t buflen) +{ + struct protoent p; + struct protoent_data pd; + const char *protoname; + struct servent s; + struct servent_data sd; + int rv = EAI_NODATA; + size_t l; + + switch (proto) { + case IPPROTO_TCP: + protoname = "tcp"; + break; + case IPPROTO_UDP: +#ifdef IPPROTO_UDPLITE + case IPPROTO_UDPLITE: +#endif + protoname = "udp"; + break; + default: + memset(&pd, 0, sizeof(pd)); + if (getprotobynumber_r(proto, &p, &pd) == -1) + goto nodata; + + protoname = p.p_name; + break; + } + + memset(&sd, 0, sizeof(sd)); + if (getservbyport_r(port, protoname, &s, &sd) == -1) + goto endprotoent; + + l = strlcpy(buf, s.s_name, buflen); + if (l >= buflen) { + rv = EAI_OVERFLOW; + goto endservent; + } + + rv = 0; + +endservent: + endservent_r(&sd); +endprotoent: + if (protoname == p.p_name) + endprotoent_r(&pd); +nodata: + return (rv); +} + /* * Print the textual representation of the port set on "sa". - * - * If proto is not NULL, it is used as parameter to "getservbyport_r(3)" to - * return a service name. If it's not set, or if no matching service is found, - * it prints the portno. - * - * Return the total length of the string it tried to create or 0 if an error - * occured, in which case errno is set. On success, the constructed string - * is guaranteed to be NUL-terminated. Overflow must be detected by checking - * the returned size against buflen. */ -static size_t -asr_print_port(const struct sockaddr *sa, const char *proto, char *buf, size_t buflen) +int +_asr_servname(const struct sockaddr *sa, int proto, + char *buf, size_t buflen, int flags) { - struct servent s; - struct servent_data sd; - int port, r, saved_errno; - size_t n; + int port, r, n; + const char *fmt; + + if (buf == NULL || buflen == 0) + return (0); switch(sa->sa_family) { case AF_INET: @@ -123,35 +166,40 @@ asr_print_port(const struct sockaddr *sa break; default: errno = EINVAL; - return (0); + return (EAI_SYSTEM); } - if (proto) { - memset(&sd, 0, sizeof (sd)); - saved_errno = errno; - if (getservbyport_r(port, proto, &s, &sd) != -1) { - n = strlcpy(buf, s.s_name, buflen); - endservent_r(&sd); - return (n); - } - errno = saved_errno; + if (!(flags & NI_NUMERICSERV)) { + r = asr_print_proto_port(port, proto, buf, buflen); + if (r != EAI_NODATA) + return (r); } - r = snprintf(buf, buflen, "%u", ntohs(port)); - if (r < 0 || r >= buflen) /* Actually, this can not happen */ - return (0); + n = snprintf(buf, buflen, "%u", ntohs(port)); + if (n < 0) /* Actually, this can not happen */ + return (EAI_FAIL); + if (n >= buflen) + return (EAI_OVERFLOW); - return (r); + return (0); +} + +int +getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, char *serv, size_t servlen, int flags) +{ + int proto = (flags & NI_DGRAM) ? IPPROTO_UDP : IPPROTO_TCP; + return (getprotonameinfo(sa, salen, + proto, host, hostlen, serv, servlen, flags)); } int -getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, - size_t hostlen, char *serv, size_t servlen, int flags) +getprotonameinfo(const struct sockaddr *sa, socklen_t salen, int proto, + char *host, size_t hostlen, char *serv, size_t servlen, int flags) { struct asr_query *as; struct asr_result ar; int saved_errno = errno; - const char *proto; size_t r; /* @@ -168,20 +216,12 @@ getnameinfo(const struct sockaddr *sa, s return (EAI_OVERFLOW); } - if (serv && servlen) { - if (flags & NI_NUMERICSERV) - proto = NULL; - else - proto = (flags & NI_DGRAM) ? "udp" : "tcp"; - r = asr_print_port(sa, proto, serv, servlen); - if (r == 0) - return (EAI_SYSTEM); /* errno set */ - if (r >= servlen) - return (EAI_OVERFLOW); - } + r = _asr_servname(sa, proto, serv, servlen, flags); + if (r == EAI_SYSTEM) + return (r); errno = saved_errno; - return (0); + return (r); } res_init(); Index: lib/libc/asr/getnameinfo_async.c =================================================================== RCS file: /cvs/src/lib/libc/asr/getnameinfo_async.c,v retrieving revision 1.14 diff -u -p -r1.14 getnameinfo_async.c --- lib/libc/asr/getnameinfo_async.c 3 Jul 2019 03:24:03 -0000 1.14 +++ lib/libc/asr/getnameinfo_async.c 22 Oct 2019 04:41:09 -0000 @@ -32,13 +32,22 @@ #include "asr_private.h" static int getnameinfo_async_run(struct asr_query *, struct asr_result *); -static int _servname(struct asr_query *); static int _numerichost(struct asr_query *); struct asr_query * getnameinfo_async(const struct sockaddr *sa, socklen_t slen, char *host, size_t hostlen, char *serv, size_t servlen, int flags, void *asr) { + int proto = (flags & NI_DGRAM) ? IPPROTO_UDP : IPPROTO_TCP; + return (getprotonameinfo_async(sa, slen, proto, + host, hostlen, serv, servlen, flags, asr)); +} + +struct asr_query * +getprotonameinfo_async(const struct sockaddr *sa, socklen_t slen, int proto, + char *host, size_t hostlen, char *serv, size_t servlen, int flags, + void *asr) +{ struct asr_ctx *ac; struct asr_query *as; @@ -57,6 +66,7 @@ getnameinfo_async(const struct sockaddr as->as.ni.hostnamelen = hostlen; as->as.ni.servname = serv; as->as.ni.servnamelen = servlen; + as->as.ni.proto = proto; as->as.ni.flags = flags; _asr_ctx_unref(ac); @@ -101,8 +111,11 @@ getnameinfo_async_run(struct asr_query * } /* Set the service name first, if needed. */ - if (_servname(as) == -1) { - ar->ar_gai_errno = EAI_OVERFLOW; + r = _asr_servname(&as->as.ni.sa.sa, as->as.ni.proto, + as->as.ni.servname, as->as.ni.servnamelen, + as->as.ni.flags); + if (r != 0) { + ar->ar_gai_errno = r; async_set_state(as, ASR_STATE_HALT); break; } @@ -199,46 +212,6 @@ getnameinfo_async_run(struct asr_query * break; } goto next; -} - - -/* - * Set the service name on the result buffer is not NULL. - * return (-1) if the buffer is too small. - */ -static int -_servname(struct asr_query *as) -{ - struct servent s; - struct servent_data sd; - int port, r; - char *buf = as->as.ni.servname; - size_t buflen = as->as.ni.servnamelen; - - if (as->as.ni.servname == NULL || as->as.ni.servnamelen == 0) - return (0); - - if (as->as.ni.sa.sa.sa_family == AF_INET) - port = as->as.ni.sa.sain.sin_port; - else - port = as->as.ni.sa.sain6.sin6_port; - - if (!(as->as.ni.flags & NI_NUMERICSERV)) { - memset(&sd, 0, sizeof (sd)); - if (getservbyport_r(port, - (as->as.ni.flags & NI_DGRAM) ? "udp" : "tcp", - &s, &sd) != -1) { - r = strlcpy(buf, s.s_name, buflen) >= buflen; - endservent_r(&sd); - return (r ? -1 : 0); - } - } - - r = snprintf(buf, buflen, "%u", ntohs(port)); - if (r < 0 || r >= buflen) - return (-1); - - return (0); } /*