In message <[EMAIL PROTECTED]>, 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 [EMAIL PROTECTED]
with "unsubscribe freebsd-net" in the body of the message

Reply via email to