diff options
author | Philipp Tölke <toelke@in.tum.de> | 2010-11-02 21:40:05 +0000 |
---|---|---|
committer | Philipp Tölke <toelke@in.tum.de> | 2010-11-02 21:40:05 +0000 |
commit | 736b5e9964c384c85c3e00a128cefb34b15d9f11 (patch) | |
tree | 1afee399200b423c694e348a83e2aa807ca6b67c /src/vpn/gnunet-dns-parser.c | |
parent | 55278d42655a4175ea222275966f7df10654908a (diff) | |
download | gnunet-736b5e9964c384c85c3e00a128cefb34b15d9f11.tar.gz gnunet-736b5e9964c384c85c3e00a128cefb34b15d9f11.zip |
Fixes and documentation
Diffstat (limited to 'src/vpn/gnunet-dns-parser.c')
-rw-r--r-- | src/vpn/gnunet-dns-parser.c | 234 |
1 files changed, 151 insertions, 83 deletions
diff --git a/src/vpn/gnunet-dns-parser.c b/src/vpn/gnunet-dns-parser.c index 7b81f6da4..e26638141 100644 --- a/src/vpn/gnunet-dns-parser.c +++ b/src/vpn/gnunet-dns-parser.c | |||
@@ -2,92 +2,160 @@ | |||
2 | #include "gnunet-dns-parser.h" | 2 | #include "gnunet-dns-parser.h" |
3 | #include "gnunet-vpn-packet.h" | 3 | #include "gnunet-vpn-packet.h" |
4 | 4 | ||
5 | unsigned int parse_dns_name(char* d, const unsigned char* src, unsigned short idx) {/*{{{*/ | 5 | /** |
6 | char* dest = d; | 6 | * Parse a name from DNS to a normal .-delimited, 0-terminated string. |
7 | 7 | * | |
8 | int len = src[idx++]; | 8 | * @param d The destination of the name. Should have at least 255 bytes allocated. |
9 | while (len != 0) { | 9 | * @param src The DNS-Packet |
10 | if (len & 0xC0) { /* Compressed name, offset in this and the next octet */ | 10 | * @param idx The offset inside the Packet from which on the name should be read |
11 | unsigned short offset = ((len & 0x3F) << 8) | src[idx++]; | 11 | * @returns The offset of the first unparsed byte (the byte right behind the name) |
12 | parse_dns_name(dest, src, offset - 12); /* 12 for the Header of the DNS-Packet, idx starts at 0 which is 12 bytes from the start of the packet */ | 12 | */ |
13 | return idx; | 13 | static unsigned int |
14 | } | 14 | parse_dns_name(char* d, const unsigned char* src, unsigned short idx) {/*{{{*/ |
15 | memcpy(dest, src+idx, len); | 15 | char* dest = d; |
16 | idx += len; | 16 | |
17 | dest += len; | 17 | int len = src[idx++]; |
18 | *dest = '.'; | 18 | while (len != 0) |
19 | dest++; | 19 | { |
20 | len = src[idx++]; | 20 | if (len & 0xC0) |
21 | }; | 21 | { /* Compressed name, offset in this and the next octet */ |
22 | *dest = 0; | 22 | unsigned short offset = ((len & 0x3F) << 8) | src[idx++]; |
23 | 23 | parse_dns_name(dest, src, offset - 12); /* 12 for the Header of the DNS-Packet, idx starts at 0 which is 12 bytes from the start of the packet */ | |
24 | return idx; | 24 | return idx; |
25 | } | ||
26 | memcpy(dest, src+idx, len); | ||
27 | idx += len; | ||
28 | dest += len; | ||
29 | *dest = '.'; | ||
30 | dest++; | ||
31 | len = src[idx++]; | ||
32 | }; | ||
33 | *dest = 0; | ||
34 | |||
35 | return idx; | ||
25 | } | 36 | } |
26 | /*}}}*/ | 37 | /*}}}*/ |
27 | 38 | ||
28 | unsigned short parse_dns_record(unsigned char* data, struct dns_record** dst, unsigned short count, unsigned short idx) {/*{{{*/ | 39 | /** |
29 | int i; | 40 | * Parse a complete DNS-Record from raw DNS-data to a struct dns_record |
30 | unsigned short _idx; | 41 | * |
31 | for (i = 0; i < count; i++) { | 42 | * @param data The DNS-data |
32 | dst[i] = GNUNET_malloc(sizeof(struct dns_record)); | 43 | * @param dst Pointer to count pointers; individual pointers will be allocated |
33 | dst[i]->name = alloca(255); // see RFC1035 | 44 | * @param count Number of records to parse |
34 | char* name = dst[i]->name; | 45 | * @param idx The offset inside the Packet from which on the name should be read |
35 | 46 | * @returns The offset of the first unparsed byte (the byte right behind the last record) | |
36 | _idx = parse_dns_name(name, data, idx); | 47 | */ |
37 | dst[i]->namelen = _idx - idx; | 48 | static unsigned short |
38 | idx = _idx; | 49 | parse_dns_record(unsigned char* data, /*{{{*/ |
39 | 50 | struct dns_record** dst, | |
40 | dst[i]->type = *((unsigned short*)(data+idx)); | 51 | unsigned short count, |
41 | idx += 2; | 52 | unsigned short idx) { |
42 | dst[i]->class = *((unsigned short*)(data+idx)); | 53 | int i; |
43 | idx += 2; | 54 | unsigned short _idx; |
44 | dst[i]->ttl = *((unsigned int*)(data+idx)); | 55 | for (i = 0; i < count; i++) { |
45 | idx += 4; | 56 | dst[i] = GNUNET_malloc(sizeof(struct dns_record)); |
46 | dst[i]->data_len = *((unsigned short*)(data+idx)); | 57 | dst[i]->name = alloca(255); // see RFC1035, no name can be longer than this. |
47 | idx += 2; | 58 | char* name = dst[i]->name; |
48 | dst[i]->data = GNUNET_malloc(ntohs(dst[i]->data_len)); | 59 | |
49 | memcpy(dst[i]->data, data+idx, ntohs(dst[i]->data_len)); | 60 | _idx = parse_dns_name(name, data, idx); |
50 | idx += ntohs(dst[i]->data_len); | 61 | dst[i]->namelen = _idx - idx; |
51 | } | 62 | |
52 | return idx; | 63 | dst[i]->name = GNUNET_malloc(dst[i]->namelen); |
64 | memcpy(dst[i]->name, name, dst[i]->namelen); | ||
65 | |||
66 | idx = _idx; | ||
67 | |||
68 | dst[i]->type = *((unsigned short*)(data+idx)); | ||
69 | idx += 2; | ||
70 | dst[i]->class = *((unsigned short*)(data+idx)); | ||
71 | idx += 2; | ||
72 | dst[i]->ttl = *((unsigned int*)(data+idx)); | ||
73 | idx += 4; | ||
74 | dst[i]->data_len = *((unsigned short*)(data+idx)); | ||
75 | idx += 2; | ||
76 | dst[i]->data = GNUNET_malloc(ntohs(dst[i]->data_len)); | ||
77 | memcpy(dst[i]->data, data+idx, ntohs(dst[i]->data_len)); | ||
78 | idx += ntohs(dst[i]->data_len); | ||
79 | } | ||
80 | return idx; | ||
53 | }/*}}}*/ | 81 | }/*}}}*/ |
54 | 82 | ||
55 | struct dns_pkt_parsed* parse_dns_packet(struct dns_pkt* pkt) {/*{{{*/ | 83 | /** |
56 | struct dns_pkt_parsed* ppkt = GNUNET_malloc(sizeof(struct dns_pkt_parsed)); | 84 | * Parse a raw DNS-Packet into an usable struct |
57 | memcpy(&ppkt->s, &pkt->s, sizeof pkt->s); | 85 | */ |
58 | 86 | struct dns_pkt_parsed* | |
59 | unsigned short qdcount = ntohs(ppkt->s.qdcount); | 87 | parse_dns_packet(struct dns_pkt* pkt) {/*{{{*/ |
60 | unsigned short ancount = ntohs(ppkt->s.ancount); | 88 | struct dns_pkt_parsed* ppkt = GNUNET_malloc(sizeof(struct dns_pkt_parsed)); |
61 | unsigned short nscount = ntohs(ppkt->s.nscount); | 89 | memcpy(&ppkt->s, &pkt->s, sizeof pkt->s); |
62 | unsigned short arcount = ntohs(ppkt->s.arcount); | 90 | |
63 | 91 | unsigned short qdcount = ntohs(ppkt->s.qdcount); | |
64 | ppkt->queries = GNUNET_malloc(qdcount*sizeof(struct dns_query*)); | 92 | unsigned short ancount = ntohs(ppkt->s.ancount); |
65 | ppkt->answers = GNUNET_malloc(ancount*sizeof(struct dns_record*)); | 93 | unsigned short nscount = ntohs(ppkt->s.nscount); |
66 | ppkt->nameservers = GNUNET_malloc(nscount*sizeof(struct dns_record*)); | 94 | unsigned short arcount = ntohs(ppkt->s.arcount); |
67 | ppkt->additional = GNUNET_malloc(arcount*sizeof(struct dns_record*)); | 95 | |
68 | 96 | ppkt->queries = GNUNET_malloc(qdcount*sizeof(struct dns_query*)); | |
69 | unsigned short idx = 0, _idx; /* This keeps track how far we have parsed the data */ | 97 | ppkt->answers = GNUNET_malloc(ancount*sizeof(struct dns_record*)); |
70 | 98 | ppkt->nameservers = GNUNET_malloc(nscount*sizeof(struct dns_record*)); | |
71 | int i; | 99 | ppkt->additional = GNUNET_malloc(arcount*sizeof(struct dns_record*)); |
72 | for (i = 0; i < qdcount; i++) { /*{{{*/ | 100 | |
73 | ppkt->queries[i] = GNUNET_malloc(sizeof(struct dns_query)); | 101 | unsigned short idx = 0, _idx; /* This keeps track how far we have parsed the data */ |
74 | char* name = alloca(255); /* see RFC1035, it can't be more than this. */ | 102 | |
75 | 103 | /* Parse the Query */ | |
76 | _idx = parse_dns_name(name, pkt->data, idx); | 104 | int i; |
77 | ppkt->queries[i]->namelen = _idx - idx; | 105 | for (i = 0; i < qdcount; i++) |
78 | idx = _idx; | 106 | { /*{{{*/ |
79 | 107 | ppkt->queries[i] = GNUNET_malloc(sizeof(struct dns_query)); | |
80 | ppkt->queries[i]->name = GNUNET_malloc(ppkt->queries[i]->namelen + 1); | 108 | char* name = alloca(255); /* see RFC1035, it can't be more than this. */ |
81 | memcpy(ppkt->queries[i]->name, name, ppkt->queries[i]->namelen + 1); | 109 | |
82 | 110 | _idx = parse_dns_name(name, pkt->data, idx); | |
83 | ppkt->queries[i]->qtype = *((unsigned short*)(pkt->data+idx)); | 111 | ppkt->queries[i]->namelen = _idx - idx; |
84 | idx += 2; | 112 | idx = _idx; |
85 | ppkt->queries[i]->qclass = *((unsigned short*)(pkt->data+idx)); | 113 | |
86 | idx += 2; | 114 | ppkt->queries[i]->name = GNUNET_malloc(ppkt->queries[i]->namelen); |
87 | } | 115 | memcpy(ppkt->queries[i]->name, name, ppkt->queries[i]->namelen); |
88 | /*}}}*/ | 116 | |
89 | idx = parse_dns_record(pkt->data, ppkt->answers, ancount, idx); | 117 | ppkt->queries[i]->qtype = *((unsigned short*)(pkt->data+idx)); |
90 | idx = parse_dns_record(pkt->data, ppkt->nameservers, nscount, idx); | 118 | idx += 2; |
91 | idx = parse_dns_record(pkt->data, ppkt->additional, arcount, idx); | 119 | ppkt->queries[i]->qclass = *((unsigned short*)(pkt->data+idx)); |
92 | return ppkt; | 120 | idx += 2; |
121 | } | ||
122 | /*}}}*/ | ||
123 | idx = parse_dns_record(pkt->data, ppkt->answers, ancount, idx); | ||
124 | idx = parse_dns_record(pkt->data, ppkt->nameservers, nscount, idx); | ||
125 | idx = parse_dns_record(pkt->data, ppkt->additional, arcount, idx); | ||
126 | return ppkt; | ||
93 | }/*}}}*/ | 127 | }/*}}}*/ |
128 | |||
129 | void | ||
130 | free_parsed_dns_packet(struct dns_pkt_parsed* ppkt) { | ||
131 | unsigned short qdcount = ntohs(ppkt->s.qdcount); | ||
132 | unsigned short ancount = ntohs(ppkt->s.ancount); | ||
133 | unsigned short nscount = ntohs(ppkt->s.nscount); | ||
134 | unsigned short arcount = ntohs(ppkt->s.arcount); | ||
135 | |||
136 | int i; | ||
137 | for (i = 0; i < qdcount; i++) { | ||
138 | GNUNET_free(ppkt->queries[i]->name); | ||
139 | GNUNET_free(ppkt->queries[i]); | ||
140 | } | ||
141 | GNUNET_free(ppkt->queries); | ||
142 | for (i = 0; i < ancount; i++) { | ||
143 | GNUNET_free(ppkt->answers[i]->name); | ||
144 | GNUNET_free(ppkt->answers[i]->data); | ||
145 | GNUNET_free(ppkt->answers[i]); | ||
146 | } | ||
147 | GNUNET_free(ppkt->answers); | ||
148 | for (i = 0; i < nscount; i++) { | ||
149 | GNUNET_free(ppkt->nameservers[i]->name); | ||
150 | GNUNET_free(ppkt->nameservers[i]->data); | ||
151 | GNUNET_free(ppkt->nameservers[i]); | ||
152 | } | ||
153 | GNUNET_free(ppkt->nameservers); | ||
154 | for (i = 0; i < arcount; i++) { | ||
155 | GNUNET_free(ppkt->additional[i]->name); | ||
156 | GNUNET_free(ppkt->additional[i]->data); | ||
157 | GNUNET_free(ppkt->additional[i]); | ||
158 | } | ||
159 | GNUNET_free(ppkt->additional); | ||
160 | GNUNET_free(ppkt); | ||
161 | } | ||