📄 name6.c
字号:
bp += n; buflen -= n; } break;#else template->h_name = bp; *errp = NETDB_SUCCESS; return (template);#endif case T_A: case T_AAAA: DNS_ASSERT(strcasecmp(template->h_name, bp) == 0); DNS_ASSERT(n == template->h_length); if (!haveanswer) { int nn; template->h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; buflen -= nn; }#ifdef ALIGN bp = (char *)ALIGN(bp);#else bp = (char *)(bp);#endif DNS_FATAL(bp + n < &hostbuf[sizeof hostbuf]); DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]);#ifdef FILTER_V4MAPPED if (type == T_AAAA) { struct in6_addr in6; memcpy(&in6, cp, sizeof(in6)); DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0); }#endif bcopy(cp, *hap++ = bp, n); bp += n; buflen -= n; cp += n; if (cp != erdata) { *errp = NO_RECOVERY; return (NULL); } break; default: abort(); } if (!had_error) haveanswer++; } if (haveanswer) { *ap = NULL; *hap = NULL; if (!template->h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); template->h_name = bp; bp += n; buflen -= n; } *errp = NETDB_SUCCESS; return (template); } no_recovery: *errp = NO_RECOVERY; return (NULL);#undef BOUNDED_INCR#undef BOUNDS_CHECK#undef DNS_ASSERT#undef DNS_FATAL}/* res_search() variant with multiple query support. */static struct hostent *_res_search_multi(name, rtl, errp) const char *name; /* domain name */ struct __res_type_list *rtl; /* list of query types */ int *errp;{ const char *cp, * const *domain; struct hostent *hp0 = NULL, *hp; struct hostent hpbuf; u_int dots; int trailing_dot, ret, saved_herrno; int got_nodata = 0, got_servfail = 0, tried_as_is = 0; struct __res_type_list *rtl0 = rtl; querybuf buf; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { *errp = NETDB_INTERNAL; return (NULL); } dots = 0; for (cp = name; *cp; cp++) dots += (*cp == '.'); trailing_dot = 0; if (cp > name && *--cp == '.') trailing_dot++; /* If there aren't any dots, it could be a user-level alias */ if (!dots && (cp = hostalias(name)) != NULL) { for(rtl = rtl0; rtl != NULL; rtl = rtl->rtl_entry) { ret = res_query(cp, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } return (hp0); } /* * If there are dots in the name already, let's just give it a try * 'as is'. The threshold can be set with the "ndots" option. */ saved_herrno = -1; if (dots >= _res.ndots) { for(rtl = rtl0; rtl != NULL; rtl = rtl->rtl_entry) { ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } if (hp0 != NULL) return (hp0); saved_herrno = *errp; tried_as_is++; } /* * We do at least one level of search if * - there is no dot and RES_DEFNAME is set, or * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ if ((!dots && (_res.options & RES_DEFNAMES)) || (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { int done = 0; for (domain = (const char * const *)_res.dnsrch; *domain && !done; domain++) { for(rtl = rtl0; rtl != NULL; rtl = rtl->rtl_entry) { ret = res_querydomain(name, *domain, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } if (hp0 != NULL) return (hp0); /* * If no server present, give up. * If name isn't found in this domain, * keep trying higher domains in the search list * (if that's enabled). * On a NO_DATA error, keep trying, otherwise * a wildcard entry of another type could keep us * from finding this entry higher in the domain. * If we get some other error (negative answer or * server failure), then stop searching up, * but try the input name below in case it's * fully-qualified. */ if (errno == ECONNREFUSED) { *errp = TRY_AGAIN; return (NULL); } switch (*errp) { case NO_DATA: got_nodata++; /* FALLTHROUGH */ case HOST_NOT_FOUND: /* keep trying */ break; case TRY_AGAIN: if (buf.hdr.rcode == SERVFAIL) { /* try next search element, if any */ got_servfail++; break; } /* FALLTHROUGH */ default: /* anything else implies that we're done */ done++; } /* if we got here for some reason other than DNSRCH, * we only wanted one iteration of the loop, so stop. */ if (!(_res.options & RES_DNSRCH)) done++; } } /* * If we have not already tried the name "as is", do that now. * note that we do this regardless of how many dots were in the * name or whether it ends with a dot unless NOTLDQUERY is set. */ if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { for(rtl = rtl0; rtl != NULL; rtl = rtl->rtl_entry) { ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } if (hp0 != NULL) return (hp0); } /* if we got here, we didn't satisfy the search. * if we did an initial full query, return that query's h_errno * (note that we wouldn't be here if that query had succeeded). * else if we ever got a nodata, send that back as the reason. * else send back meaningless h_errno, that being the one from * the last DNSRCH we did. */ if (saved_herrno != -1) *errp = saved_herrno; else if (got_nodata) *errp = NO_DATA; else if (got_servfail) *errp = TRY_AGAIN; return (NULL);}static int_dns_ghbyname(void *rval, void *cb_data, va_list ap){ const char *name; int af; int *errp; res_type_list *rtl, rtl4;#ifdef INET6 res_type_list rtl6;#endif name = va_arg(ap, const char *); af = va_arg(ap, int); errp = va_arg(ap, int *);#ifdef INET6 switch (af) { case AF_UNSPEC: rtl4.rtl_entry = NULL; rtl4.rtl_type = T_A; rtl6.rtl_entry = &rtl4; rtl6.rtl_type = T_AAAA; rtl = &rtl6; break; case AF_INET6: rtl6.rtl_entry = NULL; rtl6.rtl_type = T_AAAA; rtl = &rtl6; break; case AF_INET: rtl4.rtl_entry = NULL; rtl4.rtl_type = T_A; rtl = &rtl4; break; }#else (&rtl4)->rtl_entry = NULL; rtl4.rtl_type = T_A; rtl = &rtl4;#endif *(struct hostent **)rval = _res_search_multi(name, rtl, errp); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;}static int_dns_ghbyaddr(void *rval, void *cb_data, va_list ap){ const void *addr; int addrlen; int af; int *errp; int n; struct hostent *hp; u_char c, *cp; char *bp; struct hostent hbuf; int na;#ifdef INET6 static const char hex[] = "0123456789abcdef";#endif querybuf buf; char qbuf[MAXDNAME+1]; char *hlist[2]; addr = va_arg(ap, const void *); addrlen = va_arg(ap, int); af = va_arg(ap, int); errp = va_arg(ap, int *); *(struct hostent **)rval = NULL;#ifdef INET6 /* XXX */ if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr)) return NS_NOTFOUND;#endif if ((_res.options & RES_INIT) == 0) { if (res_init() < 0) { *errp = h_errno; return NS_UNAVAIL; } } memset(&hbuf, 0, sizeof(hbuf)); hbuf.h_name = NULL; hbuf.h_addrtype = af; hbuf.h_length = addrlen; na = 0; /* XXX assumes that MAXDNAME is big enough */ n = 0; bp = qbuf; cp = (u_char *)addr+addrlen-1; switch (af) {#ifdef INET6 case AF_INET6: for (; n < addrlen; n++, cp--) { c = *cp; *bp++ = hex[c & 0xf]; *bp++ = '.'; *bp++ = hex[c >> 4]; *bp++ = '.'; } strcpy(bp, "ip6.int"); break;#endif default: for (; n < addrlen; n++, cp--) { c = *cp; if (c >= 100) *bp++ = '0' + c / 100; if (c >= 10) *bp++ = '0' + (c % 100) / 10; *bp++ = '0' + c % 10; *bp++ = '.'; } strcpy(bp, "in-addr.arpa"); break; } n = res_query(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf); if (n < 0) { *errp = h_errno; return NS_UNAVAIL; } hp = getanswer(&buf, n, qbuf, T_PTR, &hbuf, errp); if (!hp) return NS_NOTFOUND; hbuf.h_addrtype = af; hbuf.h_length = addrlen; hbuf.h_addr_list = hlist; hlist[0] = (char *)addr; hlist[1] = NULL; *(struct hostent **)rval = _hpcopy(&hbuf, errp); return NS_SUCCESS;}#if 0 // keep gcc happystatic void_dns_shent(int stayopen){ if ((_res.options & RES_INIT) == 0) { if (res_init() < 0) return; } if (stayopen) _res.options |= RES_STAYOPEN | RES_USEVC;}static void_dns_ehent(void){ _res.options &= ~(RES_STAYOPEN | RES_USEVC); res_close();}#endif#ifdef ICMPNL/* * experimental: * draft-ietf-ipngwg-icmp-namelookups-02.txt * ifindex is assumed to be encoded in addr. */#include <sys/uio.h>#include <netinet/ip6.h>#include <netinet/icmp6.h>struct _icmp_host_cache { struct _icmp_host_cache *hc_next; int hc_ifindex; struct in6_addr hc_addr; char *hc_name;};static char *_icmp_fqdn_query(const struct in6_addr *addr, int ifindex){ int s; struct icmp6_filter filter; struct msghdr msg; struct cmsghdr *cmsg; struct in6_pktinfo *pkt; char cbuf[256]; char buf[1024]; int cc; struct icmp6_fqdn_query *fq; struct icmp6_fqdn_reply *fr; struct _icmp_host_cache *hc; struct sockaddr_in6 sin6; struct iovec iov; fd_set s_fds, fds; struct timeval tout; int len; char *name; static int pid; static struct _icmp_host_cache *hc_head; for (hc = hc_head; hc; hc = hc->hc_next) { if (hc->hc_ifindex == ifindex && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) return hc->hc_name; } if (pid == 0) pid = getpid(); ICMP6_FILTER_SETBLOCKALL(&filter); ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter); FD_ZERO(&s_fds); tout.tv_sec = 0; tout.tv_usec = 200000; /*XXX: 200ms*/ 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)pid; fq->icmp6_fqdn_unused = 0; fq->icmp6_fqdn_cookie[0] = 0; fq->icmp6_fqdn_cookie[1] = 0; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr; memset(&msg, 0, sizeof(msg)); msg.msg_name = (caddr_t)&sin6; msg.msg_namelen = sizeof(sin6); msg.msg_iov = &iov; 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); if (ifindex) { msg.msg_control = cbuf; msg.msg_controllen = sizeof(cbuf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; pkt = (struct in6_pktinfo *)&cmsg[1]; memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); pkt->ipi6_ifindex = ifindex; cmsg = CMSG_NXTHDR(&msg, cmsg); msg.msg_controllen = (char *)cmsg - cbuf; } if ((s = socket(PF_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; } FD_SET(s, &s_fds); for (;;) { fds = s_fds; if (select(s + 1, &fds, NULL, NULL, &tout) <= 0) { close(s); return NULL; } len = sizeof(sin6); cc = _recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&sin6, &len); if (cc <= 0) { close(s); return NULL; } if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) continue; if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr)) continue; fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr)); if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY) break; } close(s); 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; } if (len <= 0) return NULL; name[len] = 0; 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); hc->hc_next = hc_head; hc_head = hc; return hc->hc_name;}static struct hostent *_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp){ char *hname; int ifindex; struct in6_addr addr6; if (af != AF_INET6) { /* * Note: rfc1788 defines Who Are You for IPv4, * but no one implements it. */ 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)) return NULL; /*XXX*/ if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL) return NULL; return _hpaddr(af, hname, &addr6, errp);}#endif /* ICMPNL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -