Parse and pretty-print dns
authorPhilipp Tölke <toelke@in.tum.de>
Tue, 20 Jul 2010 05:45:21 +0000 (05:45 +0000)
committerPhilipp Tölke <toelke@in.tum.de>
Tue, 20 Jul 2010 05:45:21 +0000 (05:45 +0000)
src/vpn/packet.h
src/vpn/pretty-print.c
src/vpn/pretty-print.h
src/vpn/test.c
src/vpn/tun.h
src/vpn/udp.c [new file with mode: 0644]
src/vpn/udp.h [new file with mode: 0644]

index ccf3cb7fc1ec99d55eec9eace2a662295fae3d15..c19e7a101a2df175754ff85950206e78fe06a9cb 100644 (file)
@@ -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*);
 
index 096afbf961a24bf91a1d8b3ef57b6aa3b730ded8..90bbe7bea36b4888c47ea9ddee7330f5bd177224 100644 (file)
@@ -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)));
+       }
+}}}
index f2aa5b7951d859ba0dd1534ec58def58a449fd0d..57b1825b4a59a95df34bb7e985f4ecf23f92f967 100644 (file)
@@ -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
index 959c56b231905640aee39293bc43abbe116f6028..b24397c718a7e8e7067a85def20f4caa67d8e8f9 100644 (file)
@@ -10,6 +10,7 @@
 #include "debug.h"
 #include "pretty-print.h"
 #include "tcp.h"
+#include "udp.h"
 #include <arpa/inet.h>
 
 
@@ -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;
index ebd92199a0b59df74eafd7399e3f9fed7701c2ea..3ba61771aa704517de8e1b0f7dabd72908b520a9 100644 (file)
@@ -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 (file)
index 0000000..4a7cb94
--- /dev/null
@@ -0,0 +1,22 @@
+#include "debug.h"
+#include "packet.h"
+#include "udp.h"
+
+#include "pretty-print.h"
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+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 (file)
index 0000000..ab285d6
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _GNTUN_UDP_H_
+#define _GNTUN_UDP_H_
+
+#include "packet.h"
+
+extern void handle_udp(struct ip6_udp*);
+
+#endif