diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-04 15:17:53 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-04 15:17:53 +0000 |
commit | c217aa8750bebf75b4a4a0d020cc516e8efad7be (patch) | |
tree | 6147622e7fb3e893e9a4c3d4910a61d0c96f06d5 | |
parent | c8fe500945cd968e37f2e6c462689e0ada061bce (diff) | |
download | gnunet-c217aa8750bebf75b4a4a0d020cc516e8efad7be.tar.gz gnunet-c217aa8750bebf75b4a4a0d020cc516e8efad7be.zip |
-dns parser works now well-enough
-rw-r--r-- | src/dns/dnsparser.c | 143 | ||||
-rw-r--r-- | src/dns/gnunet-dns-monitor.c | 49 | ||||
-rw-r--r-- | src/include/gnunet_dns_service-new.h | 11 | ||||
-rw-r--r-- | src/include/gnunet_dnsparser_lib.h | 98 | ||||
-rw-r--r-- | src/transport/gnunet-transport.c | 2 |
5 files changed, 273 insertions, 30 deletions
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c index 468c984aa..e02ce73fb 100644 --- a/src/dns/dnsparser.c +++ b/src/dns/dnsparser.c | |||
@@ -55,6 +55,15 @@ struct record_line | |||
55 | uint16_t data_len GNUNET_PACKED; | 55 | uint16_t data_len GNUNET_PACKED; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct soa_data | ||
59 | { | ||
60 | uint32_t serial GNUNET_PACKED; | ||
61 | uint32_t refresh GNUNET_PACKED; | ||
62 | uint32_t retry GNUNET_PACKED; | ||
63 | uint32_t expire GNUNET_PACKED; | ||
64 | uint32_t minimum GNUNET_PACKED; | ||
65 | }; | ||
66 | |||
58 | GNUNET_NETWORK_STRUCT_END | 67 | GNUNET_NETWORK_STRUCT_END |
59 | 68 | ||
60 | 69 | ||
@@ -191,6 +200,9 @@ parse_record (const char *udp_payload, | |||
191 | { | 200 | { |
192 | char *name; | 201 | char *name; |
193 | struct record_line rl; | 202 | struct record_line rl; |
203 | size_t old_off; | ||
204 | struct soa_data soa; | ||
205 | uint16_t mxpref; | ||
194 | 206 | ||
195 | name = parse_name (udp_payload, | 207 | name = parse_name (udp_payload, |
196 | udp_payload_length, | 208 | udp_payload_length, |
@@ -201,7 +213,7 @@ parse_record (const char *udp_payload, | |||
201 | if (*off + sizeof (struct record_line) > udp_payload_length) | 213 | if (*off + sizeof (struct record_line) > udp_payload_length) |
202 | return GNUNET_SYSERR; | 214 | return GNUNET_SYSERR; |
203 | memcpy (&rl, &udp_payload[*off], sizeof (rl)); | 215 | memcpy (&rl, &udp_payload[*off], sizeof (rl)); |
204 | *off += sizeof (rl); | 216 | (*off) += sizeof (rl); |
205 | r->type = ntohs (rl.type); | 217 | r->type = ntohs (rl.type); |
206 | r->class = ntohs (rl.class); | 218 | r->class = ntohs (rl.class); |
207 | r->expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | 219 | r->expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, |
@@ -211,9 +223,62 @@ parse_record (const char *udp_payload, | |||
211 | return GNUNET_SYSERR; | 223 | return GNUNET_SYSERR; |
212 | if (0 == r->data_len) | 224 | if (0 == r->data_len) |
213 | return GNUNET_OK; | 225 | return GNUNET_OK; |
214 | r->data = GNUNET_malloc (r->data_len); | 226 | switch (r->type) |
215 | memcpy (r->data, &udp_payload[*off], r->data_len); | 227 | { |
216 | *off += r->data_len; | 228 | case GNUNET_DNSPARSER_TYPE_NS: |
229 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
230 | case GNUNET_DNSPARSER_TYPE_PTR: | ||
231 | old_off = *off; | ||
232 | r->data.hostname = parse_name (udp_payload, | ||
233 | udp_payload_length, | ||
234 | off); | ||
235 | if ( (NULL == r->data.hostname) || | ||
236 | (old_off + r->data_len != *off) ) | ||
237 | return GNUNET_SYSERR; | ||
238 | return GNUNET_OK; | ||
239 | case GNUNET_DNSPARSER_TYPE_SOA: | ||
240 | old_off = *off; | ||
241 | r->data.soa = GNUNET_malloc (sizeof (struct GNUNET_DNSPARSER_SoaRecord)); | ||
242 | r->data.soa->mname = parse_name (udp_payload, | ||
243 | udp_payload_length, | ||
244 | off); | ||
245 | r->data.soa->rname = parse_name (udp_payload, | ||
246 | udp_payload_length, | ||
247 | off); | ||
248 | if ( (NULL == r->data.soa->mname) || | ||
249 | (NULL == r->data.soa->rname) || | ||
250 | (*off + sizeof (soa) > udp_payload_length) ) | ||
251 | return GNUNET_SYSERR; | ||
252 | memcpy (&soa, &udp_payload[*off], sizeof (soa)); | ||
253 | r->data.soa->serial = ntohl (soa.serial); | ||
254 | r->data.soa->refresh = ntohl (soa.refresh); | ||
255 | r->data.soa->retry = ntohl (soa.retry); | ||
256 | r->data.soa->expire = ntohl (soa.expire); | ||
257 | r->data.soa->minimum_ttl = ntohl (soa.minimum); | ||
258 | (*off) += sizeof (soa); | ||
259 | if (old_off + r->data_len != *off) | ||
260 | return GNUNET_SYSERR; | ||
261 | return GNUNET_OK; | ||
262 | case GNUNET_DNSPARSER_TYPE_MX: | ||
263 | old_off = *off; | ||
264 | if (*off + sizeof (uint16_t) > udp_payload_length) | ||
265 | return GNUNET_SYSERR; | ||
266 | memcpy (&mxpref, &udp_payload[*off], sizeof (uint16_t)); | ||
267 | (*off) += sizeof (uint16_t); | ||
268 | r->data.mx = GNUNET_malloc (sizeof (struct GNUNET_DNSPARSER_MxRecord)); | ||
269 | r->data.mx->preference = ntohs (mxpref); | ||
270 | r->data.mx->mxhost = parse_name (udp_payload, | ||
271 | udp_payload_length, | ||
272 | off); | ||
273 | if (old_off + r->data_len != *off) | ||
274 | return GNUNET_SYSERR; | ||
275 | return GNUNET_OK; | ||
276 | default: | ||
277 | r->data.raw = GNUNET_malloc (r->data_len); | ||
278 | memcpy (r->data.raw, &udp_payload[*off], r->data_len); | ||
279 | break; | ||
280 | } | ||
281 | (*off) += r->data_len; | ||
217 | return GNUNET_OK; | 282 | return GNUNET_OK; |
218 | } | 283 | } |
219 | 284 | ||
@@ -303,6 +368,61 @@ GNUNET_DNSPARSER_parse (const char *udp_payload, | |||
303 | 368 | ||
304 | 369 | ||
305 | /** | 370 | /** |
371 | * Free SOA information record. | ||
372 | * | ||
373 | * @param soa record to free | ||
374 | */ | ||
375 | static void | ||
376 | free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa) | ||
377 | { | ||
378 | if (NULL == soa) | ||
379 | return; | ||
380 | GNUNET_free_non_null (soa->mname); | ||
381 | GNUNET_free_non_null (soa->rname); | ||
382 | GNUNET_free (soa); | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Free MX information record. | ||
388 | * | ||
389 | * @param mx record to free | ||
390 | */ | ||
391 | static void | ||
392 | free_mx (struct GNUNET_DNSPARSER_MxRecord *mx) | ||
393 | { | ||
394 | if (NULL == mx) | ||
395 | return; | ||
396 | GNUNET_free_non_null (mx->mxhost); | ||
397 | GNUNET_free (mx); | ||
398 | } | ||
399 | |||
400 | |||
401 | static void | ||
402 | free_record (struct GNUNET_DNSPARSER_Record *r) | ||
403 | { | ||
404 | GNUNET_free_non_null (r->name); | ||
405 | switch (r->type) | ||
406 | { | ||
407 | case GNUNET_DNSPARSER_TYPE_MX: | ||
408 | free_mx (r->data.mx); | ||
409 | break; | ||
410 | case GNUNET_DNSPARSER_TYPE_SOA: | ||
411 | free_soa (r->data.soa); | ||
412 | break; | ||
413 | case GNUNET_DNSPARSER_TYPE_NS: | ||
414 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
415 | case GNUNET_DNSPARSER_TYPE_PTR: | ||
416 | GNUNET_free_non_null (r->data.hostname); | ||
417 | break; | ||
418 | default: | ||
419 | GNUNET_free_non_null (r->data.raw); | ||
420 | break; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | |||
425 | /** | ||
306 | * Free memory taken by a packet. | 426 | * Free memory taken by a packet. |
307 | * | 427 | * |
308 | * @param p packet to free | 428 | * @param p packet to free |
@@ -316,22 +436,13 @@ GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p) | |||
316 | GNUNET_free_non_null (p->queries[i].name); | 436 | GNUNET_free_non_null (p->queries[i].name); |
317 | GNUNET_free_non_null (p->queries); | 437 | GNUNET_free_non_null (p->queries); |
318 | for (i=0;i<p->num_answers;i++) | 438 | for (i=0;i<p->num_answers;i++) |
319 | { | 439 | free_record (&p->answers[i]); |
320 | GNUNET_free_non_null (p->answers[i].name); | ||
321 | GNUNET_free_non_null (p->answers[i].data); | ||
322 | } | ||
323 | GNUNET_free_non_null (p->answers); | 440 | GNUNET_free_non_null (p->answers); |
324 | for (i=0;i<p->num_authority_records;i++) | 441 | for (i=0;i<p->num_authority_records;i++) |
325 | { | 442 | free_record (&p->authority_records[i]); |
326 | GNUNET_free_non_null (p->authority_records[i].name); | ||
327 | GNUNET_free_non_null (p->authority_records[i].data); | ||
328 | } | ||
329 | GNUNET_free_non_null (p->authority_records); | 443 | GNUNET_free_non_null (p->authority_records); |
330 | for (i=0;i<p->num_additional_records;i++) | 444 | for (i=0;i<p->num_additional_records;i++) |
331 | { | 445 | free_record (&p->additional_records[i]); |
332 | GNUNET_free_non_null (p->additional_records[i].name); | ||
333 | GNUNET_free_non_null (p->additional_records[i].data); | ||
334 | } | ||
335 | GNUNET_free_non_null (p->additional_records); | 446 | GNUNET_free_non_null (p->additional_records); |
336 | GNUNET_free (p); | 447 | GNUNET_free (p); |
337 | } | 448 | } |
diff --git a/src/dns/gnunet-dns-monitor.c b/src/dns/gnunet-dns-monitor.c index c8fb646e5..96d2a4959 100644 --- a/src/dns/gnunet-dns-monitor.c +++ b/src/dns/gnunet-dns-monitor.c | |||
@@ -70,8 +70,6 @@ get_type (uint16_t type) | |||
70 | case GNUNET_DNSPARSER_TYPE_MX: return "MX"; | 70 | case GNUNET_DNSPARSER_TYPE_MX: return "MX"; |
71 | case GNUNET_DNSPARSER_TYPE_TXT: return "TXT"; | 71 | case GNUNET_DNSPARSER_TYPE_TXT: return "TXT"; |
72 | case GNUNET_DNSPARSER_TYPE_AAAA: return "AAAA"; | 72 | case GNUNET_DNSPARSER_TYPE_AAAA: return "AAAA"; |
73 | case GNUNET_DNSPARSER_TYPE_IXFR: return "IXFR"; | ||
74 | case GNUNET_DNSPARSER_TYPE_AXFR: return "AXFR"; | ||
75 | } | 73 | } |
76 | GNUNET_snprintf (buf, sizeof (buf), "%u", (unsigned int) type); | 74 | GNUNET_snprintf (buf, sizeof (buf), "%u", (unsigned int) type); |
77 | return buf; | 75 | return buf; |
@@ -134,16 +132,55 @@ display_record (const struct GNUNET_DNSPARSER_Record *record) | |||
134 | if (record->data_len != sizeof (struct in_addr)) | 132 | if (record->data_len != sizeof (struct in_addr)) |
135 | format = "<invalid>"; | 133 | format = "<invalid>"; |
136 | else | 134 | else |
137 | format = inet_ntop (AF_INET, record->data, buf, sizeof (buf)); | 135 | format = inet_ntop (AF_INET, record->data.raw, buf, sizeof (buf)); |
138 | break; | 136 | break; |
139 | case GNUNET_DNSPARSER_TYPE_AAAA: | 137 | case GNUNET_DNSPARSER_TYPE_AAAA: |
140 | if (record->data_len != sizeof (struct in6_addr)) | 138 | if (record->data_len != sizeof (struct in6_addr)) |
141 | format = "<invalid>"; | 139 | format = "<invalid>"; |
142 | else | 140 | else |
143 | format = inet_ntop (AF_INET6, record->data, buf, sizeof (buf)); | 141 | format = inet_ntop (AF_INET6, record->data.raw, buf, sizeof (buf)); |
144 | break; | 142 | break; |
143 | case GNUNET_DNSPARSER_TYPE_NS: | ||
145 | case GNUNET_DNSPARSER_TYPE_CNAME: | 144 | case GNUNET_DNSPARSER_TYPE_CNAME: |
146 | tmp = GNUNET_strdup ("FIXME"); | 145 | case GNUNET_DNSPARSER_TYPE_PTR: |
146 | format = record->data.hostname; | ||
147 | break; | ||
148 | case GNUNET_DNSPARSER_TYPE_SOA: | ||
149 | if (record->data.soa == NULL) | ||
150 | format = "<invalid>"; | ||
151 | else | ||
152 | { | ||
153 | GNUNET_asprintf (&tmp, | ||
154 | "origin: %s, mail: %s, serial = %u, refresh = %u s, retry = %u s, expire = %u s, minimum = %u s", | ||
155 | record->data.soa->mname, | ||
156 | record->data.soa->rname, | ||
157 | (unsigned int) record->data.soa->serial, | ||
158 | (unsigned int) record->data.soa->refresh, | ||
159 | (unsigned int) record->data.soa->retry, | ||
160 | (unsigned int) record->data.soa->expire, | ||
161 | (unsigned int) record->data.soa->minimum_ttl); | ||
162 | format = tmp; | ||
163 | } | ||
164 | break; | ||
165 | case GNUNET_DNSPARSER_TYPE_MX: | ||
166 | if (record->data.mx == NULL) | ||
167 | format = "<invalid>"; | ||
168 | else | ||
169 | { | ||
170 | GNUNET_asprintf (&tmp, | ||
171 | "%u: %s", | ||
172 | record->data.mx->preference, | ||
173 | record->data.mx->mxhost); | ||
174 | format = tmp; | ||
175 | } | ||
176 | break; | ||
177 | case GNUNET_DNSPARSER_TYPE_TXT: | ||
178 | GNUNET_asprintf (&tmp, | ||
179 | "%.*s", | ||
180 | (unsigned int) record->data_len, | ||
181 | record->data.raw); | ||
182 | format = tmp; | ||
183 | break; | ||
147 | default: | 184 | default: |
148 | format = "<payload>"; | 185 | format = "<payload>"; |
149 | break; | 186 | break; |
@@ -215,7 +252,7 @@ display_request (void *cls, | |||
215 | return; | 252 | return; |
216 | } | 253 | } |
217 | fprintf (stdout, | 254 | fprintf (stdout, |
218 | "%s with ID: %5u Flags: %s%s%s%s%s%s Return Code: %s Opcode: %s\n", | 255 | "%s with ID: %5u Flags: %s%s%s%s%s%s, Return Code: %s, Opcode: %s\n", |
219 | p->flags.query_or_response ? "Response" : "Query", | 256 | p->flags.query_or_response ? "Response" : "Query", |
220 | p->id, | 257 | p->id, |
221 | p->flags.recursion_desired ? "RD " : "", | 258 | p->flags.recursion_desired ? "RD " : "", |
diff --git a/src/include/gnunet_dns_service-new.h b/src/include/gnunet_dns_service-new.h index bab8a2485..3517a4609 100644 --- a/src/include/gnunet_dns_service-new.h +++ b/src/include/gnunet_dns_service-new.h | |||
@@ -78,7 +78,16 @@ enum GNUNET_DNS_Flags | |||
78 | * be dropped). There is no guarantee that other POST-RESOLUTION | 78 | * be dropped). There is no guarantee that other POST-RESOLUTION |
79 | * client's won't modify (or drop) the answer afterwards. | 79 | * client's won't modify (or drop) the answer afterwards. |
80 | */ | 80 | */ |
81 | GNUNET_DNS_FLAG_POST_RESOLUTION = 4 | 81 | GNUNET_DNS_FLAG_POST_RESOLUTION = 4, |
82 | |||
83 | /** | ||
84 | * Set this flag to see all requests just before they are | ||
85 | * returned to the network. Clients that set this flag must then | ||
86 | * call "GNUNET_DNS_request_forward" when they process a request | ||
87 | * for the last time. Caling "GNUNET_DNS_request_answer" is | ||
88 | * not allowed for MONITOR peers. | ||
89 | */ | ||
90 | GNUNET_DNS_FLAG_RESPONSE_MONITOR = 8 | ||
82 | 91 | ||
83 | }; | 92 | }; |
84 | 93 | ||
diff --git a/src/include/gnunet_dnsparser_lib.h b/src/include/gnunet_dnsparser_lib.h index ef2ec389f..70dc63326 100644 --- a/src/include/gnunet_dnsparser_lib.h +++ b/src/include/gnunet_dnsparser_lib.h | |||
@@ -41,8 +41,6 @@ | |||
41 | #define GNUNET_DNSPARSER_TYPE_MX 15 | 41 | #define GNUNET_DNSPARSER_TYPE_MX 15 |
42 | #define GNUNET_DNSPARSER_TYPE_TXT 16 | 42 | #define GNUNET_DNSPARSER_TYPE_TXT 16 |
43 | #define GNUNET_DNSPARSER_TYPE_AAAA 28 | 43 | #define GNUNET_DNSPARSER_TYPE_AAAA 28 |
44 | #define GNUNET_DNSPARSER_TYPE_IXFR 251 | ||
45 | #define GNUNET_DNSPARSER_TYPE_AXFR 252 | ||
46 | 44 | ||
47 | /** | 45 | /** |
48 | * A few common DNS classes (ok, only one is common, but I list a | 46 | * A few common DNS classes (ok, only one is common, but I list a |
@@ -158,6 +156,74 @@ struct GNUNET_DNSPARSER_Query | |||
158 | 156 | ||
159 | 157 | ||
160 | /** | 158 | /** |
159 | * Information from MX records (RFC 1035). | ||
160 | */ | ||
161 | struct GNUNET_DNSPARSER_MxRecord | ||
162 | { | ||
163 | |||
164 | /** | ||
165 | * Preference for this entry (lower value is higher preference). | ||
166 | */ | ||
167 | uint16_t preference; | ||
168 | |||
169 | /** | ||
170 | * Name of the mail server. | ||
171 | */ | ||
172 | char *mxhost; | ||
173 | |||
174 | }; | ||
175 | |||
176 | |||
177 | /** | ||
178 | * Information from SOA records (RFC 1035). | ||
179 | */ | ||
180 | struct GNUNET_DNSPARSER_SoaRecord | ||
181 | { | ||
182 | |||
183 | /** | ||
184 | *The domainname of the name server that was the | ||
185 | * original or primary source of data for this zone. | ||
186 | */ | ||
187 | char *mname; | ||
188 | |||
189 | /** | ||
190 | * A domainname which specifies the mailbox of the | ||
191 | * person responsible for this zone. | ||
192 | */ | ||
193 | char *rname; | ||
194 | |||
195 | /** | ||
196 | * The version number of the original copy of the zone. | ||
197 | */ | ||
198 | uint32_t serial; | ||
199 | |||
200 | /** | ||
201 | * Time interval before the zone should be refreshed. | ||
202 | */ | ||
203 | uint32_t refresh; | ||
204 | |||
205 | /** | ||
206 | * Time interval that should elapse before a failed refresh should | ||
207 | * be retried. | ||
208 | */ | ||
209 | uint32_t retry; | ||
210 | |||
211 | /** | ||
212 | * Time value that specifies the upper limit on the time interval | ||
213 | * that can elapse before the zone is no longer authoritative. | ||
214 | */ | ||
215 | uint32_t expire; | ||
216 | |||
217 | /** | ||
218 | * The bit minimum TTL field that should be exported with any RR | ||
219 | * from this zone. | ||
220 | */ | ||
221 | uint32_t minimum_ttl; | ||
222 | |||
223 | }; | ||
224 | |||
225 | |||
226 | /** | ||
161 | * A DNS response record. | 227 | * A DNS response record. |
162 | */ | 228 | */ |
163 | struct GNUNET_DNSPARSER_Record | 229 | struct GNUNET_DNSPARSER_Record |
@@ -168,10 +234,30 @@ struct GNUNET_DNSPARSER_Record | |||
168 | */ | 234 | */ |
169 | char *name; | 235 | char *name; |
170 | 236 | ||
171 | /** | 237 | union |
172 | * Raw data, NOT a 0-terminated string (at least not always). | 238 | { |
173 | */ | 239 | |
174 | char *data; | 240 | /** |
241 | * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname. | ||
242 | */ | ||
243 | char *hostname; | ||
244 | |||
245 | /** | ||
246 | * SOA data for SOA records. | ||
247 | */ | ||
248 | struct GNUNET_DNSPARSER_SoaRecord *soa; | ||
249 | |||
250 | /** | ||
251 | * MX data for MX records. | ||
252 | */ | ||
253 | struct GNUNET_DNSPARSER_MxRecord *mx; | ||
254 | |||
255 | /** | ||
256 | * Raw data for all other types. | ||
257 | */ | ||
258 | char *raw; | ||
259 | |||
260 | } data; | ||
175 | 261 | ||
176 | /** | 262 | /** |
177 | * Number of bytes in data. | 263 | * Number of bytes in data. |
diff --git a/src/transport/gnunet-transport.c b/src/transport/gnunet-transport.c index d15b952d4..c78518813 100644 --- a/src/transport/gnunet-transport.c +++ b/src/transport/gnunet-transport.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009 Christian Grothoff (and other contributing authors) | 3 | (C) 2011 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |