summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/resolv.h52
-rw-r--r--lib/libc/net/res_init.c115
-rw-r--r--lib/libc/net/res_send.c202
3 files changed, 321 insertions, 48 deletions
diff --git a/include/resolv.h b/include/resolv.h
index 1f9cf6a89d4..a4d3b108508 100644
--- a/include/resolv.h
+++ b/include/resolv.h
@@ -1,4 +1,33 @@
-/* $OpenBSD: resolv.h,v 1.3 1997/03/13 19:11:51 downsj Exp $ */
+/* $OpenBSD: resolv.h,v 1.4 2000/06/22 07:31:18 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
* ++Copyright++ 1983, 1987, 1989, 1993
@@ -70,6 +99,7 @@
# include <sys/types.h>
#endif
#include <sys/cdefs.h>
+#include <sys/socket.h>
#include <stdio.h>
/*
@@ -128,6 +158,23 @@ struct __res_state {
char pad[68]; /* on an i386 this means 512b total */
};
+#if 1 /* INET6 */
+/*
+ * replacement of __res_state, separated to keep binary compatibility.
+ */
+struct __res_state_ext {
+ struct sockaddr_storage nsaddr_list[MAXNS];
+ struct {
+ int af; /* address family for addr, mask */
+ union {
+ struct in_addr ina;
+ struct in6_addr in6a;
+ } addr, mask;
+ } sort_list[MAXRESOLVSORT];
+};
+#endif
+
+
/*
* Resolver options (keep these in synch with res_debug.c, please)
*/
@@ -193,6 +240,9 @@ struct res_sym {
};
extern struct __res_state _res;
+#if 1 /* INET6 */
+extern struct __res_state_ext _res_ext;
+#endif
extern const struct res_sym __p_class_syms[];
extern const struct res_sym __p_type_syms[];
diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c
index fd8d279cf08..ac75a4babb9 100644
--- a/lib/libc/net/res_init.c
+++ b/lib/libc/net/res_init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: res_init.c,v 1.18 1999/09/03 21:14:51 deraadt Exp $ */
+/* $OpenBSD: res_init.c,v 1.19 2000/06/22 07:31:18 itojun Exp $ */
/*
* ++Copyright++ 1985, 1989, 1993
@@ -55,12 +55,16 @@
* --Copyright--
*/
+#ifndef INET6
+#define INET6
+#endif
+
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $";
#else
-static char rcsid[] = "$OpenBSD: res_init.c,v 1.18 1999/09/03 21:14:51 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: res_init.c,v 1.19 2000/06/22 07:31:18 itojun Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -78,6 +82,9 @@ static char rcsid[] = "$OpenBSD: res_init.c,v 1.18 1999/09/03 21:14:51 deraadt E
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#ifdef INET6
+#include <netdb.h>
+#endif /* INET6 */
/*-------------------------------------- info about "sortlist" --------------
* Marc Majka 1994/04/16
@@ -119,6 +126,9 @@ struct __res_state _res
= { RES_TIMEOUT, } /* Motorola, et al. */
# endif
;
+#ifdef INET6
+struct __res_state_ext _res_ext;
+#endif /* INET6 */
/*
* Set up default settings. If the configuration file exist, the values
@@ -193,6 +203,11 @@ res_init()
#endif
_res.nsaddr.sin_family = AF_INET;
_res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+ _res.nsaddr.sin_len = sizeof(struct sockaddr_in);
+#ifdef INET6
+ if (sizeof(_res_ext.nsaddr) >= _res.nsaddr.sin_len)
+ memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len);
+#endif
_res.nscount = 1;
_res.ndots = 1;
_res.pfcode = 0;
@@ -336,23 +351,69 @@ res_init()
}
/* read nameservers to query */
if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+#ifdef INET6
+ char *q;
+ struct addrinfo hints, *res;
+ char pbuf[NI_MAXSERV];
+#else
struct in_addr a;
+#endif /* INET6 */
cp = buf + sizeof("nameserver") - 1;
while (*cp == ' ' || *cp == '\t')
cp++;
+#ifdef INET6
+ 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++;
+ }
+#else /* INET6 */
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);
+ _res.nsaddr_list[nserv].sin_len =
+ sizeof(struct sockaddr_in);
nserv++;
}
+#endif /* INET6 */
continue;
}
#ifdef RESOLVSORT
if (MATCH(buf, "sortlist")) {
struct in_addr a;
+#ifdef INET6
+ struct in6_addr a6;
+ int m, i;
+ u_char *u;
+#endif /* INET6 */
cp = buf + sizeof("sortlist") - 1;
while (nsort < MAXRESOLVSORT) {
@@ -386,8 +447,58 @@ res_init()
_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) {
+ _res_ext.sort_list[nsort].af = AF_INET6;
+ _res_ext.sort_list[nsort].addr.in6a = a6;
+ u = (u_char *)&_res_ext.sort_list[nsort].mask.in6a;
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) && !isspace(*cp))
+ cp++;
+ m = n;
+ n = *cp;
+ *cp = 0;
+ switch (m) {
+ case '/':
+ m = atoi(net);
+ break;
+ case '&':
+ if (inet_pton(AF_INET6, net, u) == 1) {
+ m = -1;
+ break;
+ }
+ /*FALLTHRU*/
+ default:
+ m = sizeof(struct in6_addr) * NBBY;
+ break;
+ }
+ if (m >= 0) {
+ for (i = 0; i < sizeof(struct in6_addr); i++) {
+ if (m <= 0) {
+ *u = 0;
+ } else {
+ m -= NBBY;
+ *u = (u_char)~0;
+ if (m < 0)
+ *u <<= -m;
+ }
+ u++;
+ }
+ }
nsort++;
}
+#endif /* INET6 */
*cp = n;
}
continue;
diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c
index 0cda3510ebe..d0f17af8ed9 100644
--- a/lib/libc/net/res_send.c
+++ b/lib/libc/net/res_send.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: res_send.c,v 1.8 1998/03/19 00:30:08 millert Exp $ */
+/* $OpenBSD: res_send.c,v 1.9 2000/06/22 07:31:18 itojun Exp $ */
/*
* ++Copyright++ 1985, 1989, 1993
@@ -55,12 +55,16 @@
* --Copyright--
*/
+#ifndef INET6
+#define INET6
+#endif
+
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
#else
-static char rcsid[] = "$OpenBSD: res_send.c,v 1.8 1998/03/19 00:30:08 millert Exp $";
+static char rcsid[] = "$OpenBSD: res_send.c,v 1.9 2000/06/22 07:31:18 itojun Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -95,6 +99,7 @@ static char rcsid[] = "$OpenBSD: res_send.c,v 1.8 1998/03/19 00:30:08 millert Ex
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 ciruit? */
+static int af = 0; /* address family of socket */
#ifndef FD_SET
/* XXX - should be in portability.h */
@@ -119,21 +124,29 @@ static int vc = 0; /* is the socket a virtual ciruit? */
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));
+ if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
+ pbuf, sizeof(pbuf),
+ NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) {
+ strncpy(abuf, "?", sizeof(abuf));
+ strncpy(pbuf, "?", sizeof(pbuf));
+ }
+ fprintf(file, "res_send: %s ([%s].%s): %s\n",
+ string, abuf, pbuf, strerror(error));
}
errno = save;
}
@@ -172,6 +185,37 @@ res_send_setrhook(hook)
Rhook = hook;
}
+#ifdef INET6
+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];
+ }
+}
+#else
+#define get_nsaddr(n) ((struct sockaddr *)&_res.nsaddr_list[(n)])
+#endif
+
/* int
* res_isourserver(ina)
* looks up "ina" in _res.ns_addr_list[]
@@ -185,21 +229,43 @@ int
res_isourserver(inp)
const struct sockaddr_in *inp;
{
- struct sockaddr_in ina;
- register int ns, ret;
+#ifdef INET6
+ const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
+ const struct sockaddr_in6 *srv6;
+#endif
+ const struct sockaddr_in *srv;
+ int ns, ret;
- ina = *inp;
ret = 0;
- for (ns = 0; ns < _res.nscount; ns++) {
- register 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) {
+#ifdef INET6
+ 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;
+#endif
+ 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);
}
@@ -308,7 +374,20 @@ res_send(buf, buflen, ans, anssiz)
*/
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);
+ socklen_t salen;
+
+ if (nsap->sa_len)
+ salen = nsap->sa_len;
+#ifdef INET6
+ else if (nsap->sa_family == AF_INET6)
+ salen = sizeof(struct sockaddr_in6);
+#endif
+ else if (nsap->sa_family == AF_INET)
+ salen = sizeof(struct sockaddr_in);
+ else
+ salen = 0; /*unknown, die on connect*/
+
same_ns:
if (badns & (1 << ns)) {
res_close();
@@ -321,7 +400,8 @@ res_send(buf, buflen, ans, anssiz)
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:
@@ -345,9 +425,11 @@ res_send(buf, buflen, ans, anssiz)
} while (!done);
}
- Dprint(_res.options & RES_DEBUG,
+ Dprint((_res.options & RES_DEBUG) &&
+ getnameinfo(nsap, salen, 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;
@@ -361,22 +443,28 @@ res_send(buf, buflen, ans, anssiz)
*/
try = _res.retry;
truncated = 0;
- if ((s < 0) || (!vc)) {
+ if ((s < 0) || (!vc) || (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);
+#if 0
return (-1);
+#else
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+#endif
}
errno = 0;
- if (connect(s, (struct sockaddr *)nsap,
- sizeof(struct sockaddr)) < 0) {
+ if (connect(s, nsap, salen) < 0) {
terrno = errno;
Aerror(stderr, "connect/vc",
- errno, *nsap);
+ errno, nsap);
badns |= (1 << ns);
res_close();
goto next_ns;
@@ -490,21 +578,36 @@ read_len:
*/
struct timeval timeout;
fd_set *dsmaskp;
- 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) {
#if !CAN_RECONNECT
bad_dg_sock:
#endif
terrno = errno;
Perror(stderr, "socket(dg)", errno);
+#if 0
return (-1);
+#else
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+#endif
+ }
+#ifdef IPV6_MINMTU
+ if (af == AF_INET6) {
+ const int yes = 1;
+ (void)setsockopt(s, IPPROTO_IPV6,
+ IPV6_USE_MIN_MTU, &yes,
+ sizeof(yes));
}
+#endif
connected = 0;
}
/*
@@ -528,12 +631,10 @@ read_len:
* receive a response from another server.
*/
if (!connected) {
- if (connect(s, (struct sockaddr *)nsap,
- sizeof(struct sockaddr)
- ) < 0) {
+ if (connect(s, nsap, salen) < 0) {
Aerror(stderr,
"connect(dg)",
- errno, *nsap);
+ errno, nsap);
badns |= (1 << ns);
res_close();
goto next_ns;
@@ -553,6 +654,9 @@ read_len:
*/
if (connected) {
#if CAN_RECONNECT
+#ifdef INET6
+ /* XXX: any errornous address */
+#endif /* INET6 */
struct sockaddr_in no_addr;
no_addr.sin_family = AF_INET;
@@ -563,7 +667,7 @@ read_len:
&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);
@@ -571,14 +675,20 @@ read_len:
Dprint(_res.options & RES_DEBUG,
(stdout, ";; new DG socket\n"))
#endif
+#ifdef IPV6_MINMTU
+ if (af == AF_INET6) {
+ const int yes = 1;
+ (void)setsockopt(s, IPPROTO_IPV6,
+ IPV6_USE_MIN_MTU, &yes,
+ sizeof(yes));
+ }
+#endif
connected = 0;
errno = 0;
}
if (sendto(s, (char*)buf, buflen, 0,
- (struct sockaddr *)nsap,
- sizeof(struct sockaddr))
- != buflen) {
- Aerror(stderr, "sendto", errno, *nsap);
+ nsap, salen) != buflen) {
+ Aerror(stderr, "sendto", errno, nsap);
badns |= (1 << ns);
res_close();
goto next_ns;
@@ -623,7 +733,7 @@ read_len:
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) {
@@ -646,7 +756,7 @@ read_len:
}
#if 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
@@ -703,7 +813,7 @@ read_len:
(stdout, ";; got answer:\n"));
DprintQ((_res.options & RES_DEBUG) ||
(_res.pfcode & RES_PRF_REPLY),
- (stdout, ""),
+ (stdout, "%s", ""),
ans, (resplen>anssiz)?anssiz:resplen);
/*
* If using virtual circuits, we assume that the first server
@@ -723,7 +833,8 @@ read_len:
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:
@@ -776,5 +887,6 @@ res_close()
s = -1;
connected = 0;
vc = 0;
+ af = 0;
}
}