IPv6 DNS transport support for resolver.

Now you can write
	nameserver 3ffe:0501:4819::42
in /etc/resolv.conf for DNS query over IPv6 network.
(the above address is alive as DNS server)
This commit is contained in:
itojun 1999-07-01 18:19:35 +00:00
parent 7f7f5bff87
commit e24b45d811
2 changed files with 199 additions and 30 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: res_init.c,v 1.23 1999/01/16 07:48:24 lukem Exp $ */
/* $NetBSD: res_init.c,v 1.24 1999/07/01 18:19:35 itojun Exp $ */
/*-
* Copyright (c) 1985, 1989, 1993
@ -59,7 +59,7 @@
static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
static char rcsid[] = "Id: res_init.c,v 8.8 1997/06/01 20:34:37 vixie Exp ";
#else
__RCSID("$NetBSD: res_init.c,v 1.23 1999/01/16 07:48:24 lukem Exp $");
__RCSID("$NetBSD: res_init.c,v 1.24 1999/07/01 18:19:35 itojun Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@ -78,6 +78,7 @@ __RCSID("$NetBSD: res_init.c,v 1.23 1999/01/16 07:48:24 lukem Exp $");
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netdb.h>
#if defined(_LIBC) && defined(__weak_alias)
__weak_alias(res_init,_res_init);
@ -98,6 +99,9 @@ struct __res_state _res = {
RES_DEFAULT, /* options flags */
1, /* number of name servers */
};
#ifdef INET6
struct __res_state_ext _res_ext;
#endif /* INET6 */
/*
* Set up default settings. If the configuration file exist, the values
@ -134,8 +138,27 @@ res_init()
#ifdef SEARCH_LOCAL_DOMAINS
int dots;
#endif
#ifdef INET6
struct sockaddr_in6 *sin6;
struct addrinfo *ai;
static char nsport[32];
struct addrinfo hints;
#endif
_res.id = res_randomid();
#ifdef INET6
if (nsport[0] == '\0')
sprintf(nsport, "%u", NAMESERVER_PORT);
sin6 = (struct sockaddr_in6 *)&_res_ext.nsaddr;
sin6->sin6_len = sizeof(struct sockaddr_in6);
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(NAMESERVER_PORT);
#ifdef USELOOPBACK
sin6->sin6_addr = in6addr_loopback;
#else
sin6->sin6_addr = in6addr_any;
#endif
#endif
_res.nsaddr.sin_len = sizeof(struct sockaddr_in);
_res.nsaddr.sin_family = AF_INET;
_res.nsaddr.sin_port = htons(NAMESERVER_PORT);
@ -253,11 +276,37 @@ res_init()
}
/* read nameservers to query */
if (MATCH(buf, "nameserver") && nserv < MAXNS) {
#ifdef INET6
char *q;
#else /* INET6 */
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;
if (getaddrinfo(cp, nsport, &hints, &ai) == 0) {
memcpy(&_res_ext.nsaddr_list[nserv],
ai->ai_addr, ai->ai_addrlen);
/* for compatibility */
if (ai->ai_family == AF_INET)
memcpy(&_res.nsaddr_list[nserv],
ai->ai_addr, ai->ai_addrlen);
nserv++;
freeaddrinfo(ai);
}
#else /* INET6 */
if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
_res.nsaddr_list[nserv].sin_len = sizeof(struct sockaddr_in);
_res.nsaddr_list[nserv].sin_family = AF_INET;
@ -266,10 +315,16 @@ res_init()
_res.nsaddr_list[nserv].sin_addr = a;
nserv++;
}
#endif /* INET6 */
continue;
}
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) {
@ -303,8 +358,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;

View File

@ -1,4 +1,4 @@
/* $NetBSD: res_send.c,v 1.17 1999/05/03 15:26:12 christos Exp $ */
/* $NetBSD: res_send.c,v 1.18 1999/07/01 18:19:35 itojun Exp $ */
/*-
* Copyright (c) 1985, 1989, 1993
@ -59,7 +59,7 @@
static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
static char rcsid[] = "Id: res_send.c,v 8.13 1997/06/01 20:34:37 vixie Exp ";
#else
__RCSID("$NetBSD: res_send.c,v 1.17 1999/05/03 15:26:12 christos Exp $");
__RCSID("$NetBSD: res_send.c,v 1.18 1999/07/01 18:19:35 itojun Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@ -106,6 +106,7 @@ __RCSID("$NetBSD: res_send.c,v 1.17 1999/05/03 15:26:12 christos Exp $");
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 */
#define CAN_RECONNECT 1
@ -120,7 +121,9 @@ static int vc = 0; /* is the socket a virtual ciruit? */
fprintf args;\
__fp_nquery(query, size, stdout);\
} else {}
static void Aerror __P((FILE *, char *, int, struct sockaddr_in));
static char abuf[INET6_ADDRSTRLEN];
static char pbuf[32];
static void Aerror __P((FILE *, char *, int, struct sockaddr *));
static void Perror __P((FILE *, char *, int));
static void
@ -128,16 +131,15 @@ static int vc = 0; /* is the socket a virtual ciruit? */
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);
fprintf(file, "res_send: %s ([%s].%s): %s\n",
string, abuf, pbuf, strerror(error));
}
errno = save;
}
@ -192,9 +194,46 @@ int
res_isourserver(inp)
const struct sockaddr_in *inp;
{
#ifdef INET6
struct sockaddr_in6 *in6p = (struct sockaddr_in6 *)inp;
const struct sockaddr_in6 *srv6;
const struct sockaddr_in *srv;
#else /* INET6 */
struct sockaddr_in ina;
#endif /* INET6 */
register int ns, ret;
#ifdef INET6
ret = 0;
switch (inp->sin_family) {
case AF_INET6:
for (ns = 0; ns < _res.nscount; ns++) {
srv6 = (struct sockaddr_in6 *)&_res_ext.nsaddr_list[ns];
if (srv6->sin6_family == in6p->sin6_family &&
srv6->sin6_port == in6p->sin6_port &&
(memcmp(&srv6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)) == 0 ||
memcmp(&srv6->sin6_addr, &in6p->sin6_addr,
sizeof(struct in6_addr)) == 0)) {
ret++;
break;
}
}
break;
case AF_INET:
for (ns = 0; ns < _res.nscount; ns++) {
srv = (struct sockaddr_in *)&_res_ext.nsaddr_list[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;
}
#else /* INET6 */
ina = *inp;
ret = 0;
for (ns = 0; ns < _res.nscount; ns++) {
@ -208,6 +247,7 @@ res_isourserver(inp)
break;
}
}
#endif /* INET6 */
return (ret);
}
@ -315,7 +355,13 @@ 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];
#ifdef INET6
struct sockaddr *nsap = (struct sockaddr *)
&_res_ext.nsaddr_list[ns];
#else /* INET6 */
struct sockaddr *nsap = (struct sockaddr *)
&_res.nsaddr_list[ns];
#endif
same_ns:
if (badns & (1 << ns)) {
res_close();
@ -328,7 +374,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:
@ -352,9 +399,17 @@ res_send(buf, buflen, ans, anssiz)
} while (!done);
}
#ifdef INET6
Dprint((_res.options & RES_DEBUG) &&
getnameinfo(nsap, nsap->sa_len, abuf, sizeof(abuf),
NULL, 0, NI_NUMERICHOST) == 0,
(stdout, ";; Querying server (# %d) address = %s\n",
ns + 1, abuf));
#else /* INET6 */
Dprint(_res.options & RES_DEBUG,
(stdout, ";; Querying server (# %d) address = %s\n",
ns + 1, inet_ntoa(nsap->sin_addr)));
ns + 1, inet_ntoa(((struct sockaddr_in *)nsap)->sin_addr)));
#endif /* INET6 */
if (v_circuit) {
int truncated;
@ -368,11 +423,12 @@ 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);
@ -380,10 +436,10 @@ res_send(buf, buflen, ans, anssiz)
}
errno = 0;
if (connect(s, (struct sockaddr *)(void *)nsap,
sizeof(struct sockaddr)) < 0) {
nsap->sa_len) < 0) {
terrno = errno;
Aerror(stderr, "connect/vc",
errno, *nsap);
errno, (struct sockaddr *)nsap);
badns |= (1 << ns);
res_close();
goto next_ns;
@ -499,13 +555,14 @@ read_len:
*/
time_t seconds;
struct pollfd dsfd;
struct sockaddr_in from;
struct sockaddr_storage from;
socklen_t 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:
@ -539,11 +596,12 @@ read_len:
if (!connected) {
if (connect(s,
(struct sockaddr *)(void *)nsap,
sizeof(struct sockaddr)
nsap->sa_len
) < 0) {
Aerror(stderr,
"connect(dg)",
errno, *nsap);
errno,
(struct sockaddr *)nsap);
badns |= (1 << ns);
res_close();
goto next_ns;
@ -563,6 +621,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;
@ -572,7 +633,7 @@ read_len:
(struct sockaddr *)(void *)&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);
@ -585,9 +646,10 @@ read_len:
}
if (sendto(s, buf, (size_t)buflen, 0,
(struct sockaddr *)(void *)nsap,
sizeof(struct sockaddr))
nsap->sa_len)
!= buflen) {
Aerror(stderr, "sendto", errno, *nsap);
Aerror(stderr, "sendto", errno,
(struct sockaddr *)nsap);
badns |= (1 << ns);
res_close();
goto next_ns;
@ -624,7 +686,7 @@ wait:
goto next_ns;
}
errno = 0;
fromlen = sizeof(struct sockaddr_in);
fromlen = sizeof from;
resplen = recvfrom(s, ans, (size_t)anssiz, 0,
(struct sockaddr *)(void *)&from, &fromlen);
if (resplen <= 0) {
@ -647,7 +709,7 @@ wait:
}
#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
@ -724,7 +786,8 @@ wait:
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:
@ -777,6 +840,7 @@ res_close()
s = -1;
connected = 0;
vc = 0;
af = 0;
}
}