Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Oct 2006 12:54:52 GMT
From:      Michael Bushkov <bushman@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 108739 for review
Message-ID:  <200610301254.k9UCsq8Y025303@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=108739

Change 108739 by bushman@bushman_nss_ldap_cached on 2006/10/30 12:53:52

	IFC

Affected files ...

.. //depot/projects/soc2006/nss_ldap_cached_no_nss_ldap/src/lib/Makefile#3 integrate
.. //depot/projects/soc2006/nss_ldap_cached_no_nss_ldap/src/lib/nss_icmp/icmp_hosts_namadr.c#2 integrate
.. //depot/projects/soc2006/nss_ldap_cached_no_nss_ldap/src/share/mk/bsd.own.mk#2 integrate

Differences ...

==== //depot/projects/soc2006/nss_ldap_cached_no_nss_ldap/src/lib/Makefile#3 (text+ko) ====

@@ -33,7 +33,7 @@
 	libradius librpcsvc libsbuf libtacplus libutil \
 	${_libypclnt} libalias libarchive ${_libatm} \
 	libbegemot ${_libbluetooth} libbsnmp libbz2 \
-	nss_compat nss_dns nss_files nss_icmp ${_nss_nis} libc \
+	nss_compat nss_dns nss_files ${_nss_icmp} ${_nss_nis} libc \
 	libcalendar libcam libcompat libdevinfo libdevstat libdisk \
 	libedit libexpat libfetch libform libftpio libgeom ${_libgpib} \
 	libgssapi libipsec \
@@ -120,6 +120,10 @@
 _libusbhid=	libusbhid
 .endif
 
+.if ${MK_NSS_ICMP} != "no"
+_nss_icmp=	nss_icmp
+.endif
+
 .if ${MK_NIS} != "no"
 _libypclnt=	libypclnt
 _nss_nis=	nss_nis

==== //depot/projects/soc2006/nss_ldap_cached_no_nss_ldap/src/lib/nss_icmp/icmp_hosts_namadr.c#2 (text+ko) ====

@@ -156,151 +156,119 @@
 
 /*
  * experimental:
- *	draft-ietf-ipngwg-icmp-namelookups-02.txt
+ *	draft-ietf-ipngwg-icmp-namelookups-09.txt
  *	ifindex is assumed to be encoded in addr.
  */
 #include <sys/uio.h>
 #include <netinet/ip6.h>
 #include <netinet/icmp6.h>
+#include <ctype.h>
 
-struct _icmp_host_cache {
-	struct _icmp_host_cache *hc_next;
-	int hc_ifindex;
-	struct in6_addr hc_addr;
-	char *hc_name;
-};
+#ifndef NI_QTYPE_NODENAME
+#define NI_QTYPE_NODENAME	NI_QTYPE_DNSNAME
+#endif
 
-/* setting the query/reply structures according to 
- * draft-ietf-ipngwg-icmp-namelookups-02.txt */
-
-struct icmp6_fqdn_query {
-	u_int8_t        icmp6_fqdn_type;     /* type field */
-	u_int8_t        icmp6_fqdn_code;     /* code field */
-	u_int16_t       icmp6_fqdn_cksum;    /* checksum field */
-	u_short		icmp6_fqdn_id;
-	u_int16_t	icmp6_fqdn_nonce[4];
-};
-
-#define MAX_ICMP6_NAMELEN 255
-
-struct icmp6_fqdn_reply {
-	u_int8_t        icmp6_fqdn_type;     /* type field */
-	u_int8_t        icmp6_fqdn_code;     /* code field */
-	u_int16_t       icmp6_fqdn_cksum;    /* checksum field */
-	u_short		icmp6_fqdn_id;
-	u_int16_t	icmp6_fqdn_nonce[4];
-	int16_t		icmp6_fqdn_ttl;
-	uint8_t		icmp6_fqdn_namelen;
-	char		icmp6_fqdn_name[MAX_ICMP6_NAMELEN];
-};
-
-static int
-__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf,
-    size_t buflen)
+static char *
+dnsdecode(sp, ep, base, buf, bufsiz)
+	const u_char **sp;
+	const u_char *ep;
+	const u_char *base;	/*base for compressed name*/
+	u_char *buf;
+	size_t bufsiz;
 {
-	char *cp;
-	char **ptr;
-	int i, n;
-	int nptr, len;
+	int i;
+	const u_char *cp;
+	char cresult[MAXDNAME + 1];
+	const u_char *comp;
+	int l;
 
-	/* Find out the amount of space required to store the answer. */
-	nptr = 2; /* NULL ptrs */
-	len = (char *)ALIGN(buf) - buf;
-	for (i = 0; he->h_addr_list[i]; i++, nptr++) {
-		len += he->h_length;
-	}
-	for (i = 0; he->h_aliases[i]; i++, nptr++) {
-		len += strlen(he->h_aliases[i]) + 1;
-	}
-	len += strlen(he->h_name) + 1;
-	len += nptr * sizeof(char*);
+	cp = *sp;
+	*buf = '\0';
 
-	if (len > buflen) {
-		errno = ERANGE;
-		return (-1);
-	}
+	if (cp >= ep)
+		return NULL;
+	while (cp < ep) {
+		i = *cp;
+		if (i == 0 || cp != *sp) {
+			if (strlcat(buf, ".", bufsiz) >= bufsiz)
+				return NULL;	/* result overrun */
+		}
+		if (i == 0)
+			break;
+		cp++;
 
-	/* copy address size and type */
-	hptr->h_addrtype = he->h_addrtype;
-	n = hptr->h_length = he->h_length;
+		if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) {
+			/* DNS compression */
+			if (!base)
+				return NULL;
 
-	ptr = (char **)ALIGN(buf);
-	cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
-
-	/* copy address list */
-	hptr->h_addr_list = ptr;
-	for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
-		memcpy(cp, he->h_addr_list[i], n);
-		hptr->h_addr_list[i] = cp;
-		cp += n;
+			comp = base + (i & 0x3f);
+			if (dnsdecode(&comp, cp, base, cresult,
+			    sizeof(cresult)) == NULL)
+				return NULL;
+			if (strlcat(buf, cresult, bufsiz) >= bufsiz)
+				return NULL;	/* result overrun */
+			break;
+		} else if ((i & 0x3f) == i) {
+			if (i > ep - cp)
+				return NULL;	/* source overrun */
+			while (i-- > 0 && cp < ep) {
+				l = snprintf(cresult, sizeof(cresult),
+				    isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff);
+				if (l >= sizeof(cresult) || l < 0)
+					return NULL;
+				if (strlcat(buf, cresult, bufsiz) >= bufsiz)
+					return NULL;	/* result overrun */
+				cp++;
+			}
+		} else
+			return NULL;	/* invalid label */
 	}
-	hptr->h_addr_list[i] = NULL;
-	ptr++;
-
-	/* copy official name */
-	n = strlen(he->h_name) + 1;
-	strcpy(cp, he->h_name);
-	hptr->h_name = cp;
-	cp += n;
-
-	/* copy aliases */
-	hptr->h_aliases = ptr;
-	for (i = 0 ; he->h_aliases[i]; i++) {
-		n = strlen(he->h_aliases[i]) + 1;
-		strcpy(cp, he->h_aliases[i]);
-		hptr->h_aliases[i] = cp;
-		cp += n;
-	}
-	hptr->h_aliases[i] = NULL;
-
-	return (0);
+	if (i != 0)
+		return NULL;	/* not terminated */
+	cp++;
+	*sp = cp;
+	return buf;
 }
 
 static char *
-_icmp_fqdn_query(const struct in6_addr *addr, int ifindex)
+_icmp_nodeinfo_query(const struct in6_addr *addr, int ifindex, char *dnsname)
 {
 	int s;
 	struct icmp6_filter filter;
 	struct msghdr msg;
 	struct cmsghdr *cmsg;
 	struct in6_pktinfo *pkt;
-	char cbuf[256];
-	char buf[1024];
+	char cbuf[256], buf[1024], *cp, *end;
 	int cc;
-	struct icmp6_fqdn_query *fq;
-	struct icmp6_fqdn_reply *fr;
-	struct _icmp_host_cache *hc;
+	struct icmp6_nodeinfo niq, *nir;
 	struct sockaddr_in6 sin6;
 	struct iovec iov;
 	fd_set s_fds, fds;
 	struct timeval tout;
 	int len;
-	char *name;
-	static struct _icmp_host_cache *hc_head;
+	static int pid;
+	u_int32_t r1, r2;
 
-	THREAD_LOCK();
-	for (hc = hc_head; hc; hc = hc->hc_next) {
-		if (hc->hc_ifindex == ifindex
-		&&  IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) {
-			THREAD_UNLOCK();
-			return hc->hc_name;	/* XXX: never freed */
-		}
-	}
-	THREAD_UNLOCK();
+	if (pid == 0)
+		pid = getpid();
 
 	ICMP6_FILTER_SETBLOCKALL(&filter);
-	ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter);
+	ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filter);
 
 	FD_ZERO(&s_fds);
 	tout.tv_sec = 0;
-	tout.tv_usec = 200000;	/*XXX: 200ms*/
+	tout.tv_usec = 500000;	/* 500ms */
 
-	fq = (struct icmp6_fqdn_query *)buf;
-	fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY;
-	fq->icmp6_fqdn_code = 0;
-	fq->icmp6_fqdn_cksum = 0;
-	fq->icmp6_fqdn_id = (u_short)getpid();
-	memset(&fq->icmp6_fqdn_nonce, 0, sizeof(fq->icmp6_fqdn_nonce));
+	memset(&niq, 0, sizeof(niq));
+	niq.ni_type = ICMP6_NI_QUERY;
+	niq.ni_code = ICMP6_NI_SUBJ_IPV6;
+	niq.ni_qtype = htons(NI_QTYPE_NODENAME);
+	niq.ni_flags = 0;
+	r1 = arc4random();
+	r2 = arc4random();
+	memcpy(&niq.icmp6_ni_nonce[0], &r1, sizeof(r1));
+	memcpy(&niq.icmp6_ni_nonce[4], &r2, sizeof(r2));
 
 	memset(&sin6, 0, sizeof(sin6));
 	sin6.sin6_family = AF_INET6;
@@ -313,8 +281,8 @@
 	msg.msg_iovlen = 1;
 	msg.msg_control = NULL;
 	msg.msg_controllen = 0;
-	iov.iov_base = (caddr_t)buf;
-	iov.iov_len = sizeof(struct icmp6_fqdn_query);
+	iov.iov_base = (caddr_t)&niq;
+	iov.iov_len = sizeof(struct icmp6_nodeinfo);
 
 	if (ifindex) {
 		msg.msg_control = cbuf;
@@ -330,68 +298,85 @@
 		msg.msg_controllen = (char *)cmsg - cbuf;
 	}
 
-	if ((s = _socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
+	/* XXX: we need root privilege here */
+	if ((s = _socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
 		return NULL;
 	(void)_setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
 			 (char *)&filter, sizeof(filter));
 	cc = _sendmsg(s, &msg, 0);
 	if (cc < 0) {
 		_close(s);
-		return NULL;
+		return (NULL);
 	}
 	FD_SET(s, &s_fds);
 	for (;;) {
 		fds = s_fds;
 		if (_select(s + 1, &fds, NULL, NULL, &tout) <= 0) {
 			_close(s);
-			return NULL;
+			return (NULL);
 		}
 		len = sizeof(sin6);
 		cc = _recvfrom(s, buf, sizeof(buf), 0,
 			      (struct sockaddr *)&sin6, &len);
 		if (cc <= 0) {
 			_close(s);
-			return NULL;
+			return (NULL);
 		}
-		if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr))
+		if (cc < sizeof(struct icmp6_hdr))
+			continue;
+		nir = (struct icmp6_nodeinfo *)buf;
+		if (nir->ni_type != ICMP6_NI_REPLY)
+			continue;
+		if (nir->ni_qtype != htons(NI_QTYPE_NODENAME))
 			continue;
-		if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr))
+		if (memcmp(nir->icmp6_ni_nonce, niq.icmp6_ni_nonce,
+		    sizeof(nir->icmp6_ni_nonce)) != 0) {
 			continue;
-		fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr));
-		if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY)
-			break;
+		}
+		if (nir->ni_code != htons(ICMP6_NI_SUCCESS))
+			continue; /* or should we fail? */
+
+		/* this is an expected reply. */
+		break;
 	}
 	_close(s);
-	/* TODO: this check confuses me a bit */
-	/* if (fr->icmp6_fqdn_cookie[1] != 0) { */
-		/* rfc1788 type */
-	/*	name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4;
-	 *	len = (buf + cc) - name;
-	 * } else { */
-	len = fr->icmp6_fqdn_namelen;
-	name = fr->icmp6_fqdn_name;
-	/* } */
+
+	memset(dnsname, 0, MAXDNAME + 1);
+	cp = (char *)(nir + 1);
+	end = ((char *)nir) + cc;
+	if (end - cp < sizeof(int32_t))	/* for TTL.  we don't use it. */
+		return (NULL);
+	cp += sizeof(int32_t);
+	if (*cp == end - cp - 1) { /* an old version */
+		int nlen;
+
+		cp++;	/* skip length */
+		nlen = end - cp;
+		if (nlen > MAXDNAME)
+			return (NULL); /* XXX: use it anyway? */
+		memcpy(dnsname, cp, nlen);
+	} else {
+		/* XXX: should we use a generic function? */
+		if (dnsdecode((const u_char **)(void *)&cp, end,
+		    (const u_char *)(nir + 1), dnsname, MAXDNAME + 1)
+		    == NULL) {
+			return (NULL); /* bogus name */
+		}
+		/* Name-lookup special handling for truncated name. */
+		if (cp + 1 <= end && !*cp && strlen(dnsname) > 0)
+			dnsname[strlen(dnsname) - 1] = '\0';
 
-	if (len <= 0)
-		return NULL;
-	name[len] = 0;
+		/* There may be other names, but we ignore them. */
+	}
 
-	if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL)
-		return NULL;
-	/* XXX: limit number of cached entries */
-	hc->hc_ifindex = ifindex;
-	hc->hc_addr = *addr;
-	hc->hc_name = strdup(name);
-	THREAD_LOCK();
-	hc->hc_next = hc_head;
-	hc_head = hc;
-	THREAD_UNLOCK();
-	return hc->hc_name;
+	return (dnsname);
 }
 
+
 static struct hostent *
 _icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
 {
+	char dnsname[MAXDNAME + 1];
 	struct icmp_hostent_data *hed;
 	struct hostent *he;
 		
@@ -405,29 +390,23 @@
 		return (NULL);
 	}
 	
-	if (af != AF_INET6) {
+	if (af != AF_INET6 || addrlen != sizeof(addr6)) {
 		/*
 		 * Note: rfc1788 defines Who Are You for IPv4,
 		 * but no one implements it.
 		 */
-		return NULL;
+		return (NULL);
 	}
 
 	memcpy(&addr6, addr, addrlen);
-	ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];
-	addr6.s6_addr[2] = addr6.s6_addr[3] = 0;
+	if (IN6_IS_ADDR_LINKLOCAL(&addr6)) {
+		ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];
+		addr6.s6_addr[2] = addr6.s6_addr[3] = 0;
+	}
 
-	if (!IN6_IS_ADDR_LINKLOCAL(&addr6))
-		return (NULL);	/*XXX*/
-
-	if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL)
+	if ((hname = _icmp_nodeinfo_query(&addr6, ifindex, dnsname)) == NULL)
 		return (NULL);
 	
-	if (strlen(hname) > sizeof(hed->hostbuf) - 1) {
-		*errp = NO_RECOVERY;
-		return (NULL);
-	}
-
 	he->h_name = hed->hostbuf;
 	he->h_aliases = NULL;
 	he->h_addrtype = af;

==== //depot/projects/soc2006/nss_ldap_cached_no_nss_ldap/src/share/mk/bsd.own.mk#2 (text+ko) ====

@@ -367,7 +367,8 @@
 .for var in \
     BIND_LIBS \
     HESIOD \
-    IDEA
+    IDEA \
+    NSS_ICMP \
 .if defined(WITH_${var}) && defined(WITHOUT_${var})
 .error WITH_${var} and WITHOUT_${var} can't both be set.
 .endif



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