… | |
… | |
25 | |
25 | |
26 | // dns processing is EXTREMELY ugly. For obvious(?) reasons. |
26 | // dns processing is EXTREMELY ugly. For obvious(?) reasons. |
27 | // it's a hack, use only in emergency situations please. |
27 | // it's a hack, use only in emergency situations please. |
28 | |
28 | |
29 | #include <cstring> |
29 | #include <cstring> |
|
|
30 | #include <cassert> |
30 | |
31 | |
31 | #include <sys/types.h> |
32 | #include <sys/types.h> |
32 | #include <sys/socket.h> |
33 | #include <sys/socket.h> |
33 | #include <sys/wait.h> |
34 | #include <sys/wait.h> |
34 | #include <sys/uio.h> |
35 | #include <sys/uio.h> |
… | |
… | |
622 | |
623 | |
623 | pkt->flags = htons (DEFAULT_CLIENT_FLAGS); |
624 | pkt->flags = htons (DEFAULT_CLIENT_FLAGS); |
624 | pkt->qdcount = htons (1); |
625 | pkt->qdcount = htons (1); |
625 | |
626 | |
626 | int offs = 6*2; |
627 | int offs = 6*2; |
627 | int dlen = MAX_DOMAIN_SIZE - (strlen (THISNODE->domain) + 2); |
628 | int dlen = MAX_DOMAIN_SIZE - (strlen (dns->c->conf->domain) + 2); |
628 | // MAX_DOMAIN_SIZE is technically 255, but bind doesn't compress responses well, |
629 | // MAX_DOMAIN_SIZE is technically 255, but bind doesn't compress responses well, |
629 | // so we need to have space for 2*MAX_DOMAIN_SIZE + header + extra |
630 | // so we need to have space for 2*MAX_DOMAIN_SIZE + header + extra |
630 | |
631 | |
631 | char enc[256], *encp = enc; |
632 | char enc[256], *encp = enc; |
632 | encode_header (enc, THISNODE->id, seqno); |
633 | encode_header (enc, THISNODE->id, seqno); |
… | |
… | |
650 | encp += lbllen; |
651 | encp += lbllen; |
651 | |
652 | |
652 | enclen -= lbllen; |
653 | enclen -= lbllen; |
653 | } |
654 | } |
654 | |
655 | |
655 | append_domain (*pkt, offs, THISNODE->domain); |
656 | append_domain (*pkt, offs, dns->c->conf->domain); |
656 | |
657 | |
657 | (*pkt)[offs++] = 0; |
658 | (*pkt)[offs++] = 0; |
658 | (*pkt)[offs++] = RR_TYPE_ANY >> 8; (*pkt)[offs++] = RR_TYPE_ANY; |
659 | (*pkt)[offs++] = RR_TYPE_ANY >> 8; (*pkt)[offs++] = RR_TYPE_ANY; |
659 | (*pkt)[offs++] = RR_CLASS_IN >> 8; (*pkt)[offs++] = RR_CLASS_IN; |
660 | (*pkt)[offs++] = RR_CLASS_IN >> 8; (*pkt)[offs++] = RR_CLASS_IN; |
660 | |
661 | |
… | |
… | |
676 | |
677 | |
677 | assert (elen <= MAX_LBL_SIZE); |
678 | assert (elen <= MAX_LBL_SIZE); |
678 | |
679 | |
679 | (*pkt)[offs] = elen; |
680 | (*pkt)[offs] = elen; |
680 | offs += elen + 1; |
681 | offs += elen + 1; |
681 | append_domain (*pkt, offs, THISNODE->domain); |
682 | append_domain (*pkt, offs, dns->c->conf->domain); |
682 | |
683 | |
683 | (*pkt)[offs++] = 0; |
684 | (*pkt)[offs++] = 0; |
684 | (*pkt)[offs++] = RR_TYPE_A >> 8; (*pkt)[offs++] = RR_TYPE_A; |
685 | (*pkt)[offs++] = RR_TYPE_A >> 8; (*pkt)[offs++] = RR_TYPE_A; |
685 | (*pkt)[offs++] = RR_CLASS_IN >> 8; (*pkt)[offs++] = RR_CLASS_IN; |
686 | (*pkt)[offs++] = RR_CLASS_IN >> 8; (*pkt)[offs++] = RR_CLASS_IN; |
686 | |
687 | |
… | |
… | |
874 | // new packet, queue |
875 | // new packet, queue |
875 | rcv = new dns_rcv (seqno, data, datalen); |
876 | rcv = new dns_rcv (seqno, data, datalen); |
876 | dns->receive_rep (rcv); |
877 | dns->receive_rep (rcv); |
877 | } |
878 | } |
878 | |
879 | |
|
|
880 | { |
879 | pkt [offs++] = 0xc0; pkt [offs++] = 6 * 2; // refer to name in query section |
881 | pkt [offs++] = 0xc0; pkt [offs++] = 6 * 2; // refer to name in query section |
880 | |
882 | |
881 | int rtype = dns ? dns->cfg.rrtype : RR_TYPE_A; |
883 | int rtype = dns ? dns->cfg.rrtype : RR_TYPE_A; |
882 | pkt [offs++] = rtype >> 8; pkt [offs++] = rtype; // type |
884 | pkt [offs++] = rtype >> 8; pkt [offs++] = rtype; // type |
883 | pkt [offs++] = RR_CLASS_IN >> 8; pkt [offs++] = RR_CLASS_IN; // class |
885 | pkt [offs++] = RR_CLASS_IN >> 8; pkt [offs++] = RR_CLASS_IN; // class |
884 | pkt [offs++] = 0; pkt [offs++] = 0; |
886 | pkt [offs++] = 0; pkt [offs++] = 0; |
885 | pkt [offs++] = 0; pkt [offs++] = dns ? dns->cfg.def_ttl : 0; // TTL |
887 | pkt [offs++] = 0; pkt [offs++] = dns ? dns->cfg.def_ttl : 0; // TTL |
886 | |
888 | |
887 | int rdlen_offs = offs += 2; |
889 | int rdlen_offs = offs += 2; |
888 | |
890 | |
889 | int dlen = (dns ? ntohs (dns->cfg.max_size) : MAX_PKT_SIZE) - offs; |
891 | int dlen = (dns ? ntohs (dns->cfg.max_size) : MAX_PKT_SIZE) - offs; |
890 | // bind doesn't compress well, so reduce further by one label length |
892 | // bind doesn't compress well, so reduce further by one label length |
891 | dlen -= qlen; |
893 | dlen -= qlen; |
892 | |
894 | |
893 | if (dns) |
895 | if (dns) |
894 | { |
896 | { |
895 | // only put data into in-order sequence packets, if |
897 | // only put data into in-order sequence packets, if |
896 | // we receive out-of-order packets we generate empty |
898 | // we receive out-of-order packets we generate empty |
897 | // replies |
899 | // replies |
898 | while (dlen > 1 && !dns->snddq.empty () && in_seq) |
900 | while (dlen > 1 && !dns->snddq.empty () && in_seq) |
899 | { |
901 | { |
900 | int txtlen = dlen <= 255 ? dlen - 1 : 255; |
902 | int txtlen = dlen <= 255 ? dlen - 1 : 255; |
901 | |
903 | |
902 | if (txtlen > dns->snddq.size ()) |
904 | if (txtlen > dns->snddq.size ()) |
903 | txtlen = dns->snddq.size (); |
905 | txtlen = dns->snddq.size (); |
904 | |
906 | |
905 | pkt[offs++] = txtlen; |
907 | pkt[offs++] = txtlen; |
906 | memcpy (pkt.at (offs), dns->snddq.begin (), txtlen); |
908 | memcpy (pkt.at (offs), dns->snddq.begin (), txtlen); |
907 | offs += txtlen; |
909 | offs += txtlen; |
908 | dns->snddq.remove (txtlen); |
910 | dns->snddq.remove (txtlen); |
909 | |
911 | |
910 | dlen -= txtlen + 1; |
912 | dlen -= txtlen + 1; |
911 | } |
913 | } |
912 | |
914 | |
913 | // avoid empty TXT rdata |
915 | // avoid empty TXT rdata |
914 | if (offs == rdlen_offs) |
916 | if (offs == rdlen_offs) |
915 | pkt[offs++] = 0; |
917 | pkt[offs++] = 0; |
916 | |
918 | |
917 | slog (L_NOISE, "DNS: snddq %d", dns->snddq.size ()); |
919 | slog (L_NOISE, "DNS: snddq %d", dns->snddq.size ()); |
918 | } |
920 | } |
919 | else |
921 | else |
920 | { |
922 | { |
921 | // send RST |
923 | // send RST |
922 | pkt [offs++] = CMD_IP_1; pkt [offs++] = CMD_IP_2; pkt [offs++] = CMD_IP_3; |
924 | pkt [offs++] = CMD_IP_1; pkt [offs++] = CMD_IP_2; pkt [offs++] = CMD_IP_3; |
923 | pkt [offs++] = CMD_IP_RST; |
925 | pkt [offs++] = CMD_IP_RST; |
924 | } |
926 | } |
925 | |
927 | |
926 | int rdlen = offs - rdlen_offs; |
928 | int rdlen = offs - rdlen_offs; |
927 | |
929 | |
928 | pkt [rdlen_offs - 2] = rdlen >> 8; |
930 | pkt [rdlen_offs - 2] = rdlen >> 8; |
929 | pkt [rdlen_offs - 1] = rdlen; |
931 | pkt [rdlen_offs - 1] = rdlen; |
930 | |
932 | |
931 | if (dns) |
933 | if (dns) |
932 | { |
934 | { |
933 | // now update dns_rcv copy |
935 | // now update dns_rcv copy |
934 | rcv->pkt->len = offs; |
936 | rcv->pkt->len = offs; |
935 | memcpy (rcv->pkt->at (0), pkt.at (0), offs); |
937 | memcpy (rcv->pkt->at (0), pkt.at (0), offs); |
936 | } |
938 | } |
|
|
939 | } |
937 | |
940 | |
938 | duplicate_request: ; |
941 | duplicate_request: ; |
939 | } |
942 | } |
940 | else |
943 | else |
941 | pkt.flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_FORMERR); |
944 | pkt.flags = htons (DEFAULT_SERVER_FLAGS | FLAG_RCODE_FORMERR); |