]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/protozero.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.
23 #include "protozero.hh"
25 #ifndef DISABLE_PROTOBUF
26 #include "dnsparser.hh"
28 void pdns::ProtoZero::Message::encodeComboAddress(const protozero::pbf_tag_type type
, const ComboAddress
& ca
)
30 if (ca
.sin4
.sin_family
== AF_INET
) {
31 d_message
.add_bytes(type
, reinterpret_cast<const char*>(&ca
.sin4
.sin_addr
.s_addr
), sizeof(ca
.sin4
.sin_addr
.s_addr
));
33 else if (ca
.sin4
.sin_family
== AF_INET6
) {
34 d_message
.add_bytes(type
, reinterpret_cast<const char*>(&ca
.sin6
.sin6_addr
.s6_addr
), sizeof(ca
.sin6
.sin6_addr
.s6_addr
));
38 void pdns::ProtoZero::Message::encodeNetmask(const protozero::pbf_tag_type type
, const Netmask
& subnet
, uint8_t mask
)
40 if (!subnet
.empty()) {
41 ComboAddress
ca(subnet
.getNetwork());
43 if (ca
.sin4
.sin_family
== AF_INET
) {
44 d_message
.add_bytes(type
, reinterpret_cast<const char*>(&ca
.sin4
.sin_addr
.s_addr
), sizeof(ca
.sin4
.sin_addr
.s_addr
));
46 else if (ca
.sin4
.sin_family
== AF_INET6
) {
47 d_message
.add_bytes(type
, reinterpret_cast<const char*>(&ca
.sin6
.sin6_addr
.s6_addr
), sizeof(ca
.sin6
.sin6_addr
.s6_addr
));
52 void pdns::ProtoZero::Message::encodeDNSName(protozero::pbf_writer
& pbf
, std::string
& buffer
, const protozero::pbf_tag_type type
, const DNSName
& name
)
54 // this will append the tag, mark the current position then reserve enough place to write the size
55 protozero::pbf_writer pbf_name
{pbf
, type
};
56 // we append the name to the buffer
57 name
.toString(buffer
);
58 // leaving the block will cause the sub writer to compute how much was written based on the new size and update the size accordingly
61 void pdns::ProtoZero::Message::setRequest(const boost::uuids::uuid
& uniqueId
, const ComboAddress
& requestor
, const ComboAddress
& local
, const DNSName
& qname
, uint16_t qtype
, uint16_t qclass
, uint16_t id
, pdns::ProtoZero::Message::TransportProtocol proto
, size_t len
)
63 setMessageIdentity(uniqueId
);
64 setSocketFamily(requestor
.sin4
.sin_family
);
65 setSocketProtocol(proto
);
71 setQuestion(qname
, qtype
, qclass
);
72 setFromPort(requestor
.getPort());
73 setToPort(local
.getPort());
76 void pdns::ProtoZero::Message::setResponse(const DNSName
& qname
, uint16_t qtype
, uint16_t qclass
)
78 setType(pdns::ProtoZero::Message::MessageType::DNSResponseType
);
79 setQuestion(qname
, qtype
, qclass
);
82 void pdns::ProtoZero::Message::addRRsFromPacket(const char* packet
, const size_t len
, bool includeCNAME
)
84 if (len
< sizeof(struct dnsheader
)) {
88 const dnsheader_aligned
dh(packet
);
90 if (ntohs(dh
->ancount
) == 0) {
94 if (ntohs(dh
->qdcount
) == 0) {
98 PacketReader
pr(std::string_view(packet
, len
));
102 uint16_t qdcount
= ntohs(dh
->qdcount
);
103 uint16_t ancount
= ntohs(dh
->ancount
);
107 struct dnsrecordheader ah
;
109 rrname
= pr
.getName();
110 rrtype
= pr
.get16BitInt();
111 rrclass
= pr
.get16BitInt();
115 /* consume remaining qd if any */
117 for(idx
= 1; idx
< qdcount
; idx
++) {
118 rrname
= pr
.getName();
119 rrtype
= pr
.get16BitInt();
120 rrclass
= pr
.get16BitInt();
127 for (idx
= 0; idx
< ancount
; idx
++) {
128 rrname
= pr
.getName();
129 pr
.getDnsrecordheader(ah
);
131 if (ah
.d_type
== QType::A
|| ah
.d_type
== QType::AAAA
) {
134 addRR(rrname
, ah
.d_type
, ah
.d_class
, ah
.d_ttl
, blob
);
136 } else if (ah
.d_type
== QType::CNAME
&& includeCNAME
) {
137 protozero::pbf_writer pbf_rr
{d_response
, static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::ResponseField::rrs
)};
139 encodeDNSName(pbf_rr
, d_buffer
, static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::name
), rrname
);
140 pbf_rr
.add_uint32(static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::type
), ah
.d_type
);
141 pbf_rr
.add_uint32(static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::class_
), ah
.d_class
);
142 pbf_rr
.add_uint32(static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::ttl
), ah
.d_ttl
);
144 pr
.xfrName(target
, true);
145 encodeDNSName(pbf_rr
, d_buffer
, static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::rdata
), target
);
153 void pdns::ProtoZero::Message::addRR(const DNSName
& name
, uint16_t uType
, uint16_t uClass
, uint32_t uTTL
, const std::string
& blob
)
155 protozero::pbf_writer pbf_rr
{d_response
, static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::ResponseField::rrs
)};
156 encodeDNSName(pbf_rr
, d_buffer
, static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::name
), name
);
157 pbf_rr
.add_uint32(static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::type
), uType
);
158 pbf_rr
.add_uint32(static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::class_
), uClass
);
159 pbf_rr
.add_uint32(static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::ttl
), uTTL
);
160 pbf_rr
.add_string(static_cast<protozero::pbf_tag_type
>(pdns::ProtoZero::Message::RRField::rdata
), blob
);
163 #endif /* DISABLE_PROTOBUF */