root/trunk/pdns/pdns/backends/bind/zone2sql.cc @ 155

Revision 155, 8.7 KB (checked in by ahu, 10 years ago)

work on zone2sql dot stripping
local-query-address

  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1/*
2    PowerDNS Versatile Database Driven Nameserver
3    Copyright (C) 2002  PowerDNS.COM BV
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18*/
19/* accepts a named.conf as parameter and outputs heaps of sql */
20
21// $Id: zone2sql.cc,v 1.6 2003/02/25 12:36:49 ahu Exp $
22#ifdef WIN32
23# pragma warning ( disable: 4786 )
24# include <unistd.h>
25#endif // WIN32
26
27#include <string>
28#include <map>
29
30#include <iostream>
31#include <stdio.h>
32
33using namespace std;
34
35#include "dns.hh"
36#include "arguments.hh"
37#include "zoneparser.hh"
38#include "bindparser.hh"
39#include "statbag.hh"
40#include "misc.hh"
41#include "dnspacket.hh"
42
43StatBag S;
44
45static const string sqlstr(const string &name)
46{
47  string a="\'";
48
49  for(string::const_iterator i=name.begin();i!=name.end();++i)
50    if(*i=='\'' || *i=='\\'){
51      a+='\\';
52      a+=*i;
53    }
54    else
55      a+=*i;
56  a+="\'";
57  return a;
58}
59
60static int dirty_hack_num;
61
62enum dbmode_t {MYSQL=0,ORACLE=1,BARE=2,POSTGRES=3};
63dbmode_t mode;
64bool g_intransaction;
65
66static int num_records;
67static string lastsoa_qname;
68
69static void callback(unsigned int domain_id,const string &domain, const string &qtype, const string &ocontent, int ttl, int prio)
70{
71  static int lastsoa_domain_id=-1;
72  string content(ocontent);
73
74  num_records++;
75
76  if(qtype=="SOA") {
77    //    cout<<"Juh: "<<dirty_hack_num<<", "<<lastsoa_domain_id<<", "<<lastsoa_qname<<", "<<domain<<endl;
78    if(dirty_hack_num==lastsoa_domain_id && lastsoa_qname!=domain) {
79      dirty_hack_num++;
80      cerr<<"Second SOA in zone, raised domain_id"<<endl;
81      if(mode==POSTGRES || mode==ORACLE) {
82        if(g_intransaction && arg().mustDo("transactions")) {
83          cout<<"COMMIT WORK;"<<endl;
84        }
85        if(arg().mustDo("transactions")) {
86          if(mode==POSTGRES)
87            cout<<"BEGIN TRANSACTION;"<<endl;
88          g_intransaction=1;
89        }
90       
91        if(mode==POSTGRES) {
92          cout<<"insert into domains (name,type) values ("<<toLower(sqlstr(ZoneParser::canonic(domain)))<<",'NATIVE');"<<endl;
93        }
94        else if(mode==ORACLE) {
95          cout<<"insert into domains (id,name,type) values (domains_id_sequence.nextval,"<<toLower(sqlstr(domain))<<",'NATIVE');"<<endl;
96        }
97      }
98    }
99    SOAData soadata;
100    DNSPacket::fillSOAData(content, soadata);
101    soadata.hostmaster=ZoneParser::canonic(soadata.hostmaster);
102    soadata.nameserver=ZoneParser::canonic(soadata.nameserver);
103    content=DNSPacket::serializeSOAData(soadata);
104
105
106    lastsoa_qname=ZoneParser::canonic(domain);
107  }
108 
109  lastsoa_domain_id=dirty_hack_num;
110
111  if(mode==MYSQL) {
112    cout<<"insert into records (domain_id, name,type,content,ttl,prio) values ("<< dirty_hack_num<<", "<<
113      sqlstr(ZoneParser::canonic(domain))<<", "<<
114      sqlstr(qtype)<<", "<<
115      sqlstr(ZoneParser::canonic(content))<<", "<<ttl<<", "<<prio<<");\n";
116  }
117  if(mode==POSTGRES) {
118    cout<<"insert into records (domain_id, name,type,content,ttl,prio) select id ,"<<
119      sqlstr(toLower(ZoneParser::canonic(domain)))<<", "<<
120      sqlstr(qtype)<<", "<<
121      sqlstr(ZoneParser::canonic(content))<<", "<<ttl<<", "<<prio<< 
122      " from domains where name="<<toLower(sqlstr(lastsoa_qname))<<";\n";
123  }
124  else if(mode==ORACLE) {
125    cout<<"insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,"<<
126      sqlstr(toLower(ZoneParser::canonic(domain)))<<", "<<
127      sqlstr(qtype)<<", "<<
128      sqlstr(ZoneParser::canonic(content))<<", "<<ttl<<", "<<prio<< 
129      " from Domains where name="<<toLower(sqlstr(lastsoa_qname))<<";\n";
130  }
131  else if(mode==BARE) {
132    cout<< dirty_hack_num<<"\t"<<
133      sqlstr(ZoneParser::canonic(domain))<<"\t"<<
134      sqlstr(qtype)<<"\t"<<sqlstr(ZoneParser::canonic(content))<<"\t"<<prio<<"\t"<<ttl<<"\n";
135  }
136
137}
138
139
140/* 2 modes of operation, either --named or --zone (the latter needs $ORIGIN)
141   2 further modes: --mysql or --oracle
142   and a parameter: --start-id
143*/
144
145ArgvMap &arg()
146{
147  static ArgvMap theArg;
148  return theArg;
149}
150
151
152int main(int argc, char **argv)
153{
154  try {
155#if __GNUC__ >= 3
156    ios_base::sync_with_stdio(false);
157#endif
158    lastsoa_qname=" ";
159    arg().setSwitch("mysql","Output in format suitable for mysqlbackend")="yes";
160    arg().setCmd("gpgsql","Output in format suitable for default gpgsqlbackend");
161    arg().setCmd("gmysql","Output in format suitable for default gmysqlbackend");
162    arg().setCmd("oracle","Output in format suitable for the oraclebackend");
163    arg().setCmd("bare","Output in a bare format, suitable for further parsing");
164    arg().setSwitch("verbose","Verbose comments on operation")="no";
165    arg().setSwitch("slave","Keep BIND slaves as slaves")="no";
166    arg().setSwitch("transactions","If target SQL supports it, use transactions")="no";
167    arg().setSwitch("on-error-resume-next","Continue after errors")="no";
168    arg().set("start-id","Value of first domain-id")="0";
169    arg().set("zone","Zonefile with $ORIGIN to parse")="";
170    arg().set("zone-name","Specify an $ORIGIN in case it is not present")="";
171    arg().set("named-conf","Bind 8 named.conf to parse")="";
172    arg().set("soa-minimum-ttl","Do not change")="0";
173
174    arg().setCmd("help","Provide a helpful message");
175
176    S.declare("logmessages");
177
178    string namedfile="";
179    string zonefile="";
180
181    arg().parse(argc, argv);
182 
183    if(argc<2 || arg().mustDo("help")) {
184      cerr<<"syntax:"<<endl<<endl;
185      cerr<<arg().helpstring()<<endl;
186      exit(1);
187    }
188 
189    if(arg().mustDo("mysql")) 
190      mode=MYSQL;
191    if(arg().mustDo("gpgsql") || arg().mustDo("gmysql"))
192      mode=POSTGRES;
193    if(arg().mustDo("bare"))
194      mode=BARE;
195    if(arg().mustDo("oracle")) {
196      mode=ORACLE;
197      if(!arg().mustDo("transactions"))
198        cout<<"set autocommit on;"<<endl;
199    }
200
201
202    dirty_hack_num=arg().asNum("start-id");
203    namedfile=arg()["named-conf"];
204    zonefile=arg()["zone"];
205
206    int count=0;
207
208    if(zonefile.empty()) {
209      BindParser BP;
210      BP.setVerbose(arg().mustDo("verbose"));
211      BP.parse(namedfile.empty() ? "./named.conf" : namedfile);
212   
213      ZoneParser ZP;
214   
215      const vector<BindDomainInfo> &domains=BP.getDomains();
216
217      int numdomains=domains.size();
218      int tick=numdomains/100;
219      ZP.setDirectory(BP.getDirectory());
220      ZP.setCallback(&callback); 
221   
222      for(vector<BindDomainInfo>::const_iterator i=domains.begin();
223          i!=domains.end();
224          ++i)
225        {
226          try {
227            if(mode==POSTGRES || mode==ORACLE) {
228              if(g_intransaction && arg().mustDo("transactions")) {
229                cout<<"COMMIT WORK;"<<endl;
230              }
231              if(arg().mustDo("transactions")) {
232                if(mode==POSTGRES)
233                  cout<<"BEGIN TRANSACTION;"<<endl;
234                g_intransaction=1;
235              }
236
237              if(mode==POSTGRES) {
238                if(arg().mustDo("slave")) {
239                  if(i->master.empty())
240                    cout<<"insert into domains (name,type) values ("<<sqlstr(i->name)<<",'NATIVE');"<<endl;
241                  else
242                    cout<<"insert into domains (name,type,master) values ("<<sqlstr(i->name)<<",'SLAVE'"<<", '"<<i->master<<"');"<<endl;
243                }
244                else
245                  cout<<"insert into domains (name,type) values ("<<sqlstr(i->name)<<",'NATIVE');"<<endl;
246              }
247              else if(mode==ORACLE) {
248                cout<<"insert into domains (id,name,type) values (domains_id_sequence.nextval,"<<toLower(sqlstr(i->name))<<",'NATIVE');"<<endl;
249              }
250              lastsoa_qname=i->name;
251            }
252            ZP.parse(i->filename,i->name,0);
253          }
254          catch(AhuException &ae) {
255            if(!arg().mustDo("on-error-resume-next"))
256              throw;
257            else
258              cerr<<ae.reason<<endl;
259          }
260
261          dirty_hack_num++;
262          if(!tick || !((count++)%tick))
263            cerr<<"\r"<<count*100/numdomains<<"% done ("<<i->filename<<")\033\133\113";
264        }
265      cerr<<"\r100% done\033\133\113"<<endl;
266    }
267    else {
268      dirty_hack_num=-1; // trigger first SOA output
269      ZoneParser ZP;
270      ZP.setDirectory(".");
271      ZP.setCallback(&callback); 
272      ZP.parse(zonefile,arg()["zone-name"],0);
273    }
274    cerr<<"Parsed "<<num_records<<" records"<<endl;
275   
276  }
277  catch(AhuException &ae) {
278    cerr<<"Fatal error: "<<ae.reason<<endl;
279    return 0;
280  }
281  catch(exception &e) {
282    cerr<<"died because of STL error: "<<e.what()<<endl;
283    exit(0);
284  }
285  catch(...) {
286    cerr<<"died because of unknown exception"<<endl;
287    exit(0);
288  }
289 
290  if((mode==POSTGRES || mode==ORACLE) && arg().mustDo("transactions") && g_intransaction)
291    cout<<"COMMIT WORK;"<<endl;
292  return 1;
293
294}
Note: See TracBrowser for help on using the browser.