]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/ednssubnet.cc
rec: Don't account chained queries more than once
[thirdparty/pdns.git] / pdns / ednssubnet.cc
CommitLineData
801085ac 1/*
12471842
PL
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
801085ac
BH
25#include "ednssubnet.hh"
26#include "dns.hh"
27
28namespace {
232f0877
CH
29 struct EDNSSubnetOptsWire
30 {
31 uint16_t family;
32 uint8_t sourceMask;
33 uint8_t scopeMask;
795215f2 34 } GCCPACKATTRIBUTE; // BRRRRR
801085ac
BH
35
36}
37
801085ac 38bool getEDNSSubnetOptsFromString(const string& options, EDNSSubnetOpts* eso)
dc5748ed 39{
53221eaf 40 //cerr<<"options.size:"<<options.size()<<endl;
dc5748ed 41 return getEDNSSubnetOptsFromString(options.c_str(), options.length(), eso);
42}
43bool getEDNSSubnetOptsFromString(const char* options, unsigned int len, EDNSSubnetOpts* eso)
801085ac 44{
801085ac 45 EDNSSubnetOptsWire esow;
a683e8bd 46 static_assert (sizeof(esow) == 4, "sizeof(EDNSSubnetOptsWire) must be 4 bytes");
53221eaf 47 if(len < sizeof(esow))
a683e8bd 48 return false;
dc5748ed 49 memcpy(&esow, options, sizeof(esow));
801085ac 50 esow.family = ntohs(esow.family);
af7d3ea6 51 //cerr<<"Family when parsing from string: "<<esow.family<<endl;
801085ac 52 ComboAddress address;
53221eaf 53 unsigned int octetsin = esow.sourceMask > 0 ? (((esow.sourceMask - 1)>> 3)+1) : 0;
f6c101f2 54 //cerr<<"octetsin:"<<octetsin<<endl;
801085ac 55 if(esow.family == 1) {
a683e8bd 56 if(len != sizeof(esow)+octetsin)
801085ac 57 return false;
a683e8bd 58 if(octetsin > sizeof(address.sin4.sin_addr.s_addr))
f6c101f2 59 return false;
1caa9c83 60 address.reset();
801085ac 61 address.sin4.sin_family = AF_INET;
53221eaf
RG
62 if(octetsin > 0)
63 memcpy(&address.sin4.sin_addr.s_addr, options+sizeof(esow), octetsin);
af7d3ea6 64 } else if(esow.family == 2) {
a683e8bd 65 if(len != sizeof(esow)+octetsin)
f6c101f2 66 return false;
a683e8bd 67 if(octetsin > sizeof(address.sin6.sin6_addr.s6_addr))
af7d3ea6 68 return false;
1caa9c83
RG
69
70 address.reset();
af7d3ea6 71 address.sin4.sin_family = AF_INET6;
53221eaf
RG
72 if(octetsin > 0)
73 memcpy(&address.sin6.sin6_addr.s6_addr, options+sizeof(esow), octetsin);
801085ac 74 }
af7d3ea6
BH
75 else
76 return false;
53221eaf 77 //cerr<<"Source address: "<<address.toString()<<", mask: "<<(int)esow.sourceMask<<endl;
af7d3ea6 78 eso->source = Netmask(address, esow.sourceMask);
b85f49a0 79 /* 'address' has more bits set (potentially) than scopeMask. This leads to odd looking netmasks that promise
80 more precision than they have. For this reason we truncate the address to scopeMask bits */
81
82 address.truncate(esow.scopeMask); // truncate will not throw for odd scopeMasks
af7d3ea6 83 eso->scope = Netmask(address, esow.scopeMask);
b85f49a0 84
af7d3ea6 85 return true;
801085ac
BH
86}
87
88string makeEDNSSubnetOptsString(const EDNSSubnetOpts& eso)
89{
90 string ret;
91 EDNSSubnetOptsWire esow;
92 uint16_t family = htons(eso.source.getNetwork().sin4.sin_family == AF_INET ? 1 : 2);
a683e8bd 93 esow.family = family;
801085ac
BH
94 esow.sourceMask = eso.source.getBits();
95 esow.scopeMask = eso.scope.getBits();
96 ret.assign((const char*)&esow, sizeof(esow));
f6c101f2
PD
97 int octetsout = ((esow.sourceMask - 1)>> 3)+1;
98
d7da15c5 99 ComboAddress src=eso.source.getNetwork();
100 src.truncate(esow.sourceMask);
101
801085ac 102 if(family == htons(1))
d7da15c5 103 ret.append((const char*) &src.sin4.sin_addr.s_addr, octetsout);
801085ac 104 else
d7da15c5 105 ret.append((const char*) &src.sin6.sin6_addr.s6_addr, octetsout);
801085ac
BH
106 return ret;
107}
108