]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/sdig.cc
Add ixplore manpage to docs website
[thirdparty/pdns.git] / pdns / sdig.cc
CommitLineData
870a0fe4
AT
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
ff6a1e7b
BH
4#include "dnsparser.hh"
5#include "sstuff.hh"
6#include "misc.hh"
a0a276c2
BH
7#include "dnswriter.hh"
8#include "dnsrecords.hh"
b0d4fb45 9#include "statbag.hh"
c5c4fbdc 10#include <boost/array.hpp>
a7d9ffb3 11#include "ednssubnet.hh"
b0d4fb45 12StatBag S;
ff6a1e7b 13
6e4c4a26
PD
14bool hidettl=false;
15
16string ttl(uint32_t ttl)
17{
18 if(hidettl)
19 return "[ttl]";
20 else
21 return std::to_string(ttl);
22}
23
ff6a1e7b
BH
24int main(int argc, char** argv)
25try
26{
ee6c3a6b 27 bool dnssec=false;
b97043ee 28 bool recurse=false;
c5c4fbdc 29 bool tcp=false;
b8adb30d 30 bool showflags=false;
b19ad29b 31 bool hidesoadetails=false;
a7d9ffb3 32 boost::optional<Netmask> ednsnm;
ee6c3a6b 33
b0d4fb45 34 reportAllTypes();
a0a276c2 35
ee6c3a6b 36 if(argc < 5) {
6e4c4a26 37 cerr<<"Syntax: sdig IP-address port question question-type [dnssec] [recurse] [showflags] [hidesoadetails] [hidettl] [tcp] [ednssubnet SUBNET]\n";
a8ad4624
BH
38 exit(EXIT_FAILURE);
39 }
a0a276c2 40
b19ad29b
RA
41 if (argc > 5) {
42 for(int i=5; i<argc; i++) {
43 if (strcmp(argv[i], "dnssec") == 0)
44 dnssec=true;
45 if (strcmp(argv[i], "recurse") == 0)
46 recurse=true;
b0d6eced
KM
47 if (strcmp(argv[i], "showflags") == 0)
48 showflags=true;
b19ad29b
RA
49 if (strcmp(argv[i], "hidesoadetails") == 0)
50 hidesoadetails=true;
6e4c4a26
PD
51 if (strcmp(argv[i], "hidettl") == 0)
52 hidettl=true;
54baf8be 53 if (strcmp(argv[i], "tcp") == 0)
54 tcp=true;
a7d9ffb3 55 if (strcmp(argv[i], "ednssubnet") == 0) {
76060dd7 56 ednsnm=Netmask(argv[++i]);
b19ad29b
RA
57 }
58 }
b97043ee
PD
59 }
60
a0a276c2 61 vector<uint8_t> packet;
bca6643b 62
eaedd091 63 DNSPacketWriter pw(packet, DNSName(argv[3]), DNSRecordContent::TypeToNumber(argv[4]));
a0a276c2 64
a7d9ffb3 65 if(dnssec || ednsnm || getenv("SDIGBUFSIZE"))
ee6c3a6b 66 {
794c2f92
PD
67 char *sbuf=getenv("SDIGBUFSIZE");
68 int bufsize;
69 if(sbuf)
70 bufsize=atoi(sbuf);
71 else
72 bufsize=2800;
a7d9ffb3 73 DNSPacketWriter::optvect_t opts;
74 if(ednsnm) {
a7d9ffb3 75 EDNSSubnetOpts eo;
76 eo.source = *ednsnm;
77 opts.push_back(make_pair(8, makeEDNSSubnetOptsString(eo)));
78 }
79
80 pw.addOpt(bufsize, 0, dnssec ? EDNSOpts::DNSSECOK : 0, opts);
ee6c3a6b
PD
81 pw.commit();
82 }
b97043ee
PD
83
84 if(recurse)
85 {
86 pw.getHeader()->rd=true;
87 }
fdf05fd4 88
ff6a1e7b 89 string reply;
4a549837 90 ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2]));
ff6a1e7b 91
c5c4fbdc 92 if(tcp) {
4a549837 93 Socket sock(dest.sin4.sin_family, SOCK_STREAM);
c5c4fbdc
PD
94 sock.connect(dest);
95 uint16_t len;
96 len = htons(packet.size());
97 if(sock.write((char *) &len, 2) != 2)
3f81d239 98 throw PDNSException("tcp write failed");
c5c4fbdc
PD
99
100 sock.writen(string((char*)&*packet.begin(), (char*)&*packet.end()));
101
102 if(sock.read((char *) &len, 2) != 2)
3f81d239 103 throw PDNSException("tcp read failed");
c5c4fbdc
PD
104
105 len=ntohs(len);
106 char *creply = new char[len];
107 int n=0;
108 int numread;
109 while(n<len) {
110 numread=sock.read(creply+n, len-n);
111 if(numread<0)
3f81d239 112 throw PDNSException("tcp read failed");
c5c4fbdc
PD
113 n+=numread;
114 }
115
116 reply=string(creply, len);
117 delete[] creply;
118 }
119 else //udp
120 {
4a549837 121 Socket sock(dest.sin4.sin_family, SOCK_DGRAM);
c5c4fbdc 122 sock.sendTo(string((char*)&*packet.begin(), (char*)&*packet.end()), dest);
fbf18d75 123 int result=waitForData(sock.getHandle(), 10);
124 if(result < 0)
125 throw std::runtime_error("Error waiting for data: "+string(strerror(errno)));
126 if(!result)
127 throw std::runtime_error("Timeout waiting for data");
c5c4fbdc
PD
128 sock.recvFrom(reply, dest);
129 }
ff6a1e7b 130 MOADNSParser mdp(reply);
9d7fa327 131 cout<<"Reply to question for qname='"<<mdp.d_qname.toString()<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
a7d9ffb3 132 cout<<"Rcode: "<<mdp.d_header.rcode<<" ("<<RCode::to_s(mdp.d_header.rcode)<<"), RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
7fc69fd0 133 cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
945a9ad4 134
ff6a1e7b 135 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
f809c028 136 cout<<i->first.d_place-1<<"\t"<<i->first.d_name.toString()<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
794c2f92
PD
137 if(i->first.d_type == QType::RRSIG)
138 {
139 string zoneRep = i->first.d_content->getZoneRepresentation();
140 vector<string> parts;
141 stringtok(parts, zoneRep);
6e4c4a26 142 cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< parts[0]<<" "<<parts[1]<<" "<<parts[2]<<" "<<parts[3]<<" [expiry] [inception] [keytag] "<<parts[7]<<" ...\n";
794c2f92 143 }
b8adb30d
KM
144 else if(!showflags && i->first.d_type == QType::NSEC3)
145 {
146 string zoneRep = i->first.d_content->getZoneRepresentation();
147 vector<string> parts;
148 stringtok(parts, zoneRep);
6e4c4a26 149 cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< parts[0]<<" [flags] "<<parts[2]<<" "<<parts[3]<<" "<<parts[4];
b8adb30d
KM
150 for(vector<string>::iterator iter = parts.begin()+5; iter != parts.end(); ++iter)
151 cout<<" "<<*iter;
152 cout<<"\n";
153 }
794c2f92
PD
154 else if(i->first.d_type == QType::DNSKEY)
155 {
156 string zoneRep = i->first.d_content->getZoneRepresentation();
157 vector<string> parts;
158 stringtok(parts, zoneRep);
6e4c4a26 159 cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< parts[0]<<" "<<parts[1]<<" "<<parts[2]<<" ...\n";
794c2f92 160 }
b19ad29b
RA
161 else if (i->first.d_type == QType::SOA && hidesoadetails)
162 {
163 string zoneRep = i->first.d_content->getZoneRepresentation();
164 vector<string> parts;
165 stringtok(parts, zoneRep);
6e4c4a26 166 cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<<parts[0]<<" "<<parts[1]<<" [serial] "<<parts[3]<<" "<<parts[4]<<" "<<parts[5]<<" "<<parts[6]<<"\n";
b19ad29b 167 }
794c2f92
PD
168 else
169 {
6e4c4a26 170 cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n";
794c2f92
PD
171 }
172
ff6a1e7b 173 }
fdf05fd4 174
0c70797e
BH
175 EDNSOpts edo;
176 if(getEDNSOpts(mdp, &edo)) {
a5d9f5f9 177// cerr<<"Have "<<edo.d_options.size()<<" options!"<<endl;
0c70797e 178 for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin();
4957a608
BH
179 iter != edo.d_options.end();
180 ++iter) {
fdf05fd4 181 if(iter->first == 5) {// 'EDNS PING'
4957a608 182 cerr<<"Have ednsping: '"<<iter->second<<"'\n";
a5d9f5f9
BH
183 //if(iter->second == ping)
184 // cerr<<"It is correct!"<<endl;
0c70797e 185 }
a7d9ffb3 186 if(iter->first == 8) {// 'EDNS subnet'
187 EDNSSubnetOpts reso;
188 if(getEDNSSubnetOptsFromString(iter->second, &reso)) {
189 cerr<<"EDNS Subnet response: "<<reso.source.toString()<<", scope: "<<reso.scope.toString()<<", family = "<<reso.scope.getNetwork().sin4.sin_family<<endl;
190 }
191 }
192
fdf05fd4 193 else {
4957a608 194 cerr<<"Have unknown option "<<(int)iter->first<<endl;
fdf05fd4 195 }
0c70797e
BH
196 }
197
198 }
ff6a1e7b 199}
0c70797e 200catch(std::exception &e)
ff6a1e7b
BH
201{
202 cerr<<"Fatal: "<<e.what()<<endl;
203}
1a4843e0 204catch(PDNSException &e)
205{
206 cerr<<"Fatal: "<<e.reason<<endl;
207}