summaryrefslogtreecommitdiff
path: root/src/dnsstub/dns_transmit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dnsstub/dns_transmit.c')
-rw-r--r--src/dnsstub/dns_transmit.c286
1 files changed, 166 insertions, 120 deletions
diff --git a/src/dnsstub/dns_transmit.c b/src/dnsstub/dns_transmit.c
index 2513565..e041312 100644
--- a/src/dnsstub/dns_transmit.c
+++ b/src/dnsstub/dns_transmit.c
@@ -1,13 +1,14 @@
-#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
-#include "socket_if.h"
+
#include "alloc.h"
-#include "error.h"
#include "byte.h"
-#include "uint_t.h"
-#include "ip.h"
#include "dnsresolv.h"
+#include "error.h"
+#include "ip.h"
+#include "socket_if.h"
+#include "uint_t.h"
/**
@file dns_transmit.c
@@ -21,62 +22,70 @@
uint32 scope_ids[QUERY_MAXNS];
-static const int timeouts[5] = { 1, 2, 4, 8, 16 }; /* quadratic, not exponentially */
-
-int getscopeid(const struct dns_transmit *d,const char *ip)
+static const int timeouts[5] = {1, 2, 4, 8, 16}; /* quadratic, not exponentially */
+
+int getscopeid(const struct dns_transmit *d, const char *ip)
{
int i;
- if (byte_diff(ip,2,V6linklocal)) return 0;
- for (i = 0; i < QUERY_MAXNS; ++i)
- if (byte_equal(d->servers + 16 * i,16,ip))
- return scope_ids[i];
+ if (byte_diff(ip, 2, V6linklocal)) return 0;
+ for (i = 0; i < QUERY_MAXNS; ++i)
+ if (byte_equal(d->servers + 16 * i, 16, ip)) return scope_ids[i];
return 0;
}
-int serverwantstcp(const char *buf,unsigned int len)
+int serverwantstcp(const char *buf, unsigned int len)
{
char out[12];
- if (!dns_packet_copy(buf,len,0,out,12)) return 1;
+ if (!dns_packet_copy(buf, len, 0, out, 12)) return 1;
if (out[2] & 2) return 1;
return 0;
}
-int serverfailed(const char *buf,unsigned int len)
+int serverfailed(const char *buf, unsigned int len)
{
char out[12];
unsigned int rcode;
- if (!dns_packet_copy(buf,len,0,out,12)) return 1;
+ if (!dns_packet_copy(buf, len, 0, out, 12)) return 1;
rcode = out[3];
rcode &= 15;
- if (rcode && (rcode != 3)) { errno = EAGAIN; return 1; }
+ if (rcode && (rcode != 3)) {
+ errno = EAGAIN;
+ return 1;
+ }
return 0;
}
-int irrelevant(const struct dns_transmit *d,const char *buf,unsigned int len)
+int irrelevant(const struct dns_transmit *d, const char *buf, unsigned int len)
{
char out[12];
char *dn;
unsigned int pos;
- pos = dns_packet_copy(buf,len,0,out,12); if (!pos) return 1;
- if (byte_diff(out,2,d->query + 2)) return 1;
+ pos = dns_packet_copy(buf, len, 0, out, 12);
+ if (!pos) return 1;
+ if (byte_diff(out, 2, d->query + 2)) return 1;
if (out[4] != 0) return 1;
if (out[5] != 1) return 1;
dn = 0;
- pos = dns_packet_getname(buf,len,pos,&dn); if (!pos) return 1;
- if (!dns_domain_equal(dn,d->query + 14)) { alloc_free(dn); return 1; }
+ pos = dns_packet_getname(buf, len, pos, &dn);
+ if (!pos) return 1;
+ if (!dns_domain_equal(dn, d->query + 14)) {
+ alloc_free(dn);
+ return 1;
+ }
alloc_free(dn);
- pos = dns_packet_copy(buf,len,pos,out,4); if (!pos) return 1;
- if (byte_diff(out,2,d->qtype)) return 1;
- if (byte_diff(out + 2,2,DNS_C_IN)) return 1;
+ pos = dns_packet_copy(buf, len, pos, out, 4);
+ if (!pos) return 1;
+ if (byte_diff(out, 2, d->qtype)) return 1;
+ if (byte_diff(out + 2, 2, DNS_C_IN)) return 1;
return 0;
}
@@ -112,13 +121,11 @@ void dns_transmit_free(struct dns_transmit *d)
int randombind6(struct dns_transmit *d)
{
int j;
-
+
for (j = 0; j < 10; ++j) {
- if (socket_bind6(d->s1 - 1,d->localip,1025 + dns_random(64510),d->scope_id) == 0)
- return 0;
- }
- if (socket_bind6(d->s1 - 1,d->localip,0,d->scope_id) == 0)
- return 0;
+ if (socket_bind6(d->s1 - 1, d->localip, 1025 + dns_random(64510), d->scope_id) == 0) return 0;
+ }
+ if (socket_bind6(d->s1 - 1, d->localip, 0, d->scope_id) == 0) return 0;
return DNS_COM;
}
@@ -126,13 +133,11 @@ int randombind6(struct dns_transmit *d)
int randombind4(struct dns_transmit *d)
{
int j;
-
+
for (j = 0; j < 10; ++j) {
- if (socket_bind4(d->s1 - 1,d->localip + 12,1025 + dns_random(64510)) == 0)
- return 0;
- }
- if (socket_bind4(d->s1 - 1,d->localip + 12,0) == 0)
- return 0;
+ if (socket_bind4(d->s1 - 1, d->localip + 12, 1025 + dns_random(64510)) == 0) return 0;
+ }
+ if (socket_bind4(d->s1 - 1, d->localip + 12, 0) == 0) return 0;
return DNS_COM;
}
@@ -146,28 +151,39 @@ int thisudp(struct dns_transmit *d)
while (d->udploop < 5) {
for (; d->curserver < QUERY_MAXNS; ++d->curserver) {
ip = d->servers + 16 * d->curserver;
- if (byte_diff(ip,16,V6localnet)) {
+ if (byte_diff(ip, 16, V6localnet)) {
d->query[2] = dns_random(256);
d->query[3] = dns_random(256);
-
+
if (ip6_isv4mapped(ip)) {
- d->s1 = 1 + socket_udp4();
- if (!d->s1) { dns_transmit_free(d); return DNS_COM; }
- if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; }
+ d->s1 = 1 + socket_udp4();
+ if (!d->s1) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
+ if (randombind4(d) < 0) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
} else {
- d->s1 = 1 + socket_udp6();
- if (!d->s1) { dns_transmit_free(d); return DNS_COM; }
- if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; }
- }
-
- if (byte_equal(ip,2,V6linklocal) && !d->scope_id)
- d->scope_id = getscopeid(d,ip);
- if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0)
- if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) {
+ d->s1 = 1 + socket_udp6();
+ if (!d->s1) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
+ if (randombind6(d) < 0) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
+ }
+
+ if (byte_equal(ip, 2, V6linklocal) && !d->scope_id) d->scope_id = getscopeid(d, ip);
+ if (socket_connect(d->s1 - 1, ip, DNSPORT, d->scope_id) == 0)
+ if (send(d->s1 - 1, d->query + 2, d->querylen - 2, 0) == d->querylen - 2) {
struct taia now;
taia_now(&now);
- taia_uint(&d->deadline,timeouts[d->udploop]);
- taia_add(&d->deadline,&d->deadline,&now);
+ taia_uint(&d->deadline, timeouts[d->udploop]);
+ taia_add(&d->deadline, &d->deadline, &now);
d->tcpstate = 0;
return 0;
}
@@ -178,7 +194,8 @@ int thisudp(struct dns_transmit *d)
d->curserver = 0;
}
- dns_transmit_free(d); return DNS_COM;
+ dns_transmit_free(d);
+ return DNS_COM;
}
int firstudp(struct dns_transmit *d)
@@ -203,27 +220,38 @@ int thistcp(struct dns_transmit *d)
for (; d->curserver < QUERY_MAXNS; ++d->curserver) {
ip = d->servers + 16 * d->curserver;
- if (byte_diff(ip,16,V6localnet)) {
+ if (byte_diff(ip, 16, V6localnet)) {
d->query[2] = dns_random(256);
d->query[3] = dns_random(256);
if (ip6_isv4mapped(ip)) {
d->s1 = 1 + socket_tcp4();
- if (!d->s1) { dns_transmit_free(d); return DNS_COM; }
- if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; }
+ if (!d->s1) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
+ if (randombind4(d) < 0) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
} else {
- d->s1 = 1 + socket_tcp6();
- if (!d->s1) { dns_transmit_free(d); return DNS_COM; }
- if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; }
- }
-
+ d->s1 = 1 + socket_tcp6();
+ if (!d->s1) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
+ if (randombind6(d) < 0) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
+ }
+
taia_now(&now);
- taia_uint(&d->deadline,10);
- taia_add(&d->deadline,&d->deadline,&now);
+ taia_uint(&d->deadline, 10);
+ taia_add(&d->deadline, &d->deadline, &now);
- if (byte_equal(ip,2,V6linklocal) && !d->scope_id)
- d->scope_id = getscopeid(d,ip);
- if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0) {
+ if (byte_equal(ip, 2, V6linklocal) && !d->scope_id) d->scope_id = getscopeid(d, ip);
+ if (socket_connect(d->s1 - 1, ip, DNSPORT, d->scope_id) == 0) {
d->tcpstate = 2;
return 0;
}
@@ -231,12 +259,12 @@ int thistcp(struct dns_transmit *d)
d->tcpstate = 1;
return 0;
}
-
+
socketfree(d);
}
}
- dns_transmit_free(d);
+ dns_transmit_free(d);
return DNS_COM;
}
@@ -252,8 +280,13 @@ int nexttcp(struct dns_transmit *d)
return thistcp(d);
}
-int dns_transmit_start(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \
- int flagrecursive,const char *q,const char qtype[2],const char localip[16])
+int dns_transmit_start(
+ struct dns_transmit *d,
+ const char servers[QUERY_MAXIPLEN],
+ int flagrecursive,
+ const char *q,
+ const char qtype[2],
+ const char localip[16])
{
unsigned int len;
@@ -264,17 +297,19 @@ int dns_transmit_start(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN]
d->querylen = len + 18;
d->query = alloc(d->querylen);
if (!d->query) return DNS_COM;
-
- uint16_pack_big(d->query,len + 16);
- byte_copy(d->query + 2,12,flagrecursive ? "\0\0\1\0\0\1\0\0\0\0\0\0" : \
- "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround");
- byte_copy(d->query + 14,len,q);
- byte_copy(d->query + 14 + len,2,qtype);
- byte_copy(d->query + 16 + len,2,DNS_C_IN);
-
- byte_copy(d->qtype,2,(char *) qtype);
+
+ uint16_pack_big(d->query, len + 16);
+ byte_copy(
+ d->query + 2,
+ 12,
+ flagrecursive ? "\0\0\1\0\0\1\0\0\0\0\0\0" : "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround");
+ byte_copy(d->query + 14, len, q);
+ byte_copy(d->query + 14 + len, 2, qtype);
+ byte_copy(d->query + 16 + len, 2, DNS_C_IN);
+
+ byte_copy(d->qtype, 2, (char *)qtype);
d->servers = servers;
- byte_copy(d->localip,16,(char *) localip);
+ byte_copy(d->localip, 16, (char *)localip);
d->udploop = flagrecursive ? 1 : 0;
@@ -282,33 +317,37 @@ int dns_transmit_start(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN]
return firstudp(d);
}
-int dns_transmit_start6(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \
- int flagrecursive,const char *q,const char qtype[2], \
- const char localip[16],const uint32 scopes[QUERY_MAXNS])
+int dns_transmit_start6(
+ struct dns_transmit *d,
+ const char servers[QUERY_MAXIPLEN],
+ int flagrecursive,
+ const char *q,
+ const char qtype[2],
+ const char localip[16],
+ const uint32 scopes[QUERY_MAXNS])
{
- byte_copy(scope_ids,128,(char *) scopes);
+ byte_copy(scope_ids, 128, (char *)scopes);
- return dns_transmit_start(d,servers,flagrecursive,q,qtype,localip);
+ return dns_transmit_start(d, servers, flagrecursive, q, qtype, localip);
}
-void dns_transmit_io(struct dns_transmit *d,iopause_fd *x,struct taia *deadline)
+void dns_transmit_io(struct dns_transmit *d, iopause_fd *x, struct taia *deadline)
{
x->fd = d->s1 - 1;
switch (d->tcpstate) {
- case 0: case 3: case 4: case 5:
- x->events = IOPAUSE_READ;
- break;
- case 1: case 2:
- x->events = IOPAUSE_WRITE;
- break;
+ case 0:
+ case 3:
+ case 4:
+ case 5: x->events = IOPAUSE_READ; break;
+ case 1:
+ case 2: x->events = IOPAUSE_WRITE; break;
}
- if (taia_less(&d->deadline,deadline))
- *deadline = d->deadline;
+ if (taia_less(&d->deadline, deadline)) *deadline = d->deadline;
}
-int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct taia *when)
+int dns_transmit_get(struct dns_transmit *d, const iopause_fd *x, const struct taia *when)
{
char udpbuf[MSGSIZE + 1];
unsigned char ch;
@@ -319,27 +358,28 @@ int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct tai
fd = d->s1 - 1;
if (!x->revents) {
- if (taia_less((struct taia *)when,&d->deadline)) return 0;
+ if (taia_less((struct taia *)when, &d->deadline)) return 0;
errno = ETIMEDOUT;
if (d->tcpstate == 0) return nextudp(d);
return nexttcp(d);
}
-/*
+ /*
have attempted to send UDP query to each server udploop times
have sent query to curserver on UDP socket s
*/
if (d->tcpstate == 0) {
- r = recv(fd,udpbuf,sizeof(udpbuf),0);
+ r = recv(fd, udpbuf, sizeof(udpbuf), 0);
if (r <= 0) {
- if (errno == ECONNREFUSED) if (d->udploop == 2) return 0;
+ if (errno == ECONNREFUSED)
+ if (d->udploop == 2) return 0;
return nextudp(d);
}
if (r + 1 > sizeof(udpbuf)) return 0;
- if (irrelevant(d,udpbuf,r)) return 0;
- if (serverwantstcp(udpbuf,r)) return firsttcp(d);
- if (serverfailed(udpbuf,r)) {
+ if (irrelevant(d, udpbuf, r)) return 0;
+ if (serverwantstcp(udpbuf, r)) return firsttcp(d);
+ if (serverfailed(udpbuf, r)) {
if (d->udploop == 2) return 0;
return nextudp(d);
}
@@ -347,13 +387,16 @@ have sent query to curserver on UDP socket s
d->packetlen = r;
d->packet = alloc(d->packetlen);
- if (!d->packet) { dns_transmit_free(d); return DNS_COM; }
- byte_copy(d->packet,d->packetlen,udpbuf);
+ if (!d->packet) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
+ byte_copy(d->packet, d->packetlen, udpbuf);
queryfree(d);
return 1;
}
-/*
+ /*
have sent connection attempt to curserver on TCP socket s
pos not defined
*/
@@ -364,69 +407,72 @@ pos not defined
return 0;
}
-/*
+ /*
have connection to curserver on TCP socket s
have sent pos bytes of query
*/
if (d->tcpstate == 2) {
- r = write(fd,d->query + d->pos,d->querylen - d->pos);
+ r = write(fd, d->query + d->pos, d->querylen - d->pos);
if (r <= 0) return nexttcp(d);
d->pos += r;
if (d->pos == d->querylen) {
struct taia now;
taia_now(&now);
- taia_uint(&d->deadline,10);
- taia_add(&d->deadline,&d->deadline,&now);
+ taia_uint(&d->deadline, 10);
+ taia_add(&d->deadline, &d->deadline, &now);
d->tcpstate = 3;
}
return 0;
}
-/*
+ /*
have sent entire query to curserver on TCP socket s
pos not defined
*/
if (d->tcpstate == 3) {
- r = read(fd,&ch,1);
+ r = read(fd, &ch, 1);
if (r <= 0) return nexttcp(d);
d->packetlen = ch;
d->tcpstate = 4;
return 0;
}
-/*
+ /*
have sent entire query to curserver on TCP socket s
pos not defined
have received one byte of packet length into packetlen
*/
if (d->tcpstate == 4) {
- r = read(fd,&ch,1);
+ r = read(fd, &ch, 1);
if (r <= 0) return nexttcp(d);
d->packetlen <<= 8;
d->packetlen += ch;
d->tcpstate = 5;
d->pos = 0;
d->packet = alloc(d->packetlen);
- if (!d->packet) { dns_transmit_free(d); return DNS_COM; }
+ if (!d->packet) {
+ dns_transmit_free(d);
+ return DNS_COM;
+ }
return 0;
}
-/*
+ /*
have sent entire query to curserver on TCP socket s
have received entire packet length into packetlen
packet is allocated
have received pos bytes of packet
*/
if (d->tcpstate == 5) {
- r = read(fd,d->packet + d->pos,d->packetlen - d->pos);
+ r = read(fd, d->packet + d->pos, d->packetlen - d->pos);
if (r <= 0) return nexttcp(d);
d->pos += r;
if (d->pos < d->packetlen) return 0;
socketfree(d);
- if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d);
- if (serverwantstcp(d->packet,d->packetlen)) return nexttcp(d);
- if (serverfailed(d->packet,d->packetlen)) return nexttcp(d);
+ if (irrelevant(d, d->packet, d->packetlen)) return nexttcp(d);
+ if (serverwantstcp(d->packet, d->packetlen)) return nexttcp(d);
+ if (serverfailed(d->packet, d->packetlen)) return nexttcp(d);
queryfree(d);
return 1;