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