From owner-freebsd-net Mon Jul 16 7:25:55 2001 Delivered-To: freebsd-net@freebsd.org Received: from salmon.maths.tcd.ie (salmon.maths.tcd.ie [134.226.81.11]) by hub.freebsd.org (Postfix) with SMTP id 4FFB637B401 for ; Mon, 16 Jul 2001 07:25:44 -0700 (PDT) (envelope-from iedowse@maths.tcd.ie) Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP id ; 16 Jul 2001 15:25:28 +0100 (BST) To: freebsd-net@FreeBSD.ORG Cc: Bernd Walter , Hajimu UMEMOTO Subject: Re: how to get AF_LOCAL from getaddrinfo() In-Reply-To: Your message of "Sun, 15 Jul 2001 17:18:54 BST." <200107151718.aa17383@salmon.maths.tcd.ie> Date: Mon, 16 Jul 2001 15:25:25 +0100 From: Ian Dowse Message-ID: <200107161525.aa15954@salmon.maths.tcd.ie> Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org 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 #include #include +#include #include #include #include @@ -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 #include +#include #include #include #include @@ -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