From owner-p4-projects@FreeBSD.ORG Mon Oct 30 12:54:53 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 9450316A412; Mon, 30 Oct 2006 12:54:53 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3E35516A407 for ; Mon, 30 Oct 2006 12:54:53 +0000 (UTC) (envelope-from bushman@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1BE0543D49 for ; Mon, 30 Oct 2006 12:54:53 +0000 (GMT) (envelope-from bushman@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k9UCsqoY025306 for ; Mon, 30 Oct 2006 12:54:53 GMT (envelope-from bushman@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k9UCsq8Y025303 for perforce@freebsd.org; Mon, 30 Oct 2006 12:54:52 GMT (envelope-from bushman@freebsd.org) Date: Mon, 30 Oct 2006 12:54:52 GMT Message-Id: <200610301254.k9UCsq8Y025303@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bushman@freebsd.org using -f From: Michael Bushkov To: Perforce Change Reviews Cc: Subject: PERFORCE change 108739 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Oct 2006 12:54:53 -0000 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 #include #include +#include -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