From: Philipp Tölke Date: Tue, 20 Jul 2010 05:45:21 +0000 (+0000) Subject: Parse and pretty-print dns X-Git-Tag: initial-import-from-subversion-38251~20925 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6f26625f6a432f75ff339adf7b3330d5f32855ba;p=oweals%2Fgnunet.git Parse and pretty-print dns --- diff --git a/src/vpn/packet.h b/src/vpn/packet.h index ccf3cb7fc..c19e7a101 100644 --- a/src/vpn/packet.h +++ b/src/vpn/packet.h @@ -39,28 +39,45 @@ struct udp_pkt { }; struct dns_pkt { - unsigned id:16; - unsigned qr:1; // query:0, response:1 - unsigned op:4; // query:0, inverse q.:1, status: 2 - unsigned aa:1; // authoritative answer - unsigned tc:1; // message is truncated + unsigned short id; + unsigned rd:1; // recursion desired (client -> server) - unsigned ra:1; // recursion available (server -> client) - unsigned z:2; // reserved - unsigned a:1; // answer is signed by server + unsigned tc:1; // message is truncated + unsigned aa:1; // authoritative answer + unsigned op:4; // query:0, inverse q.:1, status: 2 + unsigned qr:1; // query:0, response:1 + unsigned rcode:4; // 0 No error // 1 Format error // 2 Server failure // 3 Name Error // 4 Not Implemented // 5 Refused - unsigned qdcount:16; // number of questions - unsigned ancount:16; // number of answers - unsigned nscount:16; // number of authority-records - unsigned arcount:16; // number of additional records + unsigned z:3; // reserved + unsigned ra:1; // recursion available (server -> client) + + unsigned short qdcount; // number of questions + unsigned short ancount; // number of answers + unsigned short nscount; // number of authority-records + unsigned short arcount; // number of additional records unsigned char data[1]; }; +struct dns_query { + unsigned char* name; + unsigned short qtype; + unsigned short qclass; +}; + +struct dns_record { + unsigned char* name; + unsigned short type; + unsigned short class; + unsigned int ttl; + unsigned short data_len; + unsigned char* data; +}; + struct ip6_pkt { struct pkt_tun tun; struct ip6_hdr hdr; @@ -84,6 +101,11 @@ int recv_ipv6pkt(int fd, struct pkt_tun** pkt); int recv_pkt(int fd, struct pkt_tun** pkt); struct ip6_pkt* parse_ip6(struct pkt_tun* pkt); +struct ip6_udp_dns { + struct ip6_udp hdr; + struct dns_pkt data; +}; + struct ip6_tcp* parse_ip6_tcp(struct ip6_pkt*); struct ip6_udp* parse_ip6_udp(struct ip6_pkt*); diff --git a/src/vpn/pretty-print.c b/src/vpn/pretty-print.c index 096afbf96..90bbe7bea 100644 --- a/src/vpn/pretty-print.c +++ b/src/vpn/pretty-print.c @@ -176,3 +176,120 @@ void pkt_printf_ip6udp(struct ip6_udp* pkt) {{{ printf("len: %u\n", ntohs(pkt->data.len)); printf("crc: 0x%x\n", ntohs(pkt->data.crc)); }}} + +static char* dns_types(unsigned short type) {{{ + static char* types[] = { /*{{{*/ + "", + "A", // 1 a host address + "NS", // 2 an authoritative name server + "MD", // 3 a mail destination (Obsolete - use MX) + "MF", // 4 a mail forwarder (Obsolete - use MX) + "CNAME", // 5 the canonical name for an alias + "SOA", // 6 marks the start of a zone of authority + "MB", // 7 a mailbox domain name (EXPERIMENTAL) + "MG", // 8 a mail group member (EXPERIMENTAL) + "MR", // 9 a mail rename domain name (EXPERIMENTAL) + "NULL", // 10 a null RR (EXPERIMENTAL) + "WKS", // 11 a well known service description + "PTR", // 12 a domain name pointer + "HINFO", // 13 host information + "MINFO", // 14 mailbox or mail list information + "MX", // 15 mail exchange + "TXT", // 16 text strings + "RP", + "AFSDB" + }; /*}}}*/ + + static char* qtypes[] = { /* + 252! {{{ */ + "AXFR", // 252 A request for a transfer of an entire zone + "MAILB", // 253 A request for mailbox-related records (MB, MG or MR) + "MAILA", // 254 A request for mail agent RRs (Obsolete - see MX) + "*", // 255 A request for all records + }; /*}}}*/ + + if (type <= 18) return types[type]; + if (type >= 252 && type <= 255) return qtypes[type-252]; + + switch(type) { + case 24: return "SIG"; + case 25: return "KEY"; + case 28: return "AAAA"; + case 29: return "LOC"; + case 33: return "SRV"; + case 35: return "NAPTR"; + case 36: return "KX"; + case 37: return "CERT"; + case 39: return "DNAME"; + case 42: return "APL"; + case 43: return "DS"; + case 44: return "SSHFP"; + case 45: return "IPSECKEY"; + case 46: return "RRSIG"; + case 47: return "NSEC"; + case 48: return "DNSKEY"; + case 49: return "DHCID"; + case 50: return "NSEC3"; + case 51: return "NSEC3PARAM"; + case 55: return "HIP"; + case 99: return "SPF"; + case 249: return "TKEY"; + case 250: return "TSIG"; + case 32768: return "TA"; + case 32769: return "DLV"; + } + + return 0; + +}}} + +static char* dns_classes(short class) {{{ + static char* classes[] = { /*{{{*/ + "", + "IN", // 1 the Internet + "CS", // 2 the CSNET class (Obsolete - used only for examples in some obsolete RFCs) + "CH", // 3 the CHAOS class + "HS", // 4 Hesiod [Dyer 87] + }; /*}}}*/ + + if (class <= 4) return classes[class]; + return 0; +}}} + +void pkt_printf_ip6dns(struct ip6_udp_dns* pkt) {{{ + printf("DNS-Packet:\n"); + printf("\tid: %d\n", ntohs(pkt->data.id)); + printf("\t%d: %s\n", pkt->data.qr, pkt->data.qr == 0 ? "query" : "response"); + printf("\top: %s\n", (char*[]){"query", "inverse q.", "status", "inval"}[pkt->data.op]); + printf("\trecursion is%s desired\n", pkt->data.rd == 0 ? " not" : ""); + unsigned short qdcount = ntohs(pkt->data.qdcount); + printf("\t#qd: %d\n", qdcount); + printf("\t#an: %d\n", ntohs(pkt->data.ancount)); + printf("\t#ns: %d\n", ntohs(pkt->data.nscount)); + printf("\t#ar: %d\n", ntohs(pkt->data.arcount)); + + struct dns_query** queries = (struct dns_query**)malloc(qdcount*sizeof(struct dns_query*)); + unsigned int idx = 0; + + int i; + for (i = 0; i < qdcount; i++) { + queries[i] = (struct dns_query*)malloc(sizeof(struct dns_query)); + queries[i]->name = (unsigned char*)malloc(255); // see RFC1035 + unsigned char* name = queries[i]->name; + int len = pkt->data.data[idx++]; + while (len != 0) { + memcpy(name, pkt->data.data+idx, len); + idx += len; + name += len; + *name = '.'; + name++; + len = pkt->data.data[idx++]; + }; + printf("%d\n", idx); + *name = 0; + queries[i]->qtype = *((unsigned short*)(pkt->data.data+idx)); + idx += 2; + queries[i]->qclass = *((unsigned short*)(pkt->data.data+idx)); + idx += 2; + printf("query for %s type=%d (%s) class=%d (%s)\n", queries[i]->name, ntohs(queries[i]->qtype), dns_types(ntohs(queries[i]->qtype)), ntohs(queries[i]->qclass), dns_classes(ntohs(queries[i]->qclass))); + } +}}} diff --git a/src/vpn/pretty-print.h b/src/vpn/pretty-print.h index f2aa5b795..57b1825b4 100644 --- a/src/vpn/pretty-print.h +++ b/src/vpn/pretty-print.h @@ -9,5 +9,6 @@ extern void pkt_printf(struct ip6_pkt* pkt); void pkt_printf_ip6tcp(struct ip6_tcp* pkt); void pkt_printf_ip6udp(struct ip6_udp* pkt); +void pkt_printf_ip6dns(struct ip6_udp_dns* pkt); #endif diff --git a/src/vpn/test.c b/src/vpn/test.c index 959c56b23..b24397c71 100644 --- a/src/vpn/test.c +++ b/src/vpn/test.c @@ -10,6 +10,7 @@ #include "debug.h" #include "pretty-print.h" #include "tcp.h" +#include "udp.h" #include @@ -40,6 +41,7 @@ int main(int c, char** v) { case 0x11: pkt6_udp = parse_ip6_udp(pkt6); pkt_printf_ip6udp(pkt6_udp); + handle_udp(pkt6_udp); break; } break; diff --git a/src/vpn/tun.h b/src/vpn/tun.h index ebd92199a..3ba61771a 100644 --- a/src/vpn/tun.h +++ b/src/vpn/tun.h @@ -6,6 +6,6 @@ * if *dev == 0, uses the name supplied by the kernel * returns the fd to the tun or -1 */ -extern int init_tun(char *dev); +int init_tun(char *dev); #endif diff --git a/src/vpn/udp.c b/src/vpn/udp.c new file mode 100644 index 000000000..4a7cb94ed --- /dev/null +++ b/src/vpn/udp.c @@ -0,0 +1,22 @@ +#include "debug.h" +#include "packet.h" +#include "udp.h" + +#include "pretty-print.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void handle_udp(struct ip6_udp* pkt) { + if (ntohs(pkt->data.dpt) == 53) { //TODO check for dadr, too + pkt_printf_ip6dns((struct ip6_udp_dns*)pkt); + return; + } +} diff --git a/src/vpn/udp.h b/src/vpn/udp.h new file mode 100644 index 000000000..ab285d6c8 --- /dev/null +++ b/src/vpn/udp.h @@ -0,0 +1,8 @@ +#ifndef _GNTUN_UDP_H_ +#define _GNTUN_UDP_H_ + +#include "packet.h" + +extern void handle_udp(struct ip6_udp*); + +#endif