aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-dns-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vpn/gnunet-dns-parser.c')
-rw-r--r--src/vpn/gnunet-dns-parser.c301
1 files changed, 0 insertions, 301 deletions
diff --git a/src/vpn/gnunet-dns-parser.c b/src/vpn/gnunet-dns-parser.c
deleted file mode 100644
index e87109e0c..000000000
--- a/src/vpn/gnunet-dns-parser.c
+++ /dev/null
@@ -1,301 +0,0 @@
1#include "platform.h"
2#include "gnunet-dns-parser.h"
3#include "gnunet-vpn-packet.h"
4
5/**
6 * Parse a name from DNS to a normal .-delimited, 0-terminated string.
7 *
8 * @param d The destination of the name. Should have at least 255 bytes allocated.
9 * @param src The DNS-Packet
10 * @param idx The offset inside the Packet from which on the name should be read
11 * @returns The offset of the first unparsed byte (the byte right behind the name)
12 */
13static unsigned int
14parse_dns_name (char *d, const unsigned char *src, unsigned short idx)
15{ /*{{{ */
16 char *dest = d;
17
18 int len = src[idx++];
19
20 while (len != 0)
21 {
22 if (len & 0xC0)
23 { /* Compressed name, offset in this and the next octet */
24 unsigned short offset = ((len & 0x3F) << 8) | src[idx++];
25
26 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 */
27 return idx;
28 }
29 memcpy (dest, src + idx, len);
30 idx += len;
31 dest += len;
32 *dest = '.';
33 dest++;
34 len = src[idx++];
35 };
36 *dest = 0;
37
38 return idx;
39}
40
41/*}}}*/
42
43/**
44 * Parse a complete DNS-Record from raw DNS-data to a struct dns_record
45 *
46 * @param data The DNS-data
47 * @param dst Pointer to count pointers; individual pointers will be allocated
48 * @param count Number of records to parse
49 * @param idx The offset inside the Packet from which on the name should be read
50 * @returns The offset of the first unparsed byte (the byte right behind the last record)
51 */
52static unsigned short
53parse_dns_record (unsigned char *data, /*{{{ */
54 struct dns_record **dst, unsigned short count,
55 unsigned short idx)
56{
57 int i;
58 unsigned short _idx;
59
60 for (i = 0; i < count; i++)
61 {
62 dst[i] = GNUNET_malloc (sizeof (struct dns_record));
63 dst[i]->name = alloca (255); // see RFC1035, no name can be longer than this.
64 char *name = dst[i]->name;
65
66 _idx = parse_dns_name (name, data, idx);
67 dst[i]->namelen = _idx - idx;
68
69 dst[i]->name = GNUNET_malloc (dst[i]->namelen);
70 memcpy (dst[i]->name, name, dst[i]->namelen);
71
72 idx = _idx;
73
74 dst[i]->type = *((unsigned short *) (data + idx));
75 idx += 2;
76 dst[i]->class = *((unsigned short *) (data + idx));
77 idx += 2;
78 dst[i]->ttl = *((unsigned int *) (data + idx));
79 idx += 4;
80 dst[i]->data_len = *((unsigned short *) (data + idx));
81 idx += 2;
82 dst[i]->data = GNUNET_malloc (ntohs (dst[i]->data_len));
83 memcpy (dst[i]->data, data + idx, ntohs (dst[i]->data_len));
84 idx += ntohs (dst[i]->data_len);
85 }
86 return idx;
87} /*}}} */
88
89/**
90 * Parse a raw DNS-Packet into an usable struct
91 */
92struct dns_pkt_parsed *
93parse_dns_packet (struct dns_pkt *pkt)
94{ /*{{{ */
95 struct dns_pkt_parsed *ppkt = GNUNET_malloc (sizeof (struct dns_pkt_parsed));
96
97 memcpy (&ppkt->s, &pkt->s, sizeof pkt->s);
98
99 unsigned short qdcount = ntohs (ppkt->s.qdcount);
100 unsigned short ancount = ntohs (ppkt->s.ancount);
101 unsigned short nscount = ntohs (ppkt->s.nscount);
102 unsigned short arcount = ntohs (ppkt->s.arcount);
103
104 ppkt->queries = GNUNET_malloc (qdcount * sizeof (struct dns_query *));
105 ppkt->answers = GNUNET_malloc (ancount * sizeof (struct dns_record *));
106 ppkt->nameservers = GNUNET_malloc (nscount * sizeof (struct dns_record *));
107 ppkt->additional = GNUNET_malloc (arcount * sizeof (struct dns_record *));
108
109 unsigned short idx = 0, _idx; /* This keeps track how far we have parsed the data */
110
111 /* Parse the Query */
112 int i;
113
114 for (i = 0; i < qdcount; i++)
115 { /*{{{ */
116 ppkt->queries[i] = GNUNET_malloc (sizeof (struct dns_query));
117 char *name = alloca (255); /* see RFC1035, it can't be more than this. */
118
119 _idx = parse_dns_name (name, pkt->data, idx);
120 ppkt->queries[i]->namelen = _idx - idx;
121 idx = _idx;
122
123 ppkt->queries[i]->name = GNUNET_malloc (ppkt->queries[i]->namelen);
124 memcpy (ppkt->queries[i]->name, name, ppkt->queries[i]->namelen);
125
126 ppkt->queries[i]->qtype = *((unsigned short *) (pkt->data + idx));
127 idx += 2;
128 ppkt->queries[i]->qclass = *((unsigned short *) (pkt->data + idx));
129 idx += 2;
130 }
131 /*}}} */
132 idx = parse_dns_record (pkt->data, ppkt->answers, ancount, idx);
133 idx = parse_dns_record (pkt->data, ppkt->nameservers, nscount, idx);
134 idx = parse_dns_record (pkt->data, ppkt->additional, arcount, idx);
135 return ppkt;
136} /*}}} */
137
138static void
139unparse_dns_name (char *dest, char *src, size_t len)
140{
141 char *b = dest;
142 char cnt = 0;
143
144 dest++;
145 while (*src != 0)
146 {
147 while (*src != '.' && *src != 0)
148 {
149 *dest = *src;
150 src++;
151 dest++;
152 cnt++;
153 }
154 *b = cnt;
155 cnt = 0;
156 b = dest;
157 dest++;
158 src++;
159 }
160 *b = 0;
161}
162
163struct dns_pkt *
164unparse_dns_packet (struct dns_pkt_parsed *ppkt)
165{
166 size_t size = sizeof (struct dns_pkt) - 1;
167 int i;
168
169 for (i = 0; i < ntohs (ppkt->s.qdcount); i++)
170 size += ppkt->queries[i]->namelen + 1;
171
172 for (i = 0; i < ntohs (ppkt->s.ancount); i++)
173 {
174 size += ppkt->answers[i]->namelen + 1;
175 size += ppkt->answers[i]->data_len;
176 }
177 for (i = 0; i < ntohs (ppkt->s.nscount); i++)
178 {
179 size += ppkt->nameservers[i]->namelen + 1;
180 size += ppkt->nameservers[i]->data_len;
181 }
182 for (i = 0; i < ntohs (ppkt->s.arcount); i++)
183 {
184 size += ppkt->additional[i]->namelen + 1;
185 size += ppkt->additional[i]->data_len;
186 }
187
188 size +=
189 4 * ntohs (ppkt->s.qdcount) + 10 * (ntohs (ppkt->s.ancount) +
190 ntohs (ppkt->s.arcount) +
191 ntohs (ppkt->s.nscount));
192
193 struct dns_pkt *pkt = GNUNET_malloc (size);
194 char *pkt_c = (char *) pkt;
195
196 memcpy (&pkt->s, &ppkt->s, sizeof ppkt->s);
197 size_t idx = sizeof ppkt->s;
198
199 for (i = 0; i < ntohs (ppkt->s.qdcount); i++)
200 {
201 unparse_dns_name (&pkt_c[idx], ppkt->queries[i]->name,
202 ppkt->queries[i]->namelen);
203 idx += ppkt->queries[i]->namelen;
204 struct dns_query_line *d = (struct dns_query_line *) &pkt_c[idx];
205
206 d->class = ppkt->queries[i]->qclass;
207 d->type = ppkt->queries[i]->qtype;
208 idx += sizeof (struct dns_query_line);
209 }
210
211 for (i = 0; i < ntohs (ppkt->s.ancount); i++)
212 {
213 unparse_dns_name (&pkt_c[idx], ppkt->answers[i]->name,
214 ppkt->answers[i]->namelen);
215 idx += ppkt->answers[i]->namelen;
216 struct dns_record_line *r = (struct dns_record_line *) &pkt_c[idx];
217
218 r->type = ppkt->answers[i]->type;
219 r->class = ppkt->answers[i]->class;
220 r->ttl = ppkt->answers[i]->ttl;
221 r->data_len = ppkt->answers[i]->data_len;
222 idx += sizeof (struct dns_record_line);
223 memcpy (&r->data, ppkt->answers[i]->data, ppkt->answers[i]->data_len);
224 idx += ppkt->answers[i]->data_len;
225 }
226
227 for (i = 0; i < ntohs (ppkt->s.nscount); i++)
228 {
229 unparse_dns_name (&pkt_c[idx], ppkt->nameservers[i]->name,
230 ppkt->nameservers[i]->namelen);
231 idx += ppkt->nameservers[i]->namelen;
232 struct dns_record_line *r = (struct dns_record_line *) &pkt_c[idx];
233
234 r->type = ppkt->nameservers[i]->type;
235 r->class = ppkt->nameservers[i]->class;
236 r->ttl = ppkt->nameservers[i]->ttl;
237 r->data_len = ppkt->nameservers[i]->data_len;
238 idx += sizeof (struct dns_record_line);
239 memcpy (&r->data, ppkt->nameservers[i]->data,
240 ppkt->nameservers[i]->data_len);
241 idx += ppkt->nameservers[i]->data_len;
242 }
243
244 for (i = 0; i < ntohs (ppkt->s.arcount); i++)
245 {
246 unparse_dns_name (&pkt_c[idx], ppkt->additional[i]->name,
247 ppkt->additional[i]->namelen);
248 idx += ppkt->additional[i]->namelen;
249 struct dns_record_line *r = (struct dns_record_line *) &pkt_c[idx];
250
251 r->type = ppkt->additional[i]->type;
252 r->class = ppkt->additional[i]->class;
253 r->ttl = ppkt->additional[i]->ttl;
254 r->data_len = ppkt->additional[i]->data_len;
255 idx += sizeof (struct dns_record_line);
256 memcpy (&r->data, ppkt->additional[i]->data, ppkt->additional[i]->data_len);
257 idx += ppkt->additional[i]->data_len;
258 }
259
260 return pkt;
261}
262
263void
264free_parsed_dns_packet (struct dns_pkt_parsed *ppkt)
265{
266 unsigned short qdcount = ntohs (ppkt->s.qdcount);
267 unsigned short ancount = ntohs (ppkt->s.ancount);
268 unsigned short nscount = ntohs (ppkt->s.nscount);
269 unsigned short arcount = ntohs (ppkt->s.arcount);
270
271 int i;
272
273 for (i = 0; i < qdcount; i++)
274 {
275 GNUNET_free (ppkt->queries[i]->name);
276 GNUNET_free (ppkt->queries[i]);
277 }
278 GNUNET_free (ppkt->queries);
279 for (i = 0; i < ancount; i++)
280 {
281 GNUNET_free (ppkt->answers[i]->name);
282 GNUNET_free (ppkt->answers[i]->data);
283 GNUNET_free (ppkt->answers[i]);
284 }
285 GNUNET_free (ppkt->answers);
286 for (i = 0; i < nscount; i++)
287 {
288 GNUNET_free (ppkt->nameservers[i]->name);
289 GNUNET_free (ppkt->nameservers[i]->data);
290 GNUNET_free (ppkt->nameservers[i]);
291 }
292 GNUNET_free (ppkt->nameservers);
293 for (i = 0; i < arcount; i++)
294 {
295 GNUNET_free (ppkt->additional[i]->name);
296 GNUNET_free (ppkt->additional[i]->data);
297 GNUNET_free (ppkt->additional[i]);
298 }
299 GNUNET_free (ppkt->additional);
300 GNUNET_free (ppkt);
301}