unsigned int ip46_scan (char const *s, ip46_t_ref ip) { unsigned int len = ip6_scan(s, ip->ip) ; if (len) ip->is6 = 1 ; else { len = ip4_scan(s, ip->ip) ; if (len) ip->is6 = 0 ; } return len ; }
static int doit(stralloc *out,stralloc *fqdn) { unsigned int i; char code; char ch; char ip[16]; if (!stralloc_copys(out,"")) return -1; if (!stralloc_readyplus(fqdn,1)) return -1; fqdn->s[fqdn->len]=0; if ((i=ip6_scan(fqdn->s,ip))) { if (!fqdn->s[i]) { stralloc_copyb(out,ip,16); return 0; } } if ((i=ip4_scan(fqdn->s,ip+12))) { if (!fqdn->s[i]) { byte_zero(ip,10); ip[10]=ip[11]=0xff; stralloc_copyb(out,ip,16); return 0; } } code = 0; for (i = 0;i <= fqdn->len;++i) { if (i < fqdn->len) ch = fqdn->s[i]; else ch = '.'; if ((ch == '[') || (ch == ']')) continue; if (ch == '.') { if (!stralloc_append(out,&code)) return -1; code = 0; continue; } if ((ch >= '0') && (ch <= '9')) { code *= 10; code += ch - '0'; continue; } if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1; if (dns_resolve(q,DNS_T_AAAA) == -1) return -1; if (dns_ip6_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1; dns_transmit_free(&dns_resolve_tx); dns_domain_free(&q); return 0; } out->len &= ~3; return 0; }
unsigned int ip6_scanlist (char *out, unsigned int max, char const *s, unsigned int *num) { unsigned int n = 0, w = 0 ; for (; s[w] && (n < max) ; n++) { char ip[16] ; register unsigned int i = ip6_scan(s + w, ip) ; if (!i) break ; byte_copy(out + (n << 4), 16, ip) ; w += i ; while (byte_chr(",; \t\r\n", 6, s[w]) < 6) w++ ; } *num = n ; return w ; }
static int init2(DIR *dir) { direntry *d; const char *fqdn; static char *q; static stralloc text; char servers[256]; int serverslen; int i; int j; for (;;) { errno = 0; d = readdir(dir); if (!d) { if (errno) return 0; return 1; } if (d->d_name[0] != '.') { if (openreadclose(d->d_name,&text,32) != 1) return 0; if (!stralloc_append(&text,"\n")) return 0; fqdn = d->d_name; if (str_equal(fqdn,"@")) fqdn = "."; if (!dns_domain_fromdot(&q,fqdn,str_len(fqdn))) return 0; serverslen = 0; j = 0; for (i = 0;i < text.len;++i) if (text.s[i] == '\n') { if (serverslen <= 60) if (ip6_scan(text.s + j,servers + serverslen)) serverslen += 16; j = i + 1; } byte_zero(servers + serverslen,256 - serverslen); if (!stralloc_catb(&data,q,dns_domain_length(q))) return 0; if (!stralloc_catb(&data,servers,256)) return 0; } } }
int main() { unsigned char *remotehost, *remoteip, *remoteport, *localip, *localport; unsigned char query[256] = {0}; uint32 uid = 0xffffffff; // that's our default for "not found" int query_len = 0; int pos = 0; char *problem = "ok"; stralloc answer = {0}; char strnum[FMT_ULONG]; int proto = 0; char *x; char lip[16] = {0}; char rip[16] = {0}; uint16 lport = 0; uint16 rport = 0; didentd_init(); x = env_get("PROTO"); if(x) { if(str_equal(x, "TCP")) proto = 4; if(str_equal(x, "TCP6")) proto = 6; } if(proto == 0) { buffer_puts(buffer_2, "warning: can't determine $PROTO\n"); buffer_flush(buffer_2); } srandom(((long long) getpid () * (long long) time(0) * (long long) getppid() * (long long) random() * (long long) clock()) % 0xffffffff); /* since we run under tcpserver, we can get all info about the remote side from the enviroment */ remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteport = env_get("TCPREMOTEPORT"); if (remoteport) scan_ushort(remoteport, &rport); else remoteport = "0"; localport = env_get("TCPLOCALPORT"); if (localport) scan_ushort(localport, &lport); else localport = "0"; remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "0.0.0.0"; localip = env_get("TCPLOCALIP"); if (!localip) localip = "0.0.0.0"; if(proto == 4) { if(remoteip) ip4_scan(remoteip, rip); if(localip) ip4_scan(localip, lip); /* seed some entropy into the by IPv4 unsused bytes */ rip[5] = (char) random() & 0xff; rip[6] = (char) random() & 0xff; } if(proto == 6) { if (remoteip) ip6_scan(remoteip, rip); if (localip) ip6_scan(localip, lip); } /* Read the request from the client and \0-terminate it */ /* timeout after 60 seconds */ query_len = timeoutread(60, stdin, query, sizeof(query) - 1); query[query_len] = '\0'; /* If there was any data we can go on */ problem = "empty query"; if (query_len > 0) { problem = "illegal query"; pos = scan_ushort(query, &lport); if(query[pos++] == ' ') if(query[pos++] == ',') if(query[pos++] == ' ') { pos = scan_ushort(&query[pos], &rport); problem = "ok"; if(proto == 4) uid = get_connection_info4(lip, lport, rip, rport); if(proto == 6) uid = get_connection_info6(lip, lport, rip, rport); stralloc_copyb(&answer, strnum, fmt_ulong(strnum, lport)); stralloc_cats(&answer, " , "); stralloc_catb(&answer, strnum, fmt_ulong(strnum, rport)); if(uid != 0xffffffff) problem = generate_answer(&answer, uid, lip, lport, rip, rport); else generate_answer(&answer, uid, lip, lport, rip, rport); buffer_puts(buffer_1, answer.s); buffer_flush(buffer_1); } } /* Do logging */ buffer_puts(buffer_2, localip); buffer_puts(buffer_2, ":"); buffer_put(buffer_2, strnum, fmt_ulong(strnum, lport)); buffer_puts(buffer_2, " -> "); buffer_puts(buffer_2, remoteip); buffer_puts(buffer_2, ":"); buffer_put(buffer_2, strnum, fmt_ulong(strnum, rport)); buffer_puts(buffer_2, " ["); buffer_puts(buffer_2, problem); buffer_puts(buffer_2, "] "); if(uid < 0xffffffff) buffer_put(buffer_2, strnum, fmt_ulong(strnum,uid)); else buffer_puts(buffer_2, "unknown"); buffer_puts(buffer_2, "\n"); buffer_flush(buffer_2); return 0; }
/* 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; }
int main(int argc,char **argv) { unsigned long ttl; struct stat st; int i; int j; int k; char ch; if (!*argv) die_usage(); if (!*++argv) die_usage(); fn = *argv; if (!*++argv) die_usage(); fnnew = *argv; if (!*++argv) die_usage(); if (str_diff(*argv,"add")) die_usage(); if (!*++argv) die_usage(); if (str_equal(*argv,"ns")) mode = '.'; else if (str_equal(*argv,"childns")) mode = '&'; else if (str_equal(*argv,"host")) mode = '='; else if (str_equal(*argv,"host6")) mode = '6'; else if (str_equal(*argv,"alias")) mode = '+'; else if (str_equal(*argv,"alias6")) mode = '3'; else if (str_equal(*argv,"mx")) mode = '@'; else die_usage(); if (!*++argv) die_usage(); if (!dns_domain_fromdot(&target,*argv,str_len(*argv))) nomem(); if (!*++argv) die_usage(); if (mode == '6' || mode == '3') { if (!ip6_scan(*argv,targetip6)) die_usage(); } else { if (!ip4_scan(*argv,targetip)) die_usage(); } umask(077); fd = open_read(fn); if (fd == -1) die_read(); if (fstat(fd,&st) == -1) die_read(); buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace); fdnew = open_trunc(fnnew); if (fdnew == -1) die_write(); if (fchmod(fdnew,st.st_mode & 0644) == -1) die_write(); buffer_init(&bnew,buffer_unixwrite,fdnew,bnewspace,sizeof bnewspace); switch(mode) { case '.': case '&': ttl = TTL_NS; for (i = 0;i < 26;++i) { ch = 'a' + i; if (!stralloc_copyb(&f[0],&ch,1)) nomem(); if (!stralloc_cats(&f[0],".ns.")) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem(); } break; case '+': case '=': case '6': case '3': ttl = TTL_POSITIVE; break; case '@': ttl = TTL_POSITIVE; for (i = 0;i < 26;++i) { ch = 'a' + i; if (!stralloc_copyb(&f[0],&ch,1)) nomem(); if (!stralloc_cats(&f[0],".mx.")) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem(); } break; } while (match) { if (getln(&b,&line,&match,'\n') == -1) die_read(); put(line.s,line.len); if (line.len && !match) put("\n",1); while (line.len) { ch = line.s[line.len - 1]; if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break; --line.len; } if (!line.len) continue; if (line.s[0] == '#') continue; j = 1; for (i = 0;i < NUMFIELDS;++i) { if (j >= line.len) { if (!stralloc_copys(&f[i],"")) nomem(); } else { k = byte_chr(line.s + j,line.len - j,':'); if (!stralloc_copyb(&f[i],line.s + j,k)) nomem(); j += k + 1; } } switch(mode) { case '.': case '&': if (line.s[0] == mode) { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) { if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) { if (!stralloc_cats(&f[2],".ns.")) nomem(); if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem(); } if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem(); if (!stralloc_0(&f[3])) nomem(); if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS; for (i = 0;i < 26;++i) if (dns_domain_equal(d2,names[i])) { used[i] = 1; break; } } } break; case '=': if (line.s[0] == '=') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) strerr_die2x(100,FATAL,"host name already used"); if (!stralloc_0(&f[1])) nomem(); if (ip4_scan(f[1].s,ip)) if (byte_equal(ip,4,targetip)) strerr_die2x(100,FATAL,"IP address already used"); } break; case '6': if (line.s[0] == '6') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) strerr_die2x(100,FATAL,"host name already used"); if (!stralloc_0(&f[1])) nomem(); if (ip6_scan(f[1].s,ip6)) if (byte_equal(ip,16,targetip6)) strerr_die2x(100,FATAL,"IPv6 address already used"); } break; case '@': if (line.s[0] == '@') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) { if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) { if (!stralloc_cats(&f[2],".mx.")) nomem(); if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem(); } if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem(); if (!stralloc_0(&f[4])) nomem(); if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE; for (i = 0;i < 26;++i) if (dns_domain_equal(d2,names[i])) { used[i] = 1; break; } } } break; } } if (!stralloc_copyb(&f[0],&mode,1)) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!stralloc_cats(&f[0],":")) nomem(); if (mode == '6' || mode == '3') { if (!stralloc_catb(&f[0],ip6str,ip6_fmt_flat(ip6str,targetip6))) nomem(); } else { if (!stralloc_catb(&f[0],ipstr,ip4_fmt(ipstr,targetip))) nomem(); } switch(mode) { case '.': case '&': case '@': for (i = 0;i < 26;++i) if (!used[i]) break; if (i >= 26) strerr_die2x(100,FATAL,"too many records for that domain"); ch = 'a' + i; if (!stralloc_cats(&f[0],":")) nomem(); if (!stralloc_catb(&f[0],&ch,1)) nomem(); if (mode == '@') if (!stralloc_cats(&f[0],":")) nomem(); break; } if (!stralloc_cats(&f[0],":")) nomem(); if (!stralloc_catb(&f[0],strnum,fmt_ulong(strnum,ttl))) nomem(); if (!stralloc_cats(&f[0],"\n")) nomem(); put(f[0].s,f[0].len); if (buffer_flush(&bnew) == -1) die_write(); if (fsync(fdnew) == -1) die_write(); if (close(fdnew) == -1) die_write(); /* NFS dorks */ if (rename(fnnew,fn) == -1) strerr_die6sys(111,FATAL,"unable to move ",fnnew," to ",fn,": "); _exit(0); }
int main() { char *x; unsigned int i, j, k; unsigned long cachesize; static stralloc sa = {0}; x = env_get("INTERFACE"); if (x) scan_ulong(x,&interface); x = env_get("IP"); if (!x) strerr_die2x(111,FATAL,"$IP not set"); if (!ip6_scan(x,myipincoming)) strerr_die3x(111,FATAL,"unable to parse IP address ",x); #if 0 /* if if IP is a mapped-IPv4 address, disable IPv6 functionality */ /* this is actually a bad idea */ if (ip6_isv4mapped(myipincoming)) noipv6 = 1; #endif udp53 = socket_udp6(); if (udp53 == -1) strerr_die2sys(111,FATAL,"unable to create UDP socket: "); if (socket_bind6_reuse(udp53,myipincoming,53,interface) == -1) strerr_die2sys(111,FATAL,"unable to bind UDP socket: "); tcp53 = socket_tcp6(); if (tcp53 == -1) strerr_die2sys(111,FATAL,"unable to create TCP socket: "); if (socket_bind6_reuse(tcp53,myipincoming,53,interface) == -1) strerr_die2sys(111,FATAL,"unable to bind TCP socket: "); droproot(FATAL); socket_tryreservein(udp53,131072); byte_zero(seed,sizeof seed); read(0,seed,sizeof seed); dns_random_init(seed); close(0); x = env_get("IPSEND"); if (!x) strerr_die2x(111,FATAL,"$IPSEND not set"); if (!ip6_scan(x,myipoutgoing)) strerr_die3x(111,FATAL,"unable to parse IP address ",x); x = env_get("CACHESIZE"); if (!x) strerr_die2x(111,FATAL,"$CACHESIZE not set"); scan_ulong(x,&cachesize); if (!cache_init(cachesize)) strerr_die3x(111,FATAL,"not enough memory for cache of size ",x); if (openreadclose("ignoreip",&sa,64) < 0) strerr_die2x(111,FATAL,"trouble reading ignoreip"); for(j = k = i = 0; i < sa.len; i++) if (sa.s[i] == '\n') { sa.s[i] = '\0'; if (!stralloc_readyplus(&ignoreip,16)) strerr_die2x(111,FATAL,"out of memory parsing ignoreip"); if (!ip6_scan(sa.s+k,ignoreip.s+j)) strerr_die3x(111,FATAL,"unable to parse address in ignoreip ",ignoreip.s+k); j += 16; k = i + 1; } ignoreip.len = j; if (env_get("HIDETTL")) response_hidettl(); if (env_get("FORWARDONLY")) query_forwardonly(); if (!roots_init()) strerr_die2sys(111,FATAL,"unable to read servers: "); if (socket_listen(tcp53,20) == -1) strerr_die2sys(111,FATAL,"unable to listen on TCP socket: "); log_startup(); doit(); }
int main() { unsigned int pos; char header[12]; char qtype[2]; char qclass[2]; const char *x; droproot(FATAL); dns_random_init(seed); axfr = env_get("AXFR"); x = env_get("TCPREMOTEIP"); if (x && ip6_scan(x,ip)) ; else byte_zero(ip,16); x = env_get("TCPREMOTEPORT"); if (!x) x = "0"; scan_ulong(x,&port); for (;;) { netread(tcpheader,2); uint16_unpack_big(tcpheader,&len); if (len > 512) strerr_die2x(111,FATAL,"excessively large request"); netread(buf,len); pos = dns_packet_copy(buf,len,0,header,12); if (!pos) die_truncated(); if (header[2] & 254) strerr_die2x(111,FATAL,"bogus query"); if (header[4] || (header[5] != 1)) strerr_die2x(111,FATAL,"bogus query"); pos = dns_packet_getname(buf,len,pos,&zone); if (!pos) die_truncated(); zonelen = dns_domain_length(zone); pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) die_truncated(); pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) die_truncated(); if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY)) strerr_die2x(111,FATAL,"bogus query: bad class"); pos = check_edns0(header, buf, len, pos); if (!pos) die_truncated(); qlog(ip,port,header,zone,qtype," "); if (byte_equal(qtype,2,DNS_T_AXFR)) { case_lowerb(zone,zonelen); fdcdb = open_read("data.cdb"); if (fdcdb == -1) die_cdbread(); doaxfr(header); close(fdcdb); } else { if (!response_query(zone,qtype,qclass)) nomem(); response[2] |= 4; case_lowerb(zone,zonelen); response_id(header); response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (!respond(zone,qtype,ip)) die_outside(); print(response,response_len); } } }