ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn_dns.C
Revision: 1.8
Committed: Fri Mar 4 03:43:09 2005 UTC (19 years, 2 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +246 -108 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 vpn_dns.C -- handle the dns tunnel part of the protocol.
3 Copyright (C) 2003-2005 Marc Lehmann <gvpe@schmorp.de>
4
5 This file is part of GVPE.
6
7 GVPE is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with gvpe; if not, write to the Free Software
19 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "config.h"
23
24 #if ENABLE_DNS
25
26 // dns processing is EXTREMELY ugly. For obvious(?) reasons.
27 // it's a hack, use only in emergency situations please.
28
29 #include <cstring>
30
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/wait.h>
34 #include <sys/uio.h>
35 #include <errno.h>
36 #include <time.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39
40 #include <map>
41
42 #include <gmp.h>
43
44 #include "netcompat.h"
45
46 #include "vpn.h"
47
48 #define MIN_RETRY 1.
49 #define MAX_RETRY 60.
50
51 #define MAX_OUTSTANDING 400 // max. outstanding requests
52 #define MAX_WINDOW 1000 // max. for MAX_OUTSTANDING
53 #define MAX_RATE 10000 // requests/s
54 #define MAX_BACKLOG (10*1024) // size of protocol backlog, must be > MAXSIZE
55
56 #define MAX_DOMAIN_SIZE 220 // 255 is legal limit, but bind doesn't compress well
57 // 240 leaves about 4 bytes of server reply data
58 // every two request byte sless give room for one reply byte
59
60 // seqno has 12 bits (3 bytes a 4 bits in the header)
61 #define SEQNO_MASK 0x7fff
62 #define SEQNO_EQ(a,b) ( 0 == ( ((a) ^ (b)) & SEQNO_MASK) )
63
64 #define MAX_LBL_SIZE 63
65 #define MAX_PKT_SIZE 512
66
67 #define RR_TYPE_TXT 16
68 #define RR_TYPE_ANY 255
69 #define RR_CLASS_IN 1
70
71 // works for cmaps up to 255 (not 256!)
72 struct charmap
73 {
74 enum { INVALID = (u8)255 };
75
76 char encode [256]; // index => char
77 u8 decode [256]; // char => index
78 unsigned int size;
79
80 charmap (const char *cmap);
81 };
82
83 charmap::charmap (const char *cmap)
84 {
85 char *enc = encode;
86 u8 *dec = decode;
87
88 memset (enc, (char) 0, 256);
89 memset (dec, (char)INVALID, 256);
90
91 for (size = 0; cmap [size]; size++)
92 {
93 enc [size] = cmap [size];
94 dec [(u8)enc [size]] = size;
95 }
96
97 assert (size < 256);
98 }
99
100 #define MAX_DEC_LEN 500
101 #define MAX_ENC_LEN (MAX_DEC_LEN * 2)
102 #define MAX_LIMBS ((MAX_DEC_LEN * 8 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
103
104 // ugly. minimum base is 16(!)
105 struct basecoder
106 {
107 charmap cmap;
108 unsigned int enc_len [MAX_DEC_LEN];
109 unsigned int dec_len [MAX_ENC_LEN];
110
111 unsigned int encode_len (unsigned int len);
112 unsigned int decode_len (unsigned int len);
113
114 unsigned int encode (char *dst, u8 *src, unsigned int len);
115 unsigned int decode (u8 *dst, char *src, unsigned int len);
116
117 basecoder (const char *cmap);
118 };
119
120 basecoder::basecoder (const char *cmap)
121 : cmap (cmap)
122 {
123 for (unsigned int len = 0; len < MAX_DEC_LEN; ++len)
124 {
125 u8 src [MAX_DEC_LEN];
126 u8 dst [MAX_ENC_LEN];
127
128 memset (src, 255, len);
129
130 mp_limb_t m [MAX_LIMBS];
131 mp_size_t n;
132
133 n = mpn_set_str (m, src, len, 256);
134 n = mpn_get_str (dst, this->cmap.size, m, n);
135
136 for (int i = 0; !dst [i]; ++i)
137 n--;
138
139 enc_len [len] = n;
140 dec_len [n] = len;
141 }
142 }
143
144 unsigned int basecoder::encode_len (unsigned int len)
145 {
146 return enc_len [len];
147 }
148
149 unsigned int basecoder::decode_len (unsigned int len)
150 {
151 while (len && !dec_len [len])
152 --len;
153
154 return dec_len [len];
155 }
156
157 unsigned int basecoder::encode (char *dst, u8 *src, unsigned int len)
158 {
159 if (!len)
160 return 0;
161
162 int elen = encode_len (len);
163
164 mp_limb_t m [MAX_LIMBS];
165 mp_size_t n;
166
167 u8 dst_ [MAX_ENC_LEN];
168
169 n = mpn_set_str (m, src, len, 256);
170 n = mpn_get_str (dst_, cmap.size, m, n);
171
172 int plen = elen; // for padding
173
174 while (n < plen)
175 {
176 *dst++ = cmap.encode [0];
177 plen--;
178 }
179
180 for (unsigned int i = n - plen; i < n; ++i)
181 *dst++ = cmap.encode [dst_ [i]];
182
183 return elen;
184 }
185
186 unsigned int basecoder::decode (u8 *dst, char *src, unsigned int len)
187 {
188 if (!len)
189 return 0;
190
191 u8 src_ [MAX_ENC_LEN];
192 unsigned int elen = 0;
193
194 while (len--)
195 {
196 u8 val = cmap.decode [(u8)*src++];
197
198 if (val != charmap::INVALID)
199 src_ [elen++] = val;
200 }
201
202 int dlen = decode_len (elen);
203
204 mp_limb_t m [MAX_LIMBS];
205 mp_size_t n;
206
207 u8 dst_ [MAX_DEC_LEN];
208
209 n = mpn_set_str (m, src_, elen, cmap.size);
210 n = mpn_get_str (dst_, 256, m, n);
211
212 if (n < dlen)
213 {
214 memset (dst, 0, dlen - n);
215 memcpy (dst + dlen - n, dst_, n);
216 }
217 else
218 memcpy (dst, dst_ + n - dlen, dlen);
219
220 return dlen;
221 }
222
223 #if 0
224 struct test { test (); } test;
225
226 test::test ()
227 {
228 basecoder cdc ("0123456789abcdefghijklmnopqrstuvwxyz");
229
230 u8 in[] = "0123456789abcdefghijklmnopqrstuvwxyz";
231 static char enc[200];
232 static u8 dec[200];
233
234 for (int i = 1; i < 20; i++)
235 {
236 int elen = cdc.encode (enc, in, i);
237 int dlen = cdc.decode (dec, enc, elen);
238
239 printf ("%d>%d>%d (%s>%s)\n", i, elen, dlen, enc, dec);
240 }
241 abort ();
242 }
243 #endif
244
245 // the following sequence has been crafted to
246 // a) look somewhat random
247 // b) the even (and odd) indices never share the same character as upper/lowercase
248 // the "_" is not valid but widely accepted (all octets should be supported, but let's be conservative)
249 // the other sequences are obviously derived
250 //static basecoder cdc63 ("_dDpPhHzZrR06QqMmjJkKBb34TtSsvVlL81xXaAeEFf92WwGgYyoO57UucCNniI");
251 static basecoder cdc62 ("dDpPhHzZrR06QqMmjJkKBb34TtSsvVlL81xXaAeEFf92WwGgYyoO57UucCNniI");
252 //static basecoder cdc36 ("dphzr06qmjkb34tsvl81xaef92wgyo57ucni"); // unused as of yet
253 static basecoder cdc26 ("dPhZrQmJkBtSvLxAeFwGyO");
254
255 /////////////////////////////////////////////////////////////////////////////
256
257 #define HDRSIZE 6
258
259 inline void encode_header (char *data, int clientid, int seqno)
260 {
261 u8 hdr[3] = { clientid, seqno >> 8, seqno };
262
263 assert (clientid < 256);
264
265 cdc26.encode (data, hdr, 3);
266 }
267
268 inline void decode_header (char *data, int &clientid, int &seqno)
269 {
270 u8 hdr[3];
271
272 cdc26.decode (hdr, data, HDRSIZE);
273
274 printf ("DEC %02x %02x %02x %02x\n", hdr[0], hdr[1], hdr[2], hdr[3]);
275
276 clientid = hdr[0];
277 seqno = (hdr[1] << 8) | hdr[2];
278 }
279
280 /////////////////////////////////////////////////////////////////////////////
281
282 struct byte_stream
283 {
284 u8 *data;
285 int maxsize;
286 int fill;
287
288 byte_stream (int maxsize);
289 ~byte_stream ();
290
291 bool empty () { return !fill; }
292 int size () { return fill; }
293
294 bool put (u8 *data, unsigned int datalen);
295 bool put (vpn_packet *pkt);
296 vpn_packet *get ();
297
298 u8 *begin () { return data; }
299 void remove (int count);
300 };
301
302 byte_stream::byte_stream (int maxsize)
303 : maxsize (maxsize), fill (0)
304 {
305 data = new u8 [maxsize];
306 }
307
308 byte_stream::~byte_stream ()
309 {
310 delete data;
311 }
312
313 void byte_stream::remove (int count)
314 {
315 if (count > fill)
316 abort ();
317
318 memmove (data, data + count, fill -= count);
319 }
320
321 bool byte_stream::put (u8 *data, unsigned int datalen)
322 {
323 if (maxsize - fill < datalen)
324 return false;
325
326 memcpy (this->data + fill, data, datalen); fill += datalen;
327
328 return true;
329 }
330
331 bool byte_stream::put (vpn_packet *pkt)
332 {
333 if (maxsize - fill < pkt->len + 2)
334 return false;
335
336 data [fill++] = pkt->len >> 8;
337 data [fill++] = pkt->len;
338
339 memcpy (data + fill, &((*pkt)[0]), pkt->len); fill += pkt->len;
340
341 return true;
342 }
343
344 vpn_packet *byte_stream::get ()
345 {
346 int len = (data [0] << 8) | data [1];
347
348 if (len > MAXSIZE && fill >= 2)
349 abort (); // TODO handle this gracefully, connection reset
350
351 if (fill < len + 2)
352 return 0;
353
354 vpn_packet *pkt = new vpn_packet;
355
356 pkt->len = len;
357 memcpy (&((*pkt)[0]), data + 2, len);
358 remove (len + 2);
359
360 return pkt;
361 }
362
363 /////////////////////////////////////////////////////////////////////////////
364
365 #define FLAG_QUERY ( 0 << 15)
366 #define FLAG_RESPONSE ( 1 << 15)
367 #define FLAG_OP_MASK (15 << 14)
368 #define FLAG_OP_QUERY ( 0 << 11)
369 #define FLAG_AA ( 1 << 10)
370 #define FLAG_TC ( 1 << 9)
371 #define FLAG_RD ( 1 << 8)
372 #define FLAG_RA ( 1 << 7)
373 #define FLAG_AUTH ( 1 << 5)
374 #define FLAG_RCODE_MASK (15 << 0)
375 #define FLAG_RCODE_OK ( 0 << 0)
376 #define FLAG_RCODE_FORMERR ( 1 << 0)
377 #define FLAG_RCODE_SERVFAIL ( 2 << 0)
378 #define FLAG_RCODE_NXDOMAIN ( 3 << 0)
379 #define FLAG_RCODE_REFUSED ( 5 << 0)
380
381 #define DEFAULT_CLIENT_FLAGS (FLAG_QUERY | FLAG_OP_QUERY | FLAG_RD)
382 #define DEFAULT_SERVER_FLAGS (FLAG_RESPONSE | FLAG_OP_QUERY | FLAG_AA | FLAG_RD | FLAG_RA)
383
384 struct dns_packet : net_packet
385 {
386 u16 id;
387 u16 flags; // QR:1 Opcode:4 AA:1 TC:1 RD:1 RA:1 Z:3 RCODE:4
388 u16 qdcount, ancount, nscount, arcount;
389
390 u8 data[MAXSIZE - 6 * 2];
391
392 int decode_label (char *data, int size, int &offs);
393 };
394
395 int dns_packet::decode_label (char *data, int size, int &offs)
396 {
397 char *orig = data;
398
399 memset (data, 0, size);
400
401 while (offs < size - 1)
402 {
403 u8 len = (*this)[offs++];
404
405 if (!len)
406 break;
407 else if (len < 64)
408 {
409 if (size < len + 1 || offs + len >= MAXSIZE - 1)
410 break;
411
412 memcpy (data, &((*this)[offs]), len);
413
414 data += len; size -= len; offs += len;
415 *data++ = '.'; size--;
416 }
417 else
418 {
419 int offs2 = ((len & 63) << 8) + (*this)[offs++];
420
421 data += decode_label (data, size, offs2);
422 break;
423 }
424 }
425
426 return data - orig;
427 }
428
429 /////////////////////////////////////////////////////////////////////////////
430
431 struct dns_req
432 {
433 dns_packet *pkt;
434 tstamp next;
435 int retry;
436 connection *conn;
437 int seqno;
438
439 dns_req (connection *c);
440 void gen_stream_req (int seqno, byte_stream *stream);
441 };
442
443 static u16 dns_id = 12098; // TODO: should be per-vpn
444
445 static u16 next_id ()
446 {
447 // the simplest lsfr with periodicity 65535 i could find
448 dns_id = (dns_id << 1)
449 | (((dns_id >> 1)
450 ^ (dns_id >> 2)
451 ^ (dns_id >> 4)
452 ^ (dns_id >> 15)) & 1);
453
454 return dns_id;
455 }
456
457 dns_req::dns_req (connection *c)
458 : conn (c)
459 {
460 next = 0;
461 retry = 0;
462
463 pkt = new dns_packet;
464
465 pkt->id = next_id ();
466 }
467
468 void dns_req::gen_stream_req (int seqno, byte_stream *stream)
469 {
470 this->seqno = seqno;
471
472 pkt->flags = htons (DEFAULT_CLIENT_FLAGS);
473 pkt->qdcount = htons (1);
474
475 int offs = 6*2;
476 int dlen = MAX_DOMAIN_SIZE - (strlen (THISNODE->domain) + 2);
477 // MAX_DOMAIN_SIZE is technically 255, but bind doesn't compress responses well,
478 // so we need to have space for 2*MAX_DOMAIN_SIZE + header + extra
479
480 char enc[256], *encp = enc;
481 encode_header (enc, THISNODE->id, seqno);
482
483 int datalen = cdc62.decode_len (dlen - (dlen + MAX_LBL_SIZE - 1) / MAX_LBL_SIZE - HDRSIZE);
484
485 if (datalen > stream->size ())
486 datalen = stream->size ();
487
488 int enclen = cdc62.encode (enc + HDRSIZE, stream->begin (), datalen) + HDRSIZE;
489
490 printf ("cdc62.encode %d->%d:%02x %02x %02x %02x\n", datalen, enclen,
491 stream->begin ()[0],
492 stream->begin ()[1],
493 stream->begin ()[2],
494 stream->begin ()[3]);
495
496 stream->remove (datalen);
497
498 while (enclen)
499 {
500 int lbllen = enclen < MAX_LBL_SIZE ? enclen : MAX_LBL_SIZE;
501
502 (*pkt)[offs++] = lbllen;
503 memcpy (pkt->at (offs), encp, lbllen);
504
505 offs += lbllen;
506 encp += lbllen;
507
508 enclen -= lbllen;
509 }
510
511 const char *suffix = THISNODE->domain;
512
513 // add tunnel domain
514 for (;;)
515 {
516 const char *end = strchr (suffix, '.');
517
518 if (!end)
519 end = suffix + strlen (suffix);
520
521 int len = end - suffix;
522
523 (*pkt)[offs++] = len;
524 memcpy (&((*pkt)[offs]), suffix, len);
525 offs += len;
526
527 if (!*end)
528 break;
529
530 suffix = end + 1;
531 }
532
533 (*pkt)[offs++] = 0;
534 (*pkt)[offs++] = RR_TYPE_ANY >> 8; (*pkt)[offs++] = RR_TYPE_ANY;
535 (*pkt)[offs++] = RR_CLASS_IN >> 8; (*pkt)[offs++] = RR_CLASS_IN;
536
537 pkt->len = offs;
538 }
539
540 struct dns_rcv
541 {
542 int seqno;
543 dns_packet *pkt; // reply packet
544 u8 data [MAXSIZE]; // actually part of the reply packet...
545 int datalen;
546
547 dns_rcv (int seqno, u8 *data, int datalen);
548 ~dns_rcv ();
549 };
550
551 dns_rcv::dns_rcv (int seqno, u8 *data, int datalen)
552 : seqno (seqno), pkt (new dns_packet), datalen (datalen)
553 {
554 memcpy (this->data, data, datalen);
555 }
556
557 dns_rcv::~dns_rcv ()
558 {
559 delete pkt;
560 }
561
562 /////////////////////////////////////////////////////////////////////////////
563
564 struct dns_cfg
565 {
566 u8 id1, id2, id3;
567 u8 def_ttl;
568 u8 unused1;
569 u16 max_size;
570 u8 flags1, flags2;
571 };
572
573 void connection::dnsv4_receive_rep (struct dns_rcv *r)
574 {
575 dns_rcvpq.push_back (r);
576
577 printf ("%d got inketc %d (%02x %02x %02x %02x)\n", THISNODE->id, r->seqno
578 ,r->data[0]
579 ,r->data[1]
580 ,r->data[2]
581 ,r->data[3]
582 );
583 redo:
584
585 // find next packet
586 for (vector<dns_rcv *>::iterator i = dns_rcvpq.end (); i-- != dns_rcvpq.begin (); )
587 if (SEQNO_EQ (dns_rcvseq, (*i)->seqno))
588 {
589 // enter the packet into our input stream
590 r = *i;
591
592 printf ("%d checking for older packet %d\n", THISNODE->id, dns_rcvseq);
593 // remove the oldest packet, look forward, as it's oldest first
594 for (vector<dns_rcv *>::iterator j = dns_rcvpq.begin (); j != dns_rcvpq.end (); ++j)
595 if (SEQNO_EQ ((*j)->seqno, dns_rcvseq - MAX_WINDOW))
596 {
597 printf ("%d removing %d\n", THISNODE->id, (*j)->seqno);
598 delete *j;
599 dns_rcvpq.erase (j);
600 break;
601 }
602
603 dns_rcvseq = (dns_rcvseq + 1) & SEQNO_MASK;
604
605 if (!dns_snddq && !dns_rcvdq)
606 {
607 dns_rcvdq = new byte_stream (MAX_BACKLOG * 2);
608 dns_snddq = new byte_stream (MAX_BACKLOG);
609
610 dns_si.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4);
611 }
612
613 if (!dns_rcvdq->put (r->data, r->datalen))
614 abort (); // MUST never overflow, can be caused by data corruption, TODO
615
616 while (vpn_packet *pkt = dns_rcvdq->get ())
617 {
618 sockinfo si;
619 si.host = 0; si.port = 0; si.prot = PROT_DNSv4;
620
621 vpn->recv_vpn_packet (pkt, si);
622 }
623
624 // check for further packets
625 goto redo;
626 }
627 }
628
629 dns_packet *
630 vpn::dnsv4_server (dns_packet *pkt)
631 {
632 u16 flags = ntohs (pkt->flags);
633
634 //memcpy (&((*rep)[0]), &((*pkt)[0]), pkt->len);
635 int offs = 6 * 2; // skip header
636
637 pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_FORMERR);
638
639 if (!(flags & (FLAG_RESPONSE | FLAG_OP_MASK | FLAG_TC))
640 && pkt->qdcount == htons (1))
641 {
642 char qname[MAXSIZE];
643 int qlen = pkt->decode_label ((char *)qname, MAXSIZE - offs, offs);
644
645 u16 qtype = (*pkt) [offs++] << 8; qtype |= (*pkt) [offs++];
646 u16 qclass = (*pkt) [offs++] << 8; qclass |= (*pkt) [offs++];
647
648 pkt->qdcount = htons (1);
649 pkt->ancount = 0;
650 pkt->nscount = 0; // should be self, as other nameservers reply like this
651 pkt->arcount = 0; // a record for self, as other nameservers reply like this
652
653 pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_NXDOMAIN);
654
655 int dlen = strlen (THISNODE->domain);
656
657 if (qclass == RR_CLASS_IN
658 && (qtype == RR_TYPE_ANY || qtype == RR_TYPE_TXT)
659 && qlen > dlen + 1 + HDRSIZE
660 && !memcmp (qname + qlen - dlen - 1, THISNODE->domain, dlen))
661 {
662 // correct class, domain: parse
663 int client, seqno;
664 decode_header (qname, client, seqno);
665
666 u8 data[MAXSIZE];
667 int datalen = cdc62.decode (data, qname + HDRSIZE, qlen - (dlen + 1 + HDRSIZE));
668
669 printf ("cdc62.decode %d(%d): %02x %02x %02x %02x\n",
670 qlen - (dlen + 1 + HDRSIZE), datalen
671 ,data[0]
672 ,data[1]
673 ,data[2]
674 ,data[3]);
675
676 printf ("SRV got %d <%.*s>\n", seqno, qlen, qname + HDRSIZE);//D
677 printf ("SRV got %d <%.*s>\n", seqno, qlen - (dlen + 1 + HDRSIZE), qname + HDRSIZE);//D
678
679 if (0 < client && client <= conns.size ())
680 {
681 connection *c = conns [client - 1];
682
683 for (vector<dns_rcv *>::iterator i = c->dns_rcvpq.end (); i-- != c->dns_rcvpq.begin (); )
684 if (SEQNO_EQ ((*i)->seqno, seqno))
685 {
686 // already seen that request: simply reply with the cached reply
687 dns_rcv *r = *i;
688
689 printf ("DUPLICATE %d\n", htons (r->pkt->id));//D
690
691 memcpy (pkt->at (0), r->pkt->at (0), offs = r->pkt->len);
692 pkt->id = r->pkt->id;
693 goto duplicate_request;
694 }
695
696 // new packet, queue
697 dns_rcv *rcv = new dns_rcv (seqno, data, datalen);
698 c->dnsv4_receive_rep (rcv);
699
700 // now generate reply
701 pkt->ancount = htons (1); // one answer RR
702 pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_OK);
703
704 (*pkt) [offs++] = 0xc0;
705 (*pkt) [offs++] = 6 * 2; // same as in query section
706
707 (*pkt) [offs++] = RR_TYPE_TXT >> 8; (*pkt) [offs++] = RR_TYPE_TXT;
708 (*pkt) [offs++] = RR_CLASS_IN >> 8; (*pkt) [offs++] = RR_CLASS_IN;
709
710 (*pkt) [offs++] = 0; (*pkt) [offs++] = 0;
711 (*pkt) [offs++] = 0; (*pkt) [offs++] = 0; // TTL
712
713 int dlen = MAX_PKT_SIZE - offs - 2;
714
715 // bind doesn't compress well, so reduce further by one label length
716 dlen -= qlen;
717
718 int rdlen_offs = offs += 2;
719
720 while (c->dns_snddq
721 && !c->dns_snddq->empty ()
722 && dlen > 1)
723 {
724 int txtlen = dlen <= 255 ? dlen - 1 : 255;
725
726 if (txtlen > c->dns_snddq->size ())
727 txtlen = c->dns_snddq->size ();
728
729 (*pkt)[offs++] = txtlen;
730 memcpy (pkt->at (offs), c->dns_snddq->begin (), txtlen);
731 offs += txtlen;
732 c->dns_snddq->remove (txtlen);
733
734 dlen -= txtlen + 1;
735 }
736
737 // avoid empty TXT rdata
738 if (offs == rdlen_offs)
739 (*pkt)[offs++] = 0;
740
741 int rdlen = offs - rdlen_offs;
742
743 (*pkt) [rdlen_offs - 2] = rdlen >> 8;
744 (*pkt) [rdlen_offs - 1] = rdlen;
745
746 // now update dns_rcv copy
747 rcv->pkt->len = offs;
748 memcpy (rcv->pkt->at (0), pkt->at (0), offs);
749
750 duplicate_request: ;
751 }
752 else
753 pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_FORMERR);
754 }
755
756 pkt->len = offs;
757 }
758
759 return pkt;
760 }
761
762 void
763 vpn::dnsv4_client (dns_packet *pkt)
764 {
765 u16 flags = ntohs (pkt->flags);
766 int offs = 6 * 2; // skip header
767
768 pkt->qdcount = ntohs (pkt->qdcount);
769 pkt->ancount = ntohs (pkt->ancount);
770
771 // go through our request list and find the corresponding request
772 for (vector<dns_req *>::iterator i = dns_sndpq.begin ();
773 i != dns_sndpq.end ();
774 ++i)
775 if ((*i)->pkt->id == pkt->id)
776 {
777 connection *c = (*i)->conn;
778 int seqno = (*i)->seqno;
779 u8 data[MAXSIZE], *datap = data;
780
781 delete *i;
782 dns_sndpq.erase (i);
783
784 if (flags & (FLAG_RESPONSE | FLAG_OP_MASK | FLAG_TC))
785 {
786 char qname[MAXSIZE];
787
788 while (pkt->qdcount-- && offs < MAXSIZE - 4)
789 {
790 int qlen = pkt->decode_label ((char *)qname, MAXSIZE - offs, offs);
791 offs += 4; // skip qtype, qclass
792 }
793
794 while (pkt->ancount-- && offs < MAXSIZE - 10)
795 {
796 int qlen = //D
797 pkt->decode_label ((char *)qname, MAXSIZE - offs, offs);
798
799 printf ("got reply to <%.*s>\n", qlen, qname);//D
800
801 u16 qtype = (*pkt) [offs++] << 8; qtype |= (*pkt) [offs++];
802 u16 qclass = (*pkt) [offs++] << 8; qclass |= (*pkt) [offs++];
803 u32 ttl = (*pkt) [offs++] << 24;
804 ttl |= (*pkt) [offs++] << 16;
805 ttl |= (*pkt) [offs++] << 8;
806 ttl |= (*pkt) [offs++];
807
808 u16 rdlen = (*pkt) [offs++] << 8; rdlen |= (*pkt) [offs++];
809
810 if (rdlen <= MAXSIZE - offs)
811 {
812 // decode bytes, finally
813
814 while (rdlen)
815 {
816 int txtlen = (*pkt) [offs++];
817
818 assert (txtlen + offs < MAXSIZE - 1);
819
820 memcpy (datap, pkt->at (offs), txtlen);
821 datap += txtlen; offs += txtlen;
822
823 rdlen -= txtlen + 1;
824 }
825
826 }
827
828 }
829 }
830
831 // todo: pkt now used
832 c->dnsv4_receive_rep (new dns_rcv (seqno, data, datap - data));
833
834 break;
835 }
836
837 delete pkt;
838 }
839
840 void
841 vpn::dnsv4_ev (io_watcher &w, short revents)
842 {
843 if (revents & EVENT_READ)
844 {
845 dns_packet *pkt = new dns_packet;
846 struct sockaddr_in sa;
847 socklen_t sa_len = sizeof (sa);
848
849 pkt->len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
850
851 if (pkt->len > 0)
852 {
853 if (pkt->flags & htons (FLAG_TC))
854 {
855 slog (L_WARN, _("DNS request/response truncated, check protocol settings."));
856 //TODO connection reset
857 }
858
859 if (THISNODE->dns_port)
860 {
861 pkt = dnsv4_server (pkt);
862 sendto (w.fd, &((*pkt)[0]), pkt->len, 0, (sockaddr *)&sa, sa_len);
863 }
864 else
865 dnsv4_client (pkt);
866 }
867 }
868 }
869
870 bool
871 connection::send_dnsv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
872 {
873 // never initialized
874 if (!dns_snddq && !dns_rcvdq)
875 {
876 dns_rcvdq = new byte_stream (MAX_BACKLOG * 2);
877 dns_snddq = new byte_stream (MAX_BACKLOG);
878
879 //dns_rcvseq = dns_sndseq = 0;
880
881 dns_si.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4);
882 }
883
884 if (!dns_snddq->put (pkt))
885 return false;
886
887 // start timer if neccessary
888 if (!THISNODE->dns_port && !dnsv4_tw.active)
889 dnsv4_cb (dnsv4_tw);
890
891 return true;
892 }
893
894 void
895 connection::dnsv4_cb (time_watcher &w)
896 {
897 // check for timeouts and (re)transmit
898 tstamp next = NOW + 60;
899 dns_req *send = 0;
900
901 for (vector<dns_req *>::iterator i = vpn->dns_sndpq.begin ();
902 i != vpn->dns_sndpq.end ();
903 ++i)
904 {
905 dns_req *r = *i;
906
907 if (r->next <= NOW)
908 {
909 if (!send)
910 {
911 send = r;
912
913 if (r->retry)//D
914 printf ("req %d:%d, retry %d\n", r->seqno, r->pkt->id, r->retry);
915 r->retry++;
916 r->next = NOW + r->retry;
917 }
918 }
919
920 if (r->next < next)
921 next = r->next;
922 }
923
924 if (!send
925 && vpn->dns_sndpq.size () < MAX_OUTSTANDING)
926 {
927 send = new dns_req (this);
928 send->gen_stream_req (dns_sndseq, dns_snddq);
929 vpn->dns_sndpq.push_back (send);
930
931 dns_sndseq = (dns_sndseq + 1) & SEQNO_MASK;
932 }
933
934 tstamp min_next = NOW + (1. / (tstamp)MAX_RATE);
935
936 if (send)
937 {
938 dns_packet *pkt = send->pkt;
939
940 next = min_next;
941
942 sendto (vpn->dnsv4_fd, &((*pkt)[0]), pkt->len, 0, dns_si.sav4 (), dns_si.salenv4 ());
943 }
944 else if (next < min_next)
945 next = min_next;
946
947 w.start (next);
948 }
949
950 #endif
951