aboutsummaryrefslogtreecommitdiff
path: root/src/dns/dnsparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dns/dnsparser.c')
-rw-r--r--src/dns/dnsparser.c143
1 files changed, 127 insertions, 16 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
58struct 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
58GNUNET_NETWORK_STRUCT_END 67GNUNET_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 */
375static void
376free_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 */
391static void
392free_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
401static void
402free_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}