]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/ixfrutils.cc
ixfrdist: clean up includes
[thirdparty/pdns.git] / pdns / ixfrutils.cc
CommitLineData
4db8fd44
PL
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#include <dirent.h>
24#include "ixfrutils.hh"
25#include "sstuff.hh"
26#include "dnssecinfra.hh"
27#include "zoneparser-tng.hh"
28
29uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent>& sr, const TSIGTriplet& tt)
30{
31 vector<uint8_t> packet;
32 DNSPacketWriter pw(packet, zone, QType::SOA);
33 if(!tt.algo.empty()) {
34 TSIGRecordContent trc;
35 trc.d_algoName = tt.algo;
36 trc.d_time = time(nullptr);
37 trc.d_fudge = 300;
38 trc.d_origID=ntohs(pw.getHeader()->id);
39 trc.d_eRcode=0;
40 addTSIG(pw, trc, tt.name, tt.secret, "", false);
41 }
42
43 Socket s(master.sin4.sin_family, SOCK_DGRAM);
44 s.connect(master);
45 string msg((const char*)&packet[0], packet.size());
46 s.writen(msg);
47
48 string reply;
49 s.read(reply);
50 MOADNSParser mdp(false, reply);
51 if(mdp.d_header.rcode) {
52 throw std::runtime_error("Unable to retrieve SOA serial from master '"+master.toStringWithPort()+"': "+RCode::to_s(mdp.d_header.rcode));
53 }
54 for(const auto& r: mdp.d_answers) {
55 if(r.first.d_type == QType::SOA) {
56 sr = std::dynamic_pointer_cast<SOARecordContent>(r.first.d_content);
57 return sr->d_st.serial;
58 }
59 }
60 return 0;
61}
62
63uint32_t getSerialsFromDir(const std::string& dir)
64{
65 uint32_t ret=0;
66 DIR* dirhdl=opendir(dir.c_str());
67 if(!dirhdl)
68 throw runtime_error("Could not open IXFR directory");
69 struct dirent *entry;
70
71 while((entry = readdir(dirhdl))) {
72 uint32_t num = atoi(entry->d_name);
73 if(std::to_string(num) == entry->d_name)
74 ret = max(num, ret);
75 }
76 closedir(dirhdl);
77 return ret;
78}
79
80uint32_t getSerialFromRecords(const records_t& records, DNSRecord& soaret)
81{
82 DNSName root(".");
83 uint16_t t=QType::SOA;
84
85 auto found = records.equal_range(tie(root, t));
86
87 for(auto iter = found.first; iter != found.second; ++iter) {
88 auto soa = std::dynamic_pointer_cast<SOARecordContent>(iter->d_content);
89 soaret = *iter;
90 return soa->d_st.serial;
91 }
92 return 0;
93}
94
95void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::string& directory)
96{
97 DNSRecord soa;
98 int serial = getSerialFromRecords(records, soa);
99 string fname=directory +"/"+std::to_string(serial);
100 FILE* fp=fopen((fname+".partial").c_str(), "w");
101 if(!fp)
102 throw runtime_error("Unable to open file '"+fname+".partial' for writing: "+string(strerror(errno)));
103
104 records_t soarecord;
105 soarecord.insert(soa);
106 fprintf(fp, "$ORIGIN %s\n", zone.toString().c_str());
107 for(const auto& outer : {soarecord, records, soarecord} ) {
108 for(const auto& r: outer) {
109 fprintf(fp, "%s\tIN\t%s\t%s\n",
110 r.d_name.isRoot() ? "@" : r.d_name.toStringNoDot().c_str(),
111 DNSRecordContent::NumberToType(r.d_type).c_str(),
112 r.d_content->getZoneRepresentation().c_str());
113 }
114 }
115 fclose(fp);
116 rename( (fname+".partial").c_str(), fname.c_str());
117}
118
119void loadZoneFromDisk(records_t& records, const string& fname, const DNSName& zone)
120{
121 ZoneParserTNG zpt(fname, zone);
122
123 DNSResourceRecord rr;
124 bool seenSOA=false;
125 unsigned int nrecords=0;
126 while(zpt.get(rr)) {
127 ++nrecords;
128 if(rr.qtype.getCode() == QType::CNAME && rr.content.empty())
129 rr.content=".";
130 rr.qname = rr.qname.makeRelative(zone);
131
132 if(rr.qtype.getCode() != QType::SOA || seenSOA==false)
133 records.insert(DNSRecord(rr));
134 if(rr.qtype.getCode() == QType::SOA) {
135 seenSOA=true;
136 }
137 }
138 cout<<"Parsed "<<nrecords<<" records"<<endl;
139 if(rr.qtype.getCode() == QType::SOA && seenSOA) {
140 cout<<"Zone was complete (SOA at end)"<<endl;
141 }
142 else {
143 records.clear();
144 throw runtime_error("Zone not complete!");
145 }
146}