]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/sdig.cc
4 #include "dnsparser.hh"
5 #include "ednsoptions.hh"
8 #include "dnswriter.hh"
9 #include "dnsrecords.hh"
11 #include <boost/array.hpp>
12 #include "ednssubnet.hh"
17 string
ttl(uint32_t ttl
)
22 return std::to_string(ttl
);
27 cerr
<<"Syntax: sdig IP-ADDRESS PORT QUESTION QUESTION-TYPE [dnssec] [recurse] [showflags] [hidesoadetails] [hidettl] [tcp] [ednssubnet SUBNET/MASK] [xpf XPFDATA]"<<endl
;
30 const string
nameForClass(uint16_t qclass
, uint16_t qtype
)
32 if (qtype
== QType::OPT
) return "IN";
35 case QClass::IN
: return "IN";
36 case QClass::CHAOS
: return "CHAOS";
37 case QClass::NONE
: return "NONE";
38 case QClass::ANY
: return "ANY";
39 default: return string("CLASS")+std::to_string(qclass
);
43 int main(int argc
, char** argv
)
50 bool hidesoadetails
=false;
51 boost::optional
<Netmask
> ednsnm
;
52 uint16_t xpfcode
= 0, xpfversion
= 0, xpfproto
= 0;
53 char *xpfsrc
= NULL
, *xpfdst
= NULL
;
55 for(int i
=1; i
<argc
; i
++) {
56 if ((string
) argv
[i
] == "--help") {
61 if ((string
) argv
[i
] == "--version") {
62 cerr
<<"sdig "<<VERSION
<<endl
;
75 for(int i
=5; i
<argc
; i
++) {
76 if (strcmp(argv
[i
], "dnssec") == 0)
78 if (strcmp(argv
[i
], "recurse") == 0)
80 if (strcmp(argv
[i
], "showflags") == 0)
82 if (strcmp(argv
[i
], "hidesoadetails") == 0)
84 if (strcmp(argv
[i
], "hidettl") == 0)
86 if (strcmp(argv
[i
], "tcp") == 0)
88 if (strcmp(argv
[i
], "ednssubnet") == 0) {
90 cerr
<<"ednssubnet needs an argument"<<endl
;
93 ednsnm
=Netmask(argv
[++i
]);
95 if (strcmp(argv
[i
], "xpf") == 0) {
97 cerr
<<"xpf needs five arguments"<<endl
;
100 xpfcode
= atoi(argv
[++i
]);
101 xpfversion
= atoi(argv
[++i
]);
102 xpfproto
= atoi(argv
[++i
]);
109 vector
<uint8_t> packet
;
111 DNSPacketWriter
pw(packet
, DNSName(argv
[3]), DNSRecordContent::TypeToNumber(argv
[4]));
113 if(dnssec
|| ednsnm
|| getenv("SDIGBUFSIZE"))
115 char *sbuf
=getenv("SDIGBUFSIZE");
121 DNSPacketWriter::optvect_t opts
;
125 opts
.push_back(make_pair(EDNSOptionCode::ECS
, makeEDNSSubnetOptsString(eo
)));
128 pw
.addOpt(bufsize
, 0, dnssec
? EDNSOpts::DNSSECOK
: 0, opts
);
134 ComboAddress
src(xpfsrc
), dst(xpfdst
);
135 pw
.startRecord(DNSName("."), xpfcode
, 0, 1, DNSResourceRecord::ADDITIONAL
);
136 // xpf->toPacket(pw);
137 pw
.xfr8BitInt(xpfversion
);
138 pw
.xfr8BitInt(xpfproto
);
139 pw
.xfrCAWithoutPort(xpfversion
, src
);
140 pw
.xfrCAWithoutPort(xpfversion
, dst
);
148 pw
.getHeader()->rd
=true;
152 ComboAddress
dest(argv
[1] + (*argv
[1]=='@'), atoi(argv
[2]));
155 Socket
sock(dest
.sin4
.sin_family
, SOCK_STREAM
);
158 len
= htons(packet
.size());
159 if(sock
.write((char *) &len
, 2) != 2)
160 throw PDNSException("tcp write failed");
162 sock
.writen(string(packet
.begin(), packet
.end()));
164 if(sock
.read((char *) &len
, 2) != 2)
165 throw PDNSException("tcp read failed");
168 char *creply
= new char[len
];
172 numread
=sock
.read(creply
+n
, len
-n
);
174 throw PDNSException("tcp read failed");
178 reply
=string(creply
, len
);
183 Socket
sock(dest
.sin4
.sin_family
, SOCK_DGRAM
);
184 sock
.sendTo(string(packet
.begin(), packet
.end()), dest
);
185 int result
=waitForData(sock
.getHandle(), 10);
187 throw std::runtime_error("Error waiting for data: "+string(strerror(errno
)));
189 throw std::runtime_error("Timeout waiting for data");
190 sock
.recvFrom(reply
, dest
);
192 MOADNSParser
mdp(false, reply
);
193 cout
<<"Reply to question for qname='"<<mdp
.d_qname
.toString()<<"', qtype="<<DNSRecordContent::NumberToType(mdp
.d_qtype
)<<endl
;
194 cout
<<"Rcode: "<<mdp
.d_header
.rcode
<<" ("<<RCode::to_s(mdp
.d_header
.rcode
)<<"), RD: "<<mdp
.d_header
.rd
<<", QR: "<<mdp
.d_header
.qr
;
195 cout
<<", TC: "<<mdp
.d_header
.tc
<<", AA: "<<mdp
.d_header
.aa
<<", opcode: "<<mdp
.d_header
.opcode
<<endl
;
197 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!=mdp
.d_answers
.end(); ++i
) {
198 cout
<<i
->first
.d_place
-1<<"\t"<<i
->first
.d_name
.toString()<<"\t"<<nameForClass(i
->first
.d_class
, i
->first
.d_type
)<<"\t"<<DNSRecordContent::NumberToType(i
->first
.d_type
);
199 if(i
->first
.d_class
== QClass::IN
)
201 if(i
->first
.d_type
== QType::RRSIG
)
203 string zoneRep
= i
->first
.d_content
->getZoneRepresentation();
204 vector
<string
> parts
;
205 stringtok(parts
, zoneRep
);
206 cout
<<"\t"<<ttl(i
->first
.d_ttl
)<<"\t"<< parts
[0]<<" "<<parts
[1]<<" "<<parts
[2]<<" "<<parts
[3]<<" [expiry] [inception] [keytag] "<<parts
[7]<<" ...\n";
209 if(!showflags
&& i
->first
.d_type
== QType::NSEC3
)
211 string zoneRep
= i
->first
.d_content
->getZoneRepresentation();
212 vector
<string
> parts
;
213 stringtok(parts
, zoneRep
);
214 cout
<<"\t"<<ttl(i
->first
.d_ttl
)<<"\t"<< parts
[0]<<" [flags] "<<parts
[2]<<" "<<parts
[3]<<" "<<parts
[4];
215 for(vector
<string
>::iterator iter
= parts
.begin()+5; iter
!= parts
.end(); ++iter
)
220 if(i
->first
.d_type
== QType::DNSKEY
)
222 string zoneRep
= i
->first
.d_content
->getZoneRepresentation();
223 vector
<string
> parts
;
224 stringtok(parts
, zoneRep
);
225 cout
<<"\t"<<ttl(i
->first
.d_ttl
)<<"\t"<< parts
[0]<<" "<<parts
[1]<<" "<<parts
[2]<<" ...\n";
228 if (i
->first
.d_type
== QType::SOA
&& hidesoadetails
)
230 string zoneRep
= i
->first
.d_content
->getZoneRepresentation();
231 vector
<string
> parts
;
232 stringtok(parts
, zoneRep
);
233 cout
<<"\t"<<ttl(i
->first
.d_ttl
)<<"\t"<<parts
[0]<<" "<<parts
[1]<<" [serial] "<<parts
[3]<<" "<<parts
[4]<<" "<<parts
[5]<<" "<<parts
[6]<<"\n";
237 cout
<<"\t"<<ttl(i
->first
.d_ttl
)<<"\t"<< i
->first
.d_content
->getZoneRepresentation()<<"\n";
241 if(getEDNSOpts(mdp
, &edo
)) {
242 // cerr<<"Have "<<edo.d_options.size()<<" options!"<<endl;
243 for(vector
<pair
<uint16_t, string
> >::const_iterator iter
= edo
.d_options
.begin();
244 iter
!= edo
.d_options
.end();
246 if(iter
->first
== EDNSOptionCode::ECS
) {// 'EDNS subnet'
248 if(getEDNSSubnetOptsFromString(iter
->second
, &reso
)) {
249 cerr
<<"EDNS Subnet response: "<<reso
.source
.toString()<<", scope: "<<reso
.scope
.toString()<<", family = "<<reso
.scope
.getNetwork().sin4
.sin_family
<<endl
;
252 else if(iter
->first
== EDNSOptionCode::PADDING
) {
253 cerr
<<"EDNS Padding size: "<<(iter
->second
.size())<<endl
;
256 cerr
<<"Have unknown option "<<(int)iter
->first
<<endl
;
262 catch(std::exception
&e
)
264 cerr
<<"Fatal: "<<e
.what()<<endl
;
266 catch(PDNSException
&e
)
268 cerr
<<"Fatal: "<<e
.reason
<<endl
;