2 #include <sys/socket.h>
23 if (byte_diff(
ip,2,V6linklocal))
return 0;
25 if (byte_equal(
d->servers + 16 * i,16,
ip))
35 if (
out[2] & 2)
return 1;
46 if ((rcode == 0) || (rcode == 3))
return 0;
47 if (rcode == 5) byte_zero(server,16);
59 if (byte_diff(
out,2,
d->nonce + 8))
return 1;
60 if (
out[4] != 0)
return 1;
61 if (
out[5] != 1)
return 1;
69 if (byte_diff(
out,2,
d->qtype))
return 1;
77 if (!
d->packet)
return;
78 alloc_free(
d->packet);
84 if (!
d->query)
return;
107 for (j = 0; j < 10; ++j) {
108 if (socket_bind(
d->s1 - 1,
d->localip,1025 +
dns_random(64510),
d->scope_id) == 0)
112 if (socket_bind(
d->s1 - 1,
d->localip,0,
d->scope_id) == 0)
122 for (j = 0; j < 10; ++j) {
123 if (socket_bind6(
d->s1 - 1,
d->localip,1025 +
dns_random(64510),
d->scope_id) == 0)
127 if (socket_bind6(
d->s1 - 1,
d->localip,0,
d->scope_id) == 0)
137 for (j = 0; j < 10; ++j) {
138 if (socket_bind4(
d->s1 - 1,
d->localip + 12,1025 +
dns_random(64510)) == 0)
142 if (socket_bind4(
d->s1 - 1,
d->localip + 12,0) == 0)
148 static const int timeouts[5] = { 1, 2, 4, 8, 16 };
156 while (
d->udploop < 5) {
158 ip =
d->servers + 16 *
d->curserver;
159 if (byte_equal(
ip,16,V6localnet))
continue;
168 if (ip6_isv4mapped(
ip)) {
169 d->s1 = 1 + socket_udp4();
173 d->s1 = 1 + socket_udp6();
178 if (byte_equal(
ip,2,V6linklocal) && !
d->scope_id)
180 if (socket_connect(
d->s1 - 1,
ip,
DNSPORT,
d->scope_id) == 0)
181 if (send(
d->s1 - 1,
d->query + 2,
d->querylen - 2,0) ==
d->querylen - 2) {
184 taia_uint(&
d->deadline,timeouts[
d->udploop]);
185 taia_add(&
d->deadline,&
d->deadline,&
now);
221 ip =
d->servers + 16 *
d->curserver;
222 if (byte_equal(
ip,16,V6localnet))
continue;
225 if (ip6_isv4mapped(
ip)) {
226 d->s1 = 1 + socket_tcp4();
230 d->s1 = 1 + socket_tcp6();
235 taia_uint(&
d->deadline,10);
236 taia_add(&
d->deadline,&
d->deadline,&
now);
238 if (byte_equal(
ip,2,V6linklocal) && !
d->scope_id)
240 if (socket_connect(
d->s1 - 1,
ip,
DNSPORT,
d->scope_id) == 0) {
244 if ((errno == EINPROGRESS) || (errno == EWOULDBLOCK)) {
270 int flagrecursive,
const char *q,
const char qtype[2],
const char localip[16])
276 int flagrecursive,
const char *q,
const char qtype[2], \
288 switch (
d->tcpstate) {
289 case 0:
case 3:
case 4:
case 5:
290 x->events = IOPAUSE_READ;
293 x->events = IOPAUSE_WRITE;
297 if (taia_less(&
d->deadline,deadline))
298 *deadline =
d->deadline;
313 if (taia_less((
struct taia *)when,&
d->deadline))
return 0;
323 if (
d->tcpstate == 0) {
324 r = recv(
fd,udpbuf,
sizeof(udpbuf),0);
326 if (errno == ECONNREFUSED)
if (
d->udploop == 2)
return 0;
329 if (r + 1 >
sizeof(udpbuf))
return 0;
336 if (
serverfailed(udpbuf,r,(
char *)(
d->servers + 16 *
d->curserver))) {
337 if (
d->udploop == 2)
return 0;
343 d->packet = alloc(
d->packetlen);
345 byte_copy(
d->packet,
d->packetlen,udpbuf);
354 if (
d->tcpstate == 1) {
365 if (
d->tcpstate == 2) {
366 r = write(
fd,
d->query +
d->pos,
d->querylen -
d->pos);
369 if (
d->pos ==
d->querylen) {
372 taia_uint(&
d->deadline,10);
373 taia_add(&
d->deadline,&
d->deadline,&
now);
383 if (
d->tcpstate == 3) {
396 if (
d->tcpstate == 4) {
403 d->packet = alloc(
d->packetlen);
414 if (
d->tcpstate == 5) {
415 r = read(
fd,
d->packet +
d->pos,
d->packetlen -
d->pos);
418 if (
d->pos <
d->packetlen)
return 0;
424 if (
serverfailed(
d->packet,
d->packetlen,(
char *)(
d->servers + 16 *
d->curserver)))
int cns_transmit_start(struct dns_transmit *d, const char servers[QUERY_MAXIPLEN], int flagrecursive, const char *q, const char qtype[2], const char localip[16], const char keys[1024], const char pubkey[32], const char *suffix)
void cns_query(struct dns_transmit *d)
int cns_uncurve(const struct dns_transmit *d, char *buf, unsigned int *lenp)
void cns_altquery(struct dns_transmit *d)
unsigned int dns_packet_copy(const char *, unsigned int, unsigned int, char *, unsigned int)
int dns_domain_equal(const char *, const char *)
unsigned int dns_random(unsigned int)
unsigned int dns_packet_getname(const char *, unsigned int, unsigned int, char **)
void dns_transmit_io(struct dns_transmit *d, iopause_fd *x, struct taia *deadline)
int thisudp(struct dns_transmit *d)
void socketfree(struct dns_transmit *d)
void packetfree(struct dns_transmit *d)
void dns_transmit_free(struct dns_transmit *d)
int randombind6(struct dns_transmit *d)
int getscopeid(const struct dns_transmit *d, const char *ip)
int randombind4(struct dns_transmit *d)
int thistcp(struct dns_transmit *d)
int firstudp(struct dns_transmit *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 nexttcp(struct dns_transmit *d)
int serverwantstcp(const char *buf, unsigned int len)
uint32 scope_ids[QUERY_MAXNS]
int serverfailed(const char *buf, unsigned int len, char *server)
void queryfree(struct dns_transmit *d)
int randombind(struct dns_transmit *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_get(struct dns_transmit *d, const iopause_fd *x, const struct taia *when)
int nextudp(struct dns_transmit *d)
int irrelevant(const struct dns_transmit *d, const char *buf, unsigned int len)
int firsttcp(struct dns_transmit *d)
char servers[QUERY_MAXIPLEN]
uint32 scopes[QUERY_MAXNS]
void out(const char *s, unsigned int len)
void d(const char *home, const char *subdir, int uid, int gid, int mode)