1 | /* |
1 | /* |
2 | vpn_dns.C -- handle the dns tunnel part of the protocol. |
2 | vpn_dns.C -- handle the dns tunnel part of the protocol. |
3 | Copyright (C) 2003-2004 Marc Lehmann <pcg@goof.com> |
3 | Copyright (C) 2003-2005 Marc Lehmann <gvpe@schmorp.de> |
4 | |
4 | |
|
|
5 | This file is part of GVPE. |
|
|
6 | |
5 | This program is free software; you can redistribute it and/or modify |
7 | GVPE is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by |
8 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2 of the License, or |
9 | the Free Software Foundation; either version 2 of the License, or |
8 | (at your option) any later version. |
10 | (at your option) any later version. |
9 | |
11 | |
10 | This program is distributed in the hope that it will be useful, |
12 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. |
15 | GNU General Public License for more details. |
14 | |
16 | |
15 | You should have received a copy of the GNU General Public License |
17 | You should have received a copy of the GNU General Public License |
16 | along with this program; if not, write to the Free Software |
18 | along with gvpe; if not, write to the Free Software |
17 | Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ |
20 | */ |
19 | |
21 | |
20 | #include "config.h" |
22 | #include "config.h" |
21 | |
23 | |
… | |
… | |
51 | |
53 | |
52 | #define MAX_DOMAIN_SIZE 220 // 255 is legal limit, but bind doesn't compress well |
54 | #define MAX_DOMAIN_SIZE 220 // 255 is legal limit, but bind doesn't compress well |
53 | // 240 leaves about 4 bytes of server reply data |
55 | // 240 leaves about 4 bytes of server reply data |
54 | // every two request byte sless give room for one reply byte |
56 | // every two request byte sless give room for one reply byte |
55 | |
57 | |
|
|
58 | // seqno has 12 bits, but the lower bit is always left as zero |
|
|
59 | // as bind caches ttl=0 records and we have to generate |
|
|
60 | // sequence numbers that always differ case-insensitively |
56 | #define SEQNO_MASK 0xffff |
61 | #define SEQNO_MASK 0x07ff |
57 | |
62 | |
58 | /* |
63 | /* |
59 | |
64 | |
60 | protocol, in shorthand :) |
65 | protocol, in shorthand :) |
61 | |
66 | |
… | |
… | |
90 | static int decode (u8 *dst, char *src, int len); |
95 | static int decode (u8 *dst, char *src, int len); |
91 | |
96 | |
92 | dns64 (); |
97 | dns64 (); |
93 | } dns64; |
98 | } dns64; |
94 | |
99 | |
95 | const char dns64::encode_chars[64 + 1] = "_4B9dLphHzrqQmGjkTbJt5svlZX8xSaReEYfwKgF1DP2W6NyVOU70IouACcMn3i-"; |
100 | // the following sequence has been crafted to |
|
|
101 | // a) look somewhat random |
|
|
102 | // b) the even (and odd) indices never share the same character as upper/lowercase |
|
|
103 | const char dns64::encode_chars[64 + 1] = "_-dDpPhHzZrR06QqMmjJkKBb34TtSsvVlL81xXaAeEFf92WwGgYyoO57UucCNniI"; |
96 | s8 dns64::decode_chars[256]; |
104 | s8 dns64::decode_chars[256]; |
97 | |
105 | |
98 | dns64::dns64 () |
106 | dns64::dns64 () |
99 | { |
107 | { |
100 | for (int i = 0; i < 64; i++) |
108 | for (int i = 0; i < 64; i++) |
… | |
… | |
218 | } |
226 | } |
219 | |
227 | |
220 | vpn_packet *byte_stream::get () |
228 | vpn_packet *byte_stream::get () |
221 | { |
229 | { |
222 | int len = (data [0] << 8) | data [1]; |
230 | int len = (data [0] << 8) | data [1]; |
223 | |
|
|
224 | printf ("get len %d, fill %d\n", len, fill);//D |
|
|
225 | |
231 | |
226 | if (len > MAXSIZE && fill >= 2) |
232 | if (len > MAXSIZE && fill >= 2) |
227 | abort (); // TODO handle this gracefully, connection reset |
233 | abort (); // TODO handle this gracefully, connection reset |
228 | |
234 | |
229 | if (fill < len + 2) |
235 | if (fill < len + 2) |
… | |
… | |
356 | // so we need to have space for 2*MAX_DOMAIN_SIZE + header + extra |
362 | // so we need to have space for 2*MAX_DOMAIN_SIZE + header + extra |
357 | |
363 | |
358 | u8 data[256]; //TODO |
364 | u8 data[256]; //TODO |
359 | |
365 | |
360 | data[0] = THISNODE->id; //TODO |
366 | data[0] = THISNODE->id; //TODO |
361 | data[1] = seqno >> 8; //TODO |
367 | data[1] = seqno >> 7; //TODO |
362 | data[2] = seqno; //TODO |
368 | data[2] = seqno << 1; //TODO |
363 | |
369 | |
364 | int datalen = dns64::decode_len (dlen - (dlen + MAX_LBL_SIZE - 1) / MAX_LBL_SIZE) - 3; |
370 | int datalen = dns64::decode_len (dlen - (dlen + MAX_LBL_SIZE - 1) / MAX_LBL_SIZE) - 3; |
365 | |
371 | |
366 | if (datalen > stream->size ()) |
372 | if (datalen > stream->size ()) |
367 | datalen = stream->size (); |
373 | datalen = stream->size (); |
… | |
… | |
419 | int seqno; |
425 | int seqno; |
420 | dns_packet *pkt; // reply packet |
426 | dns_packet *pkt; // reply packet |
421 | u8 data [MAXSIZE]; // actually part of the reply packet... |
427 | u8 data [MAXSIZE]; // actually part of the reply packet... |
422 | int datalen; |
428 | int datalen; |
423 | |
429 | |
424 | dns_rcv (int seqno, dns_packet *req, u8 *data, int datalen); |
430 | dns_rcv (int seqno, u8 *data, int datalen); |
425 | ~dns_rcv (); |
431 | ~dns_rcv (); |
426 | }; |
432 | }; |
427 | |
433 | |
428 | dns_rcv::dns_rcv (int seqno, dns_packet *req, u8 *data, int datalen) |
434 | dns_rcv::dns_rcv (int seqno, u8 *data, int datalen) |
429 | : seqno (seqno), pkt (new dns_packet), datalen (datalen) |
435 | : seqno (seqno), pkt (new dns_packet), datalen (datalen) |
430 | { |
436 | { |
431 | memcpy (this->data, data, datalen); |
437 | memcpy (this->data, data, datalen); |
432 | pkt->len = req->len; |
|
|
433 | memcpy (pkt->at (0), req->at (0), req->len); |
|
|
434 | } |
438 | } |
435 | |
439 | |
436 | dns_rcv::~dns_rcv () |
440 | dns_rcv::~dns_rcv () |
437 | { |
441 | { |
438 | delete pkt; |
442 | delete pkt; |
… | |
… | |
481 | si.host = 0; si.port = 0; si.prot = PROT_DNSv4; |
485 | si.host = 0; si.port = 0; si.prot = PROT_DNSv4; |
482 | |
486 | |
483 | vpn->recv_vpn_packet (pkt, si); |
487 | vpn->recv_vpn_packet (pkt, si); |
484 | } |
488 | } |
485 | } |
489 | } |
486 | else if ((u32)dns_rcvseq - MAX_WINDOW - (u32)(*i)->seqno < MAX_WINDOW * 2) |
490 | else if ((u32)(*i)->seqno - (u32)dns_rcvseq + MAX_WINDOW > MAX_WINDOW * 2) |
487 | { |
491 | { |
|
|
492 | //D |
|
|
493 | //abort(); |
|
|
494 | printf ("%d erasing %d (%d)\n", THISNODE->id, (u32)(*i)->seqno, dns_rcvseq); |
488 | dns_rcvpq.erase (i); |
495 | dns_rcvpq.erase (i); |
489 | goto redo; |
496 | goto redo; |
490 | } |
497 | } |
491 | } |
498 | } |
492 | |
499 | |
… | |
… | |
526 | // correct class, domain: parse |
533 | // correct class, domain: parse |
527 | u8 data[MAXSIZE]; |
534 | u8 data[MAXSIZE]; |
528 | int datalen = dns64::decode (data, qname, qlen - dlen - 1); |
535 | int datalen = dns64::decode (data, qname, qlen - dlen - 1); |
529 | |
536 | |
530 | int client = data[0]; |
537 | int client = data[0]; |
531 | int seqno = ((data[1] << 8) | data[2]) & SEQNO_MASK; |
538 | int seqno = ((data[1] << 7) | (data[2] >> 1)) & SEQNO_MASK; |
532 | |
539 | |
533 | if (0 < client && client <= conns.size ()) |
540 | if (0 < client && client <= conns.size ()) |
534 | { |
541 | { |
535 | connection *c = conns [client - 1]; |
542 | connection *c = conns [client - 1]; |
|
|
543 | |
|
|
544 | redo: |
536 | |
545 | |
537 | for (vector<dns_rcv *>::iterator i = c->dns_rcvpq.begin (); |
546 | for (vector<dns_rcv *>::iterator i = c->dns_rcvpq.begin (); |
538 | i != c->dns_rcvpq.end (); |
547 | i != c->dns_rcvpq.end (); |
539 | ++i) |
548 | ++i) |
540 | if ((*i)->seqno == seqno) |
549 | if ((*i)->seqno == seqno) |
541 | { |
550 | { |
542 | // already seen that request, just reply with the original reply |
551 | // already seen that request: simply reply with the cached reply |
543 | dns_rcv *r = *i; |
552 | dns_rcv *r = *i; |
|
|
553 | |
|
|
554 | printf ("DUPLICATE %d\n", htons (r->pkt->id));//D |
544 | |
555 | |
545 | offs = r->pkt->len; |
556 | offs = r->pkt->len; |
546 | memcpy (pkt->at (0), r->pkt->at (0), offs); |
557 | memcpy (pkt->at (0), r->pkt->at (0), offs); |
547 | goto duplicate_request; |
558 | goto duplicate_request; |
548 | } |
559 | } |
549 | |
560 | |
550 | // new packet, queue |
561 | // new packet, queue |
551 | c->dnsv4_receive_rep (new dns_rcv (seqno, pkt, data + 3, datalen - 3)); |
562 | dns_rcv *rcv = new dns_rcv (seqno, data + 3, datalen - 3); |
|
|
563 | c->dnsv4_receive_rep (rcv); |
552 | |
564 | |
553 | // now generate reply |
565 | // now generate reply |
554 | pkt->ancount = htons (1); // one answer RR |
566 | pkt->ancount = htons (1); // one answer RR |
555 | pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_OK); |
567 | pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_OK); |
556 | |
568 | |
… | |
… | |
594 | int rdlen = offs - rdlen_offs; |
606 | int rdlen = offs - rdlen_offs; |
595 | |
607 | |
596 | (*pkt) [rdlen_offs - 2] = rdlen >> 8; |
608 | (*pkt) [rdlen_offs - 2] = rdlen >> 8; |
597 | (*pkt) [rdlen_offs - 1] = rdlen; |
609 | (*pkt) [rdlen_offs - 1] = rdlen; |
598 | |
610 | |
|
|
611 | // now update dns_rcv copy |
|
|
612 | rcv->pkt->len = offs; |
|
|
613 | memcpy (rcv->pkt->at (0), pkt->at (0), offs); |
|
|
614 | |
599 | duplicate_request: ; |
615 | duplicate_request: ; |
600 | } |
616 | } |
601 | else |
617 | else |
602 | pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_FORMERR); |
618 | pkt->flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_FORMERR); |
603 | } |
619 | } |
604 | } |
|
|
605 | else |
|
|
606 | offs = pkt->len; |
|
|
607 | |
620 | |
608 | pkt->len = offs; |
621 | pkt->len = offs; |
|
|
622 | } |
|
|
623 | |
609 | return pkt; |
624 | return pkt; |
610 | } |
625 | } |
611 | |
626 | |
612 | void |
627 | void |
613 | vpn::dnsv4_client (dns_packet *pkt) |
628 | vpn::dnsv4_client (dns_packet *pkt) |
… | |
… | |
673 | } |
688 | } |
674 | |
689 | |
675 | } |
690 | } |
676 | } |
691 | } |
677 | |
692 | |
678 | if (datap != data) |
693 | // todo: pkt now used |
679 | printf ("%02x %02x %02x %02x\n", |
|
|
680 | data[0], |
|
|
681 | data[1], |
|
|
682 | data[2], |
|
|
683 | data[3]); |
|
|
684 | |
|
|
685 | printf ("recv %d,%d\n", pkt->id, seqno, datap - data);//D |
|
|
686 | c->dnsv4_receive_rep (new dns_rcv (seqno, pkt, data, datap - data)); |
694 | c->dnsv4_receive_rep (new dns_rcv (seqno, data, datap - data)); |
687 | |
695 | |
688 | break; |
696 | break; |
689 | } |
697 | } |
690 | |
698 | |
691 | delete pkt; |
699 | delete pkt; |