From owner-cvs-all Thu Jun 15 11:44: 4 2000 Delivered-To: cvs-all@freebsd.org Received: from peace.mahoroba.org (peace.calm.imasy.or.jp [202.227.26.34]) by hub.freebsd.org (Postfix) with ESMTP id 6E45237B5FF; Thu, 15 Jun 2000 11:43:39 -0700 (PDT) (envelope-from ume@mahoroba.org) Received: from localhost (IDENT:LiMlCSNjdkR+QWLnnKhF75d9hCka9GvE1FgFQId6E18u0xaQw7UGx46VvzQv4OtS@localhost [::1]) (authenticated) by peace.mahoroba.org (8.10.2/3.7W-peace) with ESMTP id e5FIhD400487; Fri, 16 Jun 2000 03:43:13 +0900 (JST) (envelope-from ume@mahoroba.org) Date: Fri, 16 Jun 2000 03:43:10 +0900 (JST) Message-Id: <20000616.034310.74757991.ume@mahoroba.org> To: ache@freebsd.org Cc: alex@big.endian.de, cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org Subject: Re: cvs commit: src/lib/libc/net res_init.c res_send.c From: Hajimu UMEMOTO (=?iso-2022-jp?B?GyRCR19LXBsoQiAbJEJIJRsoQg==?=) In-Reply-To: <20000615111427.A20272@freebsd.org> References: <20000615095829.D2544@cichlids.cichlids.com> <20000616.030308.59461838.ume@mahoroba.org> <20000615111427.A20272@freebsd.org> X-Mailer: xcite1.20> Mew version 1.95b38 on Emacs 20.6 / Mule 4.0 =?iso-2022-jp?B?KBskQjJWMWMbKEIp?= X-PGP-Public-Key: http://www.imasy.org/~ume/publickey.asc X-PGP-Fingerprint: 6B 0C 53 FC 5D D0 37 91 05 D0 B3 EF 36 9B 6A BC X-URL: http://www.imasy.org/~ume/ X-OS: FreeBSD 5.0-CURRENT Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Fri_Jun_16_03:43:10_2000_697)--" Content-Transfer-Encoding: 7bit Sender: owner-cvs-all@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG ----Next_Part(Fri_Jun_16_03:43:10_2000_697)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit >>>>> On Thu, 15 Jun 2000 11:14:27 -0700 >>>>> "Andrey A. Chernov" said: ache> Not so simple. I have no resolv.conf at all and your code fails because default ache> NS localhost is set to AF_INET6. When I create this file and add some ache> nameservers to it, your code still fails because they assigned to AF_INET6 too ache> which socket() not understands. Yes, I know and it was also fixed. Above explanation is why alex doesn't met the problem. :) ache> It means that 1) you need to set AF_INET6 only for INET6 nameservers 2) you ache> must not set default NS localhost to AF_INET6. The case 2) is harder because ache> you can't run INET6 named by default, so some detection code required which ache> not affect performance. Now, default is AF_INET. I attach the diff. Please review it. Thanks itojun. ----Next_Part(Fri_Jun_16_03:43:10_2000_697)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: resolver-ipv6.diff Content-Disposition: attachment; filename="resolver-ipv6.diff" Index: lib/libc/net/res_init.c diff -u lib/libc/net/res_init.c.orig lib/libc/net/res_init.c --- lib/libc/net/res_init.c.orig Thu Jun 15 05:51:55 2000 +++ lib/libc/net/res_init.c Thu Jun 15 20:15:45 2000 @@ -87,6 +87,7 @@ #include #include #include +#include #include "res_config.h" @@ -112,9 +113,7 @@ # endif ; -#ifdef INET6 struct __res_state_ext _res_ext; -#endif /* INET6 */ /* * Set up default settings. If the configuration file exist, the values @@ -195,6 +194,8 @@ #endif _res.nsaddr.sin_family = AF_INET; _res.nsaddr.sin_port = htons(NAMESERVER_PORT); + if (sizeof(_res_ext.nsaddr) >= _res.nsaddr.sin_len) + memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len); _res.nscount = 1; _res.ndots = 1; _res.pfcode = 0; @@ -300,16 +301,41 @@ } /* read nameservers to query */ if (MATCH(buf, "nameserver") && nserv < MAXNS) { - struct in_addr a; + char *q; + struct addrinfo hints, *res; + char pbuf[NI_MAXSERV]; cp = buf + sizeof("nameserver") - 1; while (*cp == ' ' || *cp == '\t') cp++; - if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { - _res.nsaddr_list[nserv].sin_addr = a; - _res.nsaddr_list[nserv].sin_family = AF_INET; - _res.nsaddr_list[nserv].sin_port = - htons(NAMESERVER_PORT); + if ((*cp == '\0') || (*cp == '\n')) + continue; + for (q = cp; *q; q++) { + if (isspace(*q)) { + *q = '\0'; + break; + } + } + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_socktype = SOCK_DGRAM; + snprintf(pbuf, sizeof(pbuf), "%d", NAMESERVER_PORT); + if (getaddrinfo(cp, pbuf, &hints, &res) == 0 && + res->ai_next == NULL) { + if (res->ai_addrlen <= sizeof(_res_ext.nsaddr_list[nserv])) { + memcpy(&_res_ext.nsaddr_list[nserv], res->ai_addr, + res->ai_addrlen); + } else { + memset(&_res_ext.nsaddr_list[nserv], 0, + sizeof(_res_ext.nsaddr_list[nserv])); + } + if (res->ai_addrlen <= sizeof(_res.nsaddr_list[nserv])) { + memcpy(&_res.nsaddr_list[nserv], res->ai_addr, + res->ai_addrlen); + } else { + memset(&_res.nsaddr_list[nserv], 0, + sizeof(_res.nsaddr_list[nserv])); + } nserv++; } continue; @@ -317,9 +343,9 @@ #ifdef RESOLVSORT if (MATCH(buf, "sortlist")) { struct in_addr a; -#ifdef INET6 struct in6_addr a6; -#endif /* INET6 */ + int m, i; + u_char *u; cp = buf + sizeof("sortlist") - 1; while (nsort < MAXRESOLVSORT) { @@ -353,19 +379,14 @@ _res.sort_list[nsort].mask = net_mask(_res.sort_list[nsort].addr); } -#ifdef INET6 _res_ext.sort_list[nsort].af = AF_INET; _res_ext.sort_list[nsort].addr.ina = _res.sort_list[nsort].addr; _res_ext.sort_list[nsort].mask.ina.s_addr = _res.sort_list[nsort].mask; -#endif /* INET6 */ nsort++; } -#ifdef INET6 else if (inet_pton(AF_INET6, net, &a6) == 1) { - int m, i; - u_char *u; _res_ext.sort_list[nsort].af = AF_INET6; _res_ext.sort_list[nsort].addr.in6a = a6; @@ -407,7 +428,6 @@ } nsort++; } -#endif /* INET6 */ *cp = n; } continue; Index: lib/libc/net/res_send.c diff -u lib/libc/net/res_send.c.orig lib/libc/net/res_send.c --- lib/libc/net/res_send.c.orig Thu Jun 15 05:51:55 2000 +++ lib/libc/net/res_send.c Fri Jun 16 02:53:38 2000 @@ -109,6 +109,7 @@ static int s = -1; /* socket used for communications */ static int connected = 0; /* is the socket connected */ static int vc = 0; /* is the socket a virtual circuit? */ +static int af = 0; /* address family of socket */ static res_send_qhook Qhook = NULL; static res_send_rhook Rhook = NULL; @@ -126,21 +127,26 @@ fprintf args;\ __fp_nquery(query, size, stdout);\ } else {} +static char abuf[NI_MAXHOST]; +static char pbuf[NI_MAXSERV]; +static void Aerror __P((FILE *, char *, int, struct sockaddr *)); +static void Perror __P((FILE *, char *, int)); + static void Aerror(file, string, error, address) FILE *file; char *string; int error; - struct sockaddr_in address; + struct sockaddr *address; { int save = errno; if (_res.options & RES_DEBUG) { - fprintf(file, "res_send: %s ([%s].%u): %s\n", - string, - inet_ntoa(address.sin_addr), - ntohs(address.sin_port), - strerror(error)); + getnameinfo(address, address->sa_len, abuf, sizeof(abuf), + pbuf, sizeof(pbuf), + NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID); + fprintf(file, "res_send: %s ([%s].%s): %s\n", + string, abuf, pbuf, strerror(error)); } errno = save; } @@ -176,6 +182,33 @@ Rhook = hook; } +static struct sockaddr * get_nsaddr __P((size_t)); + +/* + * pick appropriate nsaddr_list for use. see res_init() for initialization. + */ +static struct sockaddr * +get_nsaddr(n) + size_t n; +{ + + if (!_res.nsaddr_list[n].sin_family) { + /* + * - _res_ext.nsaddr_list[n] holds an address that is larger + * than struct sockaddr, and + * - user code did not update _res.nsaddr_list[n]. + */ + return (struct sockaddr *)&_res_ext.nsaddr_list[n]; + } else { + /* + * - user code updated _res.nsaddr_list[n], or + * - _res.nsaddr_list[n] has the same content as + * _res_ext.nsaddr_list[n]. + */ + return (struct sockaddr *)&_res.nsaddr_list[n]; + } +} + /* int * res_isourserver(ina) * looks up "ina" in _res.ns_addr_list[] @@ -189,21 +222,39 @@ res_isourserver(inp) const struct sockaddr_in *inp; { - struct sockaddr_in ina; + const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp; + const struct sockaddr_in6 *srv6; + const struct sockaddr_in *srv; int ns, ret; - ina = *inp; ret = 0; - for (ns = 0; ns < _res.nscount; ns++) { - const struct sockaddr_in *srv = &_res.nsaddr_list[ns]; - - if (srv->sin_family == ina.sin_family && - srv->sin_port == ina.sin_port && - (srv->sin_addr.s_addr == INADDR_ANY || - srv->sin_addr.s_addr == ina.sin_addr.s_addr)) { - ret++; - break; + switch (inp->sin_family) { + case AF_INET6: + for (ns = 0; ns < _res.nscount; ns++) { + srv6 = (struct sockaddr_in6 *)get_nsaddr(ns); + if (srv6->sin6_family == in6p->sin6_family && + srv6->sin6_port == in6p->sin6_port && + srv6->sin6_scope_id == in6p->sin6_scope_id && + (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || + IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, + &in6p->sin6_addr))) { + ret++; + break; + } + } + break; + case AF_INET: + for (ns = 0; ns < _res.nscount; ns++) { + srv = (struct sockaddr_in *)get_nsaddr(ns); + if (srv->sin_family == inp->sin_family && + srv->sin_port == inp->sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == inp->sin_addr.s_addr)) { + ret++; + break; + } } + break; } return (ret); } @@ -332,7 +383,8 @@ */ for (try = 0; try < _res.retry; try++) { for (ns = 0; ns < _res.nscount; ns++) { - struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; + struct sockaddr *nsap = get_nsaddr(ns); + same_ns: if (badns & (1 << ns)) { res_close(); @@ -345,7 +397,8 @@ do { res_sendhookact act; - act = (*Qhook)(&nsap, &buf, &buflen, + act = (*Qhook)((struct sockaddr_in **)&nsap, + &buf, &buflen, ans, anssiz, &resplen); switch (act) { case res_goahead: @@ -369,9 +422,11 @@ } while (!done); } - Dprint(_res.options & RES_DEBUG, + Dprint((_res.options & RES_DEBUG) && + getnameinfo(nsap, nsap->sa_len, abuf, sizeof(abuf), + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0, (stdout, ";; Querying server (# %d) address = %s\n", - ns + 1, inet_ntoa(nsap->sin_addr))); + ns + 1, abuf)); if (v_circuit) { int truncated; @@ -385,22 +440,25 @@ */ try = _res.retry; truncated = 0; - if (s < 0 || !vc || hp->opcode == ns_o_update) { + if (s < 0 || !vc || hp->opcode == ns_o_update || + af != nsap->sa_family) { if (s >= 0) res_close(); - s = socket(PF_INET, SOCK_STREAM, 0); + af = nsap->sa_family; + s = socket(af, SOCK_STREAM, 0); if (s < 0) { terrno = errno; Perror(stderr, "socket(vc)", errno); - return (-1); + badns |= (1 << ns); + res_close(); + goto next_ns; } errno = 0; - if (connect(s, (struct sockaddr *)nsap, - sizeof *nsap) < 0) { + if (connect(s, nsap, nsap->sa_len) < 0) { terrno = errno; Aerror(stderr, "connect/vc", - errno, *nsap); + errno, nsap); badns |= (1 << ns); res_close(); goto next_ns; @@ -530,20 +588,23 @@ struct timeval timeout; fd_set dsmask, *dsmaskp; int dsmasklen; - struct sockaddr_in from; + struct sockaddr_storage from; int fromlen; - if ((s < 0) || vc) { + if (s < 0 || vc || af != nsap->sa_family) { if (vc) res_close(); - s = socket(PF_INET, SOCK_DGRAM, 0); + af = nsap->sa_family; + s = socket(af, SOCK_DGRAM, 0); if (s < 0) { #ifndef CAN_RECONNECT bad_dg_sock: #endif terrno = errno; Perror(stderr, "socket(dg)", errno); - return (-1); + badns |= (1 << ns); + res_close(); + goto next_ns; } connected = 0; } @@ -569,12 +630,10 @@ * receive a response from another server. */ if (!connected) { - if (connect(s, (struct sockaddr *)nsap, - sizeof *nsap - ) < 0) { + if (connect(s, nsap, nsap->sa_len) < 0) { Aerror(stderr, "connect(dg)", - errno, *nsap); + errno, nsap); badns |= (1 << ns); res_close(); goto next_ns; @@ -594,6 +653,7 @@ */ if (connected) { #ifdef CAN_RECONNECT + /* XXX: any errornous address */ struct sockaddr_in no_addr; no_addr.sin_family = AF_INET; @@ -604,7 +664,7 @@ &no_addr, sizeof no_addr); #else - int s1 = socket(PF_INET, SOCK_DGRAM,0); + int s1 = socket(af, SOCK_DGRAM,0); if (s1 < 0) goto bad_dg_sock; (void)dup2(s1, s); @@ -617,10 +677,8 @@ } #endif /* !CANNOT_CONNECT_DGRAM */ if (sendto(s, (char*)buf, buflen, 0, - (struct sockaddr *)nsap, - sizeof *nsap) - != buflen) { - Aerror(stderr, "sendto", errno, *nsap); + nsap, nsap->sa_len) != buflen) { + Aerror(stderr, "sendto", errno, nsap); badns |= (1 << ns); res_close(); goto next_ns; @@ -749,7 +807,7 @@ goto next_ns; } errno = 0; - fromlen = sizeof(struct sockaddr_in); + fromlen = sizeof(from); resplen = recvfrom(s, (char*)ans, anssiz, 0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { @@ -784,7 +842,7 @@ } #ifdef CHECK_SRVR_ADDR if (!(_res.options & RES_INSECURE1) && - !res_isourserver(&from)) { + !res_isourserver((struct sockaddr_in *)&from)) { /* * response from wrong server? ignore it. * XXX - potential security hazard could @@ -861,7 +919,8 @@ do { res_sendhookact act; - act = (*Rhook)(nsap, buf, buflen, + act = (*Rhook)((struct sockaddr_in *)nsap, + buf, buflen, ans, anssiz, &resplen); switch (act) { case res_goahead: @@ -914,6 +973,7 @@ s = -1; connected = 0; vc = 0; + af = 0; } } ----Next_Part(Fri_Jun_16_03:43:10_2000_697)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: My Signature Content-Disposition: attachment; filename=".signature-world" Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan ume@mahoroba.org ume@bisd.hitachi.co.jp ume@FreeBSD.org http://www.imasy.org/~ume/ ----Next_Part(Fri_Jun_16_03:43:10_2000_697)---- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe cvs-all" in the body of the message