Annotation of embedaddon/coova-chilli/src/dns.c, revision 1.1
1.1 ! misho 1: /*
! 2: * DNS library functions
! 3: * Copyright (c) 2006-2008 David Bird <david@coova.com>
! 4: *
! 5: * The contents of this file may be used under the terms of the GNU
! 6: * General Public License Version 2, provided that the above copyright
! 7: * notice and this permission notice is included in all copies or
! 8: * substantial portions of the software.
! 9: *
! 10: */
! 11:
! 12: #include "dns.h"
! 13: #include "garden.h"
! 14: #include "syserr.h"
! 15: #include "dhcp.h"
! 16: #include "options.h"
! 17:
! 18: #define antidnstunnel options.dnsparanoia
! 19:
! 20: extern struct dhcp_t *dhcp;
! 21:
! 22: char *
! 23: dns_fullname(char *data, size_t dlen, uint8_t *res, uint8_t *opkt, size_t olen, int lvl) {
! 24: char *d = data;
! 25: unsigned short l;
! 26:
! 27: if (lvl >= 15)
! 28: return 0;
! 29:
! 30: while ((l = *res++) != 0) {
! 31: if ((l & 0xC0) == 0xC0) {
! 32: unsigned short offset = ((l & ~0xC0) << 8) + *res;
! 33: if (offset > olen) {
! 34: log_dbg("bad value");
! 35: return 0;
! 36: }
! 37: /*log_dbg("skip[%d]\n",offset);*/
! 38: dns_fullname(d, dlen, opkt + (size_t)offset, opkt, olen, lvl+1);
! 39: break;
! 40: }
! 41:
! 42: if (l >= dlen) {
! 43: log_dbg("bad value");
! 44: return 0;
! 45: }
! 46:
! 47: /*log_dbg("part[%.*s]\n",l,res);*/
! 48:
! 49: memcpy(d, res, l);
! 50: d += l; dlen -= l;
! 51: res += l;
! 52:
! 53: *d = '.';
! 54: d += 1; dlen -= 1;
! 55: }
! 56:
! 57: if (!lvl && data[strlen((char*)data)-1]=='.')
! 58: data[strlen((char*)data)-1]=0;
! 59:
! 60: return data;
! 61: }
! 62:
! 63: int dns_getname(uint8_t **pktp, size_t *left, char *name, size_t namesz, size_t *nameln) {
! 64: size_t namelen = *nameln;
! 65: uint8_t *p_pkt = *pktp;
! 66: size_t len = *left;
! 67: uint8_t l;
! 68:
! 69: namelen = 0;
! 70: while (len-- && (l = name[namelen++] = *p_pkt++) != 0) {
! 71: if ((l & 0xC0) == 0xC0) {
! 72: if (namelen >= namesz) {
! 73: log_err(0, "name too long in DNS packet");
! 74: break;
! 75: }
! 76: name[namelen++] = *p_pkt++;
! 77: len--;
! 78: break;
! 79: }
! 80: }
! 81:
! 82: *pktp = p_pkt;
! 83: *nameln = namelen;
! 84: *left = len;
! 85:
! 86: if (!len) {
! 87: log_err(0, "failed to parse DNS packet");
! 88: return -1;
! 89: }
! 90:
! 91: return 0;
! 92: }
! 93:
! 94: static void
! 95: add_A_to_garden(uint8_t *p) {
! 96: struct in_addr reqaddr;
! 97: pass_through pt;
! 98: memcpy(&reqaddr.s_addr, p, 4);
! 99: memset(&pt, 0, sizeof(pass_through));
! 100: pt.mask.s_addr = 0xffffffff;
! 101: pt.host = reqaddr;
! 102: if (pass_through_add(dhcp->pass_throughs,
! 103: MAX_PASS_THROUGHS,
! 104: &dhcp->num_pass_throughs,
! 105: &pt))
! 106: ;
! 107: }
! 108:
! 109: int
! 110: dns_copy_res(int q,
! 111: uint8_t **pktp, size_t *left,
! 112: uint8_t *opkt, size_t olen,
! 113: char *question, size_t qsize) {
! 114:
! 115: #define return_error \
! 116: { log_dbg("%s:%d: failed parsing DNS packet",__FILE__,__LINE__); return -1; }
! 117:
! 118: uint8_t *p_pkt = *pktp;
! 119: size_t len = *left;
! 120:
! 121: uint8_t name[PKT_IP_PLEN];
! 122: size_t namelen = 0;
! 123:
! 124: uint16_t type;
! 125: uint16_t class;
! 126: uint32_t ttl;
! 127: uint16_t rdlen;
! 128:
! 129: uint32_t ul;
! 130: uint16_t us;
! 131:
! 132: if (dns_getname(&p_pkt, &len, (char *)name, sizeof(name), &namelen))
! 133: return_error;
! 134:
! 135: if (antidnstunnel && namelen > 128) {
! 136: log_warn(0,"dropping dns for anti-dnstunnel (namelen: %d)",namelen);
! 137: return -1;
! 138: }
! 139:
! 140: if (len < 4)
! 141: return_error;
! 142:
! 143: memcpy(&us, p_pkt, sizeof(us));
! 144: type = ntohs(us);
! 145: p_pkt += 2;
! 146: len -= 2;
! 147:
! 148: memcpy(&us, p_pkt, sizeof(us));
! 149: class = ntohs(us);
! 150: p_pkt += 2;
! 151: len -= 2;
! 152:
! 153: log_dbg("It was a dns record type: %d class: %d", type, class);
! 154:
! 155:
! 156: /* if dnsparanoia, checks here */
! 157:
! 158: if (antidnstunnel) {
! 159: switch (type) {
! 160: case 1:/* A */
! 161: log_dbg("A record");
! 162: break;
! 163: case 5:/* CNAME */
! 164: log_dbg("CNAME record");
! 165: break;
! 166: default:
! 167: if (options.debug) switch(type) {
! 168: case 6: log_dbg("SOA record"); break;
! 169: case 12: log_dbg("PTR record"); break;
! 170: case 15: log_dbg("MX record"); break;
! 171: case 16: log_dbg("TXT record"); break;
! 172: default: log_dbg("Record type %d", type); break;
! 173: }
! 174: log_warn(0, "dropping dns for anti-dnstunnel (type %d: length %d)", type, rdlen);
! 175: return -1;
! 176: }
! 177: }
! 178:
! 179: if (q) {
! 180: dns_fullname(question, qsize, *pktp, opkt, olen, 0);
! 181:
! 182: log_dbg("Q: %s", question);
! 183:
! 184: *pktp = p_pkt;
! 185: *left = len;
! 186:
! 187: return 0;
! 188: }
! 189:
! 190: if (len < 6)
! 191: return_error;
! 192:
! 193: memcpy(&ul, p_pkt, sizeof(ul));
! 194: ttl = ntohl(ul);
! 195: p_pkt += 4;
! 196: len -= 4;
! 197:
! 198: memcpy(&us, p_pkt, sizeof(us));
! 199: rdlen = ntohs(us);
! 200: p_pkt += 2;
! 201: len -= 2;
! 202:
! 203: /*log_dbg("-> w ttl: %d rdlength: %d/%d", ttl, rdlen, len);*/
! 204:
! 205: if (len < rdlen)
! 206: return_error;
! 207:
! 208: /*
! 209: * dns records
! 210: */
! 211:
! 212: switch (type) {
! 213:
! 214: case 1:/* A */
! 215: log_dbg("A record");
! 216: if (options.uamdomains) {
! 217: int id;
! 218: for (id=0; options.uamdomains[id]; id++) {
! 219:
! 220: log_dbg("checking %s [%s]", options.uamdomains[id], question);
! 221:
! 222: if (strlen(question) >= strlen(options.uamdomains[id]) &&
! 223: !strcmp(options.uamdomains[id],
! 224: question + (strlen(question) - strlen(options.uamdomains[id])))) {
! 225: size_t offset;
! 226: for (offset=0; offset < rdlen; offset += 4) {
! 227: add_A_to_garden(p_pkt+offset);
! 228: }
! 229:
! 230: break;
! 231: }
! 232: }
! 233: }
! 234: break;
! 235:
! 236: case 5:/* CNAME */
! 237: {
! 238: char cname[256];
! 239: memset(cname,0,sizeof(cname));
! 240: dns_fullname(cname, sizeof(cname)-1, p_pkt, opkt, olen, 0);
! 241: log_dbg("CNAME record %s", cname);
! 242: }
! 243: break;
! 244:
! 245: default:
! 246:
! 247: if (options.debug) switch(type) {
! 248: case 6: log_dbg("SOA record"); break;
! 249: case 12: log_dbg("PTR record"); break;
! 250: case 15: log_dbg("MX record"); break;
! 251: case 16: log_dbg("TXT record"); break;
! 252: default: log_dbg("Record type %d", type); break;
! 253: }
! 254:
! 255: if (antidnstunnel) {
! 256: log_warn(0, "dropping dns for anti-dnstunnel (type %d: length %d)", type, rdlen);
! 257: return -1;
! 258: }
! 259:
! 260: break;
! 261: }
! 262:
! 263: p_pkt += rdlen;
! 264: len -= rdlen;
! 265:
! 266: *pktp = p_pkt;
! 267: *left = len;
! 268:
! 269: return 0;
! 270: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>