]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/ixfr.cc
Merge pull request #3432 from rgacogne/dnsdist-split-tests
[thirdparty/pdns.git] / pdns / ixfr.cc
CommitLineData
39ec5d29 1#include "ixfr.hh"
2#include "sstuff.hh"
3#include "dns_random.hh"
4#include "dnsrecords.hh"
189f9579 5#include "dnssecinfra.hh"
39ec5d29 6
7eafc52f 7
8// if you the remove,add pairs always remove a SOA and add a new one. If you get an empty remove, it means you got an AXFR!
9vector<pair<vector<DNSRecord>, vector<DNSRecord> > > getIXFRDeltas(const ComboAddress& master, const DNSName& zone, const DNSRecord& oursr, const TSIGTriplet& tt)
39ec5d29 10{
11 vector<pair<vector<DNSRecord>, vector<DNSRecord> > > ret;
12 vector<uint8_t> packet;
13 DNSPacketWriter pw(packet, zone, QType::IXFR);
14 pw.getHeader()->qr=0;
15 pw.getHeader()->rd=0;
16 pw.getHeader()->id=dns_random(0xffff);
189f9579 17 pw.startRecord(zone, QType::SOA, 0, QClass::IN, DNSResourceRecord::AUTHORITY);
39ec5d29 18 oursr.d_content->toPacket(pw);
189f9579 19
39ec5d29 20 pw.commit();
98c9ec39 21 if(!tt.algo.empty()) {
189f9579 22 TSIGRecordContent trc;
98c9ec39 23 trc.d_algoName = tt.algo;
189f9579 24 trc.d_time = time((time_t*)NULL);
25 trc.d_fudge = 300;
26 trc.d_origID=ntohs(pw.getHeader()->id);
27 trc.d_eRcode=0;
98c9ec39 28 addTSIG(pw, &trc, tt.name, tt.secret, "", false);
189f9579 29 }
39ec5d29 30 uint16_t len=htons(packet.size());
31 string msg((const char*)&len, 2);
32 msg.append((const char*)&packet[0], packet.size());
33
34 Socket s(master.sin4.sin_family, SOCK_STREAM);
35 // cout<<"going to connect"<<endl;
36 s.connect(master);
37 // cout<<"Connected"<<endl;
38 s.writen(msg);
39
40 // CURRENT MASTER SOA
41 // REPEAT:
42 // SOA WHERE THIS DELTA STARTS
43 // RECORDS TO REMOVE
44 // SOA WHERE THIS DELTA GOES
45 // RECORDS TO ADD
46 // CURRENT MASTER SOA
47 shared_ptr<SOARecordContent> masterSOA;
48 vector<DNSRecord> records;
49 for(;;) {
50 if(s.read((char*)&len, 2)!=2)
51 break;
52 len=ntohs(len);
53 // cout<<"Got chunk of "<<len<<" bytes"<<endl;
54 if(!len)
55 break;
56 char reply[len];
57 readn2(s.getHandle(), reply, len);
58 MOADNSParser mdp(string(reply, len));
189f9579 59 if(mdp.d_header.rcode)
60 throw std::runtime_error("Got an error trying to IXFR zone '"+zone.toString()+"' from master '"+master.toStringWithPort()+"': "+RCode::to_s(mdp.d_header.rcode));
61
39ec5d29 62 // cout<<"Got a response, rcode: "<<mdp.d_header.rcode<<", got "<<mdp.d_answers.size()<<" answers"<<endl;
63 for(auto& r: mdp.d_answers) {
189f9579 64 if(r.first.d_type == QType::TSIG)
65 continue;
39ec5d29 66 // cout<<r.first.d_name<< " " <<r.first.d_content->getZoneRepresentation()<<endl;
67 r.first.d_name = r.first.d_name.makeRelative(zone);
68 records.push_back(r.first);
69 if(r.first.d_type == QType::SOA) {
70 auto sr = std::dynamic_pointer_cast<SOARecordContent>(r.first.d_content);
71 if(!masterSOA) {
72 if(sr->d_st.serial == std::dynamic_pointer_cast<SOARecordContent>(oursr.d_content)->d_st.serial) // we are up to date
73 goto done;
74 masterSOA=sr;
75
76 }
77 else if(sr->d_st.serial == masterSOA->d_st.serial)
78 goto done;
79
80 }
81 }
82 }
83 // cout<<"Got "<<records.size()<<" records"<<endl;
84 done:;
85 for(unsigned int pos = 1;pos < records.size();) {
86 auto sr = std::dynamic_pointer_cast<SOARecordContent>(records[pos].d_content);
7eafc52f 87 vector<DNSRecord> remove, add;
88 if(!sr) { // this is an actual AXFR!
89 return {{remove, records}};
90 }
39ec5d29 91 if(sr->d_st.serial == masterSOA->d_st.serial)
92 break;
93
7eafc52f 94
39ec5d29 95 remove.push_back(records[pos]); // this adds the SOA
96 for(pos++; pos < records.size() && records[pos].d_type != QType::SOA; ++pos) {
97 remove.push_back(records[pos]);
98 }
99 sr = std::dynamic_pointer_cast<SOARecordContent>(records[pos].d_content);
100
101 add.push_back(records[pos]); // this adds the new SOA
102 for(pos++; pos < records.size() && records[pos].d_type != QType::SOA; ++pos) {
103 add.push_back(records[pos]);
104 }
105 ret.push_back(make_pair(remove,add));
106 }
107 return ret;
108}