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