1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is free software; you can redistribute it and/or modify 4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat it under the terms of the GNU General Public License as published by 5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the Free Software Foundation; version 2 dated June, 1991, or 6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (at your option) version 3 dated 29 June, 2007. 7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is distributed in the hope that it will be useful, 9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat but WITHOUT ANY WARRANTY; without even the implied warranty of 10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GNU General Public License for more details. 12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat You should have received a copy of the GNU General Public License 14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat along with this program. If not, see <http://www.gnu.org/licenses/>. 15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/ 16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h" 18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int add_resource_record(HEADER *header, char *limit, int *truncp, 20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int nameoffset, unsigned char **pp, 21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long ttl, unsigned int *offset, unsigned short type, 22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short class, char *format, ...); 23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define CHECK_LEN(header, pp, plen, len) \ 25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen)) 26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define ADD_RDLEN(header, pp, plen, len) \ 28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (!CHECK_LEN(header, pp, plen, len) ? 0 : (long)((pp) += (len)), 1) 29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int extract_name(HEADER *header, size_t plen, unsigned char **pp, 31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *name, int isExtract, int extrabytes) 32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL; 34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int j, l, hops = 0; 35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int retvalue = 1; 36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (isExtract) 38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp = 0; 39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (1) 41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int label_type; 43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, plen, 1)) 45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((l = *p++) == 0) 48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* end marker */ 49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* check that there are the correct no of bytes after the name */ 51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, plen, extrabytes)) 52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (isExtract) 55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (cp != (unsigned char *)name) 57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cp--; 58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp = 0; /* terminate: lose final period */ 59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (*cp != 0) 61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat retvalue = 2; 62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (p1) /* we jumped via compression */ 64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *pp = p1; 65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *pp = p; 67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return retvalue; 69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat label_type = l & 0xc0; 72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (label_type == 0xc0) /* pointer */ 74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, plen, 1)) 76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* get offset */ 79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l = (l&0x3f) << 8; 80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l |= *p++; 81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!p1) /* first jump, save location to go back to */ 83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p1 = p; 84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat hops++; /* break malicious infinite loops */ 86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hops > 255) 87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p = l + (unsigned char *)header; 90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (label_type == 0x80) 92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* reserved */ 93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (label_type == 0x40) 94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { /* ELT */ 95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int count, digs; 96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((l & 0x3f) != 1) 98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* we only understand bitstrings */ 99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!isExtract) 101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* Cannot compare bitsrings */ 102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat count = *p++; 104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (count == 0) 105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat count = 256; 106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat digs = ((count-1)>>2)+1; 107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* output is \[x<hex>/siz]. which is digs+9 chars */ 109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME) 110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, plen, (count-1)>>3)) 112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp++ = '\\'; 115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp++ = '['; 116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp++ = 'x'; 117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (j=0; j<digs; j++) 118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int dig; 120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (j%2 == 0) 121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dig = *p >> 4; 122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dig = *p++ & 0x0f; 124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10; 126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cp += sprintf((char *)cp, "/%d]", count); 128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* do this here to overwrite the zero char from sprintf */ 129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp++ = '.'; 130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { /* label_type = 0 -> label. */ 133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (cp - (unsigned char *)name + l + 1 >= MAXDNAME) 134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, plen, l)) 136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for(j=0; j<l; j++, p++) 139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (isExtract) 140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char c = *p; 142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (isascii(c) && !iscntrl(c) && c != '.') 143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp++ = *p; 144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char c1 = *cp, c2 = *p; 150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (c1 == 0) 152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat retvalue = 2; 153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cp++; 156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (c1 >= 'A' && c1 <= 'Z') 157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat c1 += 'a' - 'A'; 158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (c2 >= 'A' && c2 <= 'Z') 159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat c2 += 'a' - 'A'; 160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (c1 != c2) 162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat retvalue = 2; 163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (isExtract) 167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp++ = '.'; 168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (*cp != 0 && *cp++ != '.') 169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat retvalue = 2; 170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Max size of input string (for IPv6) is 75 chars.) */ 175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define MAXARPANAME 75 176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int in_arpa_name_2_addr(char *namein, struct all_addr *addrp) 177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int j; 179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char name[MAXARPANAME+1], *cp1; 180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *addr = (unsigned char *)addrp; 181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *lastchunk = NULL, *penchunk = NULL; 182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (strlen(namein) > MAXARPANAME) 184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(addrp, 0, sizeof(struct all_addr)); 187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* turn name into a series of asciiz strings */ 189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* j counts no of labels */ 190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for(j = 1,cp1 = name; *namein; cp1++, namein++) 191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (*namein == '.') 192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat penchunk = lastchunk; 194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lastchunk = cp1 + 1; 195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp1 = 0; 196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat j++; 197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp1 = *namein; 200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *cp1 = 0; 202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (j<3) 204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr")) 207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* IP v4 */ 209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* address arives as a name of the form 210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat www.xxx.yyy.zzz.in-addr.arpa 211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat some of the low order address octets might be missing 212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat and should be set to zero. */ 213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1) 214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* check for digits only (weeds out things like 216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 50.0/24.67.28.64.in-addr.arpa which are used 217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat as CNAME targets according to RFC 2317 */ 218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *cp; 219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (cp = cp1; *cp; cp++) 220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!isdigit((int)*cp)) 221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[3] = addr[2]; 224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[2] = addr[1]; 225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[1] = addr[0]; 226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[0] = atoi(cp1); 227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_IPV4; 230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (hostname_isequal(penchunk, "ip6") && 233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa"))) 234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* IP v6: 236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa] 237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa] 238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Note that most of these the various reprentations are obsolete and 240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat left-over from the many DNS-for-IPv6 wars. We support all the formats 241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat that we can since there is no reason not to. 242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat */ 243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (*name == '\\' && *(name+1) == '[' && 245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (*(name+2) == 'x' || *(name+2) == 'X')) 246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (j = 0, cp1 = name+3; *cp1 && isxdigit((int) *cp1) && j < 32; cp1++, j++) 248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char xdig[2]; 250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat xdig[0] = *cp1; 251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat xdig[1] = 0; 252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (j%2) 253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[j/2] |= strtol(xdig, NULL, 16); 254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[j/2] = strtol(xdig, NULL, 16) << 4; 256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (*cp1 == '/' && j == 32) 259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_IPV6; 260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1) 264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (*(cp1+1) || !isxdigit((int)*cp1)) 266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (j = sizeof(struct all_addr)-1; j>0; j--) 269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[j] = (addr[j] >> 4) | (addr[j-1] << 4); 270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4); 271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_IPV6; 274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen, int extrabytes) 282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while(1) 284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int label_type; 286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, ansp, plen, 1)) 288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat label_type = (*ansp) & 0xc0; 291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (label_type == 0xc0) 293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* pointer for compression. */ 295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ansp += 2; 296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (label_type == 0x80) 299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; /* reserved */ 300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (label_type == 0x40) 301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Extended label type */ 303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int count; 304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, ansp, plen, 2)) 306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (((*ansp++) & 0x3f) != 1) 309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; /* we only understand bitstrings */ 310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat count = *(ansp++); /* Bits in bitstring */ 312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (count == 0) /* count == 0 means 256 bits */ 314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ansp += 32; 315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ansp += ((count-1)>>3)+1; 317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { /* label type == 0 Bottom six bits is length */ 320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int len = (*ansp++) & 0x3f; 321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!ADD_RDLEN(header, ansp, plen, len)) 323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (len == 0) 326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; /* zero length label marks the end. */ 327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, ansp, plen, extrabytes)) 331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ansp; 334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic unsigned char *skip_questions(HEADER *header, size_t plen) 337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int q; 339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *ansp = (unsigned char *)(header+1); 340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (q = ntohs(header->qdcount); q != 0; q--) 342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_name(ansp, header, plen, 4))) 344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ansp += 4; /* class and type */ 346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ansp; 349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic unsigned char *skip_section(unsigned char *ansp, int count, HEADER *header, size_t plen) 352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i, rdlen; 354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = 0; i < count; i++) 356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_name(ansp, header, plen, 10))) 358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ansp += 8; /* type, class, TTL */ 360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(rdlen, ansp); 361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!ADD_RDLEN(header, ansp, plen, rdlen)) 362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ansp; 366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* CRC the question section. This is used to safely detect query 369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat retransmision and to detect answers to questions we didn't ask, which 370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat might be poisoning attacks. Note that we decode the name rather 371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat than CRC the raw bytes, since replies might be compressed differently. 372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat We ignore case in the names for the same reason. Return all-ones 373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if there is not question section. */ 374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatunsigned int questions_crc(HEADER *header, size_t plen, char *name) 375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int q; 377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int crc = 0xffffffff; 378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *p1, *p = (unsigned char *)(header+1); 379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (q = ntohs(header->qdcount); q != 0; q--) 381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, plen, &p, name, 1, 4)) 383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return crc; /* bad packet */ 384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (p1 = (unsigned char *)name; *p1; p1++) 386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i = 8; 388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char c = *p1; 389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (c >= 'A' && c <= 'Z') 391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat c += 'a' - 'A'; 392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crc ^= c << 24; 394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (i--) 395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1; 396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* CRC the class and type as well */ 399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (p1 = p; p1 < p+4; p1++) 400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i = 8; 402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crc ^= *p1 << 24; 403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (i--) 404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1; 405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += 4; 408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, plen, 0)) 409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return crc; /* bad packet */ 410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return crc; 413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsize_t resize_packet(HEADER *header, size_t plen, unsigned char *pheader, size_t hlen) 417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *ansp = skip_questions(header, plen); 419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* if packet is malformed, just return as-is. */ 421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!ansp) 422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return plen; 423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header, plen))) 426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return plen; 427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* restore pseudoheader */ 429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (pheader && ntohs(header->arcount) == 0) 430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* must use memmove, may overlap */ 432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memmove(ansp, pheader, hlen); 433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->arcount = htons(1); 434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ansp += hlen; 435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ansp - (unsigned char *)header; 438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatunsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsigned char **p, int *is_sign) 441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat also return length of pseudoheader in *len and pointer to the UDP size in *p 444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Finally, check to see if a packet is signed. If it is we cannot change a single bit before 445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */ 446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i, arcount = ntohs(header->arcount); 448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *ansp = (unsigned char *)(header+1); 449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short rdlen, type, class; 450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *ret = NULL; 451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (is_sign) 453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *is_sign = 0; 455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (header->opcode == QUERY) 457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = ntohs(header->qdcount); i != 0; i--) 459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_name(ansp, header, plen, 4))) 461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(type, ansp); 464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(class, ansp); 465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (class == C_IN && type == T_TKEY) 467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *is_sign = 1; 468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_questions(header, plen))) 474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (arcount == 0) 478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen))) 481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = 0; i < arcount; i++) 484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *save, *start = ansp; 486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_name(ansp, header, plen, 10))) 487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(type, ansp); 490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat save = ansp; 491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(class, ansp); 492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ansp += 4; /* TTL */ 493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(rdlen, ansp); 494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!ADD_RDLEN(header, ansp, plen, rdlen)) 495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (type == T_OPT) 497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (len) 499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *len = ansp - start; 500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (p) 501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *p = save; 502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = start; 503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (is_sign && 505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat i == arcount - 1 && 506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat class == C_ANY && 507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (type == T_SIG || type == T_TSIG)) 508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *is_sign = 1; 509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ret; 512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* is addr in the non-globally-routed IP space? */ 516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int private_net(struct in_addr addr) 517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat in_addr_t ip_addr = ntohl(addr.s_addr); 519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((ip_addr & 0xFF000000) == 0x7F000000) /* 127.0.0.0/8 (loopback) */ || 522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ || 523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ || 524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ || 525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ; 526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, size_t qlen) 529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i, qtype, qclass, rdlen; 531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long ttl; 532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = count; i != 0; i--) 534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p = skip_name(p, header, qlen, 10))) 536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qtype, p); 539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qclass, p); 540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETLONG(ttl, p); 541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(rdlen, p); 542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((qclass == C_IN) && (qtype == T_A)) 544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct doctor *doctor; 546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in_addr addr; 547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, qlen, INADDRSZ)) 549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* alignment */ 552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(&addr, p, INADDRSZ); 553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (doctor = daemon->doctors; doctor; doctor = doctor->next) 555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (doctor->end.s_addr == 0) 557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!is_same_net(doctor->in, addr, doctor->mask)) 559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) || 562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ntohl(doctor->end.s_addr) < ntohl(addr.s_addr)) 563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.s_addr &= ~doctor->mask.s_addr; 566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr); 567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Since we munged the data, the server it came from is no longer authoritative */ 568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->aa = 0; 569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(p, &addr, INADDRSZ); 570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!ADD_RDLEN(header, p, qlen, rdlen)) 575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return p; 579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int find_soa(HEADER *header, size_t qlen) 582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *p; 584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int qtype, qclass, rdlen; 585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long ttl, minttl = ULONG_MAX; 586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i, found_soa = 0; 587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* first move to NS section and find TTL from any SOA section */ 589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p = skip_questions(header, qlen)) || 590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !(p = do_doctor(p, ntohs(header->ancount), header, qlen))) 591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = ntohs(header->nscount); i != 0; i--) 594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p = skip_name(p, header, qlen, 10))) 596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qtype, p); 599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qclass, p); 600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETLONG(ttl, p); 601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(rdlen, p); 602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((qclass == C_IN) && (qtype == T_SOA)) 604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat found_soa = 1; 606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ttl < minttl) 607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat minttl = ttl; 608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* MNAME */ 610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p = skip_name(p, header, qlen, 0))) 611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* RNAME */ 613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p = skip_name(p, header, qlen, 20))) 614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += 16; /* SERIAL REFRESH RETRY EXPIRE */ 616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETLONG(ttl, p); /* minTTL */ 618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ttl < minttl) 619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat minttl = ttl; 620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (!ADD_RDLEN(header, p, qlen, rdlen)) 622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 623ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 624ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 625ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* rewrite addresses in additioal section too */ 626ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!do_doctor(p, ntohs(header->arcount), header, qlen)) 627ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 628ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 629ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!found_soa) 630ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat minttl = daemon->neg_ttl; 631ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 632ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return minttl; 633ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 634ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 635ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Note that the following code can create CNAME chains that don't point to a real record, 636ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat either because of lack of memory, or lack of SOA records. These are treated by the cache code as 637ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat expired and cleaned out that way. 638ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Return 1 if we reject an address because it look like parct of dns-rebinding attack. */ 639ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint extract_addresses(HEADER *header, size_t qlen, char *name, time_t now) 640ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 641ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *p, *p1, *endrr, *namep; 642ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0; 643ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long ttl = 0; 644ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct all_addr addr; 645ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 646ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_start_insert(); 647ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 648ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* find_soa is needed for dns_doctor side-effects, so don't call it lazily if there are any. */ 649ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->doctors) 650ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 651ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat searched_soa = 1; 652ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ttl = find_soa(header, qlen); 653ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 654ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 655ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* go through the questions. */ 656ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p = (unsigned char *)(header+1); 657ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 658ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = ntohs(header->qdcount); i != 0; i--) 659ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 660ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int found = 0, cname_count = 5; 661ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct crec *cpp = NULL; 662ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int flags = header->rcode == NXDOMAIN ? F_NXDOMAIN : 0; 663ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long cttl = ULONG_MAX, attl; 664ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 665ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat namep = p; 666ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, qlen, &p, name, 1, 4)) 667ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 668ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 669ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qtype, p); 670ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qclass, p); 671ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 672ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qclass != C_IN) 673ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 674ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 675ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* PTRs: we chase CNAMEs here, since we have no way to 676ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat represent them in the cache. */ 677ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_PTR) 678ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 679ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int name_encoding = in_arpa_name_2_addr(name, &addr); 680ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 681ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!name_encoding) 682ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 683ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 684ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(flags & F_NXDOMAIN)) 685ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 686ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cname_loop: 687ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p1 = skip_questions(header, qlen))) 688ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 689ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 690ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (j = ntohs(header->ancount); j != 0; j--) 691ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 692ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *tmp = namep; 693ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* the loop body overwrites the original name, so get it back here. */ 694ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, qlen, &tmp, name, 1, 0) || 695ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !(res = extract_name(header, qlen, &p1, name, 0, 10))) 696ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 697ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 698ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(aqtype, p1); 699ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(aqclass, p1); 700ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETLONG(attl, p1); 701ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(ardlen, p1); 702ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat endrr = p1+ardlen; 703ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 704ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* TTL of record is minimum of CNAMES and PTR */ 705ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (attl < cttl) 706ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cttl = attl; 707ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 708ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR)) 709ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 710ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, qlen, &p1, name, 1, 0)) 711ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 712ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 713ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (aqtype == T_CNAME) 714ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 715ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!cname_count--) 716ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* looped CNAMES */ 717ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto cname_loop; 718ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 719ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 720ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_insert(name, &addr, now, cttl, name_encoding | F_REVERSE); 721ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat found = 1; 722ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 723ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 724ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p1 = endrr; 725ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p1, qlen, 0)) 726ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 727ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 728ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 729ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 730ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!found && !(daemon->options & OPT_NO_NEG)) 731ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 732ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!searched_soa) 733ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 734ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat searched_soa = 1; 735ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ttl = find_soa(header, qlen); 736ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 737ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ttl) 738ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags); 739ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 740ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 741ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 742ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 743ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* everything other than PTR */ 744ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct crec *newc; 745ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int addrlen; 746ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 747ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_A) 748ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 749ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addrlen = INADDRSZ; 750ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat flags |= F_IPV4; 751ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 752ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 753ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (qtype == T_AAAA) 754ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 755ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addrlen = IN6ADDRSZ; 756ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat flags |= F_IPV6; 757ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 758ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 759ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 760ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 761ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 762ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(flags & F_NXDOMAIN)) 763ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 764ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cname_loop1: 765ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p1 = skip_questions(header, qlen))) 766ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 767ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 768ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (j = ntohs(header->ancount); j != 0; j--) 769ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 770ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(res = extract_name(header, qlen, &p1, name, 0, 10))) 771ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 772ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 773ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(aqtype, p1); 774ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(aqclass, p1); 775ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETLONG(attl, p1); 776ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(ardlen, p1); 777ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat endrr = p1+ardlen; 778ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 779ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype)) 780ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 781ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (aqtype == T_CNAME) 782ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 783ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!cname_count--) 784ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* looped CNAMES */ 785ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD); 786ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (newc && cpp) 787ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 788ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp->addr.cname.cache = newc; 789ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp->addr.cname.uid = newc->uid; 790ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 791ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 792ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp = newc; 793ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (attl < cttl) 794ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cttl = attl; 795ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 796ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, qlen, &p1, name, 1, 0)) 797ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 798ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto cname_loop1; 799ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 800ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 801ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 802ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat found = 1; 803ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 804ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* copy address into aligned storage */ 805ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p1, qlen, addrlen)) 806ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 807ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(&addr, p1, addrlen); 808ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 809ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* check for returned address in private space */ 810ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((daemon->options & OPT_NO_REBIND) && 811ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (flags & F_IPV4) && 812ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat private_net(addr.addr.addr4)) 813ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 814ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 815ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD); 816ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (newc && cpp) 817ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 818ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp->addr.cname.cache = newc; 819ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp->addr.cname.uid = newc->uid; 820ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 821ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp = NULL; 822ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 823ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 824ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 825ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p1 = endrr; 826ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p1, qlen, 0)) 827ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 828ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 829ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 830ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 831ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!found && !(daemon->options & OPT_NO_NEG)) 832ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 833ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!searched_soa) 834ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 835ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat searched_soa = 1; 836ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ttl = find_soa(header, qlen); 837ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 838ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If there's no SOA to get the TTL from, but there is a CNAME 839ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat pointing at this, inherit its TTL */ 840ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ttl || cpp) 841ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 842ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags); 843ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (newc && cpp) 844ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 845ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp->addr.cname.cache = newc; 846ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cpp->addr.cname.uid = newc->uid; 847ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 848ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 849ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 850ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 851ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 852ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 853ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Don't put stuff from a truncated packet into the cache, but do everything else */ 854ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!header->tc) 855ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_end_insert(); 856ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 857ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 858ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 859ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 860ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* If the packet holds exactly one query 861ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_IPV4 or F_IPV6 and leave the name from the query in name. 862ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Abuse F_BIGNAME to indicate an NS query - yuck. */ 863ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 864ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatunsigned short extract_request(HEADER *header, size_t qlen, char *name, unsigned short *typep) 865ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 866ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *p = (unsigned char *)(header+1); 867ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int qtype, qclass; 868ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 869ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (typep) 870ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *typep = 0; 871ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 872ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ntohs(header->qdcount) != 1 || header->opcode != QUERY) 873ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* must be exactly one query. */ 874ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 875ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, qlen, &p, name, 1, 4)) 876ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 877ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 878ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qtype, p); 879ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qclass, p); 880ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 881ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (typep) 882ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *typep = qtype; 883ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 884ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qclass == C_IN) 885ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 886ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_A) 887ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_IPV4; 888ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_AAAA) 889ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_IPV6; 890ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_ANY) 891ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_IPV4 | F_IPV6; 892ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_NS || qtype == T_SOA) 893ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_QUERY | F_BIGNAME; 894ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 895ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 896ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return F_QUERY; 897ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 898ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 899ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 900ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsize_t setup_reply(HEADER *header, size_t qlen, 901ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct all_addr *addrp, unsigned short flags, unsigned long ttl) 902ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 903ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *p = skip_questions(header, qlen); 904ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 905ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->qr = 1; /* response */ 906ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->aa = 0; /* authoritive */ 907ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->ra = 1; /* recursion if available */ 908ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->tc = 0; /* not truncated */ 909ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->nscount = htons(0); 910ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->arcount = htons(0); 911ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->ancount = htons(0); /* no answers unless changed below */ 912ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (flags == F_NEG) 913ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = SERVFAIL; /* couldn't get memory */ 914ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (flags == F_NOERR) 915ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = NOERROR; /* empty domain */ 916ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (flags == F_NXDOMAIN) 917ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = NXDOMAIN; 918ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (p && flags == F_IPV4) 919ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { /* we know the address */ 920ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = NOERROR; 921ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->ancount = htons(1); 922ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->aa = 1; 923ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_A, C_IN, "4", addrp); 924ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 925ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 926ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (p && flags == F_IPV6) 927ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 928ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = NOERROR; 929ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->ancount = htons(1); 930ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->aa = 1; 931ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp); 932ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 933ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 934ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else /* nowhere to forward to */ 935ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = REFUSED; 936ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 937ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return p - (unsigned char *)header; 938ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 939ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 940ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */ 941ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint check_for_local_domain(char *name, time_t now) 942ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 943ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct crec *crecp; 944ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct mx_srv_record *mx; 945ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct txt_record *txt; 946ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct interface_name *intr; 947ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ptr_record *ptr; 948ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 949ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)) && 950ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (crecp->flags & (F_HOSTS | F_DHCP))) 951ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 952ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 953ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (mx = daemon->mxnames; mx; mx = mx->next) 954ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, mx->name)) 955ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 956ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 957ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (txt = daemon->txt; txt; txt = txt->next) 958ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, txt->name)) 959ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 960ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 961ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (intr = daemon->int_names; intr; intr = intr->next) 962ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, intr->name)) 963ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 964ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 965ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (ptr = daemon->ptr; ptr; ptr = ptr->next) 966ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, ptr->name)) 967ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 968ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 969ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 970ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 971ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 972ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Is the packet a reply with the answer address equal to addr? 973ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat If so mung is into an NXDOMAIN reply and also put that information 974ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat in the cache. */ 975ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name, 976ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct bogus_addr *baddr, time_t now) 977ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 978ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *p; 979ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i, qtype, qclass, rdlen; 980ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long ttl; 981ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct bogus_addr *baddrp; 982ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 983ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* skip over questions */ 984ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(p = skip_questions(header, qlen))) 985ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 986ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 987ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = ntohs(header->ancount); i != 0; i--) 988ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 989ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, qlen, &p, name, 1, 10)) 990ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 991ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 992ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qtype, p); 993ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qclass, p); 994ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETLONG(ttl, p); 995ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(rdlen, p); 996ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 997ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qclass == C_IN && qtype == T_A) 998ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 999ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!CHECK_LEN(header, p, qlen, INADDRSZ)) 1000ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 1001ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1002ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (baddrp = baddr; baddrp; baddrp = baddrp->next) 1003ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (memcmp(&baddrp->addr, p, INADDRSZ) == 0) 1004ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1005ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Found a bogus address. Insert that info here, since there no SOA record 1006ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat to get the ttl from in the normal processing */ 1007ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_start_insert(); 1008ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG); 1009ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_end_insert(); 1010ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1011ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 1012ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1013ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1014ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1015ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!ADD_RDLEN(header, p, qlen, rdlen)) 1016ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 1017ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1018ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1019ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 1020ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 1021ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1022ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int add_resource_record(HEADER *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp, 1023ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...) 1024ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 1025ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_list ap; 1026ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *sav, *p = *pp; 1027ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int j; 1028ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short usval; 1029ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat long lval; 1030ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *sval; 1031ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1032ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (truncp && *truncp) 1033ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 1034ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1035ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTSHORT(nameoffset | 0xc000, p); 1036ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTSHORT(type, p); 1037ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTSHORT(class, p); 1038ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTLONG(ttl, p); /* TTL */ 1039ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1040ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sav = p; /* Save pointer to RDLength field */ 1041ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTSHORT(0, p); /* Placeholder RDLength */ 1042ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1043ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_start(ap, format); /* make ap point to 1st unamed argument */ 1044ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1045ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (; *format; format++) 1046ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat switch (*format) 1047ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1048ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 1049ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat case '6': 1050ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sval = va_arg(ap, char *); 1051ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(p, sval, IN6ADDRSZ); 1052ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += IN6ADDRSZ; 1053ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1054ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 1055ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1056ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat case '4': 1057ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sval = va_arg(ap, char *); 1058ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(p, sval, INADDRSZ); 1059ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += INADDRSZ; 1060ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1061ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1062ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat case 's': 1063ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat usval = va_arg(ap, int); 1064ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTSHORT(usval, p); 1065ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1066ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1067ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat case 'l': 1068ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lval = va_arg(ap, long); 1069ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTLONG(lval, p); 1070ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1071ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1072ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat case 'd': 1073ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* get domain-name answer arg and store it in RDATA field */ 1074ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (offset) 1075ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *offset = p - (unsigned char *)header; 1076ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p = do_rfc1035_name(p, va_arg(ap, char *)); 1077ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *p++ = 0; 1078ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1079ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1080ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat case 't': 1081ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat usval = va_arg(ap, int); 1082ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sval = va_arg(ap, char *); 1083ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(p, sval, usval); 1084ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += usval; 1085ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1086ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1087ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat case 'z': 1088ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sval = va_arg(ap, char *); 1089ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat usval = sval ? strlen(sval) : 0; 1090ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (usval > 255) 1091ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat usval = 255; 1092ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *p++ = (unsigned char)usval; 1093ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(p, sval, usval); 1094ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += usval; 1095ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1096ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1097ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1098ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_end(ap); /* clean up variable argument pointer */ 1099ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat j = p - sav - 2; 1101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTSHORT(j, sav); /* Now, store real RDLength */ 1102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* check for overflow of buffer */ 1104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (limit && ((unsigned char *)limit - p) < 0) 1105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (truncp) 1107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *truncp = 1; 1108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 1109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *pp = p; 1112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 1113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 1114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic unsigned long crec_ttl(struct crec *crecp, time_t now) 1116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 1117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Return 0 ttl for DHCP entries, which might change 1118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat before the lease expires. */ 1119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (crecp->flags & (F_IMMORTAL | F_DHCP)) 1121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return daemon->local_ttl; 1122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return crecp->ttd - now; 1124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 1125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* return zero if we can't answer from cache, or packet size if we can */ 1128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsize_t answer_request(HEADER *header, char *limit, size_t qlen, 1129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in_addr local_addr, struct in_addr local_netmask, time_t now) 1130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 1131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *name = daemon->namebuff; 1132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *p, *ansp, *pheader; 1133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int qtype, qclass; 1134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct all_addr addr; 1135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int nameoffset; 1136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short flag; 1137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int q, ans, anscount = 0, addncount = 0; 1138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int dryrun = 0, sec_reqd = 0; 1139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int is_sign; 1140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct crec *crecp; 1141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int nxdomain = 0, auth = 1, trunc = 0; 1142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct mx_srv_record *rec; 1143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If there is an RFC2671 pseudoheader then it will be overwritten by 1145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat partial replies, so we have to do a dry run to see if we can answer 1146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the query. We check to see if the do bit is set, if so we always 1147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat forward rather than answering from the cache, which doesn't include 1148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat security information. */ 1149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign)) 1151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short udpsz, ext_rcode, flags; 1153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned char *psave = pheader; 1154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(udpsz, pheader); 1156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(ext_rcode, pheader); 1157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(flags, pheader); 1158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sec_reqd = flags & 0x8000; /* do bit */ 1160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If our client is advertising a larger UDP packet size 1162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat than we allow, trim it so that we don't get an overlarge 1163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat response from upstream */ 1164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!is_sign && (udpsz > daemon->edns_pktsz)) 1166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat PUTSHORT(daemon->edns_pktsz, psave); 1167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dryrun = 1; 1169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ntohs(header->qdcount) == 0 || header->opcode != QUERY ) 1172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 1173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (rec = daemon->mxnames; rec; rec = rec->next) 1175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat rec->offset = 0; 1176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat rerun: 1178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* determine end of question section (we put answers there) */ 1179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(ansp = skip_questions(header, qlen))) 1180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 1181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* now process each question, answers go in RRs after the question */ 1183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p = (unsigned char *)(header+1); 1184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (q = ntohs(header->qdcount); q != 0; q--) 1186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* save pointer to name for copying into answers */ 1188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat nameoffset = p - (unsigned char *)header; 1189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* now extract name as .-concatenated string into name */ 1191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!extract_name(header, qlen, &p, name, 1, 4)) 1192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* bad packet */ 1193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qtype, p); 1195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GETSHORT(qclass, p); 1196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 0; /* have we answered this question */ 1198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_TXT || qtype == T_ANY) 1200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct txt_record *t; 1202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for(t = daemon->txt; t ; t = t->next) 1203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (t->class == qclass && hostname_isequal(name, t->name)) 1205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<TXT>"); 1210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->local_ttl, NULL, 1212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat T_TXT, t->class, "t", t->len, t->txt)) 1213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qclass == C_IN) 1221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_PTR || qtype == T_ANY) 1223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* see if it's w.z.y.z.in-addr.arpa format */ 1225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int is_arpa = in_arpa_name_2_addr(name, &addr); 1226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ptr_record *ptr; 1227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct interface_name* intr = NULL; 1228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (ptr = daemon->ptr; ptr; ptr = ptr->next) 1230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, ptr->name)) 1231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (is_arpa == F_IPV4) 1234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (intr = daemon->int_names; intr; intr = intr->next) 1235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr) 1237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 1239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) 1240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat intr = intr->next; 1241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (intr) 1244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL); 1249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->local_ttl, NULL, 1251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat T_PTR, C_IN, "d", intr->name)) 1252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (ptr) 1256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<PTR>"); 1261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (ptr = daemon->ptr; ptr; ptr = ptr->next) 1262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, ptr->name) && 1263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->local_ttl, NULL, 1265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat T_PTR, C_IN, "d", ptr->ptr)) 1266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa))) 1271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat do 1272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */ 1274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) 1275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (crecp->flags & F_NEG) 1278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat auth = 0; 1281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (crecp->flags & F_NXDOMAIN) 1282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat nxdomain = 1; 1283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL); 1285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) 1287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(crecp->flags & (F_HOSTS | F_DHCP))) 1290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat auth = 0; 1291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, 1294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat record_source(crecp->uid)); 1295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crec_ttl(crecp, now), NULL, 1298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat T_PTR, C_IN, "d", cache_get_name(crecp))) 1299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa))); 1303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (is_arpa == F_IPV4 && 1304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (daemon->options & OPT_BOGUSPRIV) && 1305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat private_net(addr.addr.addr4)) 1306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */ 1308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat nxdomain = 1; 1310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, 1312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat name, &addr, NULL); 1313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0) 1317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short type = T_A; 1319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (flag == F_IPV6) 1321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 1322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat type = T_AAAA; 1323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 1324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 1326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype != type && qtype != T_ANY) 1328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Check for "A for A" queries */ 1331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_A && (addr.addr.addr4.s_addr = inet_addr(name)) != (in_addr_t) -1) 1332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL); 1337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->local_ttl, NULL, type, C_IN, "4", &addr)) 1339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* interface name stuff */ 1345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_A) 1346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct interface_name *intr; 1348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (intr = daemon->int_names; intr; intr = intr->next) 1350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, intr->name)) 1351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (intr) 1354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1) 1359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL); 1360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 1361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL); 1363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->local_ttl, NULL, type, C_IN, "4", &addr)) 1365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cname_restart: 1373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME))) 1374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int localise = 0; 1376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* See if a putative address is on the network from which we recieved 1378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the query, is so we'll filter other answers. */ 1379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (local_addr.s_addr != 0 && (daemon->options & OPT_LOCALISE) && flag == F_IPV4) 1380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct crec *save = crecp; 1382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat do { 1383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((crecp->flags & F_HOSTS) && 1384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask)) 1385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat localise = 1; 1387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME))); 1390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crecp = save; 1391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat do 1394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* don't answer wildcard queries with data not from /etc/hosts 1396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat or DHCP leases */ 1397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) 1398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 1399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (crecp->flags & F_CNAME) 1401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(crecp->flags, name, NULL, record_source(crecp->uid)); 1405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crec_ttl(crecp, now), &nameoffset, 1407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache))) 1408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcpy(name, cache_get_name(crecp->addr.cname.cache)); 1412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto cname_restart; 1413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (crecp->flags & F_NEG) 1416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat auth = 0; 1419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (crecp->flags & F_NXDOMAIN) 1420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat nxdomain = 1; 1421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(crecp->flags, name, NULL, NULL); 1423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) 1425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If we are returning local answers depending on network, 1427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat filter here. */ 1428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (localise && 1429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (crecp->flags & F_HOSTS) && 1430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask)) 1431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(crecp->flags & (F_HOSTS | F_DHCP))) 1434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat auth = 0; 1435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr, 1440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat record_source(crecp->uid)); 1441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 1443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crec_ttl(crecp, now), NULL, type, C_IN, 1444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat type == T_A ? "4" : "6", &crecp->addr)) 1445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME))); 1449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_MX || qtype == T_ANY) 1453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int found = 0; 1455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (rec = daemon->mxnames; rec; rec = rec->next) 1456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!rec->issrv && hostname_isequal(name, rec->name)) 1457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = found = 1; 1459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int offset; 1462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>"); 1463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 1464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat &offset, T_MX, C_IN, "sd", rec->weight, rec->target)) 1465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (rec->target) 1468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat rec->offset = offset; 1469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!found && (daemon->options & (OPT_SELFMX | OPT_LOCALMX)) && 1474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP)) 1475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>"); 1480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL, 1481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat T_MX, C_IN, "sd", 1, 1482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (daemon->options & OPT_SELFMX) ? name : daemon->mxtarget)) 1483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_SRV || qtype == T_ANY) 1489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int found = 0; 1491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (rec = daemon->mxnames; rec; rec = rec->next) 1493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (rec->issrv && hostname_isequal(name, rec->name)) 1494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat found = ans = 1; 1496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int offset; 1499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<SRV>"); 1500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 1501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat &offset, T_SRV, C_IN, "sssd", 1502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat rec->priority, rec->weight, rec->srvport, rec->target)) 1503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (rec->target) 1506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat rec->offset = offset; 1507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!found && (daemon->options & OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_')))) 1512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CONFIG | F_NEG, name, NULL, NULL); 1516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_NAPTR || qtype == T_ANY) 1520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct naptr *na; 1522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (na = daemon->naptr; na; na = na->next) 1523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (hostname_isequal(name, na->name)) 1524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<NAPTR>"); 1529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 1530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat NULL, T_NAPTR, C_IN, "sszzzd", 1531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat na->order, na->pref, na->flags, na->services, na->regexp, na->replace)) 1532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat anscount++; 1533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_MAILB) 1538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1, nxdomain = 1; 1539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (qtype == T_SOA && (daemon->options & OPT_FILTER)) 1541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ans = 1; 1543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!dryrun) 1544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_query(F_CONFIG | F_NEG, name, &addr, NULL); 1545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!ans) 1549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; /* failed to answer a question */ 1550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (dryrun) 1553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dryrun = 0; 1555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto rerun; 1556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* create an additional data section, for stuff in SRV and MX record replies. */ 1559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (rec = daemon->mxnames; rec; rec = rec->next) 1560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (rec->offset != 0) 1561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* squash dupes */ 1563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct mx_srv_record *tmp; 1564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (tmp = rec->next; tmp; tmp = tmp->next) 1565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target)) 1566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat tmp->offset = 0; 1567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crecp = NULL; 1569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6))) 1570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 1572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int type = crecp->flags & F_IPV4 ? T_A : T_AAAA; 1573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 1574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int type = T_A; 1575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 1576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (crecp->flags & F_NEG) 1577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (add_resource_record(header, limit, NULL, rec->offset, &ansp, 1580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crec_ttl(crecp, now), NULL, type, C_IN, 1581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr)) 1582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addncount++; 1583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* done all questions, set up header and return length of result */ 1587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->qr = 1; /* response */ 1588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->aa = auth; /* authoritive - only hosts and DHCP derived names. */ 1589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->ra = 1; /* recursion if available */ 1590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->tc = trunc; /* truncation */ 1591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (anscount == 0 && nxdomain) 1592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = NXDOMAIN; 1593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 1594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->rcode = NOERROR; /* no error */ 1595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->ancount = htons(anscount); 1596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->nscount = htons(0); 1597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat header->arcount = htons(addncount); 1598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ansp - (unsigned char *)header; 1599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 1600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1605