diff options
Diffstat (limited to 'src/vpn/gnunet-dns-parser.c')
-rw-r--r-- | src/vpn/gnunet-dns-parser.c | 301 |
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 | */ | ||
13 | static unsigned int | ||
14 | parse_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 | */ | ||
52 | static unsigned short | ||
53 | parse_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 | */ | ||
92 | struct dns_pkt_parsed * | ||
93 | parse_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 | |||
138 | static void | ||
139 | unparse_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 | |||
163 | struct dns_pkt * | ||
164 | unparse_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 | |||
263 | void | ||
264 | free_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 | } | ||