/src/pdns/pdns/dnsdistdist/dns.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This file is part of PowerDNS or dnsdist. |
3 | | * Copyright -- PowerDNS.COM B.V. and its contributors |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of version 2 of the GNU General Public License as |
7 | | * published by the Free Software Foundation. |
8 | | * |
9 | | * In addition, for the avoidance of any doubt, permission is granted to |
10 | | * link this program with OpenSSL and to (re)distribute the binaries |
11 | | * produced as the result of such linking. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
21 | | */ |
22 | | #ifdef HAVE_CONFIG_H |
23 | | #include "config.h" |
24 | | #endif |
25 | | #include "dns.hh" |
26 | | #include "misc.hh" |
27 | | #include <stdexcept> |
28 | | #include <iostream> |
29 | | #include <boost/algorithm/string.hpp> |
30 | | #include <boost/assign/list_of.hpp> |
31 | | #include "dnsparser.hh" |
32 | | |
33 | | const std::array<std::string, 24> RCode::rcodes_s = { |
34 | | "No Error", |
35 | | "Form Error", |
36 | | "Server Failure", |
37 | | "Non-Existent domain", |
38 | | "Not Implemented", |
39 | | "Query Refused", |
40 | | "Name Exists when it should not", |
41 | | "RR Set Exists when it should not", |
42 | | "RR Set that should exist does not", |
43 | | "Server Not Authoritative for zone / Not Authorized", |
44 | | "Name not contained in zone", |
45 | | "Err#11", |
46 | | "Err#12", |
47 | | "Err#13", |
48 | | "Err#14", |
49 | | "Err#15", // Last non-extended RCode |
50 | | "Bad OPT Version / TSIG Signature Failure", |
51 | | "Key not recognized", |
52 | | "Signature out of time window", |
53 | | "Bad TKEY Mode", |
54 | | "Duplicate key name", |
55 | | "Algorithm not supported", |
56 | | "Bad Truncation", |
57 | | "Bad/missing Server Cookie" |
58 | | }; |
59 | | |
60 | | static const std::array<std::string, 10> rcodes_short_s = { |
61 | | "noerror", |
62 | | "formerr", |
63 | | "servfail", |
64 | | "nxdomain", |
65 | | "notimp", |
66 | | "refused", |
67 | | "yxdomain", |
68 | | "yxrrset", |
69 | | "nxrrset", |
70 | | "notauth", |
71 | | }; |
72 | | |
73 | 0 | std::string RCode::to_s(uint8_t rcode) { |
74 | 0 | if (rcode > 0xF) { |
75 | 0 | return std::string("ErrOutOfRange"); |
76 | 0 | } |
77 | 0 | return ERCode::to_s(rcode); |
78 | 0 | } |
79 | | |
80 | 0 | std::string RCode::to_short_s(uint8_t rcode) { |
81 | 0 | if (rcode >= rcodes_short_s.size()) { |
82 | 0 | return "rcode" + std::to_string(rcode); |
83 | 0 | } |
84 | 0 | return rcodes_short_s.at(rcode); |
85 | 0 | } |
86 | | |
87 | 0 | std::string ERCode::to_s(uint16_t rcode) { |
88 | 0 | if (rcode >= RCode::rcodes_s.size()) { |
89 | 0 | return std::string("Err#")+std::to_string(rcode); |
90 | 0 | } |
91 | 0 | return RCode::rcodes_s.at(rcode); |
92 | 0 | } |
93 | | |
94 | 0 | std::string Opcode::to_s(uint8_t opcode) { |
95 | 0 | static const std::array<std::string, 6> s_opcodes = { "Query", "IQuery", "Status", "3", "Notify", "Update" }; |
96 | |
|
97 | 0 | if (opcode >= s_opcodes.size()) { |
98 | 0 | return std::to_string(opcode); |
99 | 0 | } |
100 | | |
101 | 0 | return s_opcodes.at(opcode); |
102 | 0 | } |
103 | | |
104 | | // goal is to hash based purely on the question name, and turn error into 'default' |
105 | | uint32_t hashQuestion(const uint8_t* packet, uint16_t packet_len, uint32_t init, bool& ok) |
106 | 0 | { |
107 | 0 | if (packet_len < sizeof(dnsheader)) { |
108 | 0 | ok = false; |
109 | 0 | return init; |
110 | 0 | } |
111 | | // C++ 17 does not have std::u8string_view |
112 | 0 | std::basic_string_view<uint8_t> name(packet + sizeof(dnsheader), packet_len - sizeof(dnsheader)); |
113 | 0 | std::basic_string_view<uint8_t>::size_type len = 0; |
114 | |
|
115 | 0 | while (len < name.length()) { |
116 | 0 | uint8_t labellen = name[len++]; |
117 | 0 | if (labellen == 0) { |
118 | 0 | ok = true; |
119 | | // len is name.length() at max as it was < before the increment |
120 | 0 | return burtleCI(name.data(), len, init); |
121 | 0 | } |
122 | 0 | len += labellen; |
123 | 0 | } |
124 | | // We've encountered a label that is too long |
125 | 0 | ok = false; |
126 | 0 | return init; |
127 | 0 | } |
128 | | |