| 1 | /* |
|---|
| 2 | PowerDNS Versatile Database Driven Nameserver |
|---|
| 3 | Copyright (C) 2003 - 2010 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 version 2 |
|---|
| 7 | as published by the Free Software Foundation |
|---|
| 8 | |
|---|
| 9 | This program is distributed in the hope that it will be useful, |
|---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | GNU General Public License for more details. |
|---|
| 13 | |
|---|
| 14 | You should have received a copy of the GNU General Public License |
|---|
| 15 | along with this program; if not, write to the Free Software |
|---|
| 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 17 | */ |
|---|
| 18 | |
|---|
| 19 | #include "syncres.hh" |
|---|
| 20 | #include "arguments.hh" |
|---|
| 21 | #include "zoneparser-tng.hh" |
|---|
| 22 | #include "logger.hh" |
|---|
| 23 | #include "dnsrecords.hh" |
|---|
| 24 | |
|---|
| 25 | void primeHints(void) |
|---|
| 26 | { |
|---|
| 27 | // prime root cache |
|---|
| 28 | set<DNSResourceRecord>nsset; |
|---|
| 29 | if(!t_RC) |
|---|
| 30 | t_RC = new MemRecursorCache(); |
|---|
| 31 | |
|---|
| 32 | if(::arg()["hint-file"].empty()) { |
|---|
| 33 | static const char*ips[]={"198.41.0.4", "192.228.79.201", "192.33.4.12", "128.8.10.90", "192.203.230.10", "192.5.5.241", |
|---|
| 34 | "192.112.36.4", "128.63.2.53", |
|---|
| 35 | "192.36.148.17","192.58.128.30", "193.0.14.129", "199.7.83.42", "202.12.27.33"}; |
|---|
| 36 | static const char *ip6s[]={ |
|---|
| 37 | "2001:503:ba3e::2:30", NULL, NULL, NULL, NULL, |
|---|
| 38 | "2001:500:2f::f", NULL, "2001:500:1::803f:235", NULL, |
|---|
| 39 | "2001:503:c27::2:30", "2001:7fd::1", "2001:500:3::42", "2001:dc3::35" |
|---|
| 40 | }; |
|---|
| 41 | |
|---|
| 42 | DNSResourceRecord arr, aaaarr, nsrr; |
|---|
| 43 | arr.qtype=QType::A; |
|---|
| 44 | aaaarr.qtype=QType::AAAA; |
|---|
| 45 | nsrr.qtype=QType::NS; |
|---|
| 46 | arr.ttl=aaaarr.ttl=nsrr.ttl=time(0)+3600000; |
|---|
| 47 | |
|---|
| 48 | for(char c='a';c<='m';++c) { |
|---|
| 49 | static char templ[40]; |
|---|
| 50 | strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1); |
|---|
| 51 | *templ=c; |
|---|
| 52 | aaaarr.qname=arr.qname=nsrr.content=templ; |
|---|
| 53 | arr.content=ips[c-'a']; |
|---|
| 54 | set<DNSResourceRecord> aset; |
|---|
| 55 | aset.insert(arr); |
|---|
| 56 | t_RC->replace(time(0), string(templ), QType(QType::A), aset, true); // auth, nuke it all |
|---|
| 57 | if (ip6s[c-'a'] != NULL) { |
|---|
| 58 | aaaarr.content=ip6s[c-'a']; |
|---|
| 59 | |
|---|
| 60 | set<DNSResourceRecord> aaaaset; |
|---|
| 61 | aaaaset.insert(aaaarr); |
|---|
| 62 | t_RC->replace(time(0), string(templ), QType(QType::AAAA), aaaaset, true); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | nsset.insert(nsrr); |
|---|
| 66 | } |
|---|
| 67 | } |
|---|
| 68 | else { |
|---|
| 69 | ZoneParserTNG zpt(::arg()["hint-file"]); |
|---|
| 70 | DNSResourceRecord rr; |
|---|
| 71 | |
|---|
| 72 | while(zpt.get(rr)) { |
|---|
| 73 | rr.ttl+=time(0); |
|---|
| 74 | if(rr.qtype.getCode()==QType::A) { |
|---|
| 75 | set<DNSResourceRecord> aset; |
|---|
| 76 | aset.insert(rr); |
|---|
| 77 | t_RC->replace(time(0), rr.qname, QType(QType::A), aset, true); // auth, etc see above |
|---|
| 78 | } else if(rr.qtype.getCode()==QType::AAAA) { |
|---|
| 79 | set<DNSResourceRecord> aaaaset; |
|---|
| 80 | aaaaset.insert(rr); |
|---|
| 81 | t_RC->replace(time(0), rr.qname, QType(QType::AAAA), aaaaset, true); |
|---|
| 82 | } else if(rr.qtype.getCode()==QType::NS) { |
|---|
| 83 | rr.content=toLower(rr.content); |
|---|
| 84 | nsset.insert(rr); |
|---|
| 85 | } |
|---|
| 86 | } |
|---|
| 87 | } |
|---|
| 88 | t_RC->replace(time(0),".", QType(QType::NS), nsset, true); // and stuff in the cache (auth) |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | static void makeNameToIPZone(SyncRes::domainmap_t* newMap, const string& hostname, const string& ip) |
|---|
| 92 | { |
|---|
| 93 | SyncRes::AuthDomain ad; |
|---|
| 94 | DNSResourceRecord rr; |
|---|
| 95 | rr.qname=toCanonic("", hostname); |
|---|
| 96 | rr.d_place=DNSResourceRecord::ANSWER; |
|---|
| 97 | rr.ttl=86400; |
|---|
| 98 | rr.qtype=QType::SOA; |
|---|
| 99 | rr.content="localhost. root 1 604800 86400 2419200 604800"; |
|---|
| 100 | |
|---|
| 101 | ad.d_records.insert(rr); |
|---|
| 102 | |
|---|
| 103 | rr.qtype=QType::NS; |
|---|
| 104 | rr.content="localhost."; |
|---|
| 105 | |
|---|
| 106 | ad.d_records.insert(rr); |
|---|
| 107 | |
|---|
| 108 | rr.qtype=QType::A; |
|---|
| 109 | rr.content=ip; |
|---|
| 110 | ad.d_records.insert(rr); |
|---|
| 111 | |
|---|
| 112 | if(newMap->count(rr.qname)) { |
|---|
| 113 | L<<Logger::Warning<<"Hosts file will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl; |
|---|
| 114 | } |
|---|
| 115 | else { |
|---|
| 116 | L<<Logger::Warning<<"Inserting forward zone '"<<rr.qname<<"' based on hosts file"<<endl; |
|---|
| 117 | (*newMap)[rr.qname]=ad; |
|---|
| 118 | } |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | //! parts[0] must be an IP address, the rest must be host names |
|---|
| 122 | static void makeIPToNamesZone(SyncRes::domainmap_t* newMap, const vector<string>& parts) |
|---|
| 123 | { |
|---|
| 124 | string address=parts[0]; |
|---|
| 125 | vector<string> ipparts; |
|---|
| 126 | stringtok(ipparts, address,"."); |
|---|
| 127 | |
|---|
| 128 | SyncRes::AuthDomain ad; |
|---|
| 129 | DNSResourceRecord rr; |
|---|
| 130 | for(int n=ipparts.size()-1; n>=0 ; --n) { |
|---|
| 131 | rr.qname.append(ipparts[n]); |
|---|
| 132 | rr.qname.append(1,'.'); |
|---|
| 133 | } |
|---|
| 134 | rr.qname.append("in-addr.arpa."); |
|---|
| 135 | |
|---|
| 136 | rr.d_place=DNSResourceRecord::ANSWER; |
|---|
| 137 | rr.ttl=86400; |
|---|
| 138 | rr.qtype=QType::SOA; |
|---|
| 139 | rr.content="localhost. root. 1 604800 86400 2419200 604800"; |
|---|
| 140 | |
|---|
| 141 | ad.d_records.insert(rr); |
|---|
| 142 | |
|---|
| 143 | rr.qtype=QType::NS; |
|---|
| 144 | rr.content="localhost."; |
|---|
| 145 | |
|---|
| 146 | ad.d_records.insert(rr); |
|---|
| 147 | rr.qtype=QType::PTR; |
|---|
| 148 | |
|---|
| 149 | if(ipparts.size()==4) // otherwise this is a partial zone |
|---|
| 150 | for(unsigned int n=1; n < parts.size(); ++n) { |
|---|
| 151 | rr.content=toCanonic("", parts[n]); |
|---|
| 152 | ad.d_records.insert(rr); |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | if(newMap->count(rr.qname)) { |
|---|
| 156 | L<<Logger::Warning<<"Will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl; |
|---|
| 157 | } |
|---|
| 158 | else { |
|---|
| 159 | if(ipparts.size()==4) |
|---|
| 160 | L<<Logger::Warning<<"Inserting reverse zone '"<<rr.qname<<"' based on hosts file"<<endl; |
|---|
| 161 | (*newMap)[rr.qname]=ad; |
|---|
| 162 | } |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | |
|---|
| 166 | |
|---|
| 167 | /* mission in life: parse three cases |
|---|
| 168 | 1) 1.2.3.4 |
|---|
| 169 | 2) 1.2.3.4:5300 |
|---|
| 170 | 3) 2001::1 |
|---|
| 171 | 4) [2002::1]:53 |
|---|
| 172 | */ |
|---|
| 173 | |
|---|
| 174 | ComboAddress parseIPAndPort(const std::string& input, uint16_t port) |
|---|
| 175 | { |
|---|
| 176 | if(input.find(':') == string::npos || input.empty()) // common case |
|---|
| 177 | return ComboAddress(input, port); |
|---|
| 178 | |
|---|
| 179 | pair<string,string> both; |
|---|
| 180 | |
|---|
| 181 | try { // case 2 |
|---|
| 182 | both=splitField(input,':'); |
|---|
| 183 | uint16_t newport=boost::lexical_cast<uint16_t>(both.second); |
|---|
| 184 | return ComboAddress(both.first, newport); |
|---|
| 185 | } |
|---|
| 186 | catch(...){} |
|---|
| 187 | |
|---|
| 188 | if(input[0]=='[') { // case 4 |
|---|
| 189 | both=splitField(input.substr(1),']'); |
|---|
| 190 | return ComboAddress(both.first, both.second.empty() ? port : boost::lexical_cast<uint16_t>(both.second.substr(1))); |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | return ComboAddress(input, port); // case 3 |
|---|
| 194 | } |
|---|
| 195 | |
|---|
| 196 | |
|---|
| 197 | void convertServersForAD(const std::string& input, SyncRes::AuthDomain& ad, const char* sepa, bool verbose=true) |
|---|
| 198 | { |
|---|
| 199 | vector<string> servers; |
|---|
| 200 | stringtok(servers, input, sepa); |
|---|
| 201 | ad.d_servers.clear(); |
|---|
| 202 | |
|---|
| 203 | for(vector<string>::const_iterator iter = servers.begin(); iter != servers.end(); ++iter) { |
|---|
| 204 | if(verbose && iter != servers.begin()) |
|---|
| 205 | L<<", "; |
|---|
| 206 | |
|---|
| 207 | ComboAddress addr=parseIPAndPort(*iter, 53); |
|---|
| 208 | if(verbose) |
|---|
| 209 | L<<addr.toStringWithPort(); |
|---|
| 210 | ad.d_servers.push_back(addr); |
|---|
| 211 | } |
|---|
| 212 | if(verbose) |
|---|
| 213 | L<<endl; |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | void* pleaseWipeCache(const std::string& qname) |
|---|
| 217 | { |
|---|
| 218 | t_RC->doWipeCache(qname); |
|---|
| 219 | return 0; |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | void* pleaseWipeNegCache() |
|---|
| 223 | { |
|---|
| 224 | t_sstorage->negcache.clear(); |
|---|
| 225 | return 0; |
|---|
| 226 | } |
|---|
| 227 | |
|---|
| 228 | void* pleaseUseNewSDomainsMap(SyncRes::domainmap_t* newmap) |
|---|
| 229 | { |
|---|
| 230 | t_sstorage->domainmap = newmap; |
|---|
| 231 | return 0; |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | string reloadAuthAndForwards() |
|---|
| 235 | { |
|---|
| 236 | SyncRes::domainmap_t* original=t_sstorage->domainmap; |
|---|
| 237 | |
|---|
| 238 | try { |
|---|
| 239 | L<<Logger::Warning<<"Reloading zones, purging data from cache"<<endl; |
|---|
| 240 | |
|---|
| 241 | for(SyncRes::domainmap_t::const_iterator i = t_sstorage->domainmap->begin(); i != t_sstorage->domainmap->end(); ++i) { |
|---|
| 242 | for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j) |
|---|
| 243 | broadcastFunction(boost::bind(pleaseWipeCache, j->qname)); |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | string configname=::arg()["config-dir"]+"/recursor.conf"; |
|---|
| 247 | cleanSlashes(configname); |
|---|
| 248 | |
|---|
| 249 | if(!::arg().preParseFile(configname.c_str(), "forward-zones")) |
|---|
| 250 | L<<Logger::Warning<<"Unable to re-parse configuration file '"<<configname<<"'"<<endl; |
|---|
| 251 | |
|---|
| 252 | ::arg().preParseFile(configname.c_str(), "forward-zones-file"); |
|---|
| 253 | ::arg().preParseFile(configname.c_str(), "auth-zones"); |
|---|
| 254 | ::arg().preParseFile(configname.c_str(), "export-etc-hosts", "off"); |
|---|
| 255 | ::arg().preParseFile(configname.c_str(), "serve-rfc1918"); |
|---|
| 256 | |
|---|
| 257 | SyncRes::domainmap_t* newDomainMap = parseAuthAndForwards(); |
|---|
| 258 | |
|---|
| 259 | // purge again - new zones need to blank out the cache |
|---|
| 260 | for(SyncRes::domainmap_t::const_iterator i = newDomainMap->begin(); i != newDomainMap->end(); ++i) { |
|---|
| 261 | for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j) |
|---|
| 262 | broadcastFunction(boost::bind(pleaseWipeCache, j->qname)); |
|---|
| 263 | } |
|---|
| 264 | |
|---|
| 265 | // this is pretty blunt |
|---|
| 266 | broadcastFunction(pleaseWipeNegCache); |
|---|
| 267 | broadcastFunction(boost::bind(pleaseUseNewSDomainsMap, newDomainMap)); |
|---|
| 268 | delete original; |
|---|
| 269 | return "ok\n"; |
|---|
| 270 | } |
|---|
| 271 | catch(std::exception& e) { |
|---|
| 272 | L<<Logger::Error<<"Had error reloading zones, keeping original data: "<<e.what()<<endl; |
|---|
| 273 | } |
|---|
| 274 | catch(AhuException& ae) { |
|---|
| 275 | L<<Logger::Error<<"Encountered error reloading zones, keeping original data: "<<ae.reason<<endl; |
|---|
| 276 | } |
|---|
| 277 | catch(...) { |
|---|
| 278 | L<<Logger::Error<<"Encountered unknown error reloading zones, keeping original data"<<endl; |
|---|
| 279 | } |
|---|
| 280 | return "reloading failed, see log\n"; |
|---|
| 281 | } |
|---|
| 282 | |
|---|
| 283 | SyncRes::domainmap_t* parseAuthAndForwards() |
|---|
| 284 | { |
|---|
| 285 | TXTRecordContent::report(); |
|---|
| 286 | OPTRecordContent::report(); |
|---|
| 287 | |
|---|
| 288 | SyncRes::domainmap_t* newMap = new SyncRes::domainmap_t(); |
|---|
| 289 | |
|---|
| 290 | typedef vector<string> parts_t; |
|---|
| 291 | parts_t parts; |
|---|
| 292 | const char *option_names[3]={"auth-zones", "forward-zones", "forward-zones-recurse"}; |
|---|
| 293 | for(int n=0; n < 3 ; ++n ) { |
|---|
| 294 | parts.clear(); |
|---|
| 295 | stringtok(parts, ::arg()[option_names[n]], ",\t\n\r"); |
|---|
| 296 | for(parts_t::const_iterator iter = parts.begin(); iter != parts.end(); ++iter) { |
|---|
| 297 | SyncRes::AuthDomain ad; |
|---|
| 298 | pair<string,string> headers=splitField(*iter, '='); |
|---|
| 299 | trim(headers.first); |
|---|
| 300 | trim(headers.second); |
|---|
| 301 | headers.first=toCanonic("", headers.first); |
|---|
| 302 | if(n==0) { |
|---|
| 303 | L<<Logger::Error<<"Parsing authoritative data for zone '"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl; |
|---|
| 304 | ZoneParserTNG zpt(headers.second, headers.first); |
|---|
| 305 | DNSResourceRecord rr; |
|---|
| 306 | while(zpt.get(rr)) { |
|---|
| 307 | try { |
|---|
| 308 | string tmp=DNSRR2String(rr); |
|---|
| 309 | rr=String2DNSRR(rr.qname, rr.qtype, tmp, rr.ttl); |
|---|
| 310 | } |
|---|
| 311 | catch(std::exception &e) { |
|---|
| 312 | delete newMap; |
|---|
| 313 | throw AhuException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"': "+e.what()); |
|---|
| 314 | } |
|---|
| 315 | catch(...) { |
|---|
| 316 | delete newMap; |
|---|
| 317 | throw AhuException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'"); |
|---|
| 318 | } |
|---|
| 319 | |
|---|
| 320 | ad.d_records.insert(rr); |
|---|
| 321 | } |
|---|
| 322 | } |
|---|
| 323 | else { |
|---|
| 324 | L<<Logger::Error<<"Redirecting queries for zone '"<<headers.first<<"' "; |
|---|
| 325 | if(n == 2) { |
|---|
| 326 | L<<"with recursion "; |
|---|
| 327 | ad.d_rdForward = 1; |
|---|
| 328 | } |
|---|
| 329 | else ad.d_rdForward = 0; |
|---|
| 330 | L<<"to: "; |
|---|
| 331 | |
|---|
| 332 | convertServersForAD(headers.second, ad, ";"); |
|---|
| 333 | if(n == 2) { |
|---|
| 334 | ad.d_rdForward = 1; |
|---|
| 335 | } |
|---|
| 336 | } |
|---|
| 337 | |
|---|
| 338 | (*newMap)[headers.first]=ad; |
|---|
| 339 | } |
|---|
| 340 | } |
|---|
| 341 | |
|---|
| 342 | if(!::arg()["forward-zones-file"].empty()) { |
|---|
| 343 | L<<Logger::Warning<<"Reading zone forwarding information from '"<<::arg()["forward-zones-file"]<<"'"<<endl; |
|---|
| 344 | SyncRes::AuthDomain ad; |
|---|
| 345 | FILE *rfp=fopen(::arg()["forward-zones-file"].c_str(), "r"); |
|---|
| 346 | |
|---|
| 347 | if(!rfp) { |
|---|
| 348 | delete newMap; |
|---|
| 349 | throw AhuException("Error opening forward-zones-file '"+::arg()["forward-zones-file"]+"': "+stringerror()); |
|---|
| 350 | } |
|---|
| 351 | |
|---|
| 352 | shared_ptr<FILE> fp=shared_ptr<FILE>(rfp, fclose); |
|---|
| 353 | |
|---|
| 354 | char line[1024]; |
|---|
| 355 | int linenum=0; |
|---|
| 356 | uint64_t before = newMap->size(); |
|---|
| 357 | while(linenum++, fgets(line, sizeof(line)-1, fp.get())) { |
|---|
| 358 | string domain, instructions; |
|---|
| 359 | tie(domain, instructions)=splitField(line, '='); |
|---|
| 360 | trim(domain); |
|---|
| 361 | trim(instructions); |
|---|
| 362 | if(domain.empty() && instructions.empty()) { // empty line |
|---|
| 363 | continue; |
|---|
| 364 | } |
|---|
| 365 | if(boost::starts_with(domain,"+")) { |
|---|
| 366 | domain=domain.c_str()+1; |
|---|
| 367 | ad.d_rdForward = true; |
|---|
| 368 | } |
|---|
| 369 | else |
|---|
| 370 | ad.d_rdForward = false; |
|---|
| 371 | if(domain.empty()) { |
|---|
| 372 | delete newMap; |
|---|
| 373 | throw AhuException("Error parsing line "+lexical_cast<string>(linenum)+" of " +::arg()["forward-zones-file"]); |
|---|
| 374 | } |
|---|
| 375 | |
|---|
| 376 | try { |
|---|
| 377 | convertServersForAD(instructions, ad, ",; ", false); |
|---|
| 378 | } |
|---|
| 379 | catch(...) { |
|---|
| 380 | delete newMap; |
|---|
| 381 | throw AhuException("Conversion error parsing line "+lexical_cast<string>(linenum)+" of " +::arg()["forward-zones-file"]); |
|---|
| 382 | } |
|---|
| 383 | |
|---|
| 384 | (*newMap)[toCanonic("", domain)]=ad; |
|---|
| 385 | } |
|---|
| 386 | L<<Logger::Warning<<"Done parsing " << newMap->size() - before<<" forwarding instructions from file '"<<::arg()["forward-zones-file"]<<"'"<<endl; |
|---|
| 387 | } |
|---|
| 388 | |
|---|
| 389 | if(::arg().mustDo("export-etc-hosts")) { |
|---|
| 390 | string line; |
|---|
| 391 | string fname=::arg()["etc-hosts-file"]; |
|---|
| 392 | |
|---|
| 393 | ifstream ifs(fname.c_str()); |
|---|
| 394 | if(!ifs) { |
|---|
| 395 | L<<Logger::Warning<<"Could not open /etc/hosts for reading"<<endl; |
|---|
| 396 | } |
|---|
| 397 | else { |
|---|
| 398 | string::size_type pos; |
|---|
| 399 | while(getline(ifs,line)) { |
|---|
| 400 | pos=line.find('#'); |
|---|
| 401 | if(pos!=string::npos) |
|---|
| 402 | line.resize(pos); |
|---|
| 403 | trim(line); |
|---|
| 404 | if(line.empty()) |
|---|
| 405 | continue; |
|---|
| 406 | parts.clear(); |
|---|
| 407 | stringtok(parts, line, "\t\r\n "); |
|---|
| 408 | if(parts[0].find(':')!=string::npos) |
|---|
| 409 | continue; |
|---|
| 410 | |
|---|
| 411 | for(unsigned int n=1; n < parts.size(); ++n) |
|---|
| 412 | makeNameToIPZone(newMap, parts[n], parts[0]); |
|---|
| 413 | makeIPToNamesZone(newMap, parts); |
|---|
| 414 | } |
|---|
| 415 | } |
|---|
| 416 | } |
|---|
| 417 | if(::arg().mustDo("serve-rfc1918")) { |
|---|
| 418 | L<<Logger::Warning<<"Inserting rfc 1918 private space zones"<<endl; |
|---|
| 419 | parts.clear(); |
|---|
| 420 | parts.push_back("127"); |
|---|
| 421 | makeIPToNamesZone(newMap, parts); |
|---|
| 422 | parts[0]="10"; |
|---|
| 423 | makeIPToNamesZone(newMap, parts); |
|---|
| 424 | |
|---|
| 425 | parts[0]="192.168"; |
|---|
| 426 | makeIPToNamesZone(newMap, parts); |
|---|
| 427 | for(int n=16; n < 32; n++) { |
|---|
| 428 | parts[0]="172."+lexical_cast<string>(n); |
|---|
| 429 | makeIPToNamesZone(newMap,parts); |
|---|
| 430 | } |
|---|
| 431 | } |
|---|
| 432 | return newMap; |
|---|
| 433 | } |
|---|
| 434 | |
|---|