]>
Commit | Line | Data |
---|---|---|
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! | |
9 | vector<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 | } |