1 /* 2 * This file is part of PowerDNS or dnsdist. 3 * Copyright -- PowerDNS.COM B.V. and its contributors 4 * 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. 8 * 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. 12 * 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. 17 * 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. 21 */ 22 #include "query-local-address.hh" 23 #include "iputils.hh" 24 #include "dns_random.hh" 25 26 namespace pdns { 27 static const ComboAddress local4("0.0.0.0"); 28 static const ComboAddress local6("::"); 29 30 static vector<ComboAddress> g_localQueryAddresses4; 31 static vector<ComboAddress> g_localQueryAddresses6; 32 getQueryLocalAddress(const sa_family_t family,const in_port_t port)33 ComboAddress getQueryLocalAddress(const sa_family_t family, const in_port_t port) { 34 ComboAddress ret; 35 if (family==AF_INET) { 36 if (g_localQueryAddresses4.empty()) { 37 ret = local4; 38 } else if (g_localQueryAddresses4.size() == 1) { 39 ret = g_localQueryAddresses4.at(0); 40 } else { 41 ret = g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())]; 42 } 43 ret.sin4.sin_port = htons(port); 44 } 45 else { 46 if (g_localQueryAddresses6.empty()) { 47 ret = local6; 48 } else if (g_localQueryAddresses6.size() == 1) { 49 ret = g_localQueryAddresses6.at(0); 50 } else { 51 ret = g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())]; 52 } 53 ret.sin6.sin6_port = htons(port); 54 } 55 return ret; 56 } 57 getNonAnyQueryLocalAddress(const sa_family_t family)58 ComboAddress getNonAnyQueryLocalAddress(const sa_family_t family) { 59 if (family == AF_INET) { 60 for (const auto& addr : pdns::g_localQueryAddresses4) { 61 if (!IsAnyAddress(addr)) { 62 return addr; 63 } 64 } 65 } 66 if (family == AF_INET6) { 67 for (const auto& addr : pdns::g_localQueryAddresses6) { 68 if (!IsAnyAddress(addr)) { 69 return addr; 70 } 71 } 72 } 73 ComboAddress ret("0.0.0.0"); 74 ret.reset(); // Ensure all is zero, even the addr family 75 return ret; 76 } 77 parseQueryLocalAddress(const std::string & qla)78 void parseQueryLocalAddress(const std::string &qla) { 79 vector<string> addrs; 80 stringtok(addrs, qla, ", ;"); 81 for(const string& addr : addrs) { 82 ComboAddress tmp(addr); 83 if (tmp.isIPv4()) { 84 g_localQueryAddresses4.push_back(tmp); 85 continue; 86 } 87 g_localQueryAddresses6.push_back(tmp); 88 } 89 } 90 isQueryLocalAddressFamilyEnabled(const sa_family_t family)91 bool isQueryLocalAddressFamilyEnabled(const sa_family_t family) { 92 if (family == AF_INET) { 93 return !g_localQueryAddresses4.empty(); 94 } 95 if (family == AF_INET6) { 96 return !g_localQueryAddresses6.empty(); 97 } 98 return false; 99 } 100 } // namespace pdns 101