blob: 0709ac79cbdefa589407c3ee2c52cc61bdd5b864 [file] [log] [blame]
Simon Kelleyc8e8f5c2021-01-24 21:59:37 +00001/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
Simon Kelley1d030162015-12-21 14:17:06 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17#include "dnsmasq.h"
Kyle Swenson545712c2021-11-17 12:25:04 -070018/* CRADLEPOINT */
19#include "opendns.h"
20/* CRADLEPOINT */
Simon Kelley1d030162015-12-21 14:17:06 +000021
Simon Kelley5bb88f02015-12-21 16:23:47 +000022unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t *len, unsigned char **p, int *is_sign, int *is_last)
Simon Kelley1d030162015-12-21 14:17:06 +000023{
24 /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
25 also return length of pseudoheader in *len and pointer to the UDP size in *p
26 Finally, check to see if a packet is signed. If it is we cannot change a single bit before
Simon Kelley5bb88f02015-12-21 16:23:47 +000027 forwarding. We look for TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
Simon Kelley1d030162015-12-21 14:17:06 +000028
29 int i, arcount = ntohs(header->arcount);
30 unsigned char *ansp = (unsigned char *)(header+1);
31 unsigned short rdlen, type, class;
32 unsigned char *ret = NULL;
33
34 if (is_sign)
35 {
36 *is_sign = 0;
37
38 if (OPCODE(header) == QUERY)
39 {
40 for (i = ntohs(header->qdcount); i != 0; i--)
41 {
42 if (!(ansp = skip_name(ansp, header, plen, 4)))
43 return NULL;
44
45 GETSHORT(type, ansp);
46 GETSHORT(class, ansp);
47
48 if (class == C_IN && type == T_TKEY)
49 *is_sign = 1;
50 }
51 }
52 }
53 else
54 {
55 if (!(ansp = skip_questions(header, plen)))
56 return NULL;
57 }
58
59 if (arcount == 0)
60 return NULL;
61
62 if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
63 return NULL;
64
65 for (i = 0; i < arcount; i++)
66 {
67 unsigned char *save, *start = ansp;
68 if (!(ansp = skip_name(ansp, header, plen, 10)))
69 return NULL;
70
71 GETSHORT(type, ansp);
72 save = ansp;
73 GETSHORT(class, ansp);
74 ansp += 4; /* TTL */
75 GETSHORT(rdlen, ansp);
76 if (!ADD_RDLEN(header, ansp, plen, rdlen))
77 return NULL;
78 if (type == T_OPT)
79 {
80 if (len)
81 *len = ansp - start;
Simon Kelley5bb88f02015-12-21 16:23:47 +000082
Simon Kelley1d030162015-12-21 14:17:06 +000083 if (p)
84 *p = save;
Simon Kelley5bb88f02015-12-21 16:23:47 +000085
86 if (is_last)
87 *is_last = (i == arcount-1);
88
Simon Kelley1d030162015-12-21 14:17:06 +000089 ret = start;
90 }
91 else if (is_sign &&
92 i == arcount - 1 &&
93 class == C_ANY &&
94 type == T_TSIG)
95 *is_sign = 1;
96 }
97
98 return ret;
99}
Simon Kelley1d030162015-12-21 14:17:06 +0000100
Simon Kelley87985852016-04-25 15:33:30 +0100101
102/* replace == 2 ->delete existing option only. */
Simon Kelley1d030162015-12-21 14:17:06 +0000103size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000104 unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace)
Simon Kelley1d030162015-12-21 14:17:06 +0000105{
Simon Kelley5bb88f02015-12-21 16:23:47 +0000106 unsigned char *lenp, *datap, *p, *udp_len, *buff = NULL;
107 int rdlen = 0, is_sign, is_last;
108 unsigned short flags = set_do ? 0x8000 : 0, rcode = 0;
Simon Kelley1d030162015-12-21 14:17:06 +0000109
Simon Kelley5bb88f02015-12-21 16:23:47 +0000110 p = find_pseudoheader(header, plen, NULL, &udp_len, &is_sign, &is_last);
111
112 if (is_sign)
113 return plen;
114
115 if (p)
Simon Kelley1d030162015-12-21 14:17:06 +0000116 {
Simon Kelley5bb88f02015-12-21 16:23:47 +0000117 /* Existing header */
Simon Kelley1d030162015-12-21 14:17:06 +0000118 int i;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000119 unsigned short code, len;
120
121 p = udp_len;
122 GETSHORT(udp_sz, p);
123 GETSHORT(rcode, p);
Simon Kelley1d030162015-12-21 14:17:06 +0000124 GETSHORT(flags, p);
Simon Kelley5bb88f02015-12-21 16:23:47 +0000125
Simon Kelley1d030162015-12-21 14:17:06 +0000126 if (set_do)
127 {
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000128 p -= 2;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000129 flags |= 0x8000;
130 PUTSHORT(flags, p);
Simon Kelley1d030162015-12-21 14:17:06 +0000131 }
132
133 lenp = p;
134 GETSHORT(rdlen, p);
135 if (!CHECK_LEN(header, p, plen, rdlen))
136 return plen; /* bad packet */
137 datap = p;
138
139 /* no option to add */
140 if (optno == 0)
141 return plen;
142
143 /* check if option already there */
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000144 for (i = 0; i + 4 < rdlen;)
Simon Kelley1d030162015-12-21 14:17:06 +0000145 {
146 GETSHORT(code, p);
147 GETSHORT(len, p);
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000148
149 /* malformed option, delete the whole OPT RR and start again. */
Simon Kelley897c1132017-09-25 20:11:58 +0100150 if (i + 4 + len > rdlen)
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000151 {
152 rdlen = 0;
Simon Kelleyaa300f72016-03-01 15:19:13 +0000153 is_last = 0;
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000154 break;
155 }
156
Simon Kelley1d030162015-12-21 14:17:06 +0000157 if (code == optno)
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000158 {
Simon Kelley87985852016-04-25 15:33:30 +0100159 if (replace == 0)
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000160 return plen;
161
162 /* delete option if we're to replace it. */
163 p -= 4;
164 rdlen -= len + 4;
Simon Kelley6a0b00f2017-09-25 20:19:55 +0100165 memmove(p, p+len+4, rdlen - i);
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000166 PUTSHORT(rdlen, lenp);
167 lenp -= 2;
168 }
169 else
170 {
171 p += len;
172 i += len + 4;
173 }
Simon Kelley1d030162015-12-21 14:17:06 +0000174 }
Simon Kelley5bb88f02015-12-21 16:23:47 +0000175
176 /* If we're going to extend the RR, it has to be the last RR in the packet */
177 if (!is_last)
178 {
179 /* First, take a copy of the options. */
180 if (rdlen != 0 && (buff = whine_malloc(rdlen)))
181 memcpy(buff, datap, rdlen);
182
183 /* now, delete OPT RR */
184 plen = rrfilter(header, plen, 0);
185
186 /* Now, force addition of a new one */
187 p = NULL;
188 }
Simon Kelley1d030162015-12-21 14:17:06 +0000189 }
190
Simon Kelley5bb88f02015-12-21 16:23:47 +0000191 if (!p)
192 {
193 /* We are (re)adding the pseudoheader */
194 if (!(p = skip_questions(header, plen)) ||
195 !(p = skip_section(p,
196 ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
197 header, plen)))
Simon Kelley51eadb62017-09-25 20:16:50 +0100198 {
199 free(buff);
Simon Kelley5bb88f02015-12-21 16:23:47 +0000200 return plen;
Simon Kelley51eadb62017-09-25 20:16:50 +0100201 }
Simon Kelley897c1132017-09-25 20:11:58 +0100202 if (p + 11 > limit)
Simon Kelley51eadb62017-09-25 20:16:50 +0100203 {
204 free(buff);
205 return plen; /* Too big */
206 }
Simon Kelley5bb88f02015-12-21 16:23:47 +0000207 *p++ = 0; /* empty name */
208 PUTSHORT(T_OPT, p);
209 PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
210 PUTSHORT(rcode, p); /* extended RCODE and version */
211 PUTSHORT(flags, p); /* DO flag */
212 lenp = p;
213 PUTSHORT(rdlen, p); /* RDLEN */
214 datap = p;
215 /* Copy back any options */
216 if (buff)
217 {
Simon Kelley897c1132017-09-25 20:11:58 +0100218 if (p + rdlen > limit)
219 {
220 free(buff);
221 return plen; /* Too big */
222 }
Simon Kelley5bb88f02015-12-21 16:23:47 +0000223 memcpy(p, buff, rdlen);
224 free(buff);
225 p += rdlen;
226 }
Simon Kelleya3303e12017-09-07 20:45:00 +0100227
228 /* Only bump arcount if RR is going to fit */
229 if (((ssize_t)optlen) <= (limit - (p + 4)))
230 header->arcount = htons(ntohs(header->arcount) + 1);
Simon Kelley5bb88f02015-12-21 16:23:47 +0000231 }
232
233 if (((ssize_t)optlen) > (limit - (p + 4)))
234 return plen; /* Too big */
235
236 /* Add new option */
Simon Kelley87985852016-04-25 15:33:30 +0100237 if (optno != 0 && replace != 2)
Simon Kelley1d030162015-12-21 14:17:06 +0000238 {
Simon Kelley897c1132017-09-25 20:11:58 +0100239 if (p + 4 > limit)
240 return plen; /* Too big */
Simon Kelley1d030162015-12-21 14:17:06 +0000241 PUTSHORT(optno, p);
242 PUTSHORT(optlen, p);
Simon Kelley897c1132017-09-25 20:11:58 +0100243 if (p + optlen > limit)
244 return plen; /* Too big */
Simon Kelley1d030162015-12-21 14:17:06 +0000245 memcpy(p, opt, optlen);
246 p += optlen;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000247 PUTSHORT(p - datap, lenp);
Simon Kelley1d030162015-12-21 14:17:06 +0000248 }
Simon Kelley1d030162015-12-21 14:17:06 +0000249 return p - (unsigned char *)header;
Simon Kelley1d030162015-12-21 14:17:06 +0000250}
251
Simon Kelley33702ab2015-12-28 23:17:15 +0000252size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit)
Simon Kelleyefef4972015-12-21 17:30:44 +0000253{
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000254 return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1, 0);
Simon Kelleyefef4972015-12-21 17:30:44 +0000255}
256
Simon Kelley33702ab2015-12-28 23:17:15 +0000257static unsigned char char64(unsigned char c)
258{
259 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c & 0x3f];
260}
261
262static void encoder(unsigned char *in, char *out)
263{
264 out[0] = char64(in[0]>>2);
265 out[1] = char64((in[0]<<4) | (in[1]>>4));
266 out[2] = char64((in[1]<<2) | (in[2]>>6));
267 out[3] = char64(in[2]);
268}
269
Simon Kelley25e63f12020-11-25 21:17:52 +0000270static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,
271 union mysockaddr *l3, time_t now, int *cacheablep)
Simon Kelley33702ab2015-12-28 23:17:15 +0000272{
Simon Kelley87985852016-04-25 15:33:30 +0100273 int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
Simon Kelley33702ab2015-12-28 23:17:15 +0000274 unsigned char mac[DHCP_CHADDR_MAX];
Simon Kelley9e4cf472016-02-17 20:26:32 +0000275 char encode[18]; /* handle 6 byte MACs */
Simon Kelley33702ab2015-12-28 23:17:15 +0000276
277 if ((maclen = find_mac(l3, mac, 1, now)) == 6)
278 {
Simon Kelley87985852016-04-25 15:33:30 +0100279 replace = 1;
Simon Kelley25e63f12020-11-25 21:17:52 +0000280 *cacheablep = 0;
Simon Kelley87985852016-04-25 15:33:30 +0100281
Simon Kelley9e4cf472016-02-17 20:26:32 +0000282 if (option_bool(OPT_MAC_HEX))
283 print_mac(encode, mac, maclen);
284 else
285 {
286 encoder(mac, encode);
287 encoder(mac+3, encode+4);
288 encode[8] = 0;
289 }
Simon Kelley33702ab2015-12-28 23:17:15 +0000290 }
291
Simon Kelley87985852016-04-25 15:33:30 +0100292 return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
Simon Kelley33702ab2015-12-28 23:17:15 +0000293}
294
295
Simon Kelley25e63f12020-11-25 21:17:52 +0000296static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,
297 union mysockaddr *l3, time_t now, int *cacheablep)
Simon Kelley1d030162015-12-21 14:17:06 +0000298{
Simon Kelley11867dc2015-12-23 16:15:58 +0000299 int maclen;
300 unsigned char mac[DHCP_CHADDR_MAX];
Simon Kelley1d030162015-12-21 14:17:06 +0000301
Simon Kelley33702ab2015-12-28 23:17:15 +0000302 if ((maclen = find_mac(l3, mac, 1, now)) != 0)
Simon Kelley25e63f12020-11-25 21:17:52 +0000303 {
304 *cacheablep = 0;
305 plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
306 }
307
Simon Kelley11867dc2015-12-23 16:15:58 +0000308 return plen;
Simon Kelley1d030162015-12-21 14:17:06 +0000309}
310
311struct subnet_opt {
312 u16 family;
Simon Kelleyee875042018-10-23 22:10:17 +0100313 u8 source_netmask, scope_netmask;
Simon Kelley1d030162015-12-21 14:17:06 +0000314 u8 addr[IN6ADDRSZ];
Simon Kelley1d030162015-12-21 14:17:06 +0000315};
316
317static void *get_addrp(union mysockaddr *addr, const short family)
318{
Simon Kelley1d030162015-12-21 14:17:06 +0000319 if (family == AF_INET6)
320 return &addr->in6.sin6_addr;
Simon Kelley1d030162015-12-21 14:17:06 +0000321
322 return &addr->in.sin_addr;
323}
324
Simon Kelley25e63f12020-11-25 21:17:52 +0000325static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source, int *cacheablep)
Simon Kelley1d030162015-12-21 14:17:06 +0000326{
327 /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
328
329 int len;
Simon Kelley0fbd9802017-05-21 22:24:43 +0100330 void *addrp = NULL;
Simon Kelley1d030162015-12-21 14:17:06 +0000331 int sa_family = source->sa.sa_family;
Simon Kelley25e63f12020-11-25 21:17:52 +0000332 int cacheable = 0;
333
Simon Kelley22fe2fd2016-02-28 17:07:10 +0000334 opt->source_netmask = 0;
335 opt->scope_netmask = 0;
Simon Kelley25e63f12020-11-25 21:17:52 +0000336
Simon Kelley22fe2fd2016-02-28 17:07:10 +0000337 if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
Simon Kelley1d030162015-12-21 14:17:06 +0000338 {
339 opt->source_netmask = daemon->add_subnet6->mask;
340 if (daemon->add_subnet6->addr_used)
341 {
342 sa_family = daemon->add_subnet6->addr.sa.sa_family;
343 addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
Simon Kelley25e63f12020-11-25 21:17:52 +0000344 cacheable = 1;
Simon Kelley1d030162015-12-21 14:17:06 +0000345 }
346 else
347 addrp = &source->in6.sin6_addr;
348 }
Simon Kelley22fe2fd2016-02-28 17:07:10 +0000349
350 if (source->sa.sa_family == AF_INET && daemon->add_subnet4)
Simon Kelley1d030162015-12-21 14:17:06 +0000351 {
352 opt->source_netmask = daemon->add_subnet4->mask;
353 if (daemon->add_subnet4->addr_used)
354 {
355 sa_family = daemon->add_subnet4->addr.sa.sa_family;
356 addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
Simon Kelley25e63f12020-11-25 21:17:52 +0000357 cacheable = 1; /* Address is constant */
Simon Kelley1d030162015-12-21 14:17:06 +0000358 }
Simon Kelley22fe2fd2016-02-28 17:07:10 +0000359 else
360 addrp = &source->in.sin_addr;
Simon Kelley1d030162015-12-21 14:17:06 +0000361 }
362
Simon Kelley22fe2fd2016-02-28 17:07:10 +0000363 opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
Simon Kelley22fe2fd2016-02-28 17:07:10 +0000364
Simon Kelley0fbd9802017-05-21 22:24:43 +0100365 if (addrp && opt->source_netmask != 0)
Simon Kelley1d030162015-12-21 14:17:06 +0000366 {
Simon Kelley1d030162015-12-21 14:17:06 +0000367 len = ((opt->source_netmask - 1) >> 3) + 1;
368 memcpy(opt->addr, addrp, len);
369 if (opt->source_netmask & 7)
370 opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
371 }
Simon Kelley25e63f12020-11-25 21:17:52 +0000372 else
373 {
374 cacheable = 1; /* No address ever supplied. */
375 len = 0;
376 }
377
378 if (cacheablep)
379 *cacheablep = cacheable;
Simon Kelley22fe2fd2016-02-28 17:07:10 +0000380
Simon Kelley1d030162015-12-21 14:17:06 +0000381 return len + 4;
382}
383
Simon Kelley25e63f12020-11-25 21:17:52 +0000384static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable)
Simon Kelley1d030162015-12-21 14:17:06 +0000385{
386 /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
387
388 int len;
389 struct subnet_opt opt;
390
Simon Kelley25e63f12020-11-25 21:17:52 +0000391 len = calc_subnet_opt(&opt, source, cacheable);
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000392 return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
Simon Kelley1d030162015-12-21 14:17:06 +0000393}
394
Simon Kelley1d030162015-12-21 14:17:06 +0000395int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
396{
397 /* Section 9.2, Check that subnet option in reply matches. */
Simon Kelley5aa5f0f2015-12-21 17:20:35 +0000398
399 int len, calc_len;
Simon Kelley1d030162015-12-21 14:17:06 +0000400 struct subnet_opt opt;
401 unsigned char *p;
402 int code, i, rdlen;
403
Simon Kelley25e63f12020-11-25 21:17:52 +0000404 calc_len = calc_subnet_opt(&opt, peer, NULL);
Simon Kelley1d030162015-12-21 14:17:06 +0000405
Simon Kelley25e63f12020-11-25 21:17:52 +0000406 if (!(p = skip_name(pseudoheader, header, plen, 10)))
407 return 1;
408
409 p += 8; /* skip UDP length and RCODE */
410
411 GETSHORT(rdlen, p);
412 if (!CHECK_LEN(header, p, plen, rdlen))
413 return 1; /* bad packet */
414
415 /* check if option there */
Simon Kelley1d030162015-12-21 14:17:06 +0000416 for (i = 0; i + 4 < rdlen; i += len + 4)
417 {
418 GETSHORT(code, p);
419 GETSHORT(len, p);
420 if (code == EDNS0_OPTION_CLIENT_SUBNET)
421 {
422 /* make sure this doesn't mismatch. */
423 opt.scope_netmask = p[3];
424 if (len != calc_len || memcmp(p, &opt, len) != 0)
425 return 0;
426 }
427 p += len;
428 }
429
430 return 1;
431}
Simon Kelley33702ab2015-12-28 23:17:15 +0000432
Simon Kelley25e63f12020-11-25 21:17:52 +0000433/* Set *check_subnet if we add a client subnet option, which needs to checked
434 in the reply. Set *cacheable to zero if we add an option which the answer
435 may depend on. */
Simon Kelley33702ab2015-12-28 23:17:15 +0000436size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
Simon Kelley25e63f12020-11-25 21:17:52 +0000437 union mysockaddr *source, time_t now, int *check_subnet, int *cacheable)
Simon Kelley33702ab2015-12-28 23:17:15 +0000438{
Kyle Swenson545712c2021-11-17 12:25:04 -0700439/* CRADLEPOINT */
440 unsigned char *edns_options = daemon->edns_options;
441 size_t edns_options_len = daemon->edns_options_len;
442 int i, len, code;
443/* CRADLEPOINT */
444
Simon Kelley33702ab2015-12-28 23:17:15 +0000445 *check_subnet = 0;
Simon Kelley25e63f12020-11-25 21:17:52 +0000446 *cacheable = 1;
447
Simon Kelley33702ab2015-12-28 23:17:15 +0000448 if (option_bool(OPT_ADD_MAC))
Simon Kelley25e63f12020-11-25 21:17:52 +0000449 plen = add_mac(header, plen, limit, source, now, cacheable);
Simon Kelley33702ab2015-12-28 23:17:15 +0000450
Simon Kelley9e4cf472016-02-17 20:26:32 +0000451 if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
Simon Kelley25e63f12020-11-25 21:17:52 +0000452 plen = add_dns_client(header, plen, limit, source, now, cacheable);
453
Simon Kelley1e505122016-01-25 21:29:23 +0000454 if (daemon->dns_client_id)
455 plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
Simon Kelleyc7f3bd22016-02-28 21:48:34 +0000456 (unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);
Simon Kelley33702ab2015-12-28 23:17:15 +0000457
458 if (option_bool(OPT_CLIENT_SUBNET))
459 {
Simon Kelley25e63f12020-11-25 21:17:52 +0000460 plen = add_source_addr(header, plen, limit, source, cacheable);
Simon Kelley33702ab2015-12-28 23:17:15 +0000461 *check_subnet = 1;
462 }
Kyle Swenson545712c2021-11-17 12:25:04 -0700463
464/* CRADLEPOINT */
465 if (daemon->ssid_device_id_map.map) {
466 opendns_pop_tag_from_query((unsigned char *) header, &plen,
467 &edns_options, &edns_options_len);
468 }
469
470 if (edns_options) {
471 for (i = edns_options_len; i > 0; i -= len + 4)
472 {
473 GETSHORT(code, edns_options);
474 GETSHORT(len, edns_options);
475 plen = add_pseudoheader(header, plen, limit, PACKETSZ, code,
476 (unsigned char *)edns_options, len, 0, 1);
477 edns_options += len;
478
479 /* my_syslog(LOG_DEBUG, _("EDNS options added")); */
480 }
481 }
482/* CRADLEPOINT */
483
Simon Kelley33702ab2015-12-28 23:17:15 +0000484 return plen;
485}