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 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; }