]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/zone2json.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 /* accepts a named.conf or a zone as parameter and outputs heaps of sql */
34 #include "namespaces.hh"
37 #include "arguments.hh"
38 #include "bindparserclasses.hh"
41 #include "dnspacket.hh"
42 #include "zoneparser-tng.hh"
43 #include "dnsrecords.hh"
44 #include <boost/algorithm/string.hpp>
45 #include <sys/types.h>
51 using namespace json11
;
54 static int g_numRecords
;
56 static Json::object
emitRecord(const DNSName
&DNSqname
, const string
&qtype
, const string
&ocontent
, int ttl
)
61 string
content(ocontent
);
62 if(qtype
== "MX" || qtype
== "SRV") {
63 pdns::checked_stoi_into(prio
, content
);
65 string::size_type pos
= content
.find_first_not_of("0123456789");
66 if(pos
!= string::npos
)
67 boost::erase_head(content
, pos
);
68 boost::trim_left(content
);
73 dict
["name"] = DNSqname
.toString();
77 dict
["content"] = content
;
82 /* 2 modes of operation, either --named or --zone (the latter needs $ORIGIN)
83 1 further mode: --mysql
88 static ArgvMap theArg
;
93 int main(int argc
, char **argv
)
99 std::ios_base::sync_with_stdio(false);
101 ::arg().setSwitch("verbose","Verbose comments on operation")="no";
102 ::arg().setSwitch("on-error-resume-next","Continue after errors")="no";
103 ::arg().set("zone","Zonefile to parse")="";
104 ::arg().set("zone-name","Specify an $ORIGIN in case it is not present")="";
105 ::arg().set("named-conf","Bind 8/9 named.conf to parse")="";
106 ::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
107 ::arg().set("max-include-depth", "Maximum level of nested $INCLUDE depth when loading a zone from a file")="20";
109 ::arg().setCmd("help","Provide a helpful message");
110 ::arg().setCmd("version","Print the version");
112 S
.declare("logmessages");
117 ::arg().parse(argc
, argv
);
119 if(::arg().mustDo("version")){
120 cerr
<<"zone2json "<<VERSION
<<endl
;
124 if(::arg().mustDo("help")) {
125 cout
<<"syntax:"<<endl
<<endl
;
126 cout
<<::arg().helpstring()<<endl
;
131 cerr
<<"syntax:"<<endl
<<endl
;
132 cerr
<<::arg().helpstring()<<endl
;
136 namedfile
=::arg()["named-conf"];
137 zonefile
=::arg()["zone"];
139 int count
=0, num_domainsdone
=0;
141 if(zonefile
.empty()) {
143 BP
.setVerbose(::arg().mustDo("verbose"));
144 BP
.parse(namedfile
.empty() ? "./named.conf" : namedfile
);
146 vector
<BindDomainInfo
> domains
=BP
.getDomains();
148 for(auto & domain
: domains
) {
149 if(stat(domain
.filename
.c_str(), &st
) == 0) {
150 domain
.d_dev
= st
.st_dev
;
151 domain
.d_ino
= st
.st_ino
;
155 sort(domains
.begin(), domains
.end()); // put stuff in inode order
157 int numdomains
=domains
.size();
158 int tick
=numdomains
/100;
161 for(vector
<BindDomainInfo
>::const_iterator i
=domains
.begin();
165 if (i
->type
!= "primary" && i
->type
!= "secondary" && !i
->type
.empty() && i
->type
!= "master" && i
->type
!= "slave") {
166 cerr
<< " Warning! Skipping '" << i
->type
<< "' zone '" << i
->name
<< "'" << endl
;
173 ZoneParserTNG
zpt(i
->filename
, i
->name
, BP
.getDirectory());
174 zpt
.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
175 zpt
.setMaxIncludes(::arg().asNum("max-include-depth"));
176 DNSResourceRecord rr
;
177 obj
["name"] = i
->name
.toString();
180 recs
.push_back(emitRecord(rr
.qname
, rr
.qtype
.toString(), rr
.content
, rr
.ttl
));
181 obj
["records"] = recs
;
184 if(i
+1 < domains
.end()) cout
<<",";
187 catch(std::exception
&ae
) {
188 if(!::arg().mustDo("on-error-resume-next"))
191 cerr
<<endl
<<ae
.what()<<endl
;
193 catch(PDNSException
&ae
) {
194 if(!::arg().mustDo("on-error-resume-next"))
197 cerr
<<ae
.reason
<<endl
;
199 if(!tick
|| !((count
++)%tick
))
200 cerr
<<"\r"<<count
*100/numdomains
<<"% done ("<<i
->filename
<<")\033\133\113";
203 cerr
<<"\r100% done\033\133\113"<<endl
;
206 ZoneParserTNG
zpt(zonefile
, DNSName(::arg()["zone-name"]));
207 zpt
.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
208 DNSResourceRecord rr
;
213 obj
["name"] = ::arg()["zone-name"];
216 records
.push_back(emitRecord(rr
.qname
, rr
.qtype
.toString(), rr
.content
, rr
.ttl
));
217 obj
["records"] = records
;
221 cout
<<tmp
.dump()<<endl
;
225 cerr
<<num_domainsdone
<<" domains were fully parsed, containing "<<g_numRecords
<<" records\n";
230 catch(PDNSException
&ae
) {
231 cerr
<<"\nFatal error: "<<ae
.reason
<<endl
;
234 catch(std::exception
&e
) {
235 cerr
<<"\ndied because of STL error: "<<e
.what()<<endl
;
239 cerr
<<"\ndied because of unknown exception"<<endl
;