]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/xpf.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
25 std::string
generateXPFPayload(bool tcp
, const ComboAddress
& source
, const ComboAddress
& destination
)
27 if (source
.sin4
.sin_family
!= destination
.sin4
.sin_family
) {
28 throw std::runtime_error("The XPF destination and source addresses must be of the same family");
32 const uint8_t version
= source
.isIPv4() ? 4 : 6;
33 const uint8_t protocol
= tcp
? 6 : 17;
34 const size_t addrSize
= source
.isIPv4() ? sizeof(source
.sin4
.sin_addr
.s_addr
) : sizeof(source
.sin6
.sin6_addr
.s6_addr
);
35 const uint16_t sourcePort
= source
.sin4
.sin_port
;
36 const uint16_t destinationPort
= destination
.sin4
.sin_port
;
38 ret
.reserve(sizeof(version
) + sizeof(protocol
) + (addrSize
* 2) + sizeof(sourcePort
) + sizeof(destinationPort
));
40 ret
.append(reinterpret_cast<const char*>(&version
), sizeof(version
));
41 ret
.append(reinterpret_cast<const char*>(&protocol
), sizeof(protocol
));
43 // We already established source and destination sin_family equivalence
44 if (source
.isIPv4()) {
45 assert(addrSize
== sizeof(source
.sin4
.sin_addr
.s_addr
));
46 ret
.append(reinterpret_cast<const char*>(&source
.sin4
.sin_addr
.s_addr
), addrSize
);
47 assert(addrSize
== sizeof(destination
.sin4
.sin_addr
.s_addr
));
48 ret
.append(reinterpret_cast<const char*>(&destination
.sin4
.sin_addr
.s_addr
), addrSize
);
51 assert(addrSize
== sizeof(source
.sin6
.sin6_addr
.s6_addr
));
52 ret
.append(reinterpret_cast<const char*>(&source
.sin6
.sin6_addr
.s6_addr
), addrSize
);
53 assert(addrSize
== sizeof(destination
.sin6
.sin6_addr
.s6_addr
));
54 ret
.append(reinterpret_cast<const char*>(&destination
.sin6
.sin6_addr
.s6_addr
), addrSize
);
57 ret
.append(reinterpret_cast<const char*>(&sourcePort
), sizeof(sourcePort
));
58 ret
.append(reinterpret_cast<const char*>(&destinationPort
), sizeof(destinationPort
));
63 bool parseXPFPayload(const char* payload
, size_t len
, ComboAddress
& source
, ComboAddress
* destination
)
65 static const size_t addr4Size
= sizeof(source
.sin4
.sin_addr
.s_addr
);
66 static const size_t addr6Size
= sizeof(source
.sin6
.sin6_addr
.s6_addr
);
70 uint16_t destinationPort
;
72 if (len
!= (sizeof(version
) + sizeof(protocol
) + (addr4Size
* 2) + sizeof(sourcePort
) + sizeof(destinationPort
)) &&
73 len
!= (sizeof(version
) + sizeof(protocol
) + (addr6Size
* 2) + sizeof(sourcePort
) + sizeof(destinationPort
))) {
79 memcpy(&version
, payload
+ pos
, sizeof(version
));
80 pos
+= sizeof(version
);
82 if (version
!= 4 && version
!= 6) {
86 memcpy(&protocol
, payload
+ pos
, sizeof(protocol
));
87 pos
+= sizeof(protocol
);
89 if (protocol
!= 6 && protocol
!= 17) {
93 const size_t addrSize
= version
== 4 ? sizeof(source
.sin4
.sin_addr
.s_addr
) : sizeof(source
.sin6
.sin6_addr
.s6_addr
);
94 if (len
- pos
!= ((addrSize
* 2) + sizeof(sourcePort
) + sizeof(destinationPort
))) {
98 source
= makeComboAddressFromRaw(version
, payload
+ pos
, addrSize
);
100 if (destination
!= nullptr) {
101 *destination
= makeComboAddressFromRaw(version
, payload
+ pos
, addrSize
);
105 memcpy(&sourcePort
, payload
+ pos
, sizeof(sourcePort
));
106 pos
+= sizeof(sourcePort
);
107 source
.sin4
.sin_port
= sourcePort
;
109 memcpy(&destinationPort
, payload
+ pos
, sizeof(destinationPort
));
110 pos
+= sizeof(destinationPort
);
111 if (destination
!= nullptr) {
112 destination
->sin4
.sin_port
= destinationPort
;