]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/019-Generalise_RR-filtering_code_for_use_with_EDNS0.patch
kernel: update to 3.14.62
[ipfire-2.x.git] / src / patches / dnsmasq / 019-Generalise_RR-filtering_code_for_use_with_EDNS0.patch
1 From c2bcd1e183bcc5fdd63811c045355fc57e36ecfd Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Tue, 15 Dec 2015 17:25:21 +0000
4 Subject: [PATCH] Generalise RR-filtering code, for use with EDNS0.
5
6 ---
7 Makefile | 3 +-
8 bld/Android.mk | 2 +-
9 src/dnsmasq.h | 5 +
10 src/dnssec.c | 307 +-------------------------------------------------
11 src/forward.c | 2 +-
12 src/rrfilter.c | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 6 files changed, 349 insertions(+), 309 deletions(-)
14 create mode 100644 src/rrfilter.c
15
16 diff --git a/Makefile b/Makefile
17 index 4c87ea9..b664160 100644
18 --- a/Makefile
19 +++ b/Makefile
20 @@ -73,7 +73,8 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
21 dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
22 helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
23 dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
24 - domain.o dnssec.o blockdata.o tables.o loop.o inotify.o poll.o
25 + domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
26 + poll.o rrfilter.o
27
28 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
29 dns-protocol.h radv-protocol.h ip6addr.h
30 diff --git a/bld/Android.mk b/bld/Android.mk
31 index 5364ee7..67b9c4b 100644
32 --- a/bld/Android.mk
33 +++ b/bld/Android.mk
34 @@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
35 dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
36 radv.c slaac.c auth.c ipset.c domain.c \
37 dnssec.c dnssec-openssl.c blockdata.c tables.c \
38 - loop.c inotify.c poll.c
39 + loop.c inotify.c poll.c rrfilter.c
40
41 LOCAL_MODULE := dnsmasq
42
43 diff --git a/src/dnsmasq.h b/src/dnsmasq.h
44 index 4344cae..39a930c 100644
45 --- a/src/dnsmasq.h
46 +++ b/src/dnsmasq.h
47 @@ -1513,3 +1513,8 @@ int poll_check(int fd, short event);
48 void poll_listen(int fd, short event);
49 int do_poll(int timeout);
50
51 +/* rrfilter.c */
52 +size_t rrfilter(struct dns_header *header, size_t plen, int mode);
53 +u16 *rrfilter_desc(int type);
54 +int expand_workspace(unsigned char ***wkspc, int *szp, int new);
55 +
56 diff --git a/src/dnssec.c b/src/dnssec.c
57 index 359231f..fa3eb81 100644
58 --- a/src/dnssec.c
59 +++ b/src/dnssec.c
60 @@ -507,50 +507,6 @@ static int check_date_range(unsigned long date_start, unsigned long date_end)
61 && serial_compare_32(curtime, date_end) == SERIAL_LT;
62 }
63
64 -static u16 *get_desc(int type)
65 -{
66 - /* List of RRtypes which include domains in the data.
67 - 0 -> domain
68 - integer -> no of plain bytes
69 - -1 -> end
70 -
71 - zero is not a valid RRtype, so the final entry is returned for
72 - anything which needs no mangling.
73 - */
74 -
75 - static u16 rr_desc[] =
76 - {
77 - T_NS, 0, -1,
78 - T_MD, 0, -1,
79 - T_MF, 0, -1,
80 - T_CNAME, 0, -1,
81 - T_SOA, 0, 0, -1,
82 - T_MB, 0, -1,
83 - T_MG, 0, -1,
84 - T_MR, 0, -1,
85 - T_PTR, 0, -1,
86 - T_MINFO, 0, 0, -1,
87 - T_MX, 2, 0, -1,
88 - T_RP, 0, 0, -1,
89 - T_AFSDB, 2, 0, -1,
90 - T_RT, 2, 0, -1,
91 - T_SIG, 18, 0, -1,
92 - T_PX, 2, 0, 0, -1,
93 - T_NXT, 0, -1,
94 - T_KX, 2, 0, -1,
95 - T_SRV, 6, 0, -1,
96 - T_DNAME, 0, -1,
97 - 0, -1 /* wildcard/catchall */
98 - };
99 -
100 - u16 *p = rr_desc;
101 -
102 - while (*p != type && *p != 0)
103 - while (*p++ != (u16)-1);
104 -
105 - return p+1;
106 -}
107 -
108 /* Return bytes of canonicalised rdata, when the return value is zero, the remaining
109 data, pointed to by *p, should be used raw. */
110 static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen,
111 @@ -594,34 +550,6 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
112 }
113 }
114
115 -static int expand_workspace(unsigned char ***wkspc, int *szp, int new)
116 -{
117 - unsigned char **p;
118 - int old = *szp;
119 -
120 - if (old >= new+1)
121 - return 1;
122 -
123 - if (new >= 100)
124 - return 0;
125 -
126 - new += 5;
127 -
128 - if (!(p = whine_malloc(new * sizeof(unsigned char **))))
129 - return 0;
130 -
131 - if (old != 0 && *wkspc)
132 - {
133 - memcpy(p, *wkspc, old * sizeof(unsigned char **));
134 - free(*wkspc);
135 - }
136 -
137 - *wkspc = p;
138 - *szp = new;
139 -
140 - return 1;
141 -}
142 -
143 /* Bubble sort the RRset into the canonical order.
144 Note that the byte-streams from two RRs may get unsynced: consider
145 RRs which have two domain-names at the start and then other data.
146 @@ -849,7 +777,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
147 int rdlen, j, name_labels;
148 struct crec *crecp = NULL;
149 int algo, labels, orig_ttl, key_tag;
150 - u16 *rr_desc = get_desc(type);
151 + u16 *rr_desc = rrfilter_desc(type);
152
153 if (wildcard_out)
154 *wildcard_out = NULL;
155 @@ -2266,239 +2194,6 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
156 return ret;
157 }
158
159 -/* Go through a domain name, find "pointers" and fix them up based on how many bytes
160 - we've chopped out of the packet, or check they don't point into an elided part. */
161 -static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
162 -{
163 - unsigned char *ansp = *namep;
164 -
165 - while(1)
166 - {
167 - unsigned int label_type;
168 -
169 - if (!CHECK_LEN(header, ansp, plen, 1))
170 - return 0;
171 -
172 - label_type = (*ansp) & 0xc0;
173 -
174 - if (label_type == 0xc0)
175 - {
176 - /* pointer for compression. */
177 - unsigned int offset;
178 - int i;
179 - unsigned char *p;
180 -
181 - if (!CHECK_LEN(header, ansp, plen, 2))
182 - return 0;
183 -
184 - offset = ((*ansp++) & 0x3f) << 8;
185 - offset |= *ansp++;
186 -
187 - p = offset + (unsigned char *)header;
188 -
189 - for (i = 0; i < rr_count; i++)
190 - if (p < rrs[i])
191 - break;
192 - else
193 - if (i & 1)
194 - offset -= rrs[i] - rrs[i-1];
195 -
196 - /* does the pointer end up in an elided RR? */
197 - if (i & 1)
198 - return 0;
199 -
200 - /* No, scale the pointer */
201 - if (fixup)
202 - {
203 - ansp -= 2;
204 - *ansp++ = (offset >> 8) | 0xc0;
205 - *ansp++ = offset & 0xff;
206 - }
207 - break;
208 - }
209 - else if (label_type == 0x80)
210 - return 0; /* reserved */
211 - else if (label_type == 0x40)
212 - {
213 - /* Extended label type */
214 - unsigned int count;
215 -
216 - if (!CHECK_LEN(header, ansp, plen, 2))
217 - return 0;
218 -
219 - if (((*ansp++) & 0x3f) != 1)
220 - return 0; /* we only understand bitstrings */
221 -
222 - count = *(ansp++); /* Bits in bitstring */
223 -
224 - if (count == 0) /* count == 0 means 256 bits */
225 - ansp += 32;
226 - else
227 - ansp += ((count-1)>>3)+1;
228 - }
229 - else
230 - { /* label type == 0 Bottom six bits is length */
231 - unsigned int len = (*ansp++) & 0x3f;
232 -
233 - if (!ADD_RDLEN(header, ansp, plen, len))
234 - return 0;
235 -
236 - if (len == 0)
237 - break; /* zero length label marks the end. */
238 - }
239 - }
240 -
241 - *namep = ansp;
242 -
243 - return 1;
244 -}
245 -
246 -/* Go through RRs and check or fixup the domain names contained within */
247 -static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
248 -{
249 - int i, type, class, rdlen;
250 - unsigned char *pp;
251 -
252 - for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
253 - {
254 - pp = p;
255 -
256 - if (!(p = skip_name(p, header, plen, 10)))
257 - return 0;
258 -
259 - GETSHORT(type, p);
260 - GETSHORT(class, p);
261 - p += 4; /* TTL */
262 - GETSHORT(rdlen, p);
263 -
264 - if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
265 - {
266 - /* fixup name of RR */
267 - if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
268 - return 0;
269 -
270 - if (class == C_IN)
271 - {
272 - u16 *d;
273 -
274 - for (pp = p, d = get_desc(type); *d != (u16)-1; d++)
275 - {
276 - if (*d != 0)
277 - pp += *d;
278 - else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
279 - return 0;
280 - }
281 - }
282 - }
283 -
284 - if (!ADD_RDLEN(header, p, plen, rdlen))
285 - return 0;
286 - }
287 -
288 - return 1;
289 -}
290 -
291 -
292 -size_t filter_rrsigs(struct dns_header *header, size_t plen)
293 -{
294 - static unsigned char **rrs;
295 - static int rr_sz = 0;
296 -
297 - unsigned char *p = (unsigned char *)(header+1);
298 - int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
299 -
300 - if (ntohs(header->qdcount) != 1 ||
301 - !(p = skip_name(p, header, plen, 4)))
302 - return plen;
303 -
304 - GETSHORT(qtype, p);
305 - GETSHORT(qclass, p);
306 -
307 - /* First pass, find pointers to start and end of all the records we wish to elide:
308 - records added for DNSSEC, unless explicity queried for */
309 - for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0;
310 - i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
311 - i++)
312 - {
313 - unsigned char *pstart = p;
314 - int type, class;
315 -
316 - if (!(p = skip_name(p, header, plen, 10)))
317 - return plen;
318 -
319 - GETSHORT(type, p);
320 - GETSHORT(class, p);
321 - p += 4; /* TTL */
322 - GETSHORT(rdlen, p);
323 -
324 - if ((type == T_NSEC || type == T_NSEC3 || type == T_RRSIG) &&
325 - (type != qtype || class != qclass))
326 - {
327 - if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
328 - return plen;
329 -
330 - rrs[rr_found++] = pstart;
331 -
332 - if (!ADD_RDLEN(header, p, plen, rdlen))
333 - return plen;
334 -
335 - rrs[rr_found++] = p;
336 -
337 - if (i < ntohs(header->ancount))
338 - chop_an++;
339 - else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
340 - chop_ns++;
341 - else
342 - chop_ar++;
343 - }
344 - else if (!ADD_RDLEN(header, p, plen, rdlen))
345 - return plen;
346 - }
347 -
348 - /* Nothing to do. */
349 - if (rr_found == 0)
350 - return plen;
351 -
352 - /* Second pass, look for pointers in names in the records we're keeping and make sure they don't
353 - point to records we're going to elide. This is theoretically possible, but unlikely. If
354 - it happens, we give up and leave the answer unchanged. */
355 - p = (unsigned char *)(header+1);
356 -
357 - /* question first */
358 - if (!check_name(&p, header, plen, 0, rrs, rr_found))
359 - return plen;
360 - p += 4; /* qclass, qtype */
361 -
362 - /* Now answers and NS */
363 - if (!check_rrs(p, header, plen, 0, rrs, rr_found))
364 - return plen;
365 -
366 - /* Third pass, elide records */
367 - for (p = rrs[0], i = 1; i < rr_found; i += 2)
368 - {
369 - unsigned char *start = rrs[i];
370 - unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen;
371 -
372 - memmove(p, start, end-start);
373 - p += end-start;
374 - }
375 -
376 - plen = p - (unsigned char *)header;
377 - header->ancount = htons(ntohs(header->ancount) - chop_an);
378 - header->nscount = htons(ntohs(header->nscount) - chop_ns);
379 - header->arcount = htons(ntohs(header->arcount) - chop_ar);
380 -
381 - /* Fourth pass, fix up pointers in the remaining records */
382 - p = (unsigned char *)(header+1);
383 -
384 - check_name(&p, header, plen, 1, rrs, rr_found);
385 - p += 4; /* qclass, qtype */
386 -
387 - check_rrs(p, header, plen, 1, rrs, rr_found);
388 -
389 - return plen;
390 -}
391 -
392 unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
393 {
394 int q;
395 diff --git a/src/forward.c b/src/forward.c
396 index dd22a62..3e801c8 100644
397 --- a/src/forward.c
398 +++ b/src/forward.c
399 @@ -662,7 +662,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
400
401 /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
402 if (!do_bit)
403 - n = filter_rrsigs(header, n);
404 + n = rrfilter(header, n, 1);
405 #endif
406
407 /* do this after extract_addresses. Ensure NODATA reply and remove
408 diff --git a/src/rrfilter.c b/src/rrfilter.c
409 new file mode 100644
410 index 0000000..ae12261
411 --- /dev/null
412 +++ b/src/rrfilter.c
413 @@ -0,0 +1,339 @@
414 +/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
415 +
416 + This program is free software; you can redistribute it and/or modify
417 + it under the terms of the GNU General Public License as published by
418 + the Free Software Foundation; version 2 dated June, 1991, or
419 + (at your option) version 3 dated 29 June, 2007.
420 +
421 + This program is distributed in the hope that it will be useful,
422 + but WITHOUT ANY WARRANTY; without even the implied warranty of
423 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
424 + GNU General Public License for more details.
425 +
426 + You should have received a copy of the GNU General Public License
427 + along with this program. If not, see <http://www.gnu.org/licenses/>.
428 +*/
429 +
430 +/* Code to safely remove RRs from an DNS answer */
431 +
432 +#include "dnsmasq.h"
433 +
434 +/* Go through a domain name, find "pointers" and fix them up based on how many bytes
435 + we've chopped out of the packet, or check they don't point into an elided part. */
436 +static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
437 +{
438 + unsigned char *ansp = *namep;
439 +
440 + while(1)
441 + {
442 + unsigned int label_type;
443 +
444 + if (!CHECK_LEN(header, ansp, plen, 1))
445 + return 0;
446 +
447 + label_type = (*ansp) & 0xc0;
448 +
449 + if (label_type == 0xc0)
450 + {
451 + /* pointer for compression. */
452 + unsigned int offset;
453 + int i;
454 + unsigned char *p;
455 +
456 + if (!CHECK_LEN(header, ansp, plen, 2))
457 + return 0;
458 +
459 + offset = ((*ansp++) & 0x3f) << 8;
460 + offset |= *ansp++;
461 +
462 + p = offset + (unsigned char *)header;
463 +
464 + for (i = 0; i < rr_count; i++)
465 + if (p < rrs[i])
466 + break;
467 + else
468 + if (i & 1)
469 + offset -= rrs[i] - rrs[i-1];
470 +
471 + /* does the pointer end up in an elided RR? */
472 + if (i & 1)
473 + return 0;
474 +
475 + /* No, scale the pointer */
476 + if (fixup)
477 + {
478 + ansp -= 2;
479 + *ansp++ = (offset >> 8) | 0xc0;
480 + *ansp++ = offset & 0xff;
481 + }
482 + break;
483 + }
484 + else if (label_type == 0x80)
485 + return 0; /* reserved */
486 + else if (label_type == 0x40)
487 + {
488 + /* Extended label type */
489 + unsigned int count;
490 +
491 + if (!CHECK_LEN(header, ansp, plen, 2))
492 + return 0;
493 +
494 + if (((*ansp++) & 0x3f) != 1)
495 + return 0; /* we only understand bitstrings */
496 +
497 + count = *(ansp++); /* Bits in bitstring */
498 +
499 + if (count == 0) /* count == 0 means 256 bits */
500 + ansp += 32;
501 + else
502 + ansp += ((count-1)>>3)+1;
503 + }
504 + else
505 + { /* label type == 0 Bottom six bits is length */
506 + unsigned int len = (*ansp++) & 0x3f;
507 +
508 + if (!ADD_RDLEN(header, ansp, plen, len))
509 + return 0;
510 +
511 + if (len == 0)
512 + break; /* zero length label marks the end. */
513 + }
514 + }
515 +
516 + *namep = ansp;
517 +
518 + return 1;
519 +}
520 +
521 +/* Go through RRs and check or fixup the domain names contained within */
522 +static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
523 +{
524 + int i, j, type, class, rdlen;
525 + unsigned char *pp;
526 +
527 + for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
528 + {
529 + pp = p;
530 +
531 + if (!(p = skip_name(p, header, plen, 10)))
532 + return 0;
533 +
534 + GETSHORT(type, p);
535 + GETSHORT(class, p);
536 + p += 4; /* TTL */
537 + GETSHORT(rdlen, p);
538 +
539 + /* If this RR is to be elided, don't fix up its contents */
540 + for (j = 0; j < rr_count; j += 2)
541 + if (rrs[j] == pp)
542 + break;
543 +
544 + if (j >= rr_count)
545 + {
546 + /* fixup name of RR */
547 + if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
548 + return 0;
549 +
550 + if (class == C_IN)
551 + {
552 + u16 *d;
553 +
554 + for (pp = p, d = rrfilter_desc(type); *d != (u16)-1; d++)
555 + {
556 + if (*d != 0)
557 + pp += *d;
558 + else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
559 + return 0;
560 + }
561 + }
562 + }
563 +
564 + if (!ADD_RDLEN(header, p, plen, rdlen))
565 + return 0;
566 + }
567 +
568 + return 1;
569 +}
570 +
571 +
572 +/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
573 +size_t rrfilter(struct dns_header *header, size_t plen, int mode)
574 +{
575 + static unsigned char **rrs;
576 + static int rr_sz = 0;
577 +
578 + unsigned char *p = (unsigned char *)(header+1);
579 + int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
580 +
581 + if (ntohs(header->qdcount) != 1 ||
582 + !(p = skip_name(p, header, plen, 4)))
583 + return plen;
584 +
585 + GETSHORT(qtype, p);
586 + GETSHORT(qclass, p);
587 +
588 + /* First pass, find pointers to start and end of all the records we wish to elide:
589 + records added for DNSSEC, unless explicity queried for */
590 + for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0;
591 + i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
592 + i++)
593 + {
594 + unsigned char *pstart = p;
595 + int type, class;
596 +
597 + if (!(p = skip_name(p, header, plen, 10)))
598 + return plen;
599 +
600 + GETSHORT(type, p);
601 + GETSHORT(class, p);
602 + p += 4; /* TTL */
603 + GETSHORT(rdlen, p);
604 +
605 + if (!ADD_RDLEN(header, p, plen, rdlen))
606 + return plen;
607 +
608 + /* Don't remove the answer. */
609 + if (i < ntohs(header->ancount) && type == qtype && class == qclass)
610 + continue;
611 +
612 + if (mode == 0) /* EDNS */
613 + {
614 + /* EDNS mode, remove T_OPT from additional section only */
615 + if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
616 + continue;
617 + }
618 + else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
619 + /* DNSSEC mode, remove SIGs and NSECs from all three sections. */
620 + continue;
621 +
622 +
623 + if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
624 + return plen;
625 +
626 + rrs[rr_found++] = pstart;
627 + rrs[rr_found++] = p;
628 +
629 + if (i < ntohs(header->ancount))
630 + chop_an++;
631 + else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
632 + chop_ns++;
633 + else
634 + chop_ar++;
635 + }
636 +
637 + /* Nothing to do. */
638 + if (rr_found == 0)
639 + return plen;
640 +
641 + /* Second pass, look for pointers in names in the records we're keeping and make sure they don't
642 + point to records we're going to elide. This is theoretically possible, but unlikely. If
643 + it happens, we give up and leave the answer unchanged. */
644 + p = (unsigned char *)(header+1);
645 +
646 + /* question first */
647 + if (!check_name(&p, header, plen, 0, rrs, rr_found))
648 + return plen;
649 + p += 4; /* qclass, qtype */
650 +
651 + /* Now answers and NS */
652 + if (!check_rrs(p, header, plen, 0, rrs, rr_found))
653 + return plen;
654 +
655 + /* Third pass, elide records */
656 + for (p = rrs[0], i = 1; i < rr_found; i += 2)
657 + {
658 + unsigned char *start = rrs[i];
659 + unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen;
660 +
661 + memmove(p, start, end-start);
662 + p += end-start;
663 + }
664 +
665 + plen = p - (unsigned char *)header;
666 + header->ancount = htons(ntohs(header->ancount) - chop_an);
667 + header->nscount = htons(ntohs(header->nscount) - chop_ns);
668 + header->arcount = htons(ntohs(header->arcount) - chop_ar);
669 +
670 + /* Fourth pass, fix up pointers in the remaining records */
671 + p = (unsigned char *)(header+1);
672 +
673 + check_name(&p, header, plen, 1, rrs, rr_found);
674 + p += 4; /* qclass, qtype */
675 +
676 + check_rrs(p, header, plen, 1, rrs, rr_found);
677 +
678 + return plen;
679 +}
680 +
681 +/* This is used in the DNSSEC code too, hence it's exported */
682 +u16 *rrfilter_desc(int type)
683 +{
684 + /* List of RRtypes which include domains in the data.
685 + 0 -> domain
686 + integer -> no of plain bytes
687 + -1 -> end
688 +
689 + zero is not a valid RRtype, so the final entry is returned for
690 + anything which needs no mangling.
691 + */
692 +
693 + static u16 rr_desc[] =
694 + {
695 + T_NS, 0, -1,
696 + T_MD, 0, -1,
697 + T_MF, 0, -1,
698 + T_CNAME, 0, -1,
699 + T_SOA, 0, 0, -1,
700 + T_MB, 0, -1,
701 + T_MG, 0, -1,
702 + T_MR, 0, -1,
703 + T_PTR, 0, -1,
704 + T_MINFO, 0, 0, -1,
705 + T_MX, 2, 0, -1,
706 + T_RP, 0, 0, -1,
707 + T_AFSDB, 2, 0, -1,
708 + T_RT, 2, 0, -1,
709 + T_SIG, 18, 0, -1,
710 + T_PX, 2, 0, 0, -1,
711 + T_NXT, 0, -1,
712 + T_KX, 2, 0, -1,
713 + T_SRV, 6, 0, -1,
714 + T_DNAME, 0, -1,
715 + 0, -1 /* wildcard/catchall */
716 + };
717 +
718 + u16 *p = rr_desc;
719 +
720 + while (*p != type && *p != 0)
721 + while (*p++ != (u16)-1);
722 +
723 + return p+1;
724 +}
725 +
726 +int expand_workspace(unsigned char ***wkspc, int *szp, int new)
727 +{
728 + unsigned char **p;
729 + int old = *szp;
730 +
731 + if (old >= new+1)
732 + return 1;
733 +
734 + if (new >= 100)
735 + return 0;
736 +
737 + new += 5;
738 +
739 + if (!(p = whine_malloc(new * sizeof(unsigned char **))))
740 + return 0;
741 +
742 + if (old != 0 && *wkspc)
743 + {
744 + memcpy(p, *wkspc, old * sizeof(unsigned char **));
745 + free(*wkspc);
746 + }
747 +
748 + *wkspc = p;
749 + *szp = new;
750 +
751 + return 1;
752 +}
753 --
754 1.7.10.4
755