10 #include "dnscrypt_proxy.h"
14 _skip_name(const uint8_t * const dns_packet
, const size_t dns_packet_len
,
15 size_t * const offset_p
)
17 size_t offset
= *offset_p
;
18 uint8_t name_component_len
;
20 if (dns_packet_len
< (size_t) 1U ||
21 offset
>= dns_packet_len
- (size_t) 1U) {
25 name_component_len
= dns_packet
[offset
];
26 if ((name_component_len
& 0xC0) == 0xC0) {
27 name_component_len
= 1U;
29 if (name_component_len
>= dns_packet_len
- offset
- 1U) {
32 offset
+= name_component_len
+ 1U;
33 } while (name_component_len
!= 0U);
34 if (offset
>= dns_packet_len
) {
42 #define DNS_QTYPE_PLUS_QCLASS_LEN 4U
45 edns_get_payload_size(const uint8_t * const dns_packet
,
46 const size_t dns_packet_len
)
52 assert(dns_packet_len
>= DNS_HEADER_SIZE
);
53 arcount
= (dns_packet
[DNS_OFFSET_ARCOUNT
] << 8) |
54 dns_packet
[DNS_OFFSET_ARCOUNT
+ 1U];
56 assert(DNS_OFFSET_QUESTION
<= DNS_HEADER_SIZE
);
57 if (dns_packet
[DNS_OFFSET_QDCOUNT
] != 0U ||
58 dns_packet
[DNS_OFFSET_QDCOUNT
+ 1U] != 1U ||
59 (dns_packet
[DNS_OFFSET_ANCOUNT
] |
60 dns_packet
[DNS_OFFSET_ANCOUNT
+ 1U]) != 0U ||
61 (dns_packet
[DNS_OFFSET_NSCOUNT
] |
62 dns_packet
[DNS_OFFSET_NSCOUNT
+ 1U]) != 0U) {
65 offset
= DNS_OFFSET_QUESTION
;
66 if (_skip_name(dns_packet
, dns_packet_len
, &offset
) != 0) {
69 assert(dns_packet_len
> (size_t) DNS_QTYPE_PLUS_QCLASS_LEN
);
70 if (offset
>= dns_packet_len
- (size_t) DNS_QTYPE_PLUS_QCLASS_LEN
) {
73 offset
+= DNS_QTYPE_PLUS_QCLASS_LEN
;
74 assert(dns_packet_len
>= DNS_OFFSET_EDNS_PAYLOAD_SIZE
+ 2U);
75 if (_skip_name(dns_packet
, dns_packet_len
, &offset
) != 0 ||
76 offset
>= dns_packet_len
- DNS_OFFSET_EDNS_PAYLOAD_SIZE
- 2U) {
79 assert(DNS_OFFSET_EDNS_PAYLOAD_SIZE
> DNS_OFFSET_EDNS_TYPE
);
80 if (dns_packet
[offset
+ DNS_OFFSET_EDNS_TYPE
] != 0U ||
81 dns_packet
[offset
+ DNS_OFFSET_EDNS_TYPE
+ 1U] != DNS_TYPE_OPT
) {
84 payload_size
= (dns_packet
[offset
+ DNS_OFFSET_EDNS_PAYLOAD_SIZE
] << 8) |
85 dns_packet
[offset
+ DNS_OFFSET_EDNS_PAYLOAD_SIZE
+ 1U];
86 if (payload_size
< DNS_MAX_PACKET_SIZE_UDP_SEND
) {
87 payload_size
= DNS_MAX_PACKET_SIZE_UDP_SEND
;
89 return (ssize_t
) payload_size
;
93 edns_add_section(ProxyContext
* const proxy_context
,
94 uint8_t * const dns_packet
, size_t * const dns_packet_len_p
,
95 size_t dns_packet_max_size
,
96 size_t * const request_edns_payload_size
)
98 const size_t edns_payload_size
= proxy_context
->edns_payload_size
;
100 assert(edns_payload_size
<= (size_t) 0xFFFF);
101 assert(DNS_OFFSET_ARCOUNT
+ 2U <= DNS_HEADER_SIZE
);
102 if (edns_payload_size
<= DNS_MAX_PACKET_SIZE_UDP_SEND
||
103 *dns_packet_len_p
<= DNS_HEADER_SIZE
) {
104 *request_edns_payload_size
= (size_t) 0U;
107 if ((dns_packet
[DNS_OFFSET_ARCOUNT
] |
108 dns_packet
[DNS_OFFSET_ARCOUNT
+ 1U]) != 0U) {
109 const ssize_t edns_payload_ssize
=
110 edns_get_payload_size(dns_packet
, *dns_packet_len_p
);
111 if (edns_payload_ssize
<= (ssize_t
) 0U) {
112 *request_edns_payload_size
= (size_t) 0U;
115 *request_edns_payload_size
= (size_t) edns_payload_ssize
;
118 assert(dns_packet_max_size
>= *dns_packet_len_p
);
120 assert(DNS_OFFSET_EDNS_TYPE
== 0U);
121 assert(DNS_OFFSET_EDNS_PAYLOAD_SIZE
== 2U);
124 0U, DNS_TYPE_OPT
, /* type */
125 (edns_payload_size
>> 8) & 0xFF, edns_payload_size
& 0xFF,
126 0U, 0U, 0U, 0U, /* rcode */
129 if (dns_packet_max_size
- *dns_packet_len_p
< sizeof opt_rr
) {
130 *request_edns_payload_size
= (size_t) 0U;
133 assert(dns_packet
[DNS_OFFSET_ARCOUNT
+ 1U] == 0U);
134 dns_packet
[DNS_OFFSET_ARCOUNT
+ 1U] = 1U;
135 memcpy(dns_packet
+ *dns_packet_len_p
, opt_rr
, sizeof opt_rr
);
136 *dns_packet_len_p
+= sizeof opt_rr
;
137 *request_edns_payload_size
= edns_payload_size
;
138 assert(*dns_packet_len_p
<= dns_packet_max_size
);
139 assert(*dns_packet_len_p
<= 0xFFFF);