Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Sep 2015 01:09:24 +0000 (UTC)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r287999 - head/lib/libc/net
Message-ID:  <201509200109.t8K19OtZ096488@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/types.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
@@ -62,67 +63,102 @@ __FBSDID("$FreeBSD$");
 #include <stddef.h>
 #include <errno.h>
 
-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);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509200109.t8K19OtZ096488>