]>
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 | */ | |
cf6874ba | 22 | #include "dnsrulactions.hh" |
23 | #include <iostream> | |
24 | ||
25 | using namespace std; | |
26 | ||
384c2cb2 | 27 | TeeAction::TeeAction(const ComboAddress& ca, bool addECS) : d_remote(ca), d_addECS(addECS) |
cf6874ba | 28 | { |
cf6874ba | 29 | d_fd=SSocket(d_remote.sin4.sin_family, SOCK_DGRAM, 0); |
30 | SConnect(d_fd, d_remote); | |
3d8a6b1d | 31 | setNonBlocking(d_fd); |
32 | d_worker=std::thread(std::bind(&TeeAction::worker, this)); | |
cf6874ba | 33 | } |
34 | ||
35 | TeeAction::~TeeAction() | |
36 | { | |
cf6874ba | 37 | d_pleaseQuit=true; |
38 | close(d_fd); | |
39 | d_worker.join(); | |
40 | } | |
41 | ||
42 | DNSAction::Action TeeAction::operator()(DNSQuestion* dq, string* ruleresult) const | |
43 | { | |
3d8a6b1d | 44 | if(dq->tcp) |
45 | d_tcpdrops++; | |
46 | else { | |
384c2cb2 | 47 | ssize_t res; |
3d8a6b1d | 48 | d_queries++; |
384c2cb2 RG |
49 | |
50 | if(d_addECS) { | |
51 | std::string query; | |
52 | std::string larger; | |
53 | uint16_t len = dq->len; | |
54 | bool ednsAdded = false; | |
55 | bool ecsAdded = false; | |
56 | query.reserve(dq->size); | |
57 | query.assign((char*) dq->dh, len); | |
58 | ||
ff0902ec | 59 | handleEDNSClientSubnet((char*) query.c_str(), query.size(), dq->qname->wirelength(), &len, larger, &ednsAdded, &ecsAdded, *dq->remote, dq->ecsOverride, dq->ecsPrefixLength); |
384c2cb2 RG |
60 | |
61 | if (larger.empty()) { | |
62 | res = send(d_fd, query.c_str(), len, 0); | |
63 | } | |
64 | else { | |
65 | res = send(d_fd, larger.c_str(), larger.length(), 0); | |
66 | } | |
67 | } | |
68 | else { | |
69 | res = send(d_fd, (char*)dq->dh, dq->len, 0); | |
70 | } | |
71 | ||
72 | if (res <= 0) | |
3d8a6b1d | 73 | d_senderrors++; |
74 | } | |
cf6874ba | 75 | return DNSAction::Action::None; |
76 | } | |
77 | ||
78 | string TeeAction::toString() const | |
79 | { | |
80 | return "tee to "+d_remote.toStringWithPort(); | |
81 | } | |
82 | ||
83 | std::unordered_map<string,double> TeeAction::getStats() const | |
84 | { | |
85 | return {{"queries", d_queries}, | |
3d8a6b1d | 86 | {"responses", d_responses}, |
87 | {"recv-errors", d_recverrors}, | |
88 | {"send-errors", d_senderrors}, | |
89 | {"noerrors", d_noerrors}, | |
90 | {"nxdomains", d_nxdomains}, | |
91 | {"refuseds", d_refuseds}, | |
92 | {"servfails", d_servfails}, | |
93 | {"other-rcode", d_otherrcode}, | |
94 | {"tcp-drops", d_tcpdrops} | |
95 | }; | |
cf6874ba | 96 | } |
97 | ||
98 | void TeeAction::worker() | |
99 | { | |
100 | char packet[1500]; | |
101 | int res=0; | |
3d8a6b1d | 102 | struct dnsheader* dh=(struct dnsheader*)packet; |
cf6874ba | 103 | for(;;) { |
3d8a6b1d | 104 | res=waitForData(d_fd, 0, 250000); |
105 | if(d_pleaseQuit) | |
106 | break; | |
107 | if(res < 0) { | |
108 | usleep(250000); | |
109 | continue; | |
110 | } | |
111 | if(res==0) | |
112 | continue; | |
cf6874ba | 113 | res=recv(d_fd, packet, sizeof(packet), 0); |
fa6c1f0c | 114 | if(res <= (int)sizeof(struct dnsheader)) |
3d8a6b1d | 115 | d_recverrors++; |
cf6874ba | 116 | else if(res > 0) |
117 | d_responses++; | |
3d8a6b1d | 118 | |
119 | if(dh->rcode == RCode::NoError) | |
120 | d_noerrors++; | |
121 | else if(dh->rcode == RCode::ServFail) | |
122 | d_servfails++; | |
123 | else if(dh->rcode == RCode::NXDomain) | |
124 | d_nxdomains++; | |
125 | else if(dh->rcode == RCode::Refused) | |
126 | d_refuseds++; | |
127 | else if(dh->rcode == RCode::FormErr) | |
128 | d_formerrs++; | |
129 | else if(dh->rcode == RCode::NotImp) | |
130 | d_notimps++; | |
cf6874ba | 131 | } |
132 | } |