From: Mark Wooding Date: Thu, 5 Jun 2014 09:24:23 +0000 (+0100) Subject: src/: Support for transport over IPv6 (and other protocol families). X-Git-Tag: adns-1.5.0-rc0~76 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=adns.git;a=commitdiff_plain;h=3eb20edd4ef2a509a0ff7d3973f663e35f812ea7 src/: Support for transport over IPv6 (and other protocol families). We create a UDP socket for each distinct protocol family during initialization, and then use the appropriate one for each server. The changes are somewhat invasive, but not really very complicated. Signed-off-by: Mark Wooding Signed-off-by: Ian Jackson --- diff --git a/regress/case-v6-transport-simple.err b/regress/case-v6-transport-simple.err new file mode 100644 index 0000000..e69de29 diff --git a/regress/case-v6-transport-simple.out b/regress/case-v6-transport-simple.out new file mode 100644 index 0000000..182190a --- /dev/null +++ b/regress/case-v6-transport-simple.out @@ -0,0 +1,34 @@ +adns debug: using nameserver 2001:ba8:1d9::1 +www.distorted.org.uk flags 0 type 1 A(-) submitted +www.distorted.org.uk flags 0 type 2 NS(raw) submitted +www.distorted.org.uk flags 0 type 5 CNAME(-) submitted +www.distorted.org.uk flags 0 type 6 SOA(raw) submitted +www.distorted.org.uk flags 0 type 12 PTR(raw) submitted +www.distorted.org.uk flags 0 type 13 HINFO(-) submitted +www.distorted.org.uk flags 0 type 15 MX(raw) submitted +www.distorted.org.uk flags 0 type 16 TXT(-) submitted +www.distorted.org.uk flags 0 type 17 RP(raw) submitted +www.distorted.org.uk flags 0 type 65537 A(addr) submitted +www.distorted.org.uk flags 0 type 65538 NS(+addr) submitted +www.distorted.org.uk flags 0 type 65548 PTR(checked) submitted +www.distorted.org.uk flags 0 type 65551 MX(+addr) submitted +www.distorted.org.uk flags 0 type 131078 SOA(822) submitted +www.distorted.org.uk flags 0 type 131089 RP(822) submitted +www.distorted.org.uk flags 0 type PTR(checked): Domain invalid for particular DNS query type; nrrs=0; cname=$; owner=$; ttl=604800 +www.distorted.org.uk flags 0 type A(-): OK; nrrs=1; cname=$; owner=$; ttl=14400 + 172.29.199.180 +www.distorted.org.uk flags 0 type NS(raw): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type CNAME(-): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type SOA(raw): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type PTR(raw): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type HINFO(-): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type MX(raw): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type TXT(-): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type RP(raw): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type A(addr): OK; nrrs=1; cname=$; owner=$; ttl=14400 + INET 172.29.199.180 +www.distorted.org.uk flags 0 type NS(+addr): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type MX(+addr): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type SOA(822): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +www.distorted.org.uk flags 0 type RP(822): No such data; nrrs=0; cname=$; owner=$; ttl=14400 +rc=0 diff --git a/regress/case-v6-transport-simple.sys b/regress/case-v6-transport-simple.sys new file mode 100644 index 0000000..8561ab4 --- /dev/null +++ b/regress/case-v6-transport-simple.sys @@ -0,0 +1,221 @@ +./adnstest distorted-v6 +www.distorted.org.uk + start 1402047441.083542 + socket domain=PF_INET6 type=SOCK_DGRAM + socket=6 + +0.000065 + fcntl fd=6 cmd=F_GETFL + fcntl=~O_NONBLOCK&... + +0.000031 + fcntl fd=6 cmd=F_SETFL O_NONBLOCK|... + fcntl=OK + +0.000026 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 311f0100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000001 0001. + sendto=38 + +0.000733 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31200100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000002 0001. + sendto=38 + +0.000302 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31210100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000005 0001. + sendto=38 + +0.000357 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31220100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000006 0001. + sendto=38 + +0.000275 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31230100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000c 0001. + sendto=38 + +0.000260 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31240100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000d 0001. + sendto=38 + +0.000257 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31250100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000f 0001. + sendto=38 + +0.000254 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31260100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000010 0001. + sendto=38 + +0.000272 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31270100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000011 0001. + sendto=38 + +0.000253 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 31290100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000001 0001. + sendto=38 + +0.000255 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 312a0100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000002 0001. + sendto=38 + +0.000253 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 312c0100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000f 0001. + sendto=38 + +0.000343 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 312d0100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000006 0001. + sendto=38 + +0.000269 + sendto fd=6 addr=[2001:ba8:1d9::1]:53 + 312e0100 00010000 00000000 03777777 09646973 746f7274 6564036f 72670275 + 6b000011 0001. + sendto=38 + +0.000267 + select max=7 rfds=[6] wfds=[] efds=[] to=1.995650 + select=1 rfds=[6] wfds=[] efds=[] + +0.118752 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 311f8580 00010001 00040008 03777777 09646973 746f7274 6564036f 72670275 + 6b000001 0001c00c 00010001 00003840 0004ac1d c7b4c010 00020001 00003840 + 00100a74 656c6563 61737465 72026e73 c010c010 00020001 00003840 000a0776 + 616d7069 7265c04d c0100002 00010000 38400009 06726164 697573c0 4dc01000 + 02000100 00384000 0c097072 65636973 696f6ec0 4dc07400 01000100 00384000 + 04ac1dc7 01c07400 1c000100 00384000 10200104 70974000 01000000 00000000 + 01c05e00 01000100 00384000 04ac1dc7 05c05e00 1c000100 00384000 10200104 + 70974000 01000000 00000000 05c08900 01000100 00384000 04ac1dc7 b2c08900 + 1c000100 00384000 1020010b a801d900 02000000 00000000 02c04200 01000100 + 00384000 04ac1dc7 b3c04200 1c000100 00384000 1020010b a801d900 02000000 + 00000000 03. + +0.000346 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31208580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000002 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000138 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31218580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000005 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000108 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31228580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000006 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000131 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31238580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000c 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000154 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000033 + select max=7 rfds=[6] wfds=[] efds=[] to=1.877915 + select=1 rfds=[6] wfds=[] efds=[] + +0.000368 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31248580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000d 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000117 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000034 + select max=7 rfds=[6] wfds=[] efds=[] to=1.877653 + select=1 rfds=[6] wfds=[] efds=[] + +0.000616 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31258580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000f 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000114 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31268580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000010 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000106 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31278580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000011 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000107 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000031 + select max=7 rfds=[6] wfds=[] efds=[] to=1.877458 + select=1 rfds=[6] wfds=[] efds=[] + +0.000101 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 31298580 00010001 00040008 03777777 09646973 746f7274 6564036f 72670275 + 6b000001 0001c00c 00010001 00003840 0004ac1d c7b4c010 00020001 00003840 + 00100a74 656c6563 61737465 72026e73 c010c010 00020001 00003840 000a0776 + 616d7069 7265c04d c0100002 00010000 38400009 06726164 697573c0 4dc01000 + 02000100 00384000 0c097072 65636973 696f6ec0 4dc07400 01000100 00384000 + 04ac1dc7 01c07400 1c000100 00384000 10200104 70974000 01000000 00000000 + 01c05e00 01000100 00384000 04ac1dc7 05c05e00 1c000100 00384000 10200104 + 70974000 01000000 00000000 05c08900 01000100 00384000 04ac1dc7 b2c08900 + 1c000100 00384000 1020010b a801d900 02000000 00000000 02c04200 01000100 + 00384000 04ac1dc7 b3c04200 1c000100 00384000 1020010b a801d900 02000000 + 00000000 03. + +0.000273 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000043 + select max=7 rfds=[6] wfds=[] efds=[] to=1.877296 + select=1 rfds=[6] wfds=[] efds=[] + +0.000239 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 312a8580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000002 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000113 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 312c8580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b00000f 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000108 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 312d8580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000006 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000104 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000069 + select max=7 rfds=[6] wfds=[] efds=[] to=1.877528 + select=1 rfds=[6] wfds=[] efds=[] + +0.000094 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=[2001:ba8:1d9::1]:53 + 312e8580 00010000 00010000 03777777 09646973 746f7274 6564036f 72670275 + 6b000011 0001c010 00060001 00003840 002a0672 61646975 73c0100a 686f7374 + 6d617374 6572c010 780bfb99 00015180 00000e10 00127500 00003840. + +0.000106 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000032 + close fd=6 + close=OK + +0.000110 diff --git a/regress/init-distorted-v6.text b/regress/init-distorted-v6.text new file mode 100644 index 0000000..d0c712a --- /dev/null +++ b/regress/init-distorted-v6.text @@ -0,0 +1,3 @@ +nameserver 2001:ba8:1d9::1 +sortlist 198.51.100.0/24 2001:db8:2::/48 0/0 ::/0 +search dnserr.distorted.org.uk distorted.org.uk diff --git a/src/adns.h b/src/adns.h index 568395c..2458333 100644 --- a/src/adns.h +++ b/src/adns.h @@ -912,7 +912,7 @@ int adns_beforepoll(adns_state ads, struct pollfd *fds, * In any case this call won't block. */ -#define ADNS_POLLFDS_RECOMMENDED 2 +#define ADNS_POLLFDS_RECOMMENDED 3 /* If you allocate an fds buf with at least RECOMMENDED entries then * you are unlikely to need to enlarge it. You are recommended to do * so if it's convenient. However, you must be prepared for adns to diff --git a/src/event.c b/src/event.c index 04ba26b..52a2efc 100644 --- a/src/event.c +++ b/src/event.c @@ -312,9 +312,12 @@ int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]) { nwanted++; \ }while(0) - assert(MAX_POLLFDS==2); + int i; - ADD_POLLFD(ads->udpsocket, POLLIN); + assert(MAX_POLLFDS == MAXUDP + 1); + + for (i=0; inudp; i++) + ADD_POLLFD(ads->udpsocket[i].fd, POLLIN); switch (ads->tcpstate) { case server_disconnected: @@ -336,9 +339,11 @@ int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]) { } int adns_processreadable(adns_state ads, int fd, const struct timeval *now) { - int want, dgramlen, r, udpaddrlen, serv, old_skip; + int want, dgramlen, r, i, udpaddrlen, serv, old_skip; byte udpbuf[DNS_MAXUDP]; - struct sockaddr_in udpaddr; + char addrbuf[ADNS_ADDR2TEXT_BUFLEN]; + struct udpsocket *udp; + adns_sockaddr udpaddr; adns__consistency(ads,0,cc_entex); @@ -391,45 +396,32 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) { default: abort(); } - if (fd == ads->udpsocket) { - for (;;) { - udpaddrlen= sizeof(udpaddr); - r= recvfrom(ads->udpsocket,udpbuf,sizeof(udpbuf),0, - (struct sockaddr*)&udpaddr,&udpaddrlen); - if (r<0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { r= 0; goto xit; } - if (errno == EINTR) continue; - if (errno_resources(errno)) { r= errno; goto xit; } - adns__warn(ads,-1,0,"datagram receive error: %s",strerror(errno)); - r= 0; goto xit; - } - if (udpaddrlen != sizeof(udpaddr)) { - adns__diag(ads,-1,0,"datagram received with wrong address length %d" - " (expected %lu)", udpaddrlen, - (unsigned long)sizeof(udpaddr)); - continue; - } - if (udpaddr.sin_family != AF_INET) { - adns__diag(ads,-1,0,"datagram received with wrong protocol family" - " %u (expected %u)",udpaddr.sin_family,AF_INET); - continue; - } - if (ntohs(udpaddr.sin_port) != DNS_PORT) { - adns__diag(ads,-1,0,"datagram received from wrong port" - " %u (expected %u)", ntohs(udpaddr.sin_port),DNS_PORT); - continue; - } - for (serv= 0; - serv < ads->nservers && - !adns__sockaddr_equal_p(&ads->servers[serv].addr.sa, - (const struct sockaddr *)&udpaddr); - serv++); - if (serv >= ads->nservers) { - adns__warn(ads,-1,0,"datagram received from unknown nameserver %s", - inet_ntoa(udpaddr.sin_addr)); - continue; + for (i=0; inudp; i++) { + udp= &ads->udpsocket[i]; + if (fd == udp->fd) { + for (;;) { + udpaddrlen= sizeof(udpaddr); + r= recvfrom(fd,udpbuf,sizeof(udpbuf),0, &udpaddr.sa,&udpaddrlen); + if (r<0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { r= 0; goto xit; } + if (errno == EINTR) continue; + if (errno_resources(errno)) { r= errno; goto xit; } + adns__warn(ads,-1,0,"datagram receive error: %s",strerror(errno)); + r= 0; goto xit; + } + for (serv= 0; + serv < ads->nservers && + !adns__sockaddr_equal_p(&udpaddr.sa, + &ads->servers[serv].addr.sa); + serv++); + if (serv >= ads->nservers) { + adns__warn(ads,-1,0,"datagram received from unknown nameserver %s", + adns__sockaddr_ntoa(&udpaddr.sa, addrbuf)); + continue; + } + adns__procdgram(ads,udpbuf,r,serv,0,*now); } - adns__procdgram(ads,udpbuf,r,serv,0,*now); + break; } } r= 0; diff --git a/src/internal.h b/src/internal.h index baf2a29..f25fe9c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -350,6 +350,8 @@ struct adns__query { struct query_queue { adns_query head, tail; }; +#define MAXUDP 2 + struct adns__state { adns_initflags iflags; adns_logcallbackfn *logfn; @@ -357,7 +359,9 @@ struct adns__state { int configerrno; struct query_queue udpw, tcpw, childw, output; adns_query forallnext; - int nextid, udpsocket, tcpsocket; + int nextid, tcpsocket; + struct udpsocket { int af; int fd; } udpsocket[MAXUDP]; + int nudp; vbuf tcpsend, tcprecv; int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip; enum adns__tcpstate { @@ -568,6 +572,15 @@ void adns__querysend_tcp(adns_query qu, struct timeval now); * might be broken, but no reconnect will be attempted. */ +struct udpsocket *adns__udpsocket_by_af(adns_state ads, int af); +/* Find the UDP socket structure in ads which has the given address family. + * Return null if there isn't one. + * + * This is used during initialization, so ads is only partially filled in. + * The requirements are that nudp is set, and that udpsocket[i].af are + * defined for 0<=isa_family != AF_INET) { - adns__debug(ads,-1,0,"non-IPv4 nameserver %s ignored", - adns__sockaddr_ntoa(sa, buf)); - return; - } for (i=0; inservers; i++) { if (adns__sockaddr_equal_p(sa, &ads->servers[i].addr.sa)) { @@ -566,7 +560,8 @@ static int init_begin(adns_state *ads_r, adns_initflags flags, LIST_INIT(ads->output); ads->forallnext= 0; ads->nextid= 0x311f; - ads->udpsocket= ads->tcpsocket= -1; + ads->nudp= 0; + ads->tcpsocket= -1; adns__vbuf_init(&ads->tcpsend); adns__vbuf_init(&ads->tcprecv); ads->tcprecv_skip= 0; @@ -588,7 +583,9 @@ static int init_begin(adns_state *ads_r, adns_initflags flags, static int init_finish(adns_state ads) { struct sockaddr_in sin; struct protoent *proto; - int i, r; + struct udpsocket *udp; + int i, j; + int r; if (!ads->nservers) { if (ads->logfn && ads->iflags & adns_if_debug) @@ -600,21 +597,25 @@ static int init_finish(adns_state ads) { addserver(ads,(struct sockaddr *)&sin, sizeof(sin)); } - /* we can't cope with multiple transport address families yet */ - for (i=0; inservers; i++) - assert(ads->servers[i].addr.sa.sa_family==AF_INET); - proto= getprotobyname("udp"); if (!proto) { r= ENOPROTOOPT; goto x_free; } - ads->udpsocket= socket(AF_INET,SOCK_DGRAM,proto->p_proto); - if (ads->udpsocket<0) { r= errno; goto x_free; } - - r= adns__setnonblock(ads,ads->udpsocket); - if (r) { r= errno; goto x_closeudp; } + ads->nudp= 0; + for (i=0; inservers; i++) { + if (adns__udpsocket_by_af(ads, ads->servers[i].addr.sa.sa_family)) + continue; + assert(ads->nudp < MAXUDP); + udp= &ads->udpsocket[ads->nudp]; + udp->af= ads->servers[i].addr.sa.sa_family; + udp->fd= socket(udp->af,SOCK_DGRAM,proto->p_proto); + if (udp->fd < 0) { r= errno; goto x_free; } + ads->nudp++; + r= adns__setnonblock(ads,udp->fd); + if (r) { r= errno; goto x_closeudp; } + } return 0; x_closeudp: - close(ads->udpsocket); + for (j=0; jnudp; j++) close(ads->udpsocket[j].fd); x_free: free(ads); return r; @@ -721,6 +722,7 @@ int adns_init_logfn(adns_state *newstate_r, adns_initflags flags, } void adns_finish(adns_state ads) { + int i; adns__consistency(ads,0,cc_entex); for (;;) { if (ads->udpw.head) adns_cancel(ads->udpw.head); @@ -729,7 +731,7 @@ void adns_finish(adns_state ads) { else if (ads->output.head) adns_cancel(ads->output.head); else break; } - close(ads->udpsocket); + for (i=0; inudp; i++) close(ads->udpsocket[i].fd); if (ads->tcpsocket >= 0) close(ads->tcpsocket); adns__vbuf_free(&ads->tcpsend); adns__vbuf_free(&ads->tcprecv); diff --git a/src/transmit.c b/src/transmit.c index ecea891..c2efdb5 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -242,9 +242,17 @@ static void query_usetcp(adns_query qu, struct timeval now) { adns__tcp_tryconnect(qu->ads,now); } +struct udpsocket *adns__udpsocket_by_af(adns_state ads, int af) { + int i; + for (i=0; inudp; i++) + if (ads->udpsocket[i].af == af) return &ads->udpsocket[i]; + return 0; +} + void adns__query_send(adns_query qu, struct timeval now) { int serv, r; adns_state ads; + struct udpsocket *udp; adns_rr_addr *addr; assert(qu->state == query_tosend); @@ -261,8 +269,10 @@ void adns__query_send(adns_query qu, struct timeval now) { ads= qu->ads; serv= qu->udpnextserver; addr= &ads->servers[serv]; + udp= adns__udpsocket_by_af(ads, addr->addr.sa.sa_family); + assert(udp); - r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0, + r= sendto(udp->fd,qu->query_dgram,qu->query_dglen,0, &addr->addr.sa,addr->len); if (r<0 && errno == EMSGSIZE) { qu->retries= 0;