]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/reczones-helpers.cc
Step one: remove symlinks to rec-specific files
[thirdparty/pdns.git] / pdns / recursordist / reczones-helpers.cc
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
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "syncres.hh"
28 #include "reczones-helpers.hh"
29
30 template <typename T>
31 static SyncRes::AuthDomain makeSOAAndNSNodes(DNSRecord& dr, T content)
32 {
33 dr.d_class = 1;
34 dr.d_place = DNSResourceRecord::ANSWER;
35 dr.d_ttl = 86400;
36 dr.d_type = QType::SOA;
37 dr.d_content = DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800");
38
39 SyncRes::AuthDomain ad;
40 ad.d_rdForward = false;
41 ad.d_records.insert(dr);
42
43 dr.d_type = QType::NS;
44 dr.d_content = std::make_shared<NSRecordContent>(content);
45 ad.d_records.insert(dr);
46
47 return ad;
48 }
49
50 static void addToDomainMap(SyncRes::domainmap_t& newMap,
51 SyncRes::AuthDomain ad,
52 DNSName& name,
53 Logr::log_t log,
54 const bool partial = false,
55 const bool reverse = false)
56 {
57 if (newMap.count(name) != 0) {
58 SLOG(g_log << Logger::Warning << "Will not overwrite zone '" << name << "' already loaded" << endl,
59 log->info(Logr::Warning, "Will not overwrite already loaded zone", "zone",
60 Logging::Loggable(name)));
61 }
62 else {
63 if (!partial) {
64 const auto direction = reverse ? std::string{"reverse"} : std::string{"forward"};
65 SLOG(g_log << Logger::Warning << "Inserting " << direction << " zone '" << name << "' based on hosts file" << endl,
66 log->info(Logr::Notice, "Inserting " + direction + " zone based on hosts file", "zone", Logging::Loggable(name)));
67 }
68 ad.d_name = name;
69 newMap[ad.d_name] = ad;
70 }
71 }
72
73 static void makeNameToIPZone(SyncRes::domainmap_t& newMap,
74 const DNSName& hostname,
75 const ComboAddress& address)
76 {
77 DNSRecord dr;
78 dr.d_name = hostname;
79
80 auto entry = newMap.find(hostname);
81 if (entry == newMap.end()) {
82 auto ad = makeSOAAndNSNodes(dr, "localhost.");
83 ad.d_name = dr.d_name;
84 entry = newMap.insert({dr.d_name, ad}).first;
85 }
86
87 auto recType = address.isIPv6() ? QType::AAAA : QType::A;
88 dr.d_type = recType;
89 dr.d_ttl = 86400;
90 dr.d_content = DNSRecordContent::mastermake(recType, QClass::IN, address.toStringNoInterface());
91 entry->second.d_records.insert(dr);
92 }
93
94 static void makeIPToNamesZone(SyncRes::domainmap_t& newMap,
95 const ComboAddress& address,
96 const std::string& canonicalHostname,
97 Logr::log_t log)
98 {
99 DNSRecord dr;
100 dr.d_name = DNSName(address.toStringReversed());
101 dr.d_name.appendRawLabel(address.isIPv4() ? "in-addr" : "ip6");
102 dr.d_name.appendRawLabel("arpa");
103
104 SyncRes::AuthDomain ad = makeSOAAndNSNodes(dr, DNSName("localhost."));
105
106 // Add a PTR entry for the primary name for reverse lookups.
107 dr.d_type = QType::PTR;
108 dr.d_content = DNSRecordContent::mastermake(QType::PTR, 1, DNSName(canonicalHostname).toString());
109 ad.d_records.insert(dr);
110
111 addToDomainMap(newMap, ad, dr.d_name, log, false, true);
112 }
113
114 void makePartialIPZone(SyncRes::domainmap_t& newMap,
115 std::initializer_list<const char*> labels,
116 Logr::log_t log)
117 {
118 DNSRecord dr;
119 for (auto label = std::rbegin(labels); label != std::rend(labels); ++label) {
120 dr.d_name.appendRawLabel(*label);
121 }
122 dr.d_name.appendRawLabel("in-addr");
123 dr.d_name.appendRawLabel("arpa");
124
125 SyncRes::AuthDomain ad = makeSOAAndNSNodes(dr, DNSName("localhost."));
126
127 addToDomainMap(newMap, ad, dr.d_name, log, true, true);
128 }
129
130 void addForwardAndReverseLookupEntries(SyncRes::domainmap_t& newMap,
131 const std::string& searchSuffix,
132 const std::vector<std::string>& parts,
133 Logr::log_t log)
134 {
135 const ComboAddress address{parts[0]};
136
137 // Go over the hostname and aliases (parts[1], parts[2], etc...) and add entries
138 // for forward lookups.
139 for (auto name = parts.cbegin() + 1; name != parts.cend(); ++name) {
140 if (searchSuffix.empty() || name->find('.') != string::npos) {
141 makeNameToIPZone(newMap, DNSName(*name), address);
142 }
143 else {
144 DNSName canonical = toCanonic(DNSName(searchSuffix), *name);
145 if (canonical != DNSName(*name)) {
146 makeNameToIPZone(newMap, canonical, address);
147 }
148 }
149 }
150
151 // Add entries for the primary name for reverse lookups.
152 if (searchSuffix.empty() || parts[1].find('.') != string::npos) {
153 makeIPToNamesZone(newMap, address, parts[1], log);
154 }
155 else {
156 DNSName canonical = toCanonic(DNSName(searchSuffix), parts[1]);
157 makeIPToNamesZone(newMap, address, canonical.toString(), log);
158 }
159 }
160
161 bool parseEtcHostsLine(std::vector<std::string>& parts, std::string& line)
162 {
163 const string::size_type pos = line.find('#');
164 if (pos != string::npos) {
165 line.resize(pos);
166 }
167 boost::trim(line);
168 if (line.empty()) {
169 return false;
170 }
171 parts.clear();
172 stringtok(parts, line, "\t\r\n ");
173 return parts.size() >= 2;
174 }