| 431 | | void primeHints(void) |
| 432 | | { |
| 433 | | // prime root cache |
| 434 | | set<DNSResourceRecord>nsset; |
| 435 | | #if 0 |
| 436 | | { |
| 437 | | time_t now = time(0); |
| 438 | | |
| 439 | | string templ; |
| 440 | | DNSResourceRecord arr; |
| 441 | | |
| 442 | | arr.qtype=QType::AAAA; |
| 443 | | arr.ttl=now+3600; |
| 444 | | arr.content="::1"; |
| 445 | | |
| 446 | | DTime dt; |
| 447 | | dt.set(); |
| 448 | | for(int n = 0 ; n < 500000; ++n) { |
| 449 | | set<DNSResourceRecord> aset; |
| 450 | | arr.qname=templ="blah"+lexical_cast<string>(n)+".testdomain.com"; |
| 451 | | aset.insert(arr); |
| 452 | | RC.replace(now, templ, QType(QType::AAAA), aset, true); // auth, nuke it all |
| 453 | | } |
| 454 | | cerr<<"fill1 secs: "<<dt.udiff()/1000000.0<<endl; |
| 455 | | |
| 456 | | arr.content="::2"; |
| 457 | | dt.set(); |
| 458 | | for(int n = 0 ; n < 500000; ++n) { |
| 459 | | set<DNSResourceRecord> aset; |
| 460 | | arr.qname=templ="blah"+lexical_cast<string>(n)+".testdomain.com"; |
| 461 | | aset.insert(arr); |
| 462 | | RC.replace(now, templ, QType(QType::AAAA), aset, true); // auth, nuke it all |
| 463 | | } |
| 464 | | cerr<<"refill secs: "<<dt.udiff()/1000000.0<<endl; |
| 465 | | |
| 466 | | |
| 467 | | dt.set(); |
| 468 | | for(int n = 0 ; n < 500000; ++n) { |
| 469 | | set<DNSResourceRecord> aset; |
| 470 | | templ="blah"+lexical_cast<string>(n)+".testdomain.com"; |
| 471 | | RC.get(now, templ, QType(QType::AAAA), &aset); // auth, nuke it all |
| 472 | | } |
| 473 | | cerr<<"get secs: "<<dt.udiff()/1000000.0<<endl; |
| 474 | | vector<string> names; |
| 475 | | for(int n = 0 ; n < 500000; ++n) { |
| 476 | | templ="blah"+lexical_cast<string>(n)+".testdomain.com"; |
| 477 | | names.push_back(templ); |
| 478 | | } |
| 479 | | random_shuffle(names.begin(), names.end()); |
| 480 | | cerr<<"go!"<<endl; |
| 481 | | dt.set(); |
| 482 | | for(int n = 0 ; n < 500000; ++n) { |
| 483 | | vector<DNSResourceRecord> avect; |
| 484 | | RC.get2(now, names[n], QType(QType::AAAA), &avect); // auth, nuke it all |
| 485 | | } |
| 486 | | cerr<<"get2 secs: "<<dt.udiff()/1000000.0<<endl; |
| 487 | | |
| 488 | | // exit(1); |
| 489 | | } |
| 490 | | #endif |
| 491 | | |
| 492 | | if(::arg()["hint-file"].empty()) { |
| 493 | | 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", |
| 494 | | "192.112.36.4", "128.63.2.53", |
| 495 | | "192.36.148.17","192.58.128.30", "193.0.14.129", "199.7.83.42", "202.12.27.33"}; |
| 496 | | static const char *ip6s[]={ |
| 497 | | "2001:503:ba3e::2:30", NULL, NULL, NULL, NULL, |
| 498 | | "2001:500:2f::f", NULL, "2001:500:1::803f:235", NULL, |
| 499 | | "2001:503:c27::2:30", NULL, NULL, NULL |
| 500 | | }; |
| 501 | | DNSResourceRecord arr, aaaarr, nsrr; |
| 502 | | arr.qtype=QType::A; |
| 503 | | aaaarr.qtype=QType::AAAA; |
| 504 | | nsrr.qtype=QType::NS; |
| 505 | | arr.ttl=aaaarr.ttl=nsrr.ttl=time(0)+3600000; |
| 506 | | |
| 507 | | for(char c='a';c<='m';++c) { |
| 508 | | static char templ[40]; |
| 509 | | strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1); |
| 510 | | *templ=c; |
| 511 | | aaaarr.qname=arr.qname=nsrr.content=templ; |
| 512 | | arr.content=ips[c-'a']; |
| 513 | | set<DNSResourceRecord> aset; |
| 514 | | aset.insert(arr); |
| 515 | | RC.replace(time(0), string(templ), QType(QType::A), aset, true); // auth, nuke it all |
| 516 | | if (ip6s[c-'a'] != NULL) { |
| 517 | | aaaarr.content=ip6s[c-'a']; |
| 518 | | |
| 519 | | set<DNSResourceRecord> aaaaset; |
| 520 | | aaaaset.insert(aaaarr); |
| 521 | | RC.replace(time(0), string(templ), QType(QType::AAAA), aaaaset, true); |
| 522 | | } |
| 523 | | |
| 524 | | nsset.insert(nsrr); |
| 525 | | } |
| 526 | | } |
| 527 | | else { |
| 528 | | ZoneParserTNG zpt(::arg()["hint-file"]); |
| 529 | | DNSResourceRecord rr; |
| 530 | | |
| 531 | | while(zpt.get(rr)) { |
| 532 | | rr.ttl+=time(0); |
| 533 | | if(rr.qtype.getCode()==QType::A) { |
| 534 | | set<DNSResourceRecord> aset; |
| 535 | | aset.insert(rr); |
| 536 | | RC.replace(time(0), rr.qname, QType(QType::A), aset, true); // auth, etc see above |
| 537 | | } else if(rr.qtype.getCode()==QType::AAAA) { |
| 538 | | set<DNSResourceRecord> aaaaset; |
| 539 | | aaaaset.insert(rr); |
| 540 | | RC.replace(time(0), rr.qname, QType(QType::AAAA), aaaaset, true); |
| 541 | | } else if(rr.qtype.getCode()==QType::NS) { |
| 542 | | rr.content=toLower(rr.content); |
| 543 | | nsset.insert(rr); |
| 544 | | } |
| 545 | | } |
| 546 | | } |
| 547 | | RC.replace(time(0),".", QType(QType::NS), nsset, true); // and stuff in the cache (auth) |
| 548 | | } |
| 1106 | | if(g_stats.qcounter && (RC.cacheHits + RC.cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) { |
| 1107 | | //L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<RC.size()<<" cache entries, "<<SyncRes::s_negcache.size()<<" negative entries, " |
| 1108 | | L<<Logger::Warning<<"stats: " <<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits"<<endl; |
| 1109 | | // L<<Logger::Warning<<"stats: throttle map: "<<SyncRes::s_throttle.size()<<", ns speeds: " |
| 1110 | | // <<endl; // <<SyncRes::s_nsSpeeds.size()<<endl; // ", bytes: "<<RC.bytes()<<endl; |
| | 988 | if(g_stats.qcounter && (t_RC->cacheHits + t_RC->cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) { // RC FIXME |
| | 989 | L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<t_RC->size()<<" cache entries, "<<SyncRes::t_sstorage->negcache.size()<<" negative entries, " << endl;// NEGCACHE MULTI FIXME |
| | 990 | L<<Logger::Warning<<"stats: " <<(int)((t_RC->cacheHits*100.0)/(t_RC->cacheHits+t_RC->cacheMisses))<<"% cache hits"<<endl; // RC MULTI FIXME |
| | 991 | L<<Logger::Warning<<"stats: throttle map: "<<SyncRes::t_sstorage->throttle.size()<<", ns speeds: " |
| | 992 | <<SyncRes::t_sstorage->nsSpeeds.size()<<endl; // FIXME NSSPEEDS MULTI |
| | 1061 | void makeThreadPipes() |
| | 1062 | { |
| | 1063 | int numThreads = ::arg().asNum("threads"); |
| | 1064 | for(int n=0; n < numThreads; ++n) { |
| | 1065 | struct ThreadPipeSet tps; |
| | 1066 | int fd[2]; |
| | 1067 | if(pipe(fd) < 0) |
| | 1068 | unixDie("Creating pipe for inter-thread communications"); |
| | 1069 | |
| | 1070 | tps.readToThread = fd[0]; |
| | 1071 | tps.writeToThread = fd[1]; |
| | 1072 | |
| | 1073 | if(pipe(fd) < 0) |
| | 1074 | unixDie("Creating pipe for inter-thread communications"); |
| | 1075 | tps.readFromThread = fd[0]; |
| | 1076 | tps.writeFromThread = fd[1]; |
| | 1077 | |
| | 1078 | g_pipes.push_back(tps); |
| | 1079 | } |
| | 1080 | } |
| | 1081 | |
| | 1082 | void broadcastFunction(const pipefunc_t& func, bool skipSelf) |
| | 1083 | { |
| | 1084 | typedef pair<int, int> fdss_t; |
| | 1085 | |
| | 1086 | unsigned int n = 0; |
| | 1087 | BOOST_FOREACH(ThreadPipeSet& tps, g_pipes) |
| | 1088 | { |
| | 1089 | if(n++ == t_id) { |
| | 1090 | if(!skipSelf) |
| | 1091 | func(); // don't write to ourselves! |
| | 1092 | continue; |
| | 1093 | } |
| | 1094 | |
| | 1095 | pipefunc_t *funcptr = new pipefunc_t(func); |
| | 1096 | if(write(tps.writeToThread, &funcptr, sizeof(funcptr)) != sizeof(funcptr)) |
| | 1097 | unixDie("write to thread pipe returned wrong size or error"); |
| | 1098 | |
| | 1099 | string* resp; |
| | 1100 | if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp)) |
| | 1101 | unixDie("read from thread pipe returned wrong size or error"); |
| | 1102 | |
| | 1103 | if(resp) { |
| | 1104 | // cerr <<"got response: " << *resp << endl; |
| | 1105 | delete resp; |
| | 1106 | } |
| | 1107 | } |
| | 1108 | } |
| | 1109 | |
| | 1110 | void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var) |
| | 1111 | { |
| | 1112 | pipefunc_t* func; |
| | 1113 | if(read(fd, &func, sizeof(func)) != sizeof(func)) { // fd == readToThread |
| | 1114 | unixDie("read from thread pipe returned wrong size or error"); |
| | 1115 | } |
| | 1116 | (*func)(); |
| | 1117 | string* ptr = new string("ok"); |
| | 1118 | if(write(g_pipes[t_id].writeFromThread, &ptr, sizeof(ptr)) != sizeof(ptr)) |
| | 1119 | unixDie("write to thread pipe returned wrong size or error"); |
| | 1120 | |
| | 1121 | delete func; |
| | 1122 | } |
| 1383 | | static void makeNameToIPZone(const string& hostname, const string& ip) |
| 1384 | | { |
| 1385 | | SyncRes::AuthDomain ad; |
| 1386 | | DNSResourceRecord rr; |
| 1387 | | rr.qname=toCanonic("", hostname); |
| 1388 | | rr.d_place=DNSResourceRecord::ANSWER; |
| 1389 | | rr.ttl=86400; |
| 1390 | | rr.qtype=QType::SOA; |
| 1391 | | rr.content="localhost. root 1 604800 86400 2419200 604800"; |
| 1392 | | |
| 1393 | | ad.d_records.insert(rr); |
| 1394 | | |
| 1395 | | rr.qtype=QType::NS; |
| 1396 | | rr.content="localhost."; |
| 1397 | | |
| 1398 | | ad.d_records.insert(rr); |
| 1399 | | |
| 1400 | | rr.qtype=QType::A; |
| 1401 | | rr.content=ip; |
| 1402 | | ad.d_records.insert(rr); |
| 1403 | | |
| 1404 | | if(SyncRes::s_domainmap.count(rr.qname)) { |
| 1405 | | L<<Logger::Warning<<"Hosts file will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl; |
| 1406 | | } |
| 1407 | | else { |
| 1408 | | L<<Logger::Warning<<"Inserting forward zone '"<<rr.qname<<"' based on hosts file"<<endl; |
| 1409 | | SyncRes::s_domainmap[rr.qname]=ad; |
| 1410 | | } |
| 1411 | | } |
| 1412 | | |
| 1413 | | //! parts[0] must be an IP address, the rest must be host names |
| 1414 | | static void makeIPToNamesZone(const vector<string>& parts) |
| 1415 | | { |
| 1416 | | string address=parts[0]; |
| 1417 | | vector<string> ipparts; |
| 1418 | | stringtok(ipparts, address,"."); |
| 1419 | | |
| 1420 | | SyncRes::AuthDomain ad; |
| 1421 | | DNSResourceRecord rr; |
| 1422 | | for(int n=ipparts.size()-1; n>=0 ; --n) { |
| 1423 | | rr.qname.append(ipparts[n]); |
| 1424 | | rr.qname.append(1,'.'); |
| 1425 | | } |
| 1426 | | rr.qname.append("in-addr.arpa."); |
| 1427 | | |
| 1428 | | rr.d_place=DNSResourceRecord::ANSWER; |
| 1429 | | rr.ttl=86400; |
| 1430 | | rr.qtype=QType::SOA; |
| 1431 | | rr.content="localhost. root. 1 604800 86400 2419200 604800"; |
| 1432 | | |
| 1433 | | ad.d_records.insert(rr); |
| 1434 | | |
| 1435 | | rr.qtype=QType::NS; |
| 1436 | | rr.content="localhost."; |
| 1437 | | |
| 1438 | | ad.d_records.insert(rr); |
| 1439 | | rr.qtype=QType::PTR; |
| 1440 | | |
| 1441 | | if(ipparts.size()==4) // otherwise this is a partial zone |
| 1442 | | for(unsigned int n=1; n < parts.size(); ++n) { |
| 1443 | | rr.content=toCanonic("", parts[n]); |
| 1444 | | ad.d_records.insert(rr); |
| 1445 | | } |
| 1446 | | |
| 1447 | | if(SyncRes::s_domainmap.count(rr.qname)) { |
| 1448 | | L<<Logger::Warning<<"Will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl; |
| 1449 | | } |
| 1450 | | else { |
| 1451 | | if(ipparts.size()==4) |
| 1452 | | L<<Logger::Warning<<"Inserting reverse zone '"<<rr.qname<<"' based on hosts file"<<endl; |
| 1453 | | SyncRes::s_domainmap[rr.qname]=ad; |
| 1454 | | } |
| 1455 | | } |
| 1456 | | |
| 1457 | | |
| 1458 | | void parseAuthAndForwards(); |
| 1459 | | |
| 1460 | | /* mission in life: parse three cases |
| 1461 | | 1) 1.2.3.4 |
| 1462 | | 2) 1.2.3.4:5300 |
| 1463 | | 3) 2001::1 |
| 1464 | | 4) [2002::1]:53 |
| 1465 | | */ |
| 1466 | | |
| 1467 | | ComboAddress parseIPAndPort(const std::string& input, uint16_t port) |
| 1468 | | { |
| 1469 | | if(input.find(':') == string::npos || input.empty()) // common case |
| 1470 | | return ComboAddress(input, port); |
| 1471 | | |
| 1472 | | pair<string,string> both; |
| 1473 | | |
| 1474 | | try { // case 2 |
| 1475 | | both=splitField(input,':'); |
| 1476 | | uint16_t newport=boost::lexical_cast<uint16_t>(both.second); |
| 1477 | | return ComboAddress(both.first, newport); |
| 1478 | | } |
| 1479 | | catch(...){} |
| 1480 | | |
| 1481 | | if(input[0]=='[') { // case 4 |
| 1482 | | both=splitField(input.substr(1),']'); |
| 1483 | | return ComboAddress(both.first, both.second.empty() ? port : boost::lexical_cast<uint16_t>(both.second.substr(1))); |
| 1484 | | } |
| 1485 | | |
| 1486 | | return ComboAddress(input, port); // case 3 |
| 1487 | | } |
| 1488 | | |
| 1489 | | |
| 1490 | | void convertServersForAD(const std::string& input, SyncRes::AuthDomain& ad, const char* sepa, bool verbose=true) |
| 1491 | | { |
| 1492 | | vector<string> servers; |
| 1493 | | stringtok(servers, input, sepa); |
| 1494 | | ad.d_servers.clear(); |
| 1495 | | |
| 1496 | | for(vector<string>::const_iterator iter = servers.begin(); iter != servers.end(); ++iter) { |
| 1497 | | if(verbose && iter != servers.begin()) |
| 1498 | | L<<", "; |
| 1499 | | |
| 1500 | | ComboAddress addr=parseIPAndPort(*iter, 53); |
| 1501 | | if(verbose) |
| 1502 | | L<<addr.toStringWithPort(); |
| 1503 | | ad.d_servers.push_back(addr); |
| 1504 | | } |
| 1505 | | if(verbose) |
| 1506 | | L<<endl; |
| 1507 | | } |
| 1508 | | |
| 1509 | | string reloadAuthAndForwards() |
| 1510 | | { |
| 1511 | | SyncRes::domainmap_t original=SyncRes::s_domainmap; |
| 1512 | | |
| | 1322 | |
| | 1323 | void doReloadLuaScript() |
| | 1324 | { |
| | 1325 | string fname= ::arg()["lua-dns-script"]; |
| 1514 | | L<<Logger::Warning<<"Reloading zones, purging data from cache"<<endl; |
| 1515 | | |
| 1516 | | for(SyncRes::domainmap_t::const_iterator i = SyncRes::s_domainmap.begin(); i != SyncRes::s_domainmap.end(); ++i) { |
| 1517 | | for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j) |
| 1518 | | RC.doWipeCache(j->qname); |
| 1519 | | } |
| 1520 | | |
| | 1327 | if(fname.empty()) { |
| | 1328 | t_pdl->reset(); |
| | 1329 | L<<Logger::Error<<t_id<<" Unloaded current lua script"<<endl; |
| | 1330 | } |
| | 1331 | else { |
| | 1332 | *t_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(fname)); |
| | 1333 | } |
| | 1334 | } |
| | 1335 | catch(std::exception& e) { |
| | 1336 | L<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl; |
| | 1337 | } |
| | 1338 | |
| | 1339 | L<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl; |
| | 1340 | } |
| | 1341 | |
| | 1342 | |
| | 1343 | |
| | 1344 | string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end) |
| | 1345 | { |
| | 1346 | if(begin != end) |
| | 1347 | ::arg().set("lua-dns-script") = *begin; |
| | 1348 | |
| | 1349 | broadcastFunction(doReloadLuaScript); |
| | 1350 | |
| | 1351 | return "ok, reload/unload queued\n"; |
| | 1352 | } |
| | 1353 | |
| | 1354 | void* recursorThread(void*); |
| | 1355 | |
| | 1356 | void supplantACLs(NetmaskGroup *ng) |
| | 1357 | { |
| | 1358 | t_allowFrom = ng; |
| | 1359 | } |
| | 1360 | |
| | 1361 | void parseACLs() |
| | 1362 | { |
| | 1363 | static bool l_initialized; |
| | 1364 | |
| | 1365 | if(l_initialized) { // only reload configuration file on second call |
| 1527 | | ::arg().preParseFile(configname.c_str(), "auth-zones"); |
| 1528 | | ::arg().preParseFile(configname.c_str(), "export-etc-hosts", "off"); |
| 1529 | | ::arg().preParseFile(configname.c_str(), "serve-rfc1918"); |
| 1530 | | |
| 1531 | | parseAuthAndForwards(); |
| 1532 | | |
| 1533 | | // purge again - new zones need to blank out the cache |
| 1534 | | for(SyncRes::domainmap_t::const_iterator i = SyncRes::s_domainmap.begin(); i != SyncRes::s_domainmap.end(); ++i) { |
| 1535 | | for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j) |
| 1536 | | RC.doWipeCache(j->qname); |
| 1537 | | } |
| 1538 | | |
| 1539 | | // this is pretty blunt |
| 1540 | | Lock l(&SyncRes::s_negcachelock); |
| 1541 | | SyncRes::s_negcache.clear(); |
| 1542 | | return "ok\n"; |
| 1543 | | } |
| 1544 | | catch(std::exception& e) { |
| 1545 | | L<<Logger::Error<<"Had error reloading zones, keeping original data: "<<e.what()<<endl; |
| 1546 | | } |
| 1547 | | catch(AhuException& ae) { |
| 1548 | | L<<Logger::Error<<"Encountered error reloading zones, keeping original data: "<<ae.reason<<endl; |
| 1549 | | } |
| 1550 | | catch(...) { |
| 1551 | | L<<Logger::Error<<"Encountered unknown error reloading zones, keeping original data"<<endl; |
| 1552 | | } |
| 1553 | | SyncRes::s_domainmap.swap(original); |
| 1554 | | return "reloading failed, see log\n"; |
| 1555 | | } |
| 1556 | | |
| 1557 | | void parseAuthAndForwards() |
| 1558 | | { |
| 1559 | | SyncRes::s_domainmap.clear(); // this makes us idempotent |
| 1560 | | |
| 1561 | | TXTRecordContent::report(); |
| 1562 | | OPTRecordContent::report(); |
| 1563 | | |
| 1564 | | typedef vector<string> parts_t; |
| 1565 | | parts_t parts; |
| 1566 | | const char *option_names[3]={"auth-zones", "forward-zones", "forward-zones-recurse"}; |
| 1567 | | for(int n=0; n < 3 ; ++n ) { |
| 1568 | | parts.clear(); |
| 1569 | | stringtok(parts, ::arg()[option_names[n]], ",\t\n\r"); |
| 1570 | | for(parts_t::const_iterator iter = parts.begin(); iter != parts.end(); ++iter) { |
| 1571 | | SyncRes::AuthDomain ad; |
| 1572 | | pair<string,string> headers=splitField(*iter, '='); |
| 1573 | | trim(headers.first); |
| 1574 | | trim(headers.second); |
| 1575 | | headers.first=toCanonic("", headers.first); |
| 1576 | | if(n==0) { |
| 1577 | | L<<Logger::Error<<"Parsing authoritative data for zone '"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl; |
| 1578 | | ZoneParserTNG zpt(headers.second, headers.first); |
| 1579 | | DNSResourceRecord rr; |
| 1580 | | while(zpt.get(rr)) { |
| 1581 | | try { |
| 1582 | | string tmp=DNSRR2String(rr); |
| 1583 | | rr=String2DNSRR(rr.qname, rr.qtype, tmp, rr.ttl); |
| 1584 | | } |
| 1585 | | catch(std::exception &e) { |
| 1586 | | throw AhuException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"': "+e.what()); |
| 1587 | | } |
| 1588 | | catch(...) { |
| 1589 | | throw AhuException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'"); |
| 1590 | | } |
| 1591 | | |
| 1592 | | ad.d_records.insert(rr); |
| 1593 | | } |
| 1594 | | } |
| 1595 | | else { |
| 1596 | | L<<Logger::Error<<"Redirecting queries for zone '"<<headers.first<<"' "; |
| 1597 | | if(n == 2) { |
| 1598 | | L<<"with recursion "; |
| 1599 | | ad.d_rdForward = 1; |
| 1600 | | } |
| 1601 | | else ad.d_rdForward = 0; |
| 1602 | | L<<"to: "; |
| 1603 | | |
| 1604 | | convertServersForAD(headers.second, ad, ";"); |
| 1605 | | if(n == 2) { |
| 1606 | | ad.d_rdForward = 1; |
| 1607 | | } |
| 1608 | | } |
| 1609 | | |
| 1610 | | SyncRes::s_domainmap[headers.first]=ad; |
| 1611 | | } |
| 1612 | | } |
| 1613 | | |
| 1614 | | if(!::arg()["forward-zones-file"].empty()) { |
| 1615 | | L<<Logger::Warning<<"Reading zone forwarding information from '"<<::arg()["forward-zones-file"]<<"'"<<endl; |
| 1616 | | SyncRes::AuthDomain ad; |
| 1617 | | FILE *rfp=fopen(::arg()["forward-zones-file"].c_str(), "r"); |
| 1618 | | |
| 1619 | | if(!rfp) |
| 1620 | | throw AhuException("Error opening forward-zones-file '"+::arg()["forward-zones-file"]+"': "+stringerror()); |
| 1621 | | |
| 1622 | | shared_ptr<FILE> fp=shared_ptr<FILE>(rfp, fclose); |
| 1623 | | |
| 1624 | | char line[1024]; |
| 1625 | | int linenum=0; |
| 1626 | | uint64_t before = SyncRes::s_domainmap.size(); |
| 1627 | | while(linenum++, fgets(line, sizeof(line)-1, fp.get())) { |
| 1628 | | string domain, instructions; |
| 1629 | | tie(domain, instructions)=splitField(line, '='); |
| 1630 | | trim(domain); |
| 1631 | | trim(instructions); |
| 1632 | | if(boost::starts_with(domain,"+")) { |
| 1633 | | domain=domain.c_str()+1; |
| 1634 | | ad.d_rdForward = true; |
| 1635 | | } |
| 1636 | | else |
| 1637 | | ad.d_rdForward = false; |
| 1638 | | if(domain.empty()) |
| 1639 | | throw AhuException("Error parsing line "+lexical_cast<string>(linenum)+" of " +::arg()["forward-zones-file"]); |
| 1640 | | |
| 1641 | | try { |
| 1642 | | convertServersForAD(instructions, ad, ",; ", false); |
| 1643 | | } |
| 1644 | | catch(...) { |
| 1645 | | throw AhuException("Conversion error parsing line "+lexical_cast<string>(linenum)+" of " +::arg()["forward-zones-file"]); |
| 1646 | | } |
| 1647 | | |
| 1648 | | SyncRes::s_domainmap[toCanonic("", domain)]=ad; |
| 1649 | | } |
| 1650 | | L<<Logger::Warning<<"Done parsing " << SyncRes::s_domainmap.size() - before<<" forwarding instructions from file '"<<::arg()["forward-zones-file"]<<"'"<<endl; |
| 1651 | | } |
| 1652 | | |
| 1653 | | if(::arg().mustDo("export-etc-hosts")) { |
| | 1372 | ::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS); |
| | 1373 | } |
| | 1374 | |
| | 1375 | NetmaskGroup* oldAllowFrom = t_allowFrom, *allowFrom=new NetmaskGroup; |
| | 1376 | |
| | 1377 | if(!::arg()["allow-from-file"].empty()) { |
| 1671 | | parts.clear(); |
| 1672 | | stringtok(parts, line, "\t\r\n "); |
| 1673 | | if(parts[0].find(':')!=string::npos) |
| 1674 | | continue; |
| 1675 | | |
| 1676 | | for(unsigned int n=1; n < parts.size(); ++n) |
| 1677 | | makeNameToIPZone(parts[n], parts[0]); |
| 1678 | | makeIPToNamesZone(parts); |
| 1679 | | } |
| 1680 | | } |
| 1681 | | if(::arg().mustDo("serve-rfc1918")) { |
| 1682 | | L<<Logger::Warning<<"Inserting rfc 1918 private space zones"<<endl; |
| 1683 | | parts.clear(); |
| 1684 | | parts.push_back("127"); |
| 1685 | | makeIPToNamesZone(parts); |
| 1686 | | parts[0]="10"; |
| 1687 | | makeIPToNamesZone(parts); |
| 1688 | | |
| 1689 | | parts[0]="192.168"; |
| 1690 | | makeIPToNamesZone(parts); |
| 1691 | | for(int n=16; n < 32; n++) { |
| 1692 | | parts[0]="172."+lexical_cast<string>(n); |
| 1693 | | makeIPToNamesZone(parts); |
| 1694 | | } |
| 1695 | | } |
| 1696 | | } |
| 1697 | | |
| 1698 | | string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end) |
| 1699 | | { |
| 1700 | | if(begin != end) |
| 1701 | | ::arg().set("lua-dns-script") = *begin; |
| 1702 | | |
| 1703 | | g_luaReloadCounter = 0; |
| 1704 | | return "ok, reload/unload queued\n"; |
| 1705 | | } |
| 1706 | | |
| 1707 | | |
| 1708 | | void doReloadLuaScript() |
| 1709 | | { |
| 1710 | | string fname= ::arg()["lua-dns-script"]; |
| 1711 | | try { |
| 1712 | | if(fname.empty()) { |
| 1713 | | t_pdl->reset(); |
| 1714 | | L<<Logger::Error<<t_id<<" Unloaded current lua script"<<endl; |
| 1715 | | } |
| 1716 | | else { |
| 1717 | | *t_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(fname)); |
| 1718 | | } |
| 1719 | | } |
| 1720 | | catch(std::exception& e) { |
| 1721 | | L<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl; |
| 1722 | | } |
| 1723 | | |
| 1724 | | L<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl; |
| 1725 | | } |
| 1726 | | |
| 1727 | | void* recursorThread(void*); |
| 1728 | | |
| 1729 | | void parseACLs() |
| 1730 | | { |
| 1731 | | static bool l_initialized; |
| 1732 | | if(l_initialized) { |
| 1733 | | string configname=::arg()["config-dir"]+"/recursor.conf"; |
| 1734 | | cleanSlashes(configname); |
| 1735 | | |
| 1736 | | if(!::arg().preParseFile(configname.c_str(), "allow-from-file")) |
| 1737 | | L<<Logger::Warning<<"Unable to re-parse configuration file '"<<configname<<"'"<<endl; |
| 1738 | | |
| 1739 | | ::arg().preParseFile(configname.c_str(), "allow-from"); |
| 1740 | | } |
| 1741 | | l_initialized = true; |
| 1742 | | if(!::arg()["allow-from-file"].empty()) { |
| 1743 | | string line; |
| 1744 | | NetmaskGroup* allowFrom=new NetmaskGroup; |
| 1745 | | ifstream ifs(::arg()["allow-from-file"].c_str()); |
| 1746 | | if(!ifs) { |
| 1747 | | throw AhuException("Could not open '"+::arg()["allow-from-file"]+"': "+stringerror()); |
| 1748 | | } |
| 1749 | | |
| 1750 | | string::size_type pos; |
| 1751 | | while(getline(ifs,line)) { |
| 1752 | | pos=line.find('#'); |
| 1753 | | if(pos!=string::npos) |
| 1754 | | line.resize(pos); |
| 1755 | | trim(line); |
| 1756 | | if(line.empty()) |
| 1757 | | continue; |