DNS IPv6 transport support.
It is nessesary for IPv6 only life. Obtained from: KAME
This commit is contained in:
parent
194750d657
commit
7c381eb7d5
@ -87,6 +87,7 @@ static char rcsid[] = "$FreeBSD$";
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "res_config.h"
|
||||
|
||||
@ -112,9 +113,7 @@ struct __res_state _res
|
||||
# endif
|
||||
;
|
||||
|
||||
#ifdef INET6
|
||||
struct __res_state_ext _res_ext;
|
||||
#endif /* INET6 */
|
||||
|
||||
/*
|
||||
* Set up default settings. If the configuration file exist, the values
|
||||
@ -154,6 +153,7 @@ res_init()
|
||||
#ifndef RFC1535
|
||||
int dots;
|
||||
#endif
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
/*
|
||||
* These three fields used to be statically initialized. This made
|
||||
@ -188,13 +188,15 @@ res_init()
|
||||
if (!_res.id)
|
||||
_res.id = res_randomid();
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&_res_ext.nsaddr;
|
||||
#ifdef USELOOPBACK
|
||||
_res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
|
||||
sin6->sin6_addr = in6addr_loopback;
|
||||
#else
|
||||
_res.nsaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
sin6->sin6_addr = in6addr_any;
|
||||
#endif
|
||||
_res.nsaddr.sin_family = AF_INET;
|
||||
_res.nsaddr.sin_port = htons(NAMESERVER_PORT);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons(NAMESERVER_PORT);
|
||||
sin6->sin6_len = sizeof(*sin6);
|
||||
_res.nscount = 1;
|
||||
_res.ndots = 1;
|
||||
_res.pfcode = 0;
|
||||
@ -300,16 +302,41 @@ res_init()
|
||||
}
|
||||
/* 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 +344,9 @@ res_init()
|
||||
#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 +380,14 @@ 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) {
|
||||
int m, i;
|
||||
u_char *u;
|
||||
|
||||
_res_ext.sort_list[nsort].af = AF_INET6;
|
||||
_res_ext.sort_list[nsort].addr.in6a = a6;
|
||||
@ -407,7 +429,6 @@ res_init()
|
||||
}
|
||||
nsort++;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
*cp = n;
|
||||
}
|
||||
continue;
|
||||
|
@ -109,8 +109,11 @@ static int use_poll = 1; /* adapt to poll() syscall availability */
|
||||
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;
|
||||
static char abuf[NI_MAXHOST];
|
||||
static char pbuf[32];
|
||||
|
||||
|
||||
#define CAN_RECONNECT 1
|
||||
@ -131,16 +134,16 @@ static res_send_rhook Rhook = NULL;
|
||||
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;
|
||||
}
|
||||
@ -189,21 +192,40 @@ int
|
||||
res_isourserver(inp)
|
||||
const struct sockaddr_in *inp;
|
||||
{
|
||||
struct sockaddr_in ina;
|
||||
struct sockaddr_in6 *in6p = (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 *)&_res_ext.nsaddr_list[ns];
|
||||
if (srv6->sin6_family == in6p->sin6_family &&
|
||||
srv6->sin6_port == in6p->sin6_port &&
|
||||
srv6->sin6_scope_id == in6p->sin6_scope_id &&
|
||||
(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;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
@ -332,7 +354,8 @@ 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 = (struct sockaddr *)
|
||||
&_res_ext.nsaddr_list[ns];
|
||||
same_ns:
|
||||
if (badns & (1 << ns)) {
|
||||
res_close();
|
||||
@ -345,7 +368,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:
|
||||
@ -369,9 +393,12 @@ res_send(buf, buflen, ans, anssiz)
|
||||
} 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,11 +412,13 @@ res_send(buf, buflen, ans, anssiz)
|
||||
*/
|
||||
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);
|
||||
@ -397,10 +426,10 @@ res_send(buf, buflen, ans, anssiz)
|
||||
}
|
||||
errno = 0;
|
||||
if (connect(s, (struct sockaddr *)nsap,
|
||||
sizeof *nsap) < 0) {
|
||||
nsap->sa_len) < 0) {
|
||||
terrno = errno;
|
||||
Aerror(stderr, "connect/vc",
|
||||
errno, *nsap);
|
||||
errno, nsap);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
@ -530,13 +559,14 @@ read_len:
|
||||
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:
|
||||
@ -570,11 +600,11 @@ read_len:
|
||||
*/
|
||||
if (!connected) {
|
||||
if (connect(s, (struct sockaddr *)nsap,
|
||||
sizeof *nsap
|
||||
nsap->sa_len
|
||||
) < 0) {
|
||||
Aerror(stderr,
|
||||
"connect(dg)",
|
||||
errno, *nsap);
|
||||
errno, nsap);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
@ -594,6 +624,7 @@ read_len:
|
||||
*/
|
||||
if (connected) {
|
||||
#ifdef CAN_RECONNECT
|
||||
/* XXX: any errornous address */
|
||||
struct sockaddr_in no_addr;
|
||||
|
||||
no_addr.sin_family = AF_INET;
|
||||
@ -604,7 +635,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);
|
||||
@ -618,9 +649,9 @@ read_len:
|
||||
#endif /* !CANNOT_CONNECT_DGRAM */
|
||||
if (sendto(s, (char*)buf, buflen, 0,
|
||||
(struct sockaddr *)nsap,
|
||||
sizeof *nsap)
|
||||
nsap->sa_len)
|
||||
!= buflen) {
|
||||
Aerror(stderr, "sendto", errno, *nsap);
|
||||
Aerror(stderr, "sendto", errno, nsap);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
@ -749,7 +780,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) {
|
||||
@ -784,7 +815,7 @@ read_len:
|
||||
}
|
||||
#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 +892,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:
|
||||
@ -914,6 +946,7 @@ res_close()
|
||||
s = -1;
|
||||
connected = 0;
|
||||
vc = 0;
|
||||
af = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user