Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Jul 2001 15:25:25 +0100
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        freebsd-net@FreeBSD.ORG
Cc:        Bernd Walter <ticso@mail.cicely.de>, Hajimu UMEMOTO <ume@mahoroba.org>
Subject:   Re: how to get AF_LOCAL from getaddrinfo() 
Message-ID:   <200107161525.aa15954@salmon.maths.tcd.ie>
In-Reply-To: Your message of "Sun, 15 Jul 2001 17:18:54 BST." <200107151718.aa17383@salmon.maths.tcd.ie> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <200107151718.aa17383@salmon.maths.tcd.ie>, Ian Dowse writes:
>
>I'd very much like to see PF_LOCAL support added to our getaddrinfo()
>and getnameinfo(). I know that PF_LOCAL sockets have semantics that

Here is quick and simple implementation - any comments welcome. It
probably needs a few changes to match the conventions of other
implementations, and a mention of these conventions on the manpage.

Ian


Index: getaddrinfo.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/lib/libc/net/getaddrinfo.c,v
retrieving revision 1.21
diff -u -r1.21 getaddrinfo.c
--- getaddrinfo.c	2001/06/10 20:25:23	1.21
+++ getaddrinfo.c	2001/07/16 14:20:42
@@ -87,6 +87,7 @@
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -143,13 +144,19 @@
 	 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},
+	{PF_LOCAL, sizeof(((struct sockaddr_un *)0)->sun_path),
+	 sizeof(struct sockaddr_un),
+	 offsetof(struct sockaddr_un, sun_path),
+	 NULL, NULL, 0},
 	{0, 0, 0, 0, NULL, NULL, 0},
 };
 
@@ -165,9 +172,6 @@
 };
 
 static const struct explore explore[] = {
-#if 0
-	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
-#endif
 #ifdef INET6
 	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
 	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
@@ -223,6 +227,8 @@
 	const char *, struct addrinfo **));
 static int explore_numeric_scope __P((const struct addrinfo *, const char *,
 	const char *, struct addrinfo **));
+static int explore_local __P((const struct addrinfo *, const char *,
+	const char *, struct addrinfo **));
 static int get_canonname __P((const struct addrinfo *,
 	struct addrinfo *, const char *));
 static struct addrinfo *get_ai __P((const struct addrinfo *,
@@ -317,6 +323,8 @@
 {
 	if (ecode < 0 || ecode > EAI_MAX)
 		ecode = EAI_MAX;
+	if (ecode == EAI_SYSTEM)
+		return strerror(errno);
 	return ai_errlist[ecode];
 }
 
@@ -394,6 +402,10 @@
 		case PF_INET6:
 #endif
 			break;
+		case PF_LOCAL:
+			if (hints->ai_protocol != 0)
+				ERR(EAI_BADHINTS);
+			break;
 		default:
 			ERR(EAI_FAMILY);
 		}
@@ -420,6 +432,17 @@
 	}
 
 	/*
+	 * PF_LOCAL addresses are handled specially. The protocol family
+	 * must be set to PF_LOCAL in the hints.
+	 */
+	if (pai->ai_family == PF_LOCAL) {
+		error = explore_local(pai, hostname, servname, &cur->ai_next);
+		if (error)
+			goto free;
+		goto good;
+	}
+
+	/*
 	 * post-2553: AI_ALL and AI_V4MAPPED are effective only against
 	 * AF_INET6 query.  They needs to be ignored if specified in other
 	 * occassions.
@@ -833,6 +856,56 @@
 
 	return error;
 #endif
+}
+
+/*
+ * PF_LOCAL address
+ */
+static int
+explore_local(pai, hostname, servname, res)
+	const struct addrinfo *pai;
+	const char *hostname;
+	const char *servname;
+	struct addrinfo **res;
+{
+	struct sockaddr_un sun;
+	const struct afd *afd;
+	struct addrinfo *ai;
+	int error;
+
+	*res = NULL;
+	ai = NULL;
+	afd = &afdl[N_LOCAL];
+
+	if (pai->ai_flags & ~(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST))
+		ERR(EAI_BADFLAGS);
+	if (servname == NULL)
+		ERR(EAI_SERVICE);
+	if (strlen(servname) >= sizeof(sun.sun_path)) {
+		errno = ENAMETOOLONG;
+		ERR(EAI_SYSTEM);
+	}
+	memset(&sun, 0, sizeof(sun));
+	strlcpy(sun.sun_path, servname, sizeof(sun.sun_path));
+	GET_AI(ai, afd, sun.sun_path);
+	GET_CANONNAME(ai, "localhost");
+
+	/*
+	 * XXX should we set ai->addrlen and sun_len to SUN_LEN(sun)?
+	 * The kernel doesn't mind, but (broken) userland apps might
+	 * either expect a NUL-terminated string when they bcopy
+	 * ai->addrlen bytes from ai->addr, or else they might expect
+	 * sun_len to be SUN_LEN(sun).
+	 */
+	
+	*res = ai;
+	return 0;
+
+free:
+bad:
+	if (ai != NULL)
+		freeaddrinfo(ai);
+	return error;
 }
 
 static int
Index: getnameinfo.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/lib/libc/net/getnameinfo.c,v
retrieving revision 1.7
diff -u -r1.7 getnameinfo.c
--- getnameinfo.c	2001/02/15 10:35:54	1.7
+++ getnameinfo.c	2001/07/16 00:50:38
@@ -44,6 +44,7 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -80,6 +81,8 @@
 	u_short	si_port;
 };
 
+static int local_getnameinfo __P((const struct sockaddr *,
+    socklen_t, char *, size_t, char *, size_t, int));
 #ifdef INET6
 static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *,
 				 size_t, int));
@@ -119,6 +122,11 @@
 	if (sa == NULL)
 		return ENI_NOSOCKET;
 
+	/* AF_LOCAL is treated differently to the rest. */
+	if (sa->sa_family == AF_LOCAL)
+		return local_getnameinfo(sa, salen, host, hostlen, serv,
+		    servlen, flags);
+
 	if (sa->sa_len != salen)
 		return ENI_SALEN;
 	
@@ -282,6 +290,46 @@
 			}
 		}
 	}
+	return SUCCESS;
+}
+
+static int
+local_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+	const struct sockaddr *sa;
+	socklen_t salen;
+	char *host;
+	size_t hostlen;
+	char *serv;
+	size_t servlen;
+	int flags;
+{
+	struct sockaddr_un *sun;
+	char *p;
+	int pathlen;
+
+	/*
+	 * Allow the case of salen == sizeof(struct sockaddr_un) but
+	 * sa->sa_len covering only to the end of the path.
+	 */
+	if (sa->sa_len <= offsetof(struct sockaddr_un, sun_path) ||
+	    salen < sa->sa_len || salen > sizeof(struct sockaddr_un))
+		return ENI_SALEN;
+	sun = (struct sockaddr_un *)sa;
+	pathlen = sa->sa_len - offsetof(struct sockaddr_un, sun_path);
+	if ((p = memchr(sun->sun_path, '\0', pathlen)) != NULL)
+		pathlen = p - sun->sun_path;
+
+	if (host != NULL) {
+		if (hostlen < strlen("localhost") + 1)
+			return ENI_MEMORY;
+		strlcpy(host, "localhost", hostlen);
+	}
+	if (serv != NULL) {
+		if (servlen < pathlen + 1)
+			return ENI_MEMORY;
+		snprintf(serv, servlen, "%.*s", pathlen, sun->sun_path);
+	}
+
 	return SUCCESS;
 }
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




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