int response_addname(char *d) { unsigned int dlen; unsigned int i; char buf[2]; dlen = dns_domain_length(d); while (*d) { for (i = 0;i < name_num;++i) if (dns_domain_equal(d,name[i])) { uint16_pack_big(buf,49152 + name_ptr[i]); return response_addbytes(buf,2); } if (dlen <= 128) if (name_num < NAMES) { byte_copy(name[name_num],dlen,d); name_ptr[name_num] = response_len; ++name_num; } i = (unsigned char) *d; ++i; if (!response_addbytes(d,i)) return 0; d += i; dlen -= i; } return response_addbytes(d,1); }
int response_rstart(char *d,char type[2],char ttl[4]) { if (!response_addname(d)) return 0; if (!response_addbytes(type,2)) return 0; if (!response_addbytes(DNS_C_IN,2)) return 0; if (!response_addbytes(ttl,4)) return 0; if (!response_addbytes("\0\0",2)) return 0; dpos = response_len; return 1; }
int response_query(char *q,char qtype[2]) { response_len = 0; name_num = 0; if (!response_addbytes("\0\0\201\200\0\1\0\0\0\0\0\0",12)) return 0; if (!response_addname(q)) return 0; if (!response_addbytes(qtype,2)) return 0; if (!response_addbytes(DNS_C_IN,2)) return 0; tctarget = response_len; return 1; }
int response_rstart(const char *d,const char type[2],uint32 ttl) { char ttlstr[4]; if (!response_addname(d)) return 0; if (!response_addbytes(type,2)) return 0; if (!response_addbytes(DNS_C_IN,2)) return 0; if (flaghidettl) ttl = 0; uint32_pack_big(ttlstr,ttl); if (!response_addbytes(ttlstr,4)) return 0; if (!response_addbytes("\0\0",2)) return 0; dpos = response_len; return 1; }
static int doit(char *q,char qtype[2],char ip[4]) { int r; uint32 dlen; unsigned int qlen; qlen = dns_domain_length(q); if (qlen > 255) return 0; /* impossible */ if (byte_diff(qtype,2,DNS_T_A) && byte_diff(qtype,2,DNS_T_ANY)) goto REFUSE; key[0] = '%'; byte_copy(key + 1,4,ip); r = cdb_find(&c,key,5); if (!r) r = cdb_find(&c,key,4); if (!r) r = cdb_find(&c,key,3); if (!r) r = cdb_find(&c,key,2); if (r == -1) return 0; key[0] = '+'; byte_zero(key + 1,2); if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,key + 1,2,cdb_datapos(&c)) == -1) return 0; byte_copy(key + 3,qlen,q); case_lowerb(key + 3,qlen + 3); r = cdb_find(&c,key,qlen + 3); if (!r) { byte_zero(key + 1,2); r = cdb_find(&c,key,qlen + 3); } if (!r) goto REFUSE; if (r == -1) return 0; dlen = cdb_datalen(&c); if (dlen > 512) dlen = 512; if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return 0; dns_sortip(data,dlen); if (dlen > 12) dlen = 12; while (dlen >= 4) { dlen -= 4; if (!response_rstart(q,DNS_T_A,"\0\0\0\5")) return 0; if (!response_addbytes(data + dlen,4)) return 0; response_rfinish(RESPONSE_ANSWER); } return 1; REFUSE: response[2] &= ~4; response[3] &= ~15; response[3] |= 5; return 1; }
static int dobytes(unsigned int len) { char buf[20]; if (len > 20) return 0; dpos = dns_packet_copy(data,dlen,dpos,buf,len); if (!dpos) return 0; return response_addbytes(buf,len); }
int response_query (const char *q, const char qtype[2], const char qclass[2]) { response_len = name_num = 0; if (!response_addbytes ("\0\0\201\200\0\1\0\0\0\0\0\0", 12)) return 0; if (!response_addname (q)) return 0; if (!response_addbytes (qtype, 2)) return 0; if (!response_addbytes (qclass, 2)) return 0; tctarget = response_len; return 1; }
static int doit(char *q,char qtype[2]) { unsigned int bpos; unsigned int anpos; unsigned int aupos; unsigned int arpos; char *control; char *wild; int flaggavesoa; int flagfound; int r; int flagns; int flagauthoritative; char x[20]; uint16 u16; char addr[8][4]; int addrnum; uint32 addrttl; int i; anpos = response_len; control = q; for (;;) { flagns = 0; flagauthoritative = 0; cdb_findstart(&c); while (r = find(control,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_SOA)) flagauthoritative = 1; if (byte_equal(type,2,DNS_T_NS)) flagns = 1; } if (flagns) break; if (!*control) return 0; /* q is not within our bailiwick */ control += *control; control += 1; } if (!flagauthoritative) { response[2] &= ~4; goto AUTHORITY; /* q is in a child zone */ } flaggavesoa = 0; flagfound = 0; wild = q; for (;;) { addrnum = 0; addrttl = 0; cdb_findstart(&c); while (r = find(wild,wild != q)) { if (r == -1) return 0; flagfound = 1; if (flaggavesoa && byte_equal(type,2,DNS_T_SOA)) continue; if (byte_diff(type,2,qtype) && byte_diff(qtype,2,DNS_T_ANY) && byte_diff(type,2,DNS_T_CNAME)) continue; if (byte_equal(type,2,DNS_T_A) && (dlen - dpos == 4)) { addrttl = ttl; i = dns_random(addrnum + 1); if (i < 8) { if ((i < addrnum) && (addrnum < 8)) byte_copy(addr[addrnum],4,addr[i]); byte_copy(addr[i],4,data + dpos); } if (addrnum < 1000000) ++addrnum; continue; } if (!response_rstart(q,type,ttl)) return 0; if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_CNAME) || byte_equal(type,2,DNS_T_PTR)) { if (!doname()) return 0; } else if (byte_equal(type,2,DNS_T_MX)) { if (!dobytes(2)) return 0; if (!doname()) return 0; } else if (byte_equal(type,2,DNS_T_SOA)) { if (!doname()) return 0; if (!doname()) return 0; if (!dobytes(20)) return 0; flaggavesoa = 1; } else if (!response_addbytes(data + dpos,dlen - dpos)) return 0; response_rfinish(RESPONSE_ANSWER); } for (i = 0;i < addrnum;++i) if (i < 8) { if (!response_rstart(q,DNS_T_A,addrttl)) return 0; if (!response_addbytes(addr[i],4)) return 0; response_rfinish(RESPONSE_ANSWER); } if (flagfound) break; if (wild == control) break; if (!*wild) break; /* impossible */ wild += *wild; wild += 1; } if (!flagfound) response_nxdomain(); AUTHORITY: aupos = response_len; if (flagauthoritative && (aupos == anpos)) { cdb_findstart(&c); while (r = find(control,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_SOA)) { if (!response_rstart(control,DNS_T_SOA,ttl)) return 0; if (!doname()) return 0; if (!doname()) return 0; if (!dobytes(20)) return 0; response_rfinish(RESPONSE_AUTHORITY); break; } } } else if (want(control,DNS_T_NS)) { cdb_findstart(&c); while (r = find(control,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_NS)) { if (!response_rstart(control,DNS_T_NS,ttl)) return 0; if (!doname()) return 0; response_rfinish(RESPONSE_AUTHORITY); } } } arpos = response_len; bpos = anpos; while (bpos < arpos) { bpos = dns_packet_skipname(response,arpos,bpos); if (!bpos) return 0; bpos = dns_packet_copy(response,arpos,bpos,x,10); if (!bpos) return 0; if (byte_equal(x,2,DNS_T_NS) || byte_equal(x,2,DNS_T_MX)) { if (byte_equal(x,2,DNS_T_NS)) { if (!dns_packet_getname(response,arpos,bpos,&d1)) return 0; } else if (!dns_packet_getname(response,arpos,bpos + 2,&d1)) return 0; case_lowerb(d1,dns_domain_length(d1)); if (want(d1,DNS_T_A)) { cdb_findstart(&c); while (r = find(d1,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_A)) { if (!response_rstart(d1,DNS_T_A,ttl)) return 0; if (!dobytes(4)) return 0; response_rfinish(RESPONSE_ADDITIONAL); } } } } uint16_unpack_big(x + 8,&u16); bpos += u16; } if (flagauthoritative && (response_len > 512)) { byte_zero(response + RESPONSE_ADDITIONAL,2); response_len = arpos; if (response_len > 512) { byte_zero(response + RESPONSE_AUTHORITY,2); response_len = aupos; } } return 1; }
/* this is out work routine which is called by DJBs server code */ int respond(char *q, char qtype[2]) { int flaga; int flagaaaa; int flagloc; char ip[IP6_FMT]; stralloc filename = { 0 }; int fd; buffer b; char bspace[1024]; static stralloc line; int match = 1; unsigned long linenum = 0; int data = 0; stralloc f[NUMFIELDS] = {{0}}; /* check what the client is requesting */ flaga = byte_equal(qtype,2,DNS_T_A); flagloc = byte_equal(qtype,2,DNS_T_LOC); flagaaaa = byte_equal(qtype,2,DNS_T_AAAA); if (byte_equal(qtype,2,DNS_T_ANY)) flaga = flagloc = flagaaaa = 1; /* find out in which file we should look */ query2filename(q, &filename); buffer_put(buffer_2, filename.s, filename.len); buffer_puts(buffer_2, "\n"); buffer_flush(buffer_2); fd = open_read(filename.s); if (fd == -1) { strerr_warn3("unable to open file: ", filename.s, ": ", &strerr_sys); match = 0; } buffer_init(&b, read, fd, bspace, sizeof bspace); /* Work through the file and handout the data. */ while(match) { ++linenum; if(getln(&b, &line, &match, '\n') == -1) { strerr_warn1("unable to read line: ", &strerr_sys); break; } /* clean up line end */ stralloc_cleanlineend(&line); /* skip comments & empty lines */ if(line.s[0] == '#') continue; if(line.s[0] == 0) continue; /* seperate fields */ fieldsep(f, NUMFIELDS, &line, ','); /* IPv4 */ if(f[0].s[0] == '=') { if (flaga) { ip4_scan(f[2].s, ip); data++; /* put type and ttl (60s) */ if (!response_rstart(q, DNS_T_A, "\0\0\0\74")) return 0; /* put ip */ if (!response_addbytes(ip, 4)) return 0; /* record finished */ response_rfinish(RESPONSE_ANSWER); } } /* IPv6 */ if(f[0].s[0] == '6') { if (flagaaaa) { ip6_scan(f[0].s, ip); data++; /* put type and ttl (60s) */ if (!response_rstart(q, DNS_T_AAAA, "\0\0\0\74")) return 0; /* put ip */ if (!response_addbytes(ip, 16)) return 0; /* record finished */ response_rfinish(RESPONSE_ANSWER); } } /* LOC */ if(f[0].s[0] == 'L') { if (flagloc) { txtparse(&f[2]); if(f[2].len <= 16) { buffer_puts(buffer_2, "filedns: warning: LOC record seems to short\n"); buffer_flush(buffer_2); } data++; /* put type and ttl (60s) */ if (!response_rstart(q, DNS_T_LOC, "\0\0\0\74")) return 0; /* put ip */ if (!response_addbytes(f[2].s, 16)) return 0; /* record finished */ response_rfinish(RESPONSE_ANSWER); } } } /* Disclaimer ;-) */ if (!response_rstart(q, DNS_T_TXT, "\0\0\0\74")) return 0; if (!response_addbytes("this is a response from an alpha quality dns-server", 51)) return 0; response_rfinish(RESPONSE_ADDITIONAL); if (!response_rstart(q, DNS_T_TXT, "\0\0\0\74")) return 0; if (!response_addbytes("filednes 0.00 - if problems arise contact [email protected]", 54)) return 0; response_rfinish(RESPONSE_ADDITIONAL); // if (flaga || flagptr) // { // if (dd(q,"",ip) == 4) // { // if (flaga) // { // if (!response_rstart(q,DNS_T_A,"\0\12\0\0")) return 0; // if (!response_addbytes(ip,4)) return 0; // response_rfinish(RESPONSE_ANSWER); // } // return 1; // } // j = dd(q,"\7in-addr\4arpa",ip); // if (j >= 0) // { if(data > 0) return 1; /* nothing found */ buffer_puts(buffer_2, "notfound\n"); buffer_flush(buffer_2); // XXX: this is somehow broken /* response 0-1 is transaction id */ /* set response flags */ /* clear authority bit */ response[2] &= ~4; /* clear last 4 bits */ response[3] &= ~15; /* flag not found */ response[3] |= 3; /* response[4..5]: nr of questions * response[6..7]: nr of answers rr * response[8..9]: nr of authority rr * response[10..11]: nr of additional rr */ return 1; }