From owner-svn-src-head@freebsd.org Sun Sep 20 01:09:25 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4C63FA03EF3; Sun, 20 Sep 2015 01:09:25 +0000 (UTC) (envelope-from hrs@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3CE5F18E8; Sun, 20 Sep 2015 01:09:25 +0000 (UTC) (envelope-from hrs@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t8K19P7F096492; Sun, 20 Sep 2015 01:09:25 GMT (envelope-from hrs@FreeBSD.org) Received: (from hrs@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t8K19OtZ096488; Sun, 20 Sep 2015 01:09:24 GMT (envelope-from hrs@FreeBSD.org) Message-Id: <201509200109.t8K19OtZ096488@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hrs set sender to hrs@FreeBSD.org using -f From: Hiroki Sato Date: Sun, 20 Sep 2015 01:09:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287999 - head/lib/libc/net X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Sep 2015 01:09:25 -0000 Author: hrs Date: Sun Sep 20 01:09:23 2015 New Revision: 287999 URL: https://svnweb.freebsd.org/changeset/base/287999 Log: Add PF_LOCAL support in getaddrinfo(3) and getnameinfo(3): - In a PF_LOCAL address, "hostname" must begins with '/' and "servname" is always NULL. All of ai_flags are ignored. - PF_UNSPEC matches PF_LOCAL. EAI_SERVICE is not returned to make AF-independent programming easier; "servname" is always ignored in PF_LOCAL. In practice, PF_INET* and PF_LOCAL are mutually-exclusive because a hostname which begins with '/' is invalid in PF_INET*. No domain name resolution is performed for a PF_LOCAL address. Differential Revision: https://reviews.freebsd.org/D3634 Modified: head/lib/libc/net/getaddrinfo.3 head/lib/libc/net/getaddrinfo.c head/lib/libc/net/getnameinfo.3 head/lib/libc/net/getnameinfo.c Modified: head/lib/libc/net/getaddrinfo.3 ============================================================================== --- head/lib/libc/net/getaddrinfo.3 Sat Sep 19 23:48:06 2015 (r287998) +++ head/lib/libc/net/getaddrinfo.3 Sun Sep 20 01:09:23 2015 (r287999) @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 14, 2013 +.Dd September 20, 2015 .Dt GETADDRINFO 3 .Os .Sh NAME @@ -40,7 +40,6 @@ The .Fn getaddrinfo function is used to get a list of -.Tn IP addresses and port numbers for host .Fa hostname and service @@ -59,7 +58,9 @@ arguments are either pointers to NUL-ter An acceptable value for .Fa hostname is either a valid host name or a numeric host address string consisting -of a dotted decimal IPv4 address or an IPv6 address. +of a dotted decimal IPv4 address, +an IPv6 address, +or a UNIX-domain address. The .Fa servname is either a decimal port number or a service name listed in @@ -105,6 +106,7 @@ operating system. Denotes the type of socket that is wanted: .Dv SOCK_STREAM , .Dv SOCK_DGRAM , +.Dv SOCK_SEQPACKET , or .Dv SOCK_RAW . When @@ -112,9 +114,11 @@ When is zero the caller will accept any socket type. .It Fa ai_protocol Indicates which transport protocol is desired, -.Dv IPPROTO_UDP +.Dv IPPROTO_UDP , +.Dv IPPROTO_TCP , +.Dv IPPROTO_SCTP , or -.Dv IPPROTO_TCP . +.Dv IPPROTO_UDPLITE . If .Fa ai_protocol is zero the caller will accept any protocol. @@ -131,6 +135,9 @@ or be the bitwise-inclusive OR of one or .Dv AI_NUMERICSERV and .Dv AI_PASSIVE . +For a UNIX-domain address, +.Fa ai_flags +is ignored. .Bl -tag -width "AI_CANONNAMEXX" .It Dv AI_ADDRCONFIG If the @@ -419,6 +426,9 @@ freeaddrinfo(res0); .Xr getnameinfo 3 , .Xr getservbyname 3 , .Xr resolver 3 , +.Xr inet 4 , +.Xr inet6 4 , +.Xr unix 4 , .Xr hosts 5 , .Xr resolv.conf 5 , .Xr services 5 , Modified: head/lib/libc/net/getaddrinfo.c ============================================================================== --- head/lib/libc/net/getaddrinfo.c Sat Sep 19 23:48:06 2015 (r287998) +++ head/lib/libc/net/getaddrinfo.c Sun Sep 20 01:09:23 2015 (r287999) @@ -137,13 +137,20 @@ static const struct afd { offsetof(struct sockaddr_in6, sin6_addr), in6_addrany, in6_loopback, 1}, #define N_INET 1 +#define N_LOCAL 2 #else #define N_INET 0 +#define N_LOCAL 1 #endif {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), offsetof(struct sockaddr_in, sin_addr), in_addrany, in_loopback, 0}, +#define sizeofmember(type, member) (sizeof(((type *)0)->member)) + {PF_LOCAL, sizeofmember(struct sockaddr_un, sun_path), + sizeof(struct sockaddr_un), + offsetof(struct sockaddr_un, sun_path), + NULL, NULL, 0}, {0, 0, 0, 0, NULL, NULL, 0}, }; @@ -152,29 +159,47 @@ struct explore { int e_socktype; int e_protocol; int e_wild; -#define WILD_AF(ex) ((ex)->e_wild & 0x01) -#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) -#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) +#define AF_ANY 0x01 +#define SOCKTYPE_ANY 0x02 +#define PROTOCOL_ANY 0x04 +#define WILD_AF(ex) ((ex)->e_wild & AF_ANY) +#define WILD_SOCKTYPE(ex) ((ex)->e_wild & SOCKTYPE_ANY) +#define WILD_PROTOCOL(ex) ((ex)->e_wild & PROTOCOL_ANY) }; static const struct explore explore[] = { -#if 0 - { PF_LOCAL, ANY, ANY, 0x01 }, -#endif + { PF_LOCAL, SOCK_DGRAM, ANY, + AF_ANY | PROTOCOL_ANY }, + { PF_LOCAL, SOCK_STREAM, ANY, + AF_ANY | PROTOCOL_ANY }, + { PF_LOCAL, SOCK_SEQPACKET, ANY, + AF_ANY | PROTOCOL_ANY }, #ifdef INET6 - { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, 0x07 }, - { PF_INET6, SOCK_STREAM, IPPROTO_TCP, 0x07 }, - { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, 0x03 }, - { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 }, - { PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE, 0x03 }, - { PF_INET6, SOCK_RAW, ANY, 0x05 }, -#endif - { PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0x07 }, - { PF_INET, SOCK_STREAM, IPPROTO_TCP, 0x07 }, - { PF_INET, SOCK_STREAM, IPPROTO_SCTP, 0x03 }, - { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 }, - { PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE, 0x03 }, - { PF_INET, SOCK_RAW, ANY, 0x05 }, + { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, + AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, + { PF_INET6, SOCK_STREAM, IPPROTO_TCP, + AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, + { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, + AF_ANY | SOCKTYPE_ANY }, + { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, + AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, + { PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE, + AF_ANY | SOCKTYPE_ANY }, + { PF_INET6, SOCK_RAW, ANY, + AF_ANY | PROTOCOL_ANY }, +#endif + { PF_INET, SOCK_DGRAM, IPPROTO_UDP, + AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, + { PF_INET, SOCK_STREAM, IPPROTO_TCP, + AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, + { PF_INET, SOCK_STREAM, IPPROTO_SCTP, + AF_ANY | SOCKTYPE_ANY }, + { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, + AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, + { PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE, + AF_ANY | SOCKTYPE_ANY }, + { PF_INET, SOCK_RAW, ANY, + AF_ANY | PROTOCOL_ANY }, { -1, 0, 0, 0 }, }; @@ -408,6 +433,7 @@ getaddrinfo(const char *hostname, const ERR(EAI_BADFLAGS); switch (hints->ai_family) { case PF_UNSPEC: + case PF_LOCAL: case PF_INET: #ifdef INET6 case PF_INET6: @@ -1130,6 +1156,9 @@ explore_null(const struct addrinfo *pai, *res = NULL; ai = NULL; + if (pai->ai_family == PF_LOCAL) + return (0); + /* * filter out AFs that are not supported by the kernel * XXX errno? @@ -1172,8 +1201,11 @@ explore_numeric(const struct addrinfo *p const struct afd *afd; struct addrinfo *ai; int error; - char pton[PTON_MAX]; + char pton[PTON_MAX], path[PATH_MAX], *p; +#ifdef CTASSERT + CTASSERT(sizeofmember(struct sockaddr_un, sun_path) <= PATH_MAX); +#endif *res = NULL; ai = NULL; @@ -1182,6 +1214,15 @@ explore_numeric(const struct addrinfo *p return 0; switch (afd->a_af) { + case AF_LOCAL: + if (hostname[0] != '/') + ERR(EAI_NONAME); + if (strlen(hostname) > afd->a_addrlen) + ERR(EAI_MEMORY); + /* NUL-termination does not need to be guaranteed. */ + strncpy(path, hostname, afd->a_addrlen); + p = &path[0]; + break; case AF_INET: /* * RFC3493 requires getaddrinfo() to accept AF_INET formats @@ -1192,15 +1233,17 @@ explore_numeric(const struct addrinfo *p */ if (inet_aton(hostname, (struct in_addr *)pton) != 1) return 0; + p = pton; break; default: if (inet_pton(afd->a_af, hostname, pton) != 1) return 0; + p = pton; break; } if (pai->ai_family == afd->a_af) { - GET_AI(ai, afd, pton); + GET_AI(ai, afd, p); GET_PORT(ai, servname); if ((pai->ai_flags & AI_CANONNAME)) { /* @@ -1320,6 +1363,12 @@ get_ai(const struct addrinfo *pai, const memset(ai->ai_addr, 0, (size_t)afd->a_socklen); ai->ai_addr->sa_len = afd->a_socklen; ai->ai_addrlen = afd->a_socklen; + if (ai->ai_family == PF_LOCAL) { + size_t n = strnlen(addr, afd->a_addrlen); + + ai->ai_addrlen -= afd->a_addrlen - n; + ai->ai_addr->sa_len -= afd->a_addrlen - n; + } ai->ai_addr->sa_family = ai->ai_family = afd->a_af; p = (char *)(void *)(ai->ai_addr); memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); @@ -1378,6 +1427,9 @@ get_port(struct addrinfo *ai, const char if (servname == NULL) return 0; switch (ai->ai_family) { + case AF_LOCAL: + /* AF_LOCAL ignores servname silently. */ + return (0); case AF_INET: #ifdef AF_INET6 case AF_INET6: Modified: head/lib/libc/net/getnameinfo.3 ============================================================================== --- head/lib/libc/net/getnameinfo.3 Sat Sep 19 23:48:06 2015 (r287998) +++ head/lib/libc/net/getnameinfo.3 Sun Sep 20 01:09:23 2015 (r287999) @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 14, 2013 +.Dd September 20, 2015 .Dt GETNAMEINFO 3 .Os .Sh NAME @@ -47,7 +47,7 @@ functions and is the converse of the .Xr getaddrinfo 3 function. .Pp -If a link-layer address is passed to +If a link-layer address or UNIX-domain address is passed to .Fn getnameinfo , its ASCII representation will be stored in .Fa host . @@ -56,7 +56,8 @@ The string pointed to by will be set to the empty string if non-NULL; .Fa flags will always be ignored. -This is intended as a replacement for the legacy +For a link-layer address, +this can be used as a replacement of the legacy .Xr link_ntoa 3 function. .Pp @@ -66,10 +67,17 @@ structure .Fa sa should point to either a .Li sockaddr_in , -.Li sockaddr_in6 +.Li sockaddr_in6 , +.Li sockaddr_dl , or -.Li sockaddr_dl -structure (for IPv4, IPv6 or link-layer respectively) that is +.Li sockaddr_un +structure +.Po for IPv4 , +IPv6, +link-layer, +or UNIX-domain respectively +.Pc +that is .Fa salen bytes long. .Pp @@ -182,6 +190,9 @@ printf("host=%s\en", hbuf); .Xr inet_ntop 3 , .Xr link_ntoa 3 , .Xr resolver 3 , +.Xr inet 4 , +.Xr inet6 4 , +.Xr unix 4 , .Xr hosts 5 , .Xr resolv.conf 5 , .Xr services 5 , Modified: head/lib/libc/net/getnameinfo.c ============================================================================== --- head/lib/libc/net/getnameinfo.c Sat Sep 19 23:48:06 2015 (r287998) +++ head/lib/libc/net/getnameinfo.c Sun Sep 20 01:09:23 2015 (r287999) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -62,67 +63,102 @@ __FBSDID("$FreeBSD$"); #include #include -static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *, +static const struct afd *find_afd(int); +static int getnameinfo_inet(const struct afd *, + const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int); #ifdef INET6 static int ip6_parsenumeric(const struct sockaddr *, const char *, char *, size_t, int); static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int); #endif -static int getnameinfo_link(const struct sockaddr *, socklen_t, char *, +static int getnameinfo_link(const struct afd *, + const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); +static int hexname(const u_int8_t *, size_t, char *, size_t); +static int getnameinfo_un(const struct afd *, + const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int); -static int hexname(const u_int8_t *, size_t, char *, size_t); - -int -getnameinfo(const struct sockaddr *sa, socklen_t salen, - char *host, size_t hostlen, char *serv, size_t servlen, - int flags) -{ - if (sa == NULL) - return (EAI_FAIL); - - switch (sa->sa_family) { - case AF_INET: -#ifdef INET6 - case AF_INET6: -#endif - return getnameinfo_inet(sa, salen, host, hostlen, serv, - servlen, flags); - case AF_LINK: - return getnameinfo_link(sa, salen, host, hostlen, serv, - servlen, flags); - default: - return EAI_FAMILY; - } -} static const struct afd { int a_af; size_t a_addrlen; socklen_t a_socklen; int a_off; + int (*a_func)(const struct afd *, + const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); } afdl [] = { #ifdef INET6 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), - offsetof(struct sockaddr_in6, sin6_addr)}, + offsetof(struct sockaddr_in6, sin6_addr), + getnameinfo_inet}, #endif {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), - offsetof(struct sockaddr_in, sin_addr)}, + offsetof(struct sockaddr_in, sin_addr), + getnameinfo_inet}, +#define sizeofmember(type, member) (sizeof(((type *)0)->member)) + {PF_LOCAL, sizeofmember(struct sockaddr_un, sun_path), + sizeof(struct sockaddr_un), + offsetof(struct sockaddr_un, sun_path), + getnameinfo_un}, + {PF_LINK, sizeofmember(struct sockaddr_dl, sdl_data), + sizeof(struct sockaddr_dl), + offsetof(struct sockaddr_dl, sdl_data), + getnameinfo_link}, {0, 0, 0}, }; -struct sockinet { - u_char si_len; - u_char si_family; - u_short si_port; -}; +int +getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, char *serv, size_t servlen, + int flags) +{ + const struct afd *afd; + + if (sa == NULL) + return (EAI_FAIL); + + afd = find_afd(sa->sa_family); + if (afd == NULL) + return (EAI_FAMILY); + if (sa->sa_family == PF_LOCAL) { + /* + * PF_LOCAL uses variable sa->sa_len depending on the + * content length of sun_path. Require 1 byte in + * sun_path at least. + */ + if (salen > afd->a_socklen || + salen <= afd->a_socklen - + sizeofmember(struct sockaddr_un, sun_path)) + return (EAI_FAIL); + } else if (salen != afd->a_socklen) + return (EAI_FAIL); + + return ((*afd->a_func)(afd, sa, salen, host, hostlen, + serv, servlen, flags)); +} + +static const struct afd * +find_afd(int af) +{ + const struct afd *afd; + + if (af == PF_UNSPEC) + return (NULL); + for (afd = &afdl[0]; afd->a_af > 0; afd++) { + if (afd->a_af == af) + return (afd); + } + return (NULL); +} static int -getnameinfo_inet(const struct sockaddr *sa, socklen_t salen, +getnameinfo_inet(const struct afd *afd, + const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { - const struct afd *afd; struct servent *sp; struct hostent *hp; u_short port; @@ -132,18 +168,8 @@ getnameinfo_inet(const struct sockaddr * char numserv[512]; char numaddr[512]; - for (afd = &afdl[0]; afd->a_af > 0; afd++) { - if (afd->a_af == sa->sa_family) - break; - } - if (afd->a_af == 0) - return (EAI_FAMILY); - - if (salen != afd->a_socklen) - return EAI_FAIL; - /* network byte order */ - port = ((const struct sockinet *)sa)->si_port; + port = ((const struct sockaddr_in *)sa)->sin_port; addr = (const char *)sa + afd->a_off; if (serv == NULL || servlen == 0) { @@ -377,7 +403,8 @@ ip6_sa2str(const struct sockaddr_in6 *sa */ /* ARGSUSED */ static int -getnameinfo_link(const struct sockaddr *sa, socklen_t salen, +getnameinfo_link(const struct afd *afd, + const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { const struct sockaddr_dl *sdl = @@ -465,3 +492,30 @@ hexname(const u_int8_t *cp, size_t len, } return 0; } + +/* + * getnameinfo_un(): + * Format a UNIX IPC domain address (pathname). + */ +/* ARGSUSED */ +static int +getnameinfo_un(const struct afd *afd, + const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, char *serv, size_t servlen, int flags) +{ + size_t pathlen; + + if (serv != NULL && servlen > 0) + *serv = '\0'; + if (host != NULL && hostlen > 0) { + pathlen = sa->sa_len - afd->a_off; + + if (pathlen + 1 > hostlen) { + *host = '\0'; + return (EAI_MEMORY); + } + strlcpy(host, (const char *)sa + afd->a_off, pathlen + 1); + } + + return (0); +}