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