int dns_mx_packet(stralloc *out,const char *buf,unsigned int len) { unsigned int pos; char header[12]; char pref[2]; uint16 numanswers; uint16 datalen; if (!stralloc_copys(out,"")) return -1; pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1; uint16_unpack_big(header + 6,&numanswers); pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; pos += 4; while (numanswers--) { pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1; uint16_unpack_big(header + 8,&datalen); if (byte_equal(header,2,DNS_T_MX)) if (byte_equal(header + 2,2,DNS_C_IN)) { if (!dns_packet_copy(buf,len,pos,pref,2)) return -1; if (!dns_packet_getname(buf,len,pos + 2,&q)) return -1; if (!stralloc_catb(out,pref,2)) return -1; if (!dns_domain_todot_cat(out,q)) return -1; if (!stralloc_0(out)) return -1; } pos += datalen; } return 0; }
int dns_ip4_packet(stralloc *out,const char *buf,unsigned int len) { unsigned int pos; char header[12]; uint16 numanswers; uint16 datalen; if (!stralloc_copys(out,"")) return -1; pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1; uint16_unpack_big(header + 6,&numanswers); pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; pos += 4; while (numanswers--) { pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1; uint16_unpack_big(header + 8,&datalen); if (byte_equal(header,2,DNS_T_A)) if (byte_equal(header + 2,2,DNS_C_IN)) if (datalen == 4) { if (!dns_packet_copy(buf,len,pos,header,4)) return -1; if (!stralloc_catb(out,header,4)) return -1; } pos += datalen; } dns_sortip(out->s,out->len); return 0; }
static int merge_equal (struct dns_transmit *a, struct dns_transmit *b) { const char *ip1 = a->servers + 4 * a->curserver; const char *ip2 = b->servers + 4 * b->curserver; return byte_equal (ip1, 4, ip2) && byte_equal (a->qtype, 2, b->qtype) && dns_domain_equal(a->query + 14, b->query + 14); }
static int doit(void) { unsigned int pos; char header[12]; char qtype[2]; char qclass[2]; if (len >= sizeof buf) goto NOQ; pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ; if (header[2] & 128) goto NOQ; if (header[4]) goto NOQ; if (header[5] != 1) goto NOQ; pos = dns_packet_getname(buf,len,pos,&q); if (!pos) goto NOQ; pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) goto NOQ; pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) goto NOQ; if (!response_query(q,qtype,qclass)) goto NOQ; response_id(header); if (byte_equal(qclass,2,DNS_C_IN)) response[2] |= 4; else if (byte_diff(qclass,2,DNS_C_ANY)) goto WEIRDCLASS; response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (header[2] & 126) goto NOTIMP; if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP; case_lowerb(q,dns_domain_length(q)); if (!respond(q,qtype,ip)) { qlog(ip,port,header,q,qtype," - "); return 0; } qlog(ip,port,header,q,qtype," + "); return 1; NOTIMP: response[3] &= ~15; response[3] |= 4; qlog(ip,port,header,q,qtype," I "); return 1; WEIRDCLASS: response[3] &= ~15; response[3] |= 1; qlog(ip,port,header,q,qtype," C "); return 1; NOQ: qlog(ip,port,"\0\0","","\0\0"," / "); return 0; }
static int init(char ip[64]) { int i; unsigned int j; int iplen = 0; char *x; x = env_get("DNSCACHEIP"); if (x) while (iplen <= 60) { if (*x == '.') ++x; else { i = ip4_scan(x,ip + iplen); if (!i) break; x += i; iplen += 4; } } if (!iplen) { i = openreadclose("/etc/resolv.conf",&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,'\n')) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == '\n') { if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) { i += 10; while ((data.s[i] == ' ') || (data.s[i] == '\t')) ++i; if (iplen <= 60) if (ip4_scan(data.s + i,ip + iplen)) { if (byte_equal(ip + iplen,4,"\0\0\0\0")) byte_copy(ip + iplen,4,"\177\0\0\1"); iplen += 4; } } i = j + 1; } } } if (!iplen) { byte_copy(ip,4,"\177\0\0\1"); iplen = 4; } byte_zero(ip + iplen,64 - iplen); return 0; }
ssize_t socket_send6(int s,const char *buf,size_t len,const char ip[16],uint16 port,uint32 scope_id) { #ifdef LIBC_HAS_IP6 struct sockaddr_in6 si; #else struct sockaddr_in si; #endif byte_zero(&si,sizeof si); #ifdef LIBC_HAS_IP6 if (noipv6) { #endif if (ip6_isv4mapped(ip)) return socket_send4(s,buf,len,ip+12,port); if (byte_equal(ip,16,V6loopback)) return socket_send4(s,buf,len,ip4loopback,port); #ifdef LIBC_HAS_IP6 errno=EPROTONOSUPPORT; return -1; } si.sin6_family = AF_INET6; uint16_pack_big((char *) &si.sin6_port,port); byte_copy((char *) &si.sin6_addr,16,ip); #ifdef LIBC_HAS_SCOPE_ID si.sin6_scope_id=scope_id; #else si.sin6_scope_id=0; #endif return winsock2errno(sendto(s,buf,len,0,(void*) &si,sizeof si)); #else errno=EPROTONOSUPPORT; return -1; #endif }
int socket_send6(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id) { #ifdef LIBC_HAS_IP6 struct sockaddr_in6 sa; #else struct sockaddr_in sa; #endif byte_zero(&sa,sizeof sa); #ifdef LIBC_HAS_IP6 if (noipv6) { #endif if (ip6_isv4mapped(ip)) return socket_send4(s,buf,len,ip+12,port); if (byte_equal(ip,16,V6loopback)) return socket_send4(s,buf,len,ip4loopback,port); #ifdef LIBC_HAS_IP6 errno=error_proto; return -1; } sa.sin6_family = AF_INET6; uint16_pack_big((char *) &sa.sin6_port,port); byte_copy((char *) &sa.sin6_addr,16,ip); return sendto(s,buf,len,0,(struct sockaddr *) &sa,sizeof sa); #else errno=error_proto; return -1; #endif }
int socket_connect6(int s,const char ip[16],uint16 port,uint32 scope_id) { #ifdef LIBC_HAS_IP6 struct sockaddr_in6 sa; if (noipv6) { #endif if (ip6_isv4mapped(ip)) return socket_connect4(s,ip+12,port); if (byte_equal(ip,16,V6loopback)) return socket_connect4(s,ip4loopback,port); #ifdef LIBC_HAS_IP6 } byte_zero(&sa,sizeof sa); sa.sin6_family = PF_INET6; uint16_pack_big((char *) &sa.sin6_port,port); sa.sin6_flowinfo = 0; sa.sin6_scope_id = scope_id; byte_copy((char *) &sa.sin6_addr,16,ip); return connect(s,(struct sockaddr *) &sa,sizeof sa); #else errno=EPROTONOSUPPORT; return -1; #endif }
void defaultsoa_init(int fd) { struct stat st; if (fstat(fd,&st) == -1) strerr_die2sys(111,FATAL,"unable to stat data: "); uint32_pack_big(defaultsoa,st.st_mtime); if (byte_equal(defaultsoa,4,"\0\0\0\0")) defaultsoa[3] = 1; byte_copy(defaultsoa + 4,16,"\0\0\100\000\0\0\010\000\0\020\000\000\0\0\012\000"); }
int dns_txt_packet(stralloc *out,const char *buf,unsigned int len) { unsigned int pos; char header[12]; uint16 numanswers; uint16 datalen; char ch; unsigned int txtlen; int i; if (!stralloc_copys(out,"")) return -1; pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1; uint16_unpack_big(header + 6,&numanswers); pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; pos += 4; while (numanswers--) { pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1; uint16_unpack_big(header + 8,&datalen); if (byte_equal(header,2,DNS_T_TXT)) if (byte_equal(header + 2,2,DNS_C_IN)) { if (pos + datalen > len) return -1; txtlen = 0; for (i = 0;i < datalen;++i) { ch = buf[pos + i]; if (!txtlen) txtlen = (unsigned char) ch; else { --txtlen; if (ch < 32) ch = '?'; if (ch > 126) ch = '?'; if (!stralloc_append(out,&ch)) return -1; } } } pos += datalen; } return 0; }
/* usage: rellink "http://www.nytimes.com/2005/10/06/international/middleeast/06cnd-prexy.html?ex=1129262400&en=30e300dafe83d0fc&ei=5065&partner=MYWAY" downloaded-data.html */ int main(int argc,char* argv[]) { char* baseurl; char* map,* max,* x; struct stat ss; static stralloc sa; if (argc!=3) die(0,"usage: rellink http://base/url downloaded-data.html"); errmsg_iam("rellink"); baseurl=argv[1]; map=mmap_read_stat(argv[2],&ss); if (map==0) diesys(111,"open \"",argv[2],"\" failed"); max=map+ss.st_size; for (x=map; x<max; ) { stralloc tag; /* copy non-tag */ for (; x<max && *x!='<'; ++x) if (stralloc_append(&sa,x)==0) nomem: die(111,"out of memory"); if (x>=max) break; stralloc_copys(&tag,""); { int indq,insq,ok; indq=insq=ok=0; for (; x<max; ++x) { if (*x == '\'') insq^=1; else if (*x == '"') indq^=1; if (stralloc_append(&tag,x)==0) goto nomem; if (*x == '>' && !insq && !indq) { ok=1; ++x; break; } } if (ok) if (mangleurl(&tag,baseurl)==-1) goto nomem; } if (stralloc_cat(&sa,&tag)==0) goto nomem; } if (sa.len == ss.st_size && byte_equal(sa.s,ss.st_size,map)) return 0; munmap(map,ss.st_size); { struct utimbuf utb; int fd=open(argv[2],O_WRONLY|O_TRUNC,0600); if (fd==-1) die(111,"open(\"",argv[2],"\")"); write(fd,sa.s,sa.len); close(fd); utb.actime=ss.st_atime; utb.modtime=ss.st_mtime; utime(argv[2],&utb); } return 0; }
void rr_finish(const char *owner) { if (byte_equal(owner,2,"\1*")) { owner += 2; result.s[2] -= 19; } if (!stralloc_copyb(&key,owner,dns_domain_length(owner))) nomem(); case_lowerb(key.s,key.len); if (cdb_make_add(&cdb,key.s,key.len,result.s,result.len) == -1) die_datatmp(); }
int dmarc_p_reject(const char *domain) { static stralloc data; int r; r = dmarc_fetch(&data,domain); if (r <= 0) return r; if (!dmarc_get(&data,"p",&data)) return 0; return data.len == 6 && byte_equal(data.s,6,"reject"); }
void rr_start(const char type[2],unsigned long ttl,const char ttd[8],const char loc[2]) { char buf[4]; if (!stralloc_copyb(&result,type,2)) nomem(); if (byte_equal(loc,2,"\0\0")) rr_add("=",1); else { rr_add(">",1); rr_add(loc,2); } uint32_pack_big(buf,ttl); rr_add(buf,4); rr_add(ttd,8); }
int64 strlist_indexofb(strlist* sl, const char* x, size_t n) { size_t p; const char* s = sl->sa.s; for(p = 0; p < sl->sa.len;) { size_t l = byte_chr(&sl->sa.s[p], sl->sa.len - p, sl->sep); if((l == 0 && p + 1 == sl->sa.len)) break; if((n == l && byte_equal(&sl->sa.s[p], l, x))) return p; p += l + 1; } return -1; }
void doheaders(void) { int flaggoodfield,match; if (act == AC_DIGEST) copy(&qq,"headeradd",'H'); hdr_add2s("Mailing-List: ",MSG(TXT_MAILING_LIST)); if (listid.len > 0) hdr_add2("List-ID: ",listid.s,listid.len); hdr_datemsgid(when); hdr_from("-help"); if (!stralloc_copys(&mydtline,"Delivered-To: responder for ")) die_nomem(); if (!stralloc_catb(&mydtline,outlocal.s,outlocal.len)) die_nomem(); if (!stralloc_cats(&mydtline,"@")) die_nomem(); if (!stralloc_catb(&mydtline,outhost.s,outhost.len)) die_nomem(); if (!stralloc_cats(&mydtline,"\n")) die_nomem(); qmail_put(&qq,mydtline.s,mydtline.len); flaggoodfield = 0; if (act != AC_DIGEST) for (;;) { if (getln(&ssin,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); if (!match) break; if (line.len == 1) break; if ((line.s[0] != ' ') && (line.s[0] != '\t')) { flaggoodfield = 0; if (case_startb(line.s,line.len,"mailing-list:")) { if (flageditor) /* we may be running from a sublist */ flaggoodfield = 0; else strerr_die2x(100,FATAL,MSG(ERR_MAILING_LIST)); } if (line.len == mydtline.len) if (byte_equal(line.s,line.len,mydtline.s)) strerr_die2x(100,FATAL,MSG(ERR_LOOPING)); if (case_startb(line.s,line.len,"delivered-to:")) flaggoodfield = 1; if (case_startb(line.s,line.len,"received:")) flaggoodfield = 1; } if (flaggoodfield) qmail_put(&qq,line.s,line.len); } }
/* returns 0 if the request was added and should be serviced. * returns 1 if a denial of service attack from this IP was detected and * the request should not be serviced * returns -1 if we ran out of memory trying to add the request */ int new_request_from_ip(const char ip[16],time_t now) { struct connection** x, ** base; unsigned int i; if (!max_requests_per_minute) return 0; if (now > lastpurge+60) { for (i=0; i<sizeof(root)/sizeof(root[0]); ++i) { x=root+i; while (*x) { struct connection* tmp; if ((*x)->last+60 < now || (*x)->connections <= max_requests_per_minute/10) { // had a minute of silence or very low volume -> remove tmp=*x; x=&(*x)->next; free(tmp); } else { /* halve connections count on record unless they exceed threshold */ if ((*x)->connections < max_requests_per_minute) (*x)->connections /= 2; x=&(*x)->next; } } } lastpurge=now; } x=base=root+hash(ip); while (*x) { if (byte_equal((*x)->ip,sizeof(ip),ip)) { int res; (*x)->last=now; res = (++(*x)->connections > max_requests_per_minute); if (x != base) { struct connection* tmp=*x; *x=(*x)->next; tmp->next=*base; *base=tmp; } return res; } x=&(*x)->next; } *x=malloc(sizeof(**x)); if (!*x) return -1; (*x)->last=now; byte_copy((*x)->ip,sizeof(ip),ip); (*x)->connections=1; return 0; }
static int validate_smb_packet(unsigned char* pkt,unsigned long len) { /* we actually received len bytes from the wire, so pkt+len does not * overflow; we got len bytes, because the netbios header said there * were that many bytes in the packet. */ unsigned char* x; /* demand that we have at least a full smbheader and wordcount */ if (len>=smbheadersize+1 && byte_equal(pkt,4,"\xffSMB")) { /* signature needs to be there */ x=(unsigned char*)pkt+smbheadersize; if (x[0] > 100) return -1; /* see that x + sizeof(word_count) + word_count*2 + * sizeof(byte_count) is inside the packet */ if (!range_arrayinbuf(pkt,len,x+3,*x,2)) return -1; /* now we know the word count is ok, but is the byte count? */ { size_t bytecountofs=1+*x*2; size_t bytecount; bytecount=uint16_read((const char*)x+bytecountofs); if (bytecount>len || x+bytecountofs+2+bytecount>pkt+len) return -1; } if (!hasandx(pkt[4])) return 0; for (;;) { size_t bytecount; /* see that x + sizeof(word_count) + word_count*2 + * sizeof(byte_count) is inside the packet */ if (!range_arrayinbuf(pkt,len,x+3,*x,2)) return -1; /* we know that the byte count is within the packet */ /* read it and check whether it's ok, too */ bytecount=uint16_read((const char*)x+1+*x*2); if (!range_arrayinbuf(pkt,len,x+3+bytecount,*x,2)) return -1; if (x[1]==0xff) return 0; { uint16_t next=uint16_read((char*)x+3); if (pkt+next < x+1+x[0]*2+2+bytecount) return -1; /* can't point backwards */ x=pkt+next; } if (!range_bufinbuf(pkt,len,(char*)x,5)) return -1; } } else return -1; return 0; }
void rr_finish (const char *owner) { if (byte_equal (owner, 2, "\1*")) { owner += 2; result.s[2] -= 19; } if (!stralloc_copyb (&key, owner, dns_domain_length (owner))) err (-1, "could not allocate enough memory"); case_lowerb (key.s, key.len); if (cdb_make_add (&cdb, key.s, key.len, result.s, result.len) == -1) errx (-1, "could not create file `data.tmp'"); }
void pathexec_env_run(const char *file, const char *const *argv) { const char **e; unsigned int elen; unsigned int i; unsigned int j; unsigned int split; unsigned int t; if (!stralloc_cats(&plus,"")) return; elen = 0; for (i = 0;environ[i];++i) ++elen; for (i = 0;i < plus.len;++i) if (!plus.s[i]) ++elen; e = (const char **) alloc((elen + 1) * sizeof(char *)); if (!e) return; elen = 0; for (i = 0;environ[i];++i) e[elen++] = environ[i]; j = 0; for (i = 0;i < plus.len;++i) if (!plus.s[i]) { split = str_chr(plus.s + j,'='); for (t = 0;t < elen;++t) if (byte_equal(plus.s + j,split,e[t])) if (e[t][split] == '=') { --elen; e[t] = e[elen]; break; } if (plus.s[j + split]) e[elen++] = plus.s + j; j = i + 1; } e[elen] = 0; pathexec_run(file,argv,e); alloc_free(e); }
int hashok(const char *action,const char *ac) { const char *x; datetime_sec u; x = action + 3; x += scan_ulong(x,&u); hashdate = u; if (hashdate > when) return 0; if (hashdate + 1000000 < when) return 0; u = hashdate; strnum[fmt_ulong(strnum,(unsigned long) u)] = 0; cookie(hash,key.s,key.len - flagdig,strnum,target.s,ac); if (*x == '.') ++x; if (str_len(x) != COOKIE) return 0; return byte_equal(hash,COOKIE,x); }
int main(int argc,char **argv) { uint16 u16; if (!*argv) usage(); if (!*++argv) usage(); if (!parsetype(*argv,type)) usage(); if (!*++argv) usage(); if (!dns_domain_fromdot(&q,*argv,str_len(*argv))) oops(); if (*++argv) { if (!ip4_scan(*argv,ip)) usage(); } if (!stralloc_copys(&out,"")) oops(); /* uint16_unpack_big(type,&u16); if (!stralloc_catulong0(&out,u16,0)) oops(); if (!stralloc_cats(&out," ")) oops(); if (!dns_domain_todot_cat(&out,q)) oops(); if (!stralloc_cats(&out,":\n")) oops(); */ if (!response_query(q,type,DNS_C_IN)) oops(); response[3] &= ~128; response[2] &= ~1; response[2] |= 4; case_lowerb(q,dns_domain_length(q)); if (byte_equal(type,2,DNS_T_AXFR)) { response[3] &= ~15; response[3] |= 4; } else if (!respond(q,type,ip)) goto DONE; if (!printpacket_cat(&out,response,response_len)) oops(); DONE: buffer_putflush(buffer_1,out.s,out.len); _exit(0); }
unsigned int ip6_compactaddr(char *s,char ip[16]) { unsigned long len,temp, k, pos0 = 0,len0 = 0, pos1 = 0, compr = 0; // const unsigned char V4mappedprefix[12] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff}; for (k=0; k<16; k+=2) { if (ip[k] == 0 && ip[k+1] == 0) { if (!compr) { compr=1; pos1=k; } if (k == 14) { k = 16; goto last; } } else if (compr) { last: if ((temp=k-pos1) > len0) { len0 = temp; pos0 = pos1; } compr=0; } } for (len=0,k=0; k<16; k+=2) { if (k == 12 && (byte_equal(ip,12,V4mappedprefix))) { len += ip4_fmt(s,ip+12); break; } if (pos0 == k && len0) { if (k == 0) { ++len; if (s) *s++ = ':'; } ++len; if (s) *s++ = ':'; k += len0-2; continue; } temp = ((unsigned long) (unsigned char) ip[k] << 8) + (unsigned long) (unsigned char) ip[k+1]; temp = fmt_xlong(s,temp); len += temp; if (s) s += temp; if (k<14) { ++len; if (s) *s++ = ':'; } } return len; }
int find_client_loc(char loc[2],const char ip[16]) { int r, fd; char key[32+3]; static struct cdb c; fd = open_read("data.cdb"); if (fd == -1) return 0; cdb_init(&c,fd); byte_zero(loc,2); key[0] = 0; key[1] = '%'; if (byte_equal(ip,12,V4mappedprefix)) { key[2] = 'f'; byte_copy(key + 3,4,ip+12); r = cdb_find(&c,key,7); if (!r) r = cdb_find(&c,key,6); if (!r) r = cdb_find(&c,key,5); if (!r) r = cdb_find(&c,key,4); if (!r) r = cdb_find(&c,key,3); if (r == -1) return 0; if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,loc,2,cdb_datapos(&c)) == -1) return 0; } else { unsigned int n; key[2] = 's'; ip6_fmt_flat(key+3,ip); for (n=19; n>3; --n) { r = cdb_find(&c,key,n); if (r) break; } if (r == -1) return 0; if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,loc,2,cdb_datapos(&c)) == -1) return 0; } cdb_free(&c); close(fd); return r; }
static int want(const char *owner,const char type[2]) { unsigned int pos; static char *d; char x[10]; uint16 datalen; pos = dns_packet_skipname(response,response_len,12); if (!pos) return 0; pos += 4; while (pos < response_len) { pos = dns_packet_getname(response,response_len,pos,&d); if (!pos) return 0; pos = dns_packet_copy(response,response_len,pos,x,10); if (!pos) return 0; if (dns_domain_equal(d,owner)) if (byte_equal(type,2,x)) return 0; uint16_unpack_big(x + 8,&datalen); pos += datalen; } return 1; }
int dmarc_get(const stralloc *rec,const char *key,stralloc *out) { const char *rp; const unsigned int keylen = str_len(key); const char *end = rec->s + rec->len; const char *tp; rp = rec->s; while (end - rp > keylen + 1) { if (byte_equal(rp,keylen,key) && (rp[keylen] == '=' || rp[keylen] == ' ')) { rp += keylen; /* Skip space before = */ while (rp < end && *rp == ' ') ++rp; /* Skip = */ if (rp >= end || *rp++ != '=') return 0; /* Skip space after = */ while (rp < end && *rp == ' ') ++rp; /* Skip over to trailing ; */ tp = rp; while (tp < end && *tp != ';') ++tp; /* Trim space before ; */ while (tp > rp && tp[-1] == ' ') --tp; /* Finally, can return */ stralloc_copyb(out,rp,tp - rp); return 1; } while (rp < end && *rp++ != ';') ; while (rp < end && *rp == ' ') ++rp; } return 0; }
int dns_transmit_start (struct dns_transmit *d, const char servers[64], int flagrecursive, const char *q, const char qtype[2], const char localip[4]) { unsigned int len = 0; const char s1[] = "\0\0\1\0\0\1\0\0\0\0\0\0"; const char s2[] = "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround"; dns_transmit_free (d); errno = error_io; len = dns_domain_length (q); d->querylen = len + 18; d->query = alloc (d->querylen); if (!d->query) return -1; uint16_pack_big (d->query, len + 16); byte_copy (d->query + 2, 12, flagrecursive ? s1 : s2); byte_copy (d->query + 14, len, q); byte_copy (d->query + 14 + len, 2, qtype); byte_copy (d->query + 16 + len, 2, DNS_C_IN); byte_copy (d->qtype, 2, qtype); d->servers = servers; byte_copy (d->localip, 4, localip); d->udploop = flagrecursive ? 1 : 0; if ((len + 16 > 512) || byte_equal (qtype, 2, DNS_T_ANY)) return firsttcp (d); return firstudp (d); }
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; }
int main() { int fddata; int i; int j; int k; char ch; unsigned long ttl; char ttd[8]; char loc[2]; unsigned long u; char ip[4]; char ip6[16]; char type[2]; char soa[20]; char buf[4]; umask(022); fddata = open_read("data"); if (fddata == -1) strerr_die2sys(111,FATAL,"unable to open data: "); defaultsoa_init(fddata); buffer_init(&b,buffer_unixread,fddata,bspace,sizeof bspace); fdcdb = open_trunc("data.tmp"); if (fdcdb == -1) die_datatmp(); if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp(); while (match) { ++linenum; if (getln(&b,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,"unable to read line: "); 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; 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(line.s[0]) { case '%': locparse(&f[0],loc); if (!stralloc_copyb(&key,"\0%",2)) nomem(); if (!stralloc_0(&f[1])) nomem(); ipprefix_cat(&key,f[1].s); if (cdb_make_add(&cdb,key.s,key.len,loc,2) == -1) die_datatmp(); break; case 'Z': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!stralloc_0(&f[3])) nomem(); if (!scan_ulong(f[3].s,&u)) uint32_unpack_big(defaultsoa,&u); uint32_pack_big(soa,u); if (!stralloc_0(&f[4])) nomem(); if (!scan_ulong(f[4].s,&u)) uint32_unpack_big(defaultsoa + 4,&u); uint32_pack_big(soa + 4,u); if (!stralloc_0(&f[5])) nomem(); if (!scan_ulong(f[5].s,&u)) uint32_unpack_big(defaultsoa + 8,&u); uint32_pack_big(soa + 8,u); if (!stralloc_0(&f[6])) nomem(); if (!scan_ulong(f[6].s,&u)) uint32_unpack_big(defaultsoa + 12,&u); uint32_pack_big(soa + 12,u); if (!stralloc_0(&f[7])) nomem(); if (!scan_ulong(f[7].s,&u)) uint32_unpack_big(defaultsoa + 16,&u); uint32_pack_big(soa + 16,u); if (!stralloc_0(&f[8])) nomem(); if (!scan_ulong(f[8].s,&ttl)) ttl = TTL_NEGATIVE; ttdparse(&f[9],ttd); locparse(&f[10],loc); rr_start(DNS_T_SOA,ttl,ttd,loc); if (!dns_domain_fromdot(&d2,f[1].s,f[1].len)) nomem(); rr_addname(d2); if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem(); rr_addname(d2); rr_add(soa,20); rr_finish(d1); break; case '.': case '&': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!stralloc_0(&f[3])) nomem(); if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS; ttdparse(&f[4],ttd); locparse(&f[5],loc); if (!stralloc_0(&f[1])) nomem(); 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 (line.s[0] == '.') { rr_start(DNS_T_SOA,ttl ? TTL_NEGATIVE : 0,ttd,loc); rr_addname(d2); rr_add("\12hostmaster",11); rr_addname(d1); rr_add(defaultsoa,20); rr_finish(d1); } rr_start(DNS_T_NS,ttl,ttd,loc); rr_addname(d2); rr_finish(d1); if (ip4_scan(f[1].s,ip)) { rr_start(DNS_T_A,ttl,ttd,loc); rr_add(ip,4); rr_finish(d2); } break; case '+': case '=': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!stralloc_0(&f[2])) nomem(); if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE; ttdparse(&f[3],ttd); locparse(&f[4],loc); if (!stralloc_0(&f[1])) nomem(); if (ip4_scan(f[1].s,ip)) { rr_start(DNS_T_A,ttl,ttd,loc); rr_add(ip,4); rr_finish(d1); if (line.s[0] == '=') { dns_name4_domain(dptr,ip); rr_start(DNS_T_PTR,ttl,ttd,loc); rr_addname(d1); rr_finish(dptr); } } break; case '6': case '3': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!stralloc_0(&f[2])) nomem(); if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE; ttdparse(&f[3],ttd); locparse(&f[4],loc); if (!stralloc_0(&f[1])) nomem(); if (ip6_scan_flat(f[1].s,ip6)) { rr_start(DNS_T_AAAA,ttl,ttd,loc); rr_add(ip6,16); rr_finish(d1); if (line.s[0] == '6') { /* emit both .ip6.arpa and .ip6.int */ dns_name6_domain(d6ptr,ip6,DNS_IP6_ARPA); rr_start(DNS_T_PTR,ttl,ttd,loc); rr_addname(d1); rr_finish(d6ptr); dns_name6_domain(d6ptr,ip6,DNS_IP6_INT); rr_start(DNS_T_PTR,ttl,ttd,loc); rr_addname(d1); rr_finish(d6ptr); } } break; case '@': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!stralloc_0(&f[4])) nomem(); if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE; ttdparse(&f[5],ttd); locparse(&f[6],loc); if (!stralloc_0(&f[1])) nomem(); 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[3])) nomem(); if (!scan_ulong(f[3].s,&u)) u = 0; rr_start(DNS_T_MX,ttl,ttd,loc); uint16_pack_big(buf,u); rr_add(buf,2); rr_addname(d2); rr_finish(d1); if (ip4_scan(f[1].s,ip)) { rr_start(DNS_T_A,ttl,ttd,loc); rr_add(ip,4); rr_finish(d2); } break; case '^': case 'C': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!dns_domain_fromdot(&d2,f[1].s,f[1].len)) nomem(); if (!stralloc_0(&f[2])) nomem(); if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE; ttdparse(&f[3],ttd); locparse(&f[4],loc); if (line.s[0] == 'C') rr_start(DNS_T_CNAME,ttl,ttd,loc); else rr_start(DNS_T_PTR,ttl,ttd,loc); rr_addname(d2); rr_finish(d1); break; case '\'': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!stralloc_0(&f[2])) nomem(); if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE; ttdparse(&f[3],ttd); locparse(&f[4],loc); rr_start(DNS_T_TXT,ttl,ttd,loc); txtparse(&f[1]); i = 0; while (i < f[1].len) { k = f[1].len - i; if (k > 127) k = 127; ch = k; rr_add(&ch,1); rr_add(f[1].s + i,k); i += k; } rr_finish(d1); break; case ':': if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (!stralloc_0(&f[3])) nomem(); if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_POSITIVE; ttdparse(&f[4],ttd); locparse(&f[5],loc); if (!stralloc_0(&f[1])) nomem(); scan_ulong(f[1].s,&u); uint16_pack_big(type,u); if (byte_equal(type,2,DNS_T_AXFR)) syntaxerror(": type AXFR prohibited"); if (byte_equal(type,2,"\0\0")) syntaxerror(": type 0 prohibited"); if (byte_equal(type,2,DNS_T_SOA)) syntaxerror(": type SOA prohibited"); if (byte_equal(type,2,DNS_T_NS)) syntaxerror(": type NS prohibited"); if (byte_equal(type,2,DNS_T_CNAME)) syntaxerror(": type CNAME prohibited"); if (byte_equal(type,2,DNS_T_PTR)) syntaxerror(": type PTR prohibited"); if (byte_equal(type,2,DNS_T_MX)) syntaxerror(": type MX prohibited"); txtparse(&f[2]); rr_start(type,ttl,ttd,loc); rr_add(f[2].s,f[2].len); rr_finish(d1); break; default: syntaxerror(": unrecognized leading character"); } } if (cdb_make_finish(&cdb) == -1) die_datatmp(); if (fsync(fdcdb) == -1) die_datatmp(); if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */ if (rename("data.tmp","data.cdb") == -1) strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: "); _exit(0); }
static int init(stralloc *rules) { char host[256]; const char *x; int i; int j; int k; if (!stralloc_copys(rules,"")) return -1; x = env_get("DNSREWRITEFILE"); if (!x) x = "/etc/dnsrewrite"; i = openreadclose(x,&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,"\n")) return -1; i = 0; for (j = 0; (unsigned)j < data.len;++j) if (data.s[j] == '\n') { if (!stralloc_catb(rules,data.s + i,j - i)) return -1; while (rules->len) { if (rules->s[rules->len - 1] != ' ') if (rules->s[rules->len - 1] != '\t') if (rules->s[rules->len - 1] != '\r') break; --rules->len; } if (!stralloc_0(rules)) return -1; i = j + 1; } return 0; } x = env_get("LOCALDOMAIN"); if (x) { if (!stralloc_copys(&data,x)) return -1; if (!stralloc_append(&data," ")) return -1; if (!stralloc_copys(rules,"?:")) return -1; i = 0; for (j = 0; (unsigned)j < data.len;++j) if (data.s[j] == ' ') { if (!stralloc_cats(rules,"+.")) return -1; if (!stralloc_catb(rules,data.s + i,j - i)) return -1; i = j + 1; } if (!stralloc_0(rules)) return -1; if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; } i = openreadclose("/etc/resolv.conf",&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,"\n")) return -1; i = 0; for (j = 0; (unsigned)j < data.len;++j) if (data.s[j] == '\n') { if (byte_equal("search ",7,data.s + i) || byte_equal("search\t",7,data.s + i) || byte_equal("domain ",7,data.s + i) || byte_equal("domain\t",7,data.s + i)) { if (!stralloc_copys(rules,"?:")) return -1; i += 7; while (i < j) { k = byte_chr(data.s + i,j - i,' '); k = byte_chr(data.s + i,k,'\t'); if (!k) { ++i; continue; } if (!stralloc_cats(rules,"+.")) return -1; if (!stralloc_catb(rules,data.s + i,k)) return -1; i += k; } if (!stralloc_0(rules)) return -1; if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; } i = j + 1; } } host[0] = 0; if (gethostname(host,sizeof host) == -1) return -1; host[(sizeof host) - 1] = 0; i = str_chr(host,'.'); if (host[i]) { if (!stralloc_copys(rules,"?:")) return -1; if (!stralloc_cats(rules,host + i)) return -1; if (!stralloc_0(rules)) return -1; } if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; }