1/* dnsmasq is Copyright (c) 2000 Simon Kelley 2 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. 6 7 This program is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU General Public License for more details. 11*/ 12 13#include "dnsmasq.h" 14 15static int extract_name(HEADER *header, unsigned int plen, unsigned char **pp, 16 unsigned char *name, int isExtract) 17{ 18 unsigned char *cp = name, *p = *pp, *p1 = NULL; 19 unsigned int j, l, hops = 0; 20 int retvalue = 1; 21 22 while ((l = *p++)) 23 { 24 unsigned int label_type = l & 0xc0; 25 if (label_type == 0xc0) /* pointer */ 26 { 27 if (p - (unsigned char *)header + 1u >= plen) 28 return 0; 29 30 /* get offset */ 31 l = (l&0x3f) << 8; 32 l |= *p++; 33 if (l >= (unsigned int)plen) 34 return 0; 35 36 if (!p1) /* first jump, save location to go back to */ 37 p1 = p; 38 39 hops++; /* break malicious infinite loops */ 40 if (hops > 255) 41 return 0; 42 43 p = l + (unsigned char *)header; 44 } 45 else if (label_type == 0x80) 46 return 0; /* reserved */ 47 else if (label_type == 0x40) 48 { /* ELT */ 49 unsigned int count, digs; 50 51 if ((l & 0x3f) != 1) 52 return 0; /* we only understand bitstrings */ 53 54 if (!isExtract) 55 return 0; /* Cannot compare bitsrings */ 56 57 count = *p++; 58 if (count == 0) 59 count = 256; 60 digs = ((count-1)>>2)+1; 61 62 /* output is \[x<hex>/siz]. which is digs+9 chars */ 63 if (cp - name + digs + 9 >= MAXDNAME) 64 return 0; 65 if (p - (unsigned char *)header + ((count-1)>>3) + 1u >= plen) 66 return 0; 67 68 *cp++ = '\\'; 69 *cp++ = '['; 70 *cp++ = 'x'; 71 for (j=0; j<digs; j++) 72 { 73 unsigned int dig; 74 if (j%2 == 0) 75 dig = *p >> 4; 76 else 77 dig = *p++ & 0x0f; 78 79 *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10; 80 } 81 cp += sprintf(cp, "/%d]", count); 82 /* do this here to overwrite the zero char from sprintf */ 83 *cp++ = '.'; 84 } 85 else 86 { /* label_type = 0 -> label. */ 87 if (cp - name + l + 1 >= MAXDNAME) 88 return 0; 89 if (p - (unsigned char *)header + 1u >= plen) 90 return 0; 91 for(j=0; j<l; j++, p++) 92 if (isExtract) 93 { 94 if (legal_char(*p)) 95 *cp++ = *p; 96 else 97 return 0; 98 } 99 else 100 { 101 unsigned char c1 = *cp, c2 = *p; 102 103 if (c1 == 0) 104 retvalue = 2; 105 else 106 { 107 cp++; 108 if (c1 >= 'A' && c1 <= 'Z') 109 c1 += 'a' - 'A'; 110 if (c2 >= 'A' && c2 <= 'Z') 111 c2 += 'a' - 'A'; 112 113 if (c1 != c2) 114 retvalue = 2; 115 } 116 } 117 118 if (isExtract) 119 *cp++ = '.'; 120 else 121 if (*cp != 0 && *cp++ != '.') 122 retvalue = 2; 123 } 124 125 if ((unsigned int)(p - (unsigned char *)header) >= plen) 126 return 0; 127 } 128 129 if (isExtract) 130 *--cp = 0; /* terminate: lose final period */ 131 132 if (p1) /* we jumped via compression */ 133 *pp = p1; 134 else 135 *pp = p; 136 137 return retvalue; 138} 139 140/* Max size of input string (for IPv6) is 75 chars.) */ 141#define MAXARPANAME 75 142static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp) 143{ 144 int j; 145 char name[MAXARPANAME+1], *cp1; 146 unsigned char *addr = (unsigned char *)addrp; 147 char *lastchunk = NULL, *penchunk = NULL; 148 149 if (strlen(namein) > MAXARPANAME) 150 return 0; 151 152 memset(addrp, 0, sizeof(struct all_addr)); 153 154 /* turn name into a series of asciiz strings */ 155 /* j counts no of labels */ 156 for(j = 1,cp1 = name; *namein; cp1++, namein++) 157 if (*namein == '.') 158 { 159 penchunk = lastchunk; 160 lastchunk = cp1 + 1; 161 *cp1 = 0; 162 j++; 163 } 164 else 165 *cp1 = *namein; 166 167 *cp1 = 0; 168 169 if (j<3) 170 return 0; 171 172 if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr")) 173 { 174 /* IP v4 */ 175 /* address arives as a name of the form 176 www.xxx.yyy.zzz.in-addr.arpa 177 some of the low order address octets might be missing 178 and should be set to zero. */ 179 for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1) 180 { 181 /* check for digits only (weeds out things like 182 50.0/24.67.28.64.in-addr.arpa which are used 183 as CNAME targets according to RFC 2317 */ 184 char *cp; 185 for (cp = cp1; *cp; cp++) 186 if (!isdigit((int)*cp)) 187 return 0; 188 189 addr[3] = addr[2]; 190 addr[2] = addr[1]; 191 addr[1] = addr[0]; 192 addr[0] = atoi(cp1); 193 } 194 195 return F_IPV4; 196 } 197#ifdef HAVE_IPV6 198 else if (hostname_isequal(penchunk, "ip6") && 199 (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa"))) 200 { 201 /* IP v6: 202 Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa] 203 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa] 204 205 Note that most of these the various reprentations are obsolete and 206 left-over from the many DNS-for-IPv6 wars. We support all the formats 207 that we can since there is no reason not to. 208 */ 209 210 if (*name == '\\' && *(name+1) == '[' && 211 (*(name+2) == 'x' || *(name+2) == 'X')) 212 { 213 for (j = 0, cp1 = name+3; *cp1 && isxdigit(*cp1) && j < 32; cp1++, j++) 214 { 215 char xdig[2]; 216 xdig[0] = *cp1; 217 xdig[1] = 0; 218 if (j%2) 219 addr[j/2] |= strtol(xdig, NULL, 16); 220 else 221 addr[j/2] = strtol(xdig, NULL, 16) << 4; 222 } 223 224 if (*cp1 == '/' && j == 32) 225 return F_IPV6; 226 } 227 else 228 { 229 for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1) 230 { 231 if (*(cp1+1) || !isxdigit((int)*cp1)) 232 return 0; 233 234 for (j = sizeof(struct all_addr)-1; j>0; j--) 235 addr[j] = (addr[j] >> 4) | (addr[j-1] << 4); 236 addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4); 237 } 238 239 return F_IPV6; 240 } 241 } 242#endif 243 244 return 0; 245} 246 247static unsigned char *skip_name(unsigned char *ansp, HEADER *header, unsigned int plen) 248{ 249 while(1) 250 { 251 unsigned int label_type = (*ansp) & 0xc0; 252 253 if ((unsigned int)(ansp - (unsigned char *)header) >= plen) 254 return NULL; 255 256 if (label_type == 0xc0) 257 { 258 /* pointer for compression. */ 259 ansp += 2; 260 break; 261 } 262 else if (label_type == 0x80) 263 return NULL; /* reserved */ 264 else if (label_type == 0x40) 265 { 266 /* Extended label type */ 267 unsigned int count; 268 269 if (((*ansp++) & 0x3f) != 1) 270 return NULL; /* we only understand bitstrings */ 271 272 count = *(ansp++); /* Bits in bitstring */ 273 274 if (count == 0) /* count == 0 means 256 bits */ 275 ansp += 32; 276 else 277 ansp += ((count-1)>>3)+1; 278 } 279 else 280 { /* label type == 0 Bottom six bits is length */ 281 unsigned int len = (*ansp++) & 0x3f; 282 if (len == 0) 283 break; /* zero length label marks the end. */ 284 285 ansp += len; 286 } 287 } 288 289 return ansp; 290} 291 292static unsigned char *skip_questions(HEADER *header, unsigned int plen) 293{ 294 int q, qdcount = ntohs(header->qdcount); 295 unsigned char *ansp = (unsigned char *)(header+1); 296 297 for (q = 0; q<qdcount; q++) 298 { 299 if (!(ansp = skip_name(ansp, header, plen))) 300 return NULL; 301 ansp += 4; /* class and type */ 302 } 303 if ((unsigned int)(ansp - (unsigned char *)header) > plen) 304 return NULL; 305 306 return ansp; 307} 308 309int resize_packet(HEADER *header, unsigned int plen, unsigned char *pheader, unsigned int hlen) 310{ 311 int i; 312 unsigned char *ansp = skip_questions(header, plen); 313 unsigned short rdlen; 314 315 if (!ansp) 316 return 0; 317 318 for (i = 0; 319 i < (ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount)); 320 i++) 321 { 322 if (!(ansp = skip_name(ansp, header, plen))) 323 return 0; 324 ansp += 8; /* type, class, TTL */ 325 GETSHORT(rdlen, ansp); 326 if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen) 327 return 0; 328 ansp += rdlen; 329 } 330 331 /* restore pseudoheader */ 332 if (pheader && ntohs(header->arcount) == 0) 333 { 334 /* must use memmove, may overlap */ 335 memmove(ansp, pheader, hlen); 336 header->arcount = htons(1); 337 ansp += hlen; 338 } 339 340 return ansp - (unsigned char *)header; 341} 342 343unsigned char *find_pseudoheader(HEADER *header, unsigned int plen, unsigned int *len, unsigned char **p) 344{ 345 /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 346 also return length of pseudoheader in *len and pointer to the UDP size in *p */ 347 348 int i, arcount = ntohs(header->arcount); 349 unsigned char *ansp; 350 unsigned short rdlen, type; 351 352 if (arcount == 0 || !(ansp = skip_questions(header, plen))) 353 return NULL; 354 355 for (i = 0; i < (ntohs(header->ancount) + ntohs(header->nscount)); i++) 356 { 357 if (!(ansp = skip_name(ansp, header, plen))) 358 return NULL; 359 ansp += 8; /* type, class, TTL */ 360 GETSHORT(rdlen, ansp); 361 if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen) 362 return NULL; 363 ansp += rdlen; 364 } 365 366 for (i = 0; i < arcount; i++) 367 { 368 unsigned char *save, *start = ansp; 369 if (!(ansp = skip_name(ansp, header, plen))) 370 return NULL; 371 372 GETSHORT(type, ansp); 373 save = ansp; 374 ansp += 6; /* class, TTL */ 375 GETSHORT(rdlen, ansp); 376 if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen) 377 return NULL; 378 ansp += rdlen; 379 if (type == T_OPT) 380 { 381 if (len) 382 *len = ansp - start; 383 if (p) 384 *p = save; 385 return start; 386 } 387 } 388 389 return NULL; 390} 391 392 393/* is addr in the non-globally-routed IP space? */ 394static int private_net(struct all_addr *addrp) 395{ 396 struct in_addr addr = *(struct in_addr *)addrp; 397 if (inet_netof(addr) == 0xA || 398 (inet_netof(addr) >= 0xAC10 && inet_netof(addr) < 0xAC20) || 399 (inet_netof(addr) >> 8) == 0xC0A8) 400 return 1; 401 else 402 return 0; 403} 404 405static unsigned char *add_text_record(unsigned int nameoffset, unsigned char *p, 406 unsigned long ttl, unsigned short pref, 407 unsigned short type, char *name) 408{ 409 unsigned char *sav, *cp; 410 int j; 411 412 PUTSHORT(nameoffset | 0xc000, p); 413 PUTSHORT(type, p); 414 PUTSHORT(C_IN, p); 415 PUTLONG(ttl, p); /* TTL */ 416 417 sav = p; 418 PUTSHORT(0, p); /* dummy RDLENGTH */ 419 420 if (pref) 421 PUTSHORT(pref, p); 422 423 while (*name) 424 { 425 cp = p++; 426 for (j=0; *name && (*name != '.'); name++, j++) 427 *p++ = *name; 428 *cp = j; 429 if (*name) 430 name++; 431 } 432 *p++ = 0; 433 j = p - sav - 2; 434 PUTSHORT(j, sav); /* Real RDLENGTH */ 435 436 return p; 437} 438 439/* On receiving an NXDOMAIN or NODATA reply, determine which names are known 440 not to exist for negative caching. name if a working buffer passed in. */ 441void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now, unsigned short flags) 442{ 443 unsigned char *p; 444 int i, found_soa = 0; 445 int qtype, qclass, rdlen; 446 unsigned long ttl, minttl = 0; 447 448 /* there may be more than one question with some questions 449 answered. We don't generate negative entries from those. */ 450 if (ntohs(header->ancount) != 0) 451 return; 452 453 if (!(p = skip_questions(header, qlen))) 454 return; /* bad packet */ 455 456 /* we first need to find SOA records, to get min TTL, then we 457 add a NEG cache entry for each question. */ 458 459 for (i=0; i<ntohs(header->nscount); i++) 460 { 461 if (!extract_name(header, qlen, &p, name, 1)) 462 return; /* bad packet */ 463 464 GETSHORT(qtype, p); 465 GETSHORT(qclass, p); 466 GETLONG(ttl, p); 467 GETSHORT(rdlen, p); 468 469 if ((qclass == C_IN) && (qtype == T_SOA)) 470 { 471 int dummy; 472 /* MNAME */ 473 if (!extract_name(header, qlen, &p, name, 1)) 474 return; 475 /* RNAME */ 476 if (!extract_name(header, qlen, &p, name, 1)) 477 return; 478 GETLONG(dummy, p); /* SERIAL */ 479 GETLONG(dummy, p); /* REFRESH */ 480 GETLONG(dummy, p); /* RETRY */ 481 GETLONG(dummy, p); /* EXPIRE */ 482 if (!found_soa) 483 { 484 found_soa = 1; 485 minttl = ttl; 486 } 487 else if (ttl < minttl) 488 minttl = ttl; 489 GETLONG(ttl, p); /* minTTL */ 490 if (ttl < minttl) 491 minttl = ttl; 492 } 493 else 494 p += rdlen; 495 496 if ((unsigned int)(p - (unsigned char *)header) > qlen) 497 return; /* bad packet */ 498 } 499 500 if (!found_soa) 501 return; /* failed to find SOA */ 502 503 cache_start_insert(); 504 505 p = (unsigned char *)(header+1); 506 507 for (i=0; i<ntohs(header->qdcount); i++) 508 { 509 struct all_addr addr; 510 int is_arpa; 511 512 if (!extract_name(header, qlen, &p, name, 1)) 513 return; /* bad packet */ 514 515 GETSHORT(qtype, p); 516 GETSHORT(qclass, p); 517 518 if (qclass == C_IN && qtype == T_PTR && (is_arpa = in_arpa_name_2_addr(name, &addr))) 519 cache_insert(name, &addr, now, minttl , is_arpa | F_REVERSE | flags); 520 else if (qclass == C_IN && qtype == T_A) 521 cache_insert(name, NULL, now, minttl, F_IPV4 | F_FORWARD | flags); 522#ifdef HAVE_IPV6 523 else if (qclass == C_IN && qtype == T_AAAA) 524 cache_insert(name, NULL, now, minttl, F_IPV6 | F_FORWARD | flags); 525#endif 526 } 527 528 cache_end_insert(); 529} 530 531static void dns_doctor(HEADER *header, struct doctor *doctor, struct in_addr *addr) 532{ 533 for (; doctor; doctor = doctor->next) 534 if (is_same_net(doctor->in, *addr, doctor->mask)) 535 { 536 addr->s_addr &= ~doctor->mask.s_addr; 537 addr->s_addr |= (doctor->out.s_addr & doctor->mask.s_addr); 538 /* Since we munged the data, the server it came from is no longer authoritative */ 539 header->nscount = htons(0); 540 header->arcount = htons(0); 541 break; 542 } 543} 544 545void extract_addresses(HEADER *header, unsigned int qlen, char *name, 546 time_t now, struct doctor *doctors) 547{ 548 unsigned char *p, *psave, *endrr; 549 int qtype, qclass, rdlen; 550 unsigned long ttl; 551 int i; 552 553 /* skip over questions */ 554 if (!(p = skip_questions(header, qlen))) 555 return; /* bad packet */ 556 557 cache_start_insert(); 558 559 psave = p; 560 561 for (i=0; i<ntohs(header->ancount); i++) 562 { 563 unsigned char *origname = p; 564 if (!extract_name(header, qlen, &p, name, 1)) 565 return; /* bad packet */ 566 567 GETSHORT(qtype, p); 568 GETSHORT(qclass, p); 569 GETLONG(ttl, p); 570 GETSHORT(rdlen, p); 571 572 endrr = p + rdlen; 573 if ((unsigned int)(endrr - (unsigned char *)header) > qlen) 574 return; /* bad packet */ 575 576 if (qclass != C_IN) 577 { 578 p = endrr; 579 continue; 580 } 581 582 if (qtype == T_A) /* A record. */ 583 { 584 dns_doctor(header, doctors, (struct in_addr *)p); 585 cache_insert(name, (struct all_addr *)p, now, 586 ttl, F_IPV4 | F_FORWARD); 587 } 588#ifdef HAVE_IPV6 589 else if (qtype == T_AAAA) /* IPV6 address record. */ 590 cache_insert(name, (struct all_addr *)p, now, 591 ttl, F_IPV6 | F_FORWARD); 592#endif 593 else if (qtype == T_PTR) 594 { 595 /* PTR record */ 596 struct all_addr addr; 597 int name_encoding = in_arpa_name_2_addr(name, &addr); 598 if (name_encoding) 599 { 600 if (!extract_name(header, qlen, &p, name, 1)) 601 return; /* bad packet */ 602 cache_insert(name, &addr, now, 603 ttl, name_encoding | F_REVERSE); 604 } 605 } 606 else if (qtype == T_CNAME) 607 { 608 /* CNAME, search whole answer section again */ 609 unsigned char *endrr1; 610 unsigned long cttl; 611 int j; 612 unsigned char *targp = p; 613 614 p = psave; /* rewind p */ 615 for (j=0; j<ntohs(header->ancount); j++) 616 { 617 int res; 618 unsigned char *tmp = targp; 619 /* copy since it gets altered by extract_name */ 620 /* get CNAME target each time round */ 621 if (!extract_name(header, qlen, &tmp, name, 1)) 622 return; /* bad packet */ 623 /* compare this name with target of CNAME in name buffer */ 624 if (!(res = extract_name(header, qlen, &p, name, 0))) 625 return; /* bad packet */ 626 627 GETSHORT(qtype, p); 628 GETSHORT(qclass, p); 629 GETLONG(cttl, p); 630 GETSHORT(rdlen, p); 631 632 endrr1 = p+rdlen; 633 if ((unsigned int)(endrr1 - (unsigned char *)header) > qlen) 634 return; /* bad packet */ 635 636 /* is this RR name same as target of CNAME */ 637 if ((qclass != C_IN) || (res == 2)) 638 { 639 p = endrr1; 640 continue; 641 } 642 643 /* match, use name of CNAME, data from this RR 644 use min TTL of two */ 645 646 if (ttl < cttl) 647 cttl = ttl; 648 649 /* get orig. name back again */ 650 tmp = origname; 651 if (!extract_name(header, qlen, &tmp, name, 1)) 652 return; 653 654 if (qtype == T_A) /* A record. */ 655 { 656 dns_doctor(header, doctors, (struct in_addr *)p); 657 cache_insert(name, (struct all_addr *)p, now, 658 cttl, F_IPV4 | F_FORWARD); 659 } 660#ifdef HAVE_IPV6 661 else if (qtype == T_AAAA) /* IPV6 address record. */ 662 cache_insert(name, (struct all_addr *)p, now, 663 cttl, F_IPV6 | F_FORWARD); 664#endif 665 else if (qtype == T_PTR) 666 { 667 /* PTR record extract address from CNAME name */ 668 struct all_addr addr; 669 int name_encoding = in_arpa_name_2_addr(name, &addr); 670 if (name_encoding) 671 { 672 if (!extract_name(header, qlen, &p, name, 1)) 673 return; /* bad packet */ 674 cache_insert(name, &addr, now, cttl, 675 name_encoding | F_REVERSE); 676 } 677 } 678 p = endrr1; 679 } 680 } 681 p = endrr; 682 } 683 684 cache_end_insert(); 685} 686 687/* If the packet holds exactly one query 688 return 1 and leave the name from the query in name. */ 689 690unsigned short extract_request(HEADER *header,unsigned int qlen, char *name, unsigned short *typep) 691{ 692 unsigned char *p = (unsigned char *)(header+1); 693 int qtype, qclass; 694 695 if (typep) 696 *typep = 0; 697 698 if (ntohs(header->qdcount) != 1 || header->opcode != QUERY) 699 return 0; /* must be exactly one query. */ 700 701 if (!extract_name(header, qlen, &p, name, 1)) 702 return 0; /* bad packet */ 703 704 GETSHORT(qtype, p); 705 GETSHORT(qclass, p); 706 707 if (qclass == C_IN) 708 { 709 if (typep) 710 *typep = qtype; 711 712 if (qtype == T_A) 713 return F_IPV4; 714 if (qtype == T_AAAA) 715 return F_IPV6; 716 if (qtype == T_ANY) 717 return F_IPV4 | F_IPV6; 718 } 719 720 return F_QUERY; 721} 722 723 724int setup_reply(HEADER *header, unsigned int qlen, 725 struct all_addr *addrp, unsigned short flags, unsigned long ttl) 726{ 727 unsigned char *p = skip_questions(header, qlen); 728 729 header->qr = 1; /* response */ 730 header->aa = 0; /* authoritive */ 731 header->ra = 1; /* recursion if available */ 732 header->tc = 0; /* not truncated */ 733 header->nscount = htons(0); 734 header->arcount = htons(0); 735 header->ancount = htons(0); /* no answers unless changed below */ 736 if (flags == F_NEG) 737 header->rcode = SERVFAIL; /* couldn't get memory */ 738 else if (flags == F_NOERR || flags == F_QUERY) 739 header->rcode = NOERROR; /* empty domain */ 740 else if (flags == F_NXDOMAIN) 741 header->rcode = NXDOMAIN; 742 else if (p && flags == F_IPV4) 743 { /* we know the address */ 744 header->rcode = NOERROR; 745 header->ancount = htons(1); 746 header->aa = 1; 747 PUTSHORT (sizeof(HEADER) | 0xc000, p); 748 PUTSHORT(T_A, p); 749 PUTSHORT(C_IN, p); 750 PUTLONG(ttl, p); /* TTL */ 751 PUTSHORT(INADDRSZ, p); 752 memcpy(p, addrp, INADDRSZ); 753 p += INADDRSZ; 754 } 755#ifdef HAVE_IPV6 756 else if (p && flags == F_IPV6) 757 { 758 header->rcode = NOERROR; 759 header->ancount = htons(1); 760 header->aa = 1; 761 PUTSHORT (sizeof(HEADER) | 0xc000, p); 762 PUTSHORT(T_AAAA, p); 763 PUTSHORT(C_IN, p); 764 PUTLONG(ttl, p); /* TTL */ 765 PUTSHORT(IN6ADDRSZ, p); 766 memcpy(p, addrp, IN6ADDRSZ); 767 p += IN6ADDRSZ; 768 } 769#endif 770 else /* nowhere to forward to */ 771 header->rcode = REFUSED; 772 773 return p - (unsigned char *)header; 774} 775 776/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */ 777int check_for_local_domain(char *name, time_t now, struct mx_record *mx) 778{ 779 struct crec *crecp; 780 781 if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4|F_IPV6)) && 782 (crecp->flags & (F_HOSTS | F_DHCP))) 783 return 1; 784 785 for (; mx; mx = mx->next) 786 if (hostname_isequal(name, mx->mxname)) 787 return 1; 788 789 return 0; 790} 791 792/* Is the packet a reply with the answer address equal to addr? 793 If so mung is into an NXDOMAIN reply and also put that information 794 in the cache. */ 795int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name, 796 struct bogus_addr *baddr, time_t now) 797{ 798 unsigned char *p; 799 int i, qtype, qclass, rdlen; 800 unsigned long ttl; 801 struct bogus_addr *baddrp; 802 803 /* skip over questions */ 804 if (!(p = skip_questions(header, qlen))) 805 return 0; /* bad packet */ 806 807 for (i=0; i<ntohs(header->ancount); i++) 808 { 809 if (!extract_name(header, qlen, &p, name, 1)) 810 return 0; /* bad packet */ 811 812 GETSHORT(qtype, p); 813 GETSHORT(qclass, p); 814 GETLONG(ttl, p); 815 GETSHORT(rdlen, p); 816 817 if (qclass == C_IN && qtype == T_A) 818 for (baddrp = baddr; baddrp; baddrp = baddrp->next) 819 if (memcmp(&baddrp->addr, p, INADDRSZ) == 0) 820 { 821 /* Found a bogus address. Mangle the packet into an NXDOMAIN reply */ 822 header->aa = 0; 823 header->ra = 1; /* recursion if available */ 824 header->nscount = htons(0); 825 header->arcount = htons(0); 826 header->ancount = htons(0); 827 header->rcode = NXDOMAIN; 828 829 cache_start_insert(); 830 cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG); 831 cache_end_insert(); 832 833 return 1; 834 } 835 836 p += rdlen; 837 } 838 839 return 0; 840} 841 842/* return zero if we can't answer from cache, or packet size if we can */ 843int answer_request(HEADER *header, char *limit, unsigned int qlen, struct daemon *daemon, time_t now) 844{ 845 char *name = daemon->namebuff; 846 unsigned char *p, *ansp, *pheader; 847 int qtype, qclass, is_arpa; 848 struct all_addr addr; 849 unsigned int nameoffset; 850 unsigned short flag; 851 int qdcount = ntohs(header->qdcount); 852 int q, ans, anscount; 853 int dryrun = 0, sec_reqd = 0; 854 struct crec *crecp; 855 int nxdomain, auth; 856 857 if (!qdcount || header->opcode != QUERY ) 858 return 0; 859 860 /* If there is an RFC2671 pseudoheader then it will be overwritten by 861 partial replies, so we have to do a dry run to see if we can answer 862 the query. We check to see if the do bit is set, if so we always 863 forward rather than answering from the cache, which doesn't include 864 security information. */ 865 866 if (find_pseudoheader(header, qlen, NULL, &pheader)) 867 { 868 unsigned short udpsz, ext_rcode, flags; 869 unsigned char *psave = pheader; 870 871 GETSHORT(udpsz, pheader); 872 GETSHORT(ext_rcode, pheader); 873 GETSHORT(flags, pheader); 874 875 sec_reqd = flags & 0x8000; /* do bit */ 876 877 /* If our client is advertising a larger UDP packet size 878 than we allow, trim it so that we don't get an overlarge 879 response from upstream */ 880 881 if (udpsz > daemon->edns_pktsz) 882 PUTSHORT(daemon->edns_pktsz, psave); 883 884 dryrun = 1; 885 } 886 887 rerun: 888 /* determine end of question section (we put answers there) */ 889 if (!(ansp = skip_questions(header, qlen))) 890 return 0; /* bad packet */ 891 892 /* now process each question, answers go in RRs after the question */ 893 p = (unsigned char *)(header+1); 894 nxdomain = 0, auth = 1, anscount = 0; 895 896 for (q=0; q<qdcount; q++) 897 { 898 /* save pointer to name for copying into answers */ 899 nameoffset = p - (unsigned char *)header; 900 901 /* now extract name as .-concatenated string into name */ 902 if (!extract_name(header, qlen, &p, name, 1)) 903 return 0; /* bad packet */ 904 905 /* see if it's w.z.y.z.in-addr.arpa format */ 906 907 is_arpa = in_arpa_name_2_addr(name, &addr); 908 909 GETSHORT(qtype, p); 910 GETSHORT(qclass, p); 911 912 ans = 0; /* have we answered this question */ 913 914 if (qclass == C_CHAOS && qtype == T_TXT) 915 /* special query to get version. */ 916 { 917 ans = 1; 918 if (!dryrun) 919 { 920 int len; 921 if (hostname_isequal(name, "version.bind")) 922 sprintf(name, "dnsmasq-%s", VERSION); 923 else if (hostname_isequal(name, "authors.bind")) 924 sprintf(name, "Simon Kelley"); 925 else if (hostname_isequal(name, "copyright.bind")) 926 sprintf(name, COPYRIGHT); 927 else 928 *name = 0; 929 len = strlen(name); 930 PUTSHORT(nameoffset | 0xc000, ansp); 931 PUTSHORT(T_TXT, ansp); 932 PUTSHORT(C_CHAOS, ansp); 933 PUTLONG(0, ansp); 934 PUTSHORT(len+1, ansp); 935 *ansp++ = len; 936 memcpy(ansp, name, len); 937 ansp += len; 938 anscount++; 939 } 940 } 941 else if (qclass == C_IN) 942 { 943 if ((daemon->options & OPT_FILTER) && 944 (qtype == T_SOA || qtype == T_SRV || (qtype == T_ANY && strchr(name, '_')))) 945 { 946 ans = 1; 947 log_query(F_CONFIG | F_NEG, name, &addr, 0); 948 } 949 else 950 { 951 if (qtype == T_PTR || qtype == T_ANY) 952 { 953 if (!(crecp = cache_find_by_addr(NULL, &addr, now, is_arpa))) 954 { 955 if (is_arpa == F_IPV4 && (daemon->options & OPT_BOGUSPRIV) && private_net(&addr)) 956 { 957 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */ 958 ans = 1; 959 if (!dryrun) 960 { 961 log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, name, &addr, 0); 962 nxdomain = 1; 963 } 964 } 965 } 966 else do 967 { 968 /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */ 969 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) 970 continue; 971 972 if (crecp->flags & F_NEG) 973 { 974 ans = 1; 975 if (!dryrun) 976 { 977 log_query(crecp->flags & ~F_FORWARD, name, &addr, 0); 978 auth = 0; 979 if (crecp->flags & F_NXDOMAIN) 980 nxdomain = 1; 981 } 982 } 983 else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) 984 { 985 ans = 1; 986 if (!dryrun) 987 { 988 unsigned long ttl; 989 /* Return 0 ttl for DHCP entries, which might change 990 before the lease expires. */ 991 if (crecp->flags & (F_IMMORTAL | F_DHCP)) 992 ttl = daemon->local_ttl; 993 else 994 ttl = crecp->ttd - now; 995 996 if (!(crecp->flags & (F_HOSTS | F_DHCP))) 997 auth = 0; 998 999 ansp = add_text_record(nameoffset, ansp, ttl, 0, T_PTR, 1000 cache_get_name(crecp)); 1001 1002 log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, 0); 1003 anscount++; 1004 1005 /* if last answer exceeded packet size, give up */ 1006 if (((unsigned char *)limit - ansp) < 0) 1007 return 0; 1008 } 1009 } 1010 } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa))); 1011 } 1012 1013 for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0) 1014 { 1015 unsigned short type = T_A; 1016 int addrsz = INADDRSZ; 1017 1018 if (flag == F_IPV6) 1019 { 1020#ifdef HAVE_IPV6 1021 type = T_AAAA; 1022 addrsz = IN6ADDRSZ; 1023#else 1024 break; 1025#endif 1026 } 1027 1028 if (qtype != type && qtype != T_ANY) 1029 continue; 1030 1031 crecp = NULL; 1032 while ((crecp = cache_find_by_name(crecp, name, now, flag))) 1033 { 1034 /* don't answer wildcard queries with data not from /etc/hosts 1035 or DHCP leases */ 1036 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) 1037 continue; 1038 1039 if (crecp->flags & F_NEG) 1040 { 1041 ans = 1; 1042 if (!dryrun) 1043 { 1044 log_query(crecp->flags, name, NULL, 0); 1045 auth = 0; 1046 if (crecp->flags & F_NXDOMAIN) 1047 nxdomain = 1; 1048 } 1049 } 1050 else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) 1051 { 1052 ans = 1; 1053 if (!dryrun) 1054 { 1055 unsigned long ttl; 1056 1057 if (crecp->flags & (F_IMMORTAL | F_DHCP)) 1058 ttl = daemon->local_ttl; 1059 else 1060 ttl = crecp->ttd - now; 1061 1062 if (!(crecp->flags & (F_HOSTS | F_DHCP))) 1063 auth = 0; 1064 log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr, 0); 1065 1066 /* copy question as first part of answer (use compression) */ 1067 PUTSHORT(nameoffset | 0xc000, ansp); 1068 PUTSHORT(type, ansp); 1069 PUTSHORT(C_IN, ansp); 1070 PUTLONG(ttl, ansp); /* TTL */ 1071 1072 PUTSHORT(addrsz, ansp); 1073 memcpy(ansp, &crecp->addr, addrsz); 1074 ansp += addrsz; 1075 anscount++; 1076 1077 if (((unsigned char *)limit - ansp) < 0) 1078 return 0; 1079 } 1080 } 1081 } 1082 } 1083 1084 if (qtype == T_MX || qtype == T_ANY) 1085 { 1086 struct mx_record *mx; 1087 for (mx = daemon->mxnames; mx; mx = mx->next) 1088 if (hostname_isequal(name, mx->mxname)) 1089 break; 1090 if (mx) 1091 { 1092 ans = 1; 1093 if (!dryrun) 1094 { 1095 ansp = add_text_record(nameoffset, ansp, daemon->local_ttl, 1, T_MX, 1096 mx->mxtarget ? mx->mxtarget : daemon->mxtarget); 1097 anscount++; 1098 } 1099 } 1100 else if ((daemon->options & (OPT_SELFMX | OPT_LOCALMX)) && 1101 cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP)) 1102 { 1103 ans = 1; 1104 if (!dryrun) 1105 { 1106 ansp = add_text_record(nameoffset, ansp, daemon->local_ttl, 1, T_MX, 1107 (daemon->options & OPT_SELFMX) ? name : daemon->mxtarget); 1108 anscount++; 1109 } 1110 } 1111 } 1112 1113 if (qtype == T_MAILB) 1114 ans = 1, nxdomain = 1; 1115 1116 } 1117 } 1118 1119 if (!ans || ((unsigned char *)limit - ansp) < 0) 1120 return 0; /* failed to answer a question */ 1121 } 1122 1123 if (dryrun) 1124 { 1125 dryrun = 0; 1126 goto rerun; 1127 } 1128 1129 /* done all questions, set up header and return length of result */ 1130 header->qr = 1; /* response */ 1131 header->aa = auth; /* authoritive - only hosts and DHCP derived names. */ 1132 header->ra = 1; /* recursion if available */ 1133 header->tc = 0; /* truncation */ 1134 if (anscount == 0 && nxdomain) 1135 header->rcode = NXDOMAIN; 1136 else 1137 header->rcode = NOERROR; /* no error */ 1138 header->ancount = htons(anscount); 1139 header->nscount = htons(0); 1140 header->arcount = htons(0); 1141 return ansp - (unsigned char *)header; 1142} 1143 1144/* foxconn wklin added start, 09/05/2007 @mpoe */ 1145#ifdef MULTIPLE_PPPOE 1146typedef struct { 1147 int param_count; 1148 int param_len[32]; 1149 void *param[32]; 1150} acos_t; 1151 1152unsigned long acos_ip = 0 ; 1153static void acos_set_ipaddr(struct in_addr *p) 1154{ 1155 acos_t param; 1156 int fd; 1157 unsigned long refresh_tick = 0; 1158 unsigned long ipaddr = 0; 1159 1160 fd = open("/dev/acos_nat_cli", O_RDWR); 1161 if (!fd) 1162 return; 1163 1164 ipaddr = ntohl(p->s_addr); 1165 memset((char *)¶m, 0, sizeof(acos_t)); 1166 param.param_count = 2; 1167 param.param[0] = (void *)&ipaddr; 1168 param.param_len[0] = sizeof(unsigned long); 1169 param.param[1] = (void *)&refresh_tick; 1170 param.param_len[1] = sizeof(unsigned long); 1171 /* Foxconn modified by Max Ding, 01/13/2009 for multi-language */ 1172 //if (0 > ioctl(fd, _IOR(120, 98, char *), ¶m)) 1173 if (0 > ioctl(fd, _IOR(100, 110, char *), ¶m)) 1174 fprintf(stderr, "error setting ipaddress %08x.\n", ipaddr); 1175 1176 close(fd); 1177 return; 1178} 1179 1180void extract_set_addr(HEADER *header, unsigned int qlen) 1181{ 1182 unsigned char *p, *psave, *endrr; 1183 int qtype, qclass, rdlen; 1184 unsigned long ttl; 1185 int i; 1186 1187 unsigned long *pTTL; 1188 1189 /* skip over questions */ 1190 if (!(p = skip_questions(header, qlen))) 1191 return; /* bad packet */ 1192 1193 psave = p; 1194 1195 for (i=0; i<ntohs(header->ancount); i++) 1196 { 1197 unsigned char name[256]; 1198 if (!extract_name(header, qlen, &p, &name[0], 1)) 1199 return; /* bad packet */ 1200 1201 GETSHORT(qtype, p); 1202 GETSHORT(qclass, p); 1203 pTTL = p; 1204 GETLONG(ttl, p); 1205 GETSHORT(rdlen, p); 1206 1207 endrr = p + rdlen; 1208 if ((unsigned int)(endrr - (unsigned char *)header) > qlen) 1209 return; 1210 1211 if (qclass != C_IN) 1212 { 1213 p = endrr; 1214 continue; 1215 } 1216 1217 if (qtype == T_A) { /* A record. */ 1218 *pTTL = 0; 1219 /* Add a unsigned long variable acos_ip to avoid the 4-bytes align issue. weal @ April 14 */ 1220 memcpy(&acos_ip, p, 4); 1221 acos_set_ipaddr((struct in_addr *)&acos_ip); 1222 } 1223 p = endrr; 1224 } 1225 return; 1226} 1227#endif /* MULTIPLE_PPPOE */ 1228/* foxconn wklin added end, 09/05/2007 @mpoe */ 1229