]>
Commit | Line | Data |
---|---|---|
12471842 PL |
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 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
e483a610 BH |
25 | #include <bitset> |
26 | #include "dnsparser.hh" | |
df136790 | 27 | #include "dns_random.hh" |
e483a610 | 28 | #include "iputils.hh" |
e483a610 BH |
29 | #include <boost/program_options.hpp> |
30 | ||
31 | #include <boost/format.hpp> | |
32 | #include <boost/utility.hpp> | |
33 | #include <boost/multi_index_container.hpp> | |
34 | #include <boost/multi_index/ordered_index.hpp> | |
35 | #include <boost/multi_index/key_extractors.hpp> | |
36 | ||
37 | #include "mplexer.hh" | |
d89592cd | 38 | #include "statbag.hh" |
e4bca3a9 | 39 | #include "arguments.hh" |
43fd645d | 40 | #include "version.hh" |
61b26744 | 41 | #include "namespaces.hh" |
e483a610 | 42 | using namespace ::boost::multi_index; |
10f4eea8 | 43 | #include "namespaces.hh" |
e483a610 BH |
44 | |
45 | namespace po = boost::program_options; | |
46 | po::variables_map g_vm; | |
47 | ||
d89592cd | 48 | StatBag S; |
e4bca3a9 PD |
49 | ArgvMap &arg() |
50 | { | |
51 | static ArgvMap arg; | |
52 | return arg; | |
53 | } | |
e483a610 | 54 | |
d09ce00c | 55 | void usage() { |
e929f5f7 | 56 | cerr<<"Syntax: pdns_notify IP_ADDRESS/HOSTNAME[:PORT] DOMAIN"<<endl; |
d09ce00c PL |
57 | } |
58 | ||
e483a610 BH |
59 | int main(int argc, char** argv) |
60 | try | |
61 | { | |
fc1f7fa9 | 62 | set<ComboAddress> addrs; |
cff2753d OM |
63 | ::arg().set("rng")="auto"; |
64 | ::arg().set("entropy-source")="/dev/urandom"; | |
d09ce00c PL |
65 | |
66 | for(int n=1 ; n < argc; ++n) { | |
67 | if ((string) argv[n] == "--help") { | |
68 | usage(); | |
69 | return EXIT_SUCCESS; | |
70 | } | |
71 | ||
72 | if ((string) argv[n] == "--version") { | |
73 | cerr<<"notify "<<VERSION<<endl; | |
74 | return EXIT_SUCCESS; | |
75 | } | |
76 | } | |
77 | ||
d89592cd | 78 | if(argc!=3) { |
d09ce00c | 79 | usage(); |
d89592cd BH |
80 | exit(1); |
81 | } | |
82 | ||
fc1f7fa9 | 83 | int sock = -1; |
d89592cd BH |
84 | |
85 | // ComboAddress local("127.0.0.1", (int)0); | |
86 | // if(::bind(sock, (struct sockaddr*) &local, local.getSocklen()) < 0) | |
87 | // throw runtime_error("Failed to bind local socket to address "+local.toString()+": "+stringerror()); | |
71e063fd | 88 | |
fc1f7fa9 AT |
89 | try { |
90 | addrs.emplace(ComboAddress{argv[1], 53}); | |
91 | } catch (PDNSException &ex) { | |
92 | /* needs resolving, maybe */ | |
93 | struct addrinfo *info; | |
94 | vector<string> parts; | |
95 | boost::split(parts, argv[1], [](char c){return c == ':';}); | |
96 | if (parts.size() == 1) | |
97 | parts.push_back("domain"); | |
98 | else if (parts.size() != 2) | |
99 | throw runtime_error("Invalid hostname:port syntax"); | |
100 | if (getaddrinfo(parts[0].c_str(), parts[1].c_str(), NULL, &info) < 0) | |
101 | throw runtime_error("Cannot resolve '" + string(argv[1]) +"'"); | |
102 | for(auto ptr = info; ptr != NULL; ptr = ptr->ai_next) | |
103 | addrs.emplace(ComboAddress{ptr->ai_addr, ptr->ai_addrlen}); | |
104 | } | |
e483a610 | 105 | |
fc1f7fa9 AT |
106 | for(const auto &addr: addrs) { |
107 | if (sock > -1) | |
108 | (void)close(sock); | |
109 | sock = socket(addr.sin4.sin_family, SOCK_DGRAM, 0); | |
110 | if(sock < 0) | |
111 | throw runtime_error("Creating socket for incoming packets: "+stringerror()); | |
112 | if(connect(sock, (struct sockaddr*)&addr, addr.getSocklen()) < 0) { | |
f044453d | 113 | cerr<<"Failed to connect to address "+addr.toStringWithPort()+": "+stringerror()<<endl; |
fc1f7fa9 AT |
114 | continue; |
115 | } | |
116 | vector<uint8_t> outpacket; | |
117 | DNSPacketWriter pw(outpacket, DNSName(argv[2]), QType::SOA, 1, Opcode::Notify); | |
df136790 | 118 | pw.getHeader()->id = dns_random(UINT16_MAX); |
e483a610 | 119 | |
fc1f7fa9 | 120 | if(send(sock, &outpacket[0], outpacket.size(), 0) < 0) { |
f044453d | 121 | cerr<<"Unable to send notify to "<<addr.toStringWithPort()<<": "+stringerror()<<endl; |
fc1f7fa9 AT |
122 | continue; |
123 | } | |
e483a610 | 124 | |
fc1f7fa9 | 125 | char buffer[1500]; |
5648c27c AT |
126 | fd_set rfds; |
127 | FD_ZERO(&rfds); | |
128 | FD_SET(sock, &rfds); | |
eace2c24 RG |
129 | fd_set errfds; |
130 | FD_ZERO(&errfds); | |
131 | FD_SET(sock, &errfds); | |
5648c27c AT |
132 | int len; |
133 | struct timeval tv; | |
134 | bool timeout = true; | |
135 | ||
136 | for(int tries=0; tries<60; tries++) { | |
137 | tv.tv_sec = 1; | |
138 | tv.tv_usec = 0; | |
eace2c24 | 139 | if ((len = select(sock+1, &rfds, nullptr, &errfds, &tv)) > 0) { |
5648c27c AT |
140 | len = recv(sock, buffer, sizeof(buffer), 0); |
141 | timeout = false; | |
142 | break; | |
143 | } | |
144 | } | |
e483a610 | 145 | |
fc1f7fa9 | 146 | if(len < 0) { |
f044453d | 147 | cerr<<"Unable to receive notification response from "<<addr.toStringWithPort()<<": "+stringerror()<<endl; |
fc1f7fa9 | 148 | continue; |
5648c27c | 149 | } else if (timeout) { |
f044453d | 150 | cerr<<"Unable to receive notification response from "<<addr.toStringWithPort()<<": Timed out"<<endl; |
5648c27c AT |
151 | continue; |
152 | } else if (len == 0) { | |
f044453d | 153 | cerr<<"Unable to receive notification response from "<<addr.toStringWithPort()<<": EOF"<<endl; |
5648c27c | 154 | continue; |
fc1f7fa9 AT |
155 | } |
156 | ||
157 | string packet(buffer, len); | |
158 | MOADNSParser mdp(false, packet); | |
159 | ||
f044453d AT |
160 | if (mdp.d_header.rcode == 0) |
161 | cerr<<"Successfully notified "<<addr.toStringWithPort()<<endl; | |
162 | else | |
163 | cerr<<"Received notification response with error from "<<addr.toStringWithPort()<<": "<<RCode::to_s(mdp.d_header.rcode)<<endl; | |
fc1f7fa9 AT |
164 | cerr<<"For: '"<<mdp.d_qname<<"'"<<endl; |
165 | } | |
e483a610 | 166 | } |
adc10f99 | 167 | catch(std::exception& e) |
e483a610 BH |
168 | { |
169 | cerr<<"Fatal: "<<e.what()<<endl; | |
170 | } | |
171 |