1
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
1
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
3
3
This program is free software; you can redistribute it and/or modify
4
4
it under the terms of the GNU General Public License as published by
10
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
GNU General Public License for more details.
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/>.
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/>.
17
17
#include "dnsmasq.h"
21
21
unsigned long ttl, unsigned int *offset, unsigned short type,
22
22
unsigned short class, char *format, ...);
24
#define CHECK_LEN(header, pp, plen, len) \
25
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
27
#define ADD_RDLEN(header, pp, plen, len) \
28
(!CHECK_LEN(header, pp, plen, len) ? 0 : (long)((pp) += (len)), 1)
24
30
static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
25
char *name, int isExtract)
31
char *name, int isExtract, int extrabytes)
27
33
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
28
34
unsigned int j, l, hops = 0;
36
unsigned int label_type = l & 0xc0;
42
unsigned int label_type;
44
if (!CHECK_LEN(header, p, plen, 1))
50
/* check that there are the correct no of bytes after the name */
51
if (!CHECK_LEN(header, p, plen, extrabytes))
56
if (cp != (unsigned char *)name)
58
*cp = 0; /* terminate: lose final period */
63
if (p1) /* we jumped via compression */
71
label_type = l & 0xc0;
37
73
if (label_type == 0xc0) /* pointer */
39
if ((size_t)(p - (unsigned char *)header) >= plen)
75
if (!CHECK_LEN(header, p, plen, 1))
48
82
if (!p1) /* first jump, save location to go back to */
74
108
/* output is \[x<hex>/siz]. which is digs+9 chars */
75
109
if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
77
if ((size_t)(p - (unsigned char *)header + ((count-1)>>3)) >= plen)
111
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
98
132
{ /* label_type = 0 -> label. */
99
133
if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
101
if ((size_t)(p - (unsigned char *)header) >= plen)
135
if (!CHECK_LEN(header, p, plen, l))
103
138
for(j=0; j<l; j++, p++)
132
167
else if (*cp != 0 && *cp++ != '.')
136
if ((unsigned int)(p - (unsigned char *)header) >= plen)
142
if (cp != (unsigned char *)name)
144
*cp = 0; /* terminate: lose final period */
149
if (p1) /* we jumped via compression */
157
173
/* Max size of input string (for IPv6) is 75 chars.) */
264
static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen)
280
static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen, int extrabytes)
268
unsigned int label_type = (*ansp) & 0xc0;
284
unsigned int label_type;
270
if ((unsigned int)(ansp - (unsigned char *)header) >= plen)
286
if (!CHECK_LEN(header, ansp, plen, 1))
289
label_type = (*ansp) & 0xc0;
273
291
if (label_type == 0xc0)
275
293
/* pointer for compression. */
283
301
/* Extended label type */
284
302
unsigned int count;
304
if (!CHECK_LEN(header, ansp, plen, 2))
286
307
if (((*ansp++) & 0x3f) != 1)
287
308
return NULL; /* we only understand bitstrings */
297
318
{ /* label type == 0 Bottom six bits is length */
298
319
unsigned int len = (*ansp++) & 0x3f;
321
if (!ADD_RDLEN(header, ansp, plen, len))
300
325
break; /* zero length label marks the end. */
329
if (!CHECK_LEN(header, ansp, plen, extrabytes))
314
340
for (q = ntohs(header->qdcount); q != 0; q--)
316
if (!(ansp = skip_name(ansp, header, plen)))
342
if (!(ansp = skip_name(ansp, header, plen, 4)))
318
344
ansp += 4; /* class and type */
320
if ((unsigned int)(ansp - (unsigned char *)header) > plen)
330
354
for (i = 0; i < count; i++)
332
if (!(ansp = skip_name(ansp, header, plen)))
356
if (!(ansp = skip_name(ansp, header, plen, 10)))
334
358
ansp += 8; /* type, class, TTL */
335
359
GETSHORT(rdlen, ansp);
336
if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
360
if (!ADD_RDLEN(header, ansp, plen, rdlen))
356
379
for (q = ntohs(header->qdcount); q != 0; q--)
358
if (!extract_name(header, plen, &p, name, 1))
381
if (!extract_name(header, plen, &p, name, 1, 4))
359
382
return crc; /* bad packet */
361
384
for (p1 = (unsigned char *)name; *p1; p1++)
384
if ((unsigned int)(p - (unsigned char *)header) > plen)
407
if (!CHECK_LEN(header, p, plen, 0))
385
408
return crc; /* bad packet */
394
417
unsigned char *ansp = skip_questions(header, plen);
419
/* if packet is malformed, just return as-is. */
399
423
if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
403
427
/* restore pseudoheader */
404
428
if (pheader && ntohs(header->arcount) == 0)
433
457
for (i = ntohs(header->qdcount); i != 0; i--)
435
if (!(ansp = skip_name(ansp, header, plen)))
459
if (!(ansp = skip_name(ansp, header, plen, 4)))
438
462
GETSHORT(type, ansp);
458
482
for (i = 0; i < arcount; i++)
460
484
unsigned char *save, *start = ansp;
461
if (!(ansp = skip_name(ansp, header, plen)))
485
if (!(ansp = skip_name(ansp, header, plen, 10)))
464
488
GETSHORT(type, ansp);
509
532
for (i = count; i != 0; i--)
511
if (!(p = skip_name(p, header, qlen)))
534
if (!(p = skip_name(p, header, qlen, 10)))
512
535
return 0; /* bad packet */
514
537
GETSHORT(qtype, p);
521
544
struct doctor *doctor;
522
545
struct in_addr addr;
547
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
525
551
memcpy(&addr, p, INADDRSZ);
527
553
for (doctor = daemon->doctors; doctor; doctor = doctor->next)
528
if (is_same_net(doctor->in, addr, doctor->mask))
530
addr.s_addr &= ~doctor->mask.s_addr;
531
addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
532
/* Since we munged the data, the server it came from is no longer authoritative */
534
memcpy(p, &addr, INADDRSZ);
555
if (doctor->end.s_addr == 0)
557
if (!is_same_net(doctor->in, addr, doctor->mask))
560
else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) ||
561
ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
564
addr.s_addr &= ~doctor->mask.s_addr;
565
addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
566
/* Since we munged the data, the server it came from is no longer authoritative */
568
memcpy(p, &addr, INADDRSZ);
541
if ((size_t)(p - (unsigned char *)header) > qlen)
542
return 0; /* bad packet */
573
if (!ADD_RDLEN(header, p, qlen, rdlen))
574
return 0; /* bad packet */
560
592
for (i = ntohs(header->nscount); i != 0; i--)
562
if (!(p = skip_name(p, header, qlen)))
594
if (!(p = skip_name(p, header, qlen, 10)))
563
595
return 0; /* bad packet */
565
597
GETSHORT(qtype, p);
577
if (!(p = skip_name(p, header, qlen)))
609
if (!(p = skip_name(p, header, qlen, 0)))
580
if (!(p = skip_name(p, header, qlen)))
612
if (!(p = skip_name(p, header, qlen, 20)))
582
614
p += 16; /* SERIAL REFRESH RETRY EXPIRE */
585
617
if (ttl < minttl)
591
if ((size_t)(p - (unsigned char *)header) > qlen)
620
else if (!ADD_RDLEN(header, p, qlen, rdlen))
592
621
return 0; /* bad packet */
595
624
/* rewrite addresses in additioal section too */
596
625
if (!do_doctor(p, ntohs(header->arcount), header, qlen))
633
662
unsigned long cttl = ULONG_MAX, attl;
636
if (!extract_name(header, qlen, &p, name, 1))
665
if (!extract_name(header, qlen, &p, name, 1, 4))
637
666
return 0; /* bad packet */
639
668
GETSHORT(qtype, p);
662
691
unsigned char *tmp = namep;
663
692
/* the loop body overwrites the original name, so get it back here. */
664
if (!extract_name(header, qlen, &tmp, name, 1) ||
665
!(res = extract_name(header, qlen, &p1, name, 0)))
693
if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
694
!(res = extract_name(header, qlen, &p1, name, 0, 10)))
666
695
return 0; /* bad packet */
668
697
GETSHORT(aqtype, p1);
678
707
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
680
if (!extract_name(header, qlen, &p1, name, 1))
709
if (!extract_name(header, qlen, &p1, name, 1, 0))
683
712
if (aqtype == T_CNAME)
695
if ((size_t)(p1 - (unsigned char *)header) > qlen)
724
if (!CHECK_LEN(header, p1, qlen, 0))
696
725
return 0; /* bad packet */
738
767
for (j = ntohs(header->ancount); j != 0; j--)
740
if (!(res = extract_name(header, qlen, &p1, name, 0)))
769
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
741
770
return 0; /* bad packet */
743
772
GETSHORT(aqtype, p1);
766
if (!extract_name(header, qlen, &p1, name, 1))
795
if (!extract_name(header, qlen, &p1, name, 1, 0))
768
797
goto cname_loop1;
773
803
/* copy address into aligned storage */
804
if (!CHECK_LEN(header, p1, qlen, addrlen))
805
return 0; /* bad packet */
774
806
memcpy(&addr, p1, addrlen);
776
808
/* check for returned address in private space */
793
if ((size_t)(p1 - (unsigned char *)header) > qlen)
825
if (!CHECK_LEN(header, p1, qlen, 0))
794
826
return 0; /* bad packet */
839
871
if (ntohs(header->qdcount) != 1 || header->opcode != QUERY)
840
872
return 0; /* must be exactly one query. */
842
if (!extract_name(header, qlen, &p, name, 1))
874
if (!extract_name(header, qlen, &p, name, 1, 4))
843
875
return 0; /* bad packet */
845
877
GETSHORT(qtype, p);
954
986
for (i = ntohs(header->ancount); i != 0; i--)
956
if (!extract_name(header, qlen, &p, name, 1))
988
if (!extract_name(header, qlen, &p, name, 1, 10))
957
989
return 0; /* bad packet */
959
991
GETSHORT(qtype, p);
962
994
GETSHORT(rdlen, p);
964
996
if (qclass == C_IN && qtype == T_A)
965
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
966
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
968
/* Found a bogus address. Insert that info here, since there no SOA record
969
to get the ttl from in the normal processing */
970
cache_start_insert();
971
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
998
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
1001
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
1002
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
1004
/* Found a bogus address. Insert that info here, since there no SOA record
1005
to get the ttl from in the normal processing */
1006
cache_start_insert();
1007
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
1014
if (!ADD_RDLEN(header, p, qlen, rdlen))
1114
static unsigned long crec_ttl(struct crec *crecp, time_t now)
1116
/* Return 0 ttl for DHCP entries, which might change
1117
before the lease expires. */
1119
if (crecp->flags & (F_IMMORTAL | F_DHCP))
1120
return daemon->local_ttl;
1122
return crecp->ttd - now;
1076
1126
/* return zero if we can't answer from cache, or packet size if we can */
1077
1127
size_t answer_request(HEADER *header, char *limit, size_t qlen,
1078
1128
struct in_addr local_addr, struct in_addr local_netmask, time_t now)
1137
1187
nameoffset = p - (unsigned char *)header;
1139
1189
/* now extract name as .-concatenated string into name */
1140
if (!extract_name(header, qlen, &p, name, 1))
1190
if (!extract_name(header, qlen, &p, name, 1, 4))
1141
1191
return 0; /* bad packet */
1143
1193
GETSHORT(qtype, p);
1243
/* Return 0 ttl for DHCP entries, which might change
1244
before the lease expires. */
1245
if (crecp->flags & (F_IMMORTAL | F_DHCP))
1246
ttl = daemon->local_ttl;
1248
ttl = crecp->ttd - now;
1250
1292
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
1251
1293
record_source(daemon->addn_hosts, crecp->uid));
1253
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL,
1295
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1296
crec_ttl(crecp, now), NULL,
1254
1297
T_PTR, C_IN, "d", cache_get_name(crecp)))
1360
1403
log_query(crecp->flags, name, NULL, record_source(daemon->addn_hosts, crecp->uid));
1361
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, crecp->ttd - now, &nameoffset,
1404
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1405
crec_ttl(crecp, now), &nameoffset,
1362
1406
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
1396
if (crecp->flags & (F_IMMORTAL | F_DHCP))
1397
ttl = daemon->local_ttl;
1399
ttl = crecp->ttd - now;
1401
1438
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
1402
1439
record_source(daemon->addn_hosts, crecp->uid));
1404
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, type, C_IN,
1441
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1442
crec_ttl(crecp, now), NULL, type, C_IN,
1405
1443
type == T_A ? "4" : "6", &crecp->addr))
1538
1575
if (crecp->flags & F_NEG)
1541
if (crecp->flags & (F_IMMORTAL | F_DHCP))
1542
ttl = daemon->local_ttl;
1544
ttl = crecp->ttd - now;
1546
if (add_resource_record(header, limit, NULL, rec->offset, &ansp, ttl, NULL, type, C_IN,
1578
if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
1579
crec_ttl(crecp, now), NULL, type, C_IN,
1547
1580
crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))