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 "ednsoptions.hh"
26 /* extract a specific EDNS0 option from a pointer on the beginning rdLen of the OPT RR */
27 int getEDNSOption(char* optRR
, const size_t len
, uint16_t wantedOption
, char ** optionValue
, size_t * optionValueSize
)
29 assert(optRR
!= NULL
);
30 assert(optionValue
!= NULL
);
31 assert(optionValueSize
!= NULL
);
33 if (len
< DNS_RDLENGTH_SIZE
)
36 const uint16_t rdLen
= (((unsigned char) optRR
[pos
]) * 256) + ((unsigned char) optRR
[pos
+1]);
38 pos
+= DNS_RDLENGTH_SIZE
;
39 if ((pos
+ rdLen
) > len
) {
43 while(len
>= (pos
+ EDNS_OPTION_CODE_SIZE
+ EDNS_OPTION_LENGTH_SIZE
) &&
44 rdLen
>= (rdPos
+ EDNS_OPTION_CODE_SIZE
+ EDNS_OPTION_LENGTH_SIZE
)) {
45 const uint16_t optionCode
= (((unsigned char) optRR
[pos
]) * 256) + ((unsigned char) optRR
[pos
+1]);
46 pos
+= EDNS_OPTION_CODE_SIZE
;
47 rdPos
+= EDNS_OPTION_CODE_SIZE
;
48 const uint16_t optionLen
= (((unsigned char) optRR
[pos
]) * 256) + ((unsigned char) optRR
[pos
+1]);
49 pos
+= EDNS_OPTION_LENGTH_SIZE
;
50 rdPos
+= EDNS_OPTION_LENGTH_SIZE
;
51 if (optionLen
> (rdLen
- rdPos
) || optionLen
> (len
- pos
))
54 if (optionCode
== wantedOption
) {
55 *optionValue
= optRR
+ pos
- (EDNS_OPTION_CODE_SIZE
+ EDNS_OPTION_LENGTH_SIZE
);
56 *optionValueSize
= optionLen
+ EDNS_OPTION_CODE_SIZE
+ EDNS_OPTION_LENGTH_SIZE
;
60 /* skip this option */
69 /* extract all EDNS0 options from a pointer on the beginning rdLen of the OPT RR */
70 int getEDNSOptions(const char* optRR
, const size_t len
, EDNSOptionViewMap
& options
)
72 assert(optRR
!= NULL
);
74 if (len
< DNS_RDLENGTH_SIZE
)
77 const uint16_t rdLen
= (((unsigned char) optRR
[pos
]) * 256) + ((unsigned char) optRR
[pos
+1]);
79 pos
+= DNS_RDLENGTH_SIZE
;
80 if ((pos
+ rdLen
) > len
) {
84 while(len
>= (pos
+ EDNS_OPTION_CODE_SIZE
+ EDNS_OPTION_LENGTH_SIZE
) &&
85 rdLen
>= (rdPos
+ EDNS_OPTION_CODE_SIZE
+ EDNS_OPTION_LENGTH_SIZE
)) {
86 const uint16_t optionCode
= (((unsigned char) optRR
[pos
]) * 256) + ((unsigned char) optRR
[pos
+1]);
87 pos
+= EDNS_OPTION_CODE_SIZE
;
88 rdPos
+= EDNS_OPTION_CODE_SIZE
;
89 const uint16_t optionLen
= (((unsigned char) optRR
[pos
]) * 256) + ((unsigned char) optRR
[pos
+1]);
90 pos
+= EDNS_OPTION_LENGTH_SIZE
;
91 rdPos
+= EDNS_OPTION_LENGTH_SIZE
;
92 if (optionLen
> (rdLen
- rdPos
) || optionLen
> (len
- pos
))
95 EDNSOptionViewValue value
;
96 value
.content
= optRR
+ pos
;
97 value
.size
= optionLen
;
98 options
[optionCode
].values
.push_back(std::move(value
));
100 /* skip this option */
108 void generateEDNSOption(uint16_t optionCode
, const std::string
& payload
, std::string
& res
)
110 const uint16_t ednsOptionCode
= htons(optionCode
);
111 const uint16_t payloadLen
= htons(payload
.length());
112 res
.append((const char *) &ednsOptionCode
, sizeof ednsOptionCode
);
113 res
.append((const char *) &payloadLen
, sizeof payloadLen
);