📄 dns.c
字号:
unsigned name_length;
char name2[256];
unsigned name2_length;
unsigned offset = rec->rdata_offset;
unsigned offset_max = MIN(rec->rdata_offset+rec->rdata_length, length);
/* Get the name */
name_length = dns_extract_name(frame, px, length, rec->name_offset, name, sizeof(name));
switch (rec->type<<16 | rec->clss) {
case TYPECLASS(32,1): /*NetBIOS*/
ip_address = ex32be(px+rec->rdata_offset+2);
if (rec->rdata_length != 6)
FRAMERR(frame, "dns: data not 4-bytes long, was %d-bytes instead (class=%d, type=%d, name=%s)\n", rec->rdata_length, rec->clss, rec->type, name);
translate_netbios_name(frame, name, name2, sizeof(name2));
process_record(seap,
"proto", REC_SZ, "NETBIOS", -1,
opcode, REC_SZ, "registration", -1,
"name", REC_PRINTABLE, name2, strlen(name2),
"address", REC_IPv4, &ip_address, sizeof(ip_address),
"ip.src", REC_FRAMESRC, frame, -1,
0);
process_record(seap,
"ID-IP", REC_IPv4, &ip_address, sizeof(ip_address),
"netbios", REC_PRINTABLE, name2, strlen(name2),
0);
break;
case TYPECLASS(6,1): /*SOA*/
/*
* Authoritative Name Server
*/
name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2));
process_record(seap,
"proto", REC_SZ, "DNS", -1,
opcode, REC_SZ, "SOA", -1,
"domain", REC_PRINTABLE, name, name_length,
"NS", REC_PRINTABLE, name2, name2_length,
0);
ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);
if (ip_address)
process_record(seap,
"proto", REC_SZ, "DNS", -1,
opcode, REC_SZ, "SOA", -1,
"domain", REC_PRINTABLE, name, name_length,
"NS", REC_IPv4, &ip_address, sizeof(ip_address),
0);
skip_name(px, length, &offset);
/* Contact */
if (offset < offset_max) {
name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2));
process_record(seap,
"proto", REC_SZ, "DNS", -1,
opcode, REC_SZ, "SOA", -1,
"domain", REC_PRINTABLE, name, name_length,
"contact", REC_PRINTABLE, name2, name2_length,
0);
skip_name(px, length, &offset);
}
break;
case TYPECLASS(2,1): /* NS */
dns_extract_name(frame, px, length, rec->rdata_offset, name2, sizeof(name2));
ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);
process_record(seap,
"proto", REC_SZ, "DNS", -1,
opcode, REC_SZ, "NS", -1,
"domain", REC_PRINTABLE, name, strlen(name),
"NS", REC_PRINTABLE, name2, strlen(name2),
"sender", REC_FRAMESRC, frame, -1,
0);
process_record(seap,
"proto", REC_SZ, "DNS", -1,
opcode, REC_SZ, "NS", -1,
"domain", REC_PRINTABLE, name, strlen(name),
"NS", REC_IPv4, &ip_address, sizeof(ip_address),
"sender", REC_FRAMESRC, frame, -1,
0);
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
}
void process_dns(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
unsigned offset;
struct DNS dns[1] = {0};
unsigned record_count;
unsigned total_records;
unsigned i;
memset(dns, 0, sizeof(dns[0]));
if (length < 12) {
FRAMERR(frame, "dns: frame too short\n");
return;
}
dns->id = ex16be(px+0);
dns->is_response = ((px[2]&0x80) != 0);
dns->opcode = (px[2]>>3)&0x01F;
dns->flags = ex16be(px+2)&0x7F0;
dns->rcode = px[3]&0x0F;
dns->question_count = ex16be(px+4);
dns->answer_count = ex16be(px+6);
dns->authority_count = ex16be(px+8);
dns->additional_count = ex16be(px+10);
total_records = dns->question_count + dns->answer_count + dns->authority_count + dns->additional_count;
offset = 12;
record_count = 0;
/*
* After processing the header, now process all the records
*/
while (offset < length && record_count < 100) {
struct DNSRECORD *rec = &dns->records[record_count];
if (record_count >= total_records) {
SAMPLE("dns", "too-many-records", REC_UNSIGNED, &total_records, sizeof(total_records));
break;
}
rec->name_offset = offset;
while (offset < length) {
if (px[offset] == 0x00) {
offset++;
break;
}
if (px[offset] & 0xC0) {
offset += 2;
break;
}
offset += px[offset] + 1;
if (offset > length) {
FRAMERR(frame, "dns: past end of packet\n");
return;
}
}
if (offset + 4 > length) {
FRAMERR(frame, "dns: past end of packet\n");
return;
}
rec->type = ex16be(px+offset+0);
rec->clss = ex16be(px+offset+2);
offset += 4;
record_count++;
if (record_count <= dns->question_count)
continue;
if (offset + 6 > length) {
FRAMERR(frame, "dns: past end of packet\n");
return;
}
rec->ttl = ex32be(px+offset+0);
rec->rdata_length = ex16be(px+offset+4);
offset += 6;
rec->rdata_offset = offset;
offset += rec->rdata_length;
if (offset > length) {
FRAMERR(frame, "dns: past end of packet\n");
return;
}
}
dns->record_count = record_count;
dns->questions = &dns->records[0];
dns->answers = &dns->records[dns->question_count];
dns->authorities = &dns->records[dns->question_count + dns->answer_count];
dns->additionals = &dns->records[dns->question_count + dns->answer_count + dns->authority_count];
switch (dns->opcode) {
case 0x00: /*query request*/
for (i=0; i<dns->question_count; i++) {
char name[256];
unsigned name_length;
struct DNSRECORD *rec = &dns->questions[i];
name_length = dns_extract_name(frame, px, length, rec->name_offset, name, sizeof(name));
switch (rec->type) {
case 0x0001: /*A = IPv4 address */
switch (rec->clss) {
case 0x0001: /*INTERNET*/
process_record(seap,
"proto", REC_SZ, "DNS", -1,
"query", REC_SZ, "A", -1,
"ip.src", REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name),
0);
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
case 0x001c: /*AAAA = IPv6 address */
switch (rec->clss) {
case 0x0001: /*INTERNET*/
process_record(seap,
"proto", REC_SZ, "DNS", -1,
"query", REC_SZ, "AAAA", -1,
"ip.src", REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name),
0);
break;
case 0x8001:
process_record(seap,
"proto", REC_SZ, "MDNS", -1,
"query", REC_SZ, "AAAA", -1,
"ip.src", REC_FRAMESRC, frame, -1,
"flush", REC_PRINTABLE, name, strlen(name),
0);
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
case 0x0002: /*NS*/
switch (rec->clss) {
case 0x0001: /*INTERNET*/
process_record(seap,
"proto", REC_SZ, "DNS", -1,
"query", REC_SZ, "NS", -1,
"ip.src", REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name),
0);
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
case 0x0006: /*SOA - Start of Authority */
switch (rec->clss) {
case 0x0001: /*INTERNET*/
process_record(seap,
"proto", REC_SZ, "DNS", -1,
"query", REC_SZ, "SOA", -1,
"ip.src", REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name),
0);
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
case 0x0020: /*NETBIOS */
switch (rec->clss) {
case 0x0001: /*INTERNET*/
{
unsigned ip_address = ex32be(px+rec->rdata_offset);
char netbios_name[300];
translate_netbios_name(frame, name, netbios_name, sizeof(netbios_name));
process_record(seap,
"proto", REC_SZ, "NETBIOS", -1,
"query", REC_SZ, "netbios", -1,
"ip.src", REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, netbios_name, strlen(netbios_name),
"address", REC_IPv4, &ip_address, sizeof(ip_address),
0);
}
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
case 0x0021: /*SRV (Service Location) */
switch (rec->clss) {
case 0x0001: /*INTERNET*/
process_record(seap,
"proto", REC_SZ, "DNS", -1,
"query", REC_SZ, "srv", -1,
"ip.src", dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name),
0);
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
case 12: /*PTR*/
switch (rec->clss) {
case 0x0001: /*INTERNET*/
process_record(seap,
"proto", REC_SZ, "DNS", -1,
"op", REC_SZ, "reverse", -1,
"ip.src", dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name),
0);
break;
case 0x8001: /*FLUSH*/
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
case 255: /*any*/
switch (rec->clss) {
case 0x8001: /*FLUSH*/
process_record(seap,
"proto", REC_SZ, "DNS", -1,
"op", REC_SZ, "flush", -1,
"ip.src", dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name),
0);
if (endsWith(name, "._ipp._tcp.local")) {
process_record(seap,
"Bonjour", dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
"Printer", REC_PRINTABLE, name, strlen(name)-strlen("._ipp._tcp.local"),
0);
} else if (endsWith(name, ".local"))
process_record(seap,
"ID-IP", dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
"name", REC_PRINTABLE, name, strlen(name)-strlen(".local"),
0);
else
FRAMERR(frame, "%s: unknown value: %s\n", "dns", name);
break;
case 1:
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
break;
default:
FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
}
}
break;
case 0x10: /*query response */
switch (dns->rcode) {
case 0:
for (i=0; i<dns->answer_count; i++) {
char name[256];
unsigned name_length;
struct DNSRECORD *rec = &dns->answers[i];
if (rec->type == 0x8001)
FRAMERR(frame, "test\n");
name_length = dns_extract_name(frame, px, length, rec->name_offset, name, sizeof(name));
switch (rec->type) {
case 0x0001: /*A = IPv4 address */
switch (rec->clss) {
case 0x0001: /*INTERNET*/
{
unsigned ip_address = ex32be(px+rec->rdata_offset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -