aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-06-21 10:24:08 +0000
committerChristian Grothoff <christian@grothoff.org>2012-06-21 10:24:08 +0000
commit4720597f680ae81b1a7c5e43f6d05bc1fdbe183f (patch)
treead9b8bbcd716bd404ba733ccb941a34f96298829 /src/dns
parentab8a8a6b9177b4af9aa923315a5dbf540091d3fa (diff)
downloadgnunet-4720597f680ae81b1a7c5e43f6d05bc1fdbe183f.tar.gz
gnunet-4720597f680ae81b1a7c5e43f6d05bc1fdbe183f.zip
-towards fixing #2268: srv parsing/serialization
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/dnsparser.c128
1 files changed, 124 insertions, 4 deletions
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c
index c11ec25d6..c6a60cd44 100644
--- a/src/dns/dnsparser.c
+++ b/src/dns/dnsparser.c
@@ -325,6 +325,9 @@ parse_record (const char *udp_payload,
325 struct soa_data soa; 325 struct soa_data soa;
326 uint16_t mxpref; 326 uint16_t mxpref;
327 uint16_t data_len; 327 uint16_t data_len;
328 struct srv_data srv;
329 char *ndup;
330 char *tok;
328 331
329 name = parse_name (udp_payload, 332 name = parse_name (udp_payload,
330 udp_payload_length, 333 udp_payload_length,
@@ -393,6 +396,49 @@ parse_record (const char *udp_payload,
393 if (old_off + data_len != *off) 396 if (old_off + data_len != *off)
394 return GNUNET_SYSERR; 397 return GNUNET_SYSERR;
395 return GNUNET_OK; 398 return GNUNET_OK;
399 case GNUNET_DNSPARSER_TYPE_SRV:
400 if ('_' != *r->data.hostname)
401 return GNUNET_SYSERR; /* all valid srv names must start with "_" */
402 if (NULL == strstr (r->data.hostname, "._"))
403 return GNUNET_SYSERR; /* necessary string from "._$PROTO" not present */
404 old_off = *off;
405 if (*off + sizeof (struct srv_data) > udp_payload_length)
406 return GNUNET_SYSERR;
407 memcpy (&srv, &udp_payload[*off], sizeof (struct srv_data));
408 (*off) += sizeof (struct srv_data);
409 r->data.srv = GNUNET_malloc (sizeof (struct GNUNET_DNSPARSER_SrvRecord));
410 r->data.srv->priority = ntohs (srv.prio);
411 r->data.srv->weight = ntohs (srv.weight);
412 r->data.srv->port = ntohs (srv.port);
413 /* parse 'data.hostname' into components, which are
414 "_$SERVICE._$PROTO.$DOMAIN_NAME" */
415 ndup = GNUNET_strdup (r->data.hostname);
416 tok = strtok (ndup, ".");
417 GNUNET_assert ('_' == *tok);
418 r->data.srv->service = GNUNET_strdup (&tok[1]);
419 tok = strtok (NULL, ".");
420 if ('_' != *tok)
421 {
422 GNUNET_free (r->data.srv);
423 GNUNET_free (ndup);
424 return GNUNET_SYSERR;
425 }
426 r->data.srv->proto = GNUNET_strdup (&tok[1]);
427 tok = strtok (NULL, ".");
428 if (NULL == tok)
429 {
430 GNUNET_free (r->data.srv);
431 GNUNET_free (ndup);
432 return GNUNET_SYSERR;
433 }
434 r->data.srv->domain_name = GNUNET_strdup (tok);
435 GNUNET_free (ndup);
436 r->data.srv->target = parse_name (udp_payload,
437 udp_payload_length,
438 off, 0);
439 if (old_off + data_len != *off)
440 return GNUNET_SYSERR;
441 return GNUNET_OK;
396 default: 442 default:
397 r->data.raw.data = GNUNET_malloc (data_len); 443 r->data.raw.data = GNUNET_malloc (data_len);
398 r->data.raw.data_len = data_len; 444 r->data.raw.data_len = data_len;
@@ -505,6 +551,24 @@ free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa)
505 551
506 552
507/** 553/**
554 * Free SRV information record.
555 *
556 * @param srv record to free
557 */
558static void
559free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv)
560{
561 if (NULL == srv)
562 return;
563 GNUNET_free_non_null (srv->target);
564 GNUNET_free_non_null (srv->domain_name);
565 GNUNET_free_non_null (srv->proto);
566 GNUNET_free_non_null (srv->service);
567 GNUNET_free (srv);
568}
569
570
571/**
508 * Free MX information record. 572 * Free MX information record.
509 * 573 *
510 * @param mx record to free 574 * @param mx record to free
@@ -531,6 +595,9 @@ free_record (struct GNUNET_DNSPARSER_Record *r)
531 case GNUNET_DNSPARSER_TYPE_SOA: 595 case GNUNET_DNSPARSER_TYPE_SOA:
532 free_soa (r->data.soa); 596 free_soa (r->data.soa);
533 break; 597 break;
598 case GNUNET_DNSPARSER_TYPE_SRV:
599 free_srv (r->data.srv);
600 break;
534 case GNUNET_DNSPARSER_TYPE_NS: 601 case GNUNET_DNSPARSER_TYPE_NS:
535 case GNUNET_DNSPARSER_TYPE_CNAME: 602 case GNUNET_DNSPARSER_TYPE_CNAME:
536 case GNUNET_DNSPARSER_TYPE_PTR: 603 case GNUNET_DNSPARSER_TYPE_PTR:
@@ -727,6 +794,43 @@ add_soa (char *dst,
727 794
728 795
729/** 796/**
797 * Add an SRV record to the UDP packet at the given location.
798 *
799 * @param dst where to write the SRV record
800 * @param dst_len number of bytes in dst
801 * @param off pointer to offset where to write the SRV information (increment by bytes used)
802 * can also change if there was an error
803 * @param srv SRV information to write
804 * @return GNUNET_SYSERR if 'srv' is invalid
805 * GNUNET_NO if 'srv' did not fit
806 * GNUNET_OK if 'srv' was added to 'dst'
807 */
808static int
809add_srv (char *dst,
810 size_t dst_len,
811 size_t *off,
812 const struct GNUNET_DNSPARSER_SrvRecord *srv)
813{
814 struct srv_data sd;
815 int ret;
816
817 if (*off + sizeof (struct srv_data) > dst_len)
818 return GNUNET_NO;
819 sd.prio = htons (srv->priority);
820 sd.weight = htons (srv->weight);
821 sd.port = htons (srv->port);
822 memcpy (&dst[*off], &sd, sizeof (sd));
823 (*off) += sizeof (sd);
824 if (GNUNET_OK != (ret = add_name (dst,
825 dst_len,
826 off,
827 srv->target)))
828 return ret;
829 return GNUNET_OK;
830}
831
832
833/**
730 * Add a DNS record to the UDP packet at the given location. 834 * Add a DNS record to the UDP packet at the given location.
731 * 835 *
732 * @param dst where to write the query 836 * @param dst where to write the query
@@ -748,10 +852,23 @@ add_record (char *dst,
748 size_t start; 852 size_t start;
749 size_t pos; 853 size_t pos;
750 struct record_line rl; 854 struct record_line rl;
751 855 char *name;
856
752 start = *off; 857 start = *off;
753 ret = add_name (dst, dst_len - sizeof (struct record_line), off, record->name); 858 /* for SRV records, we can create the name from the details
754 if (ret != GNUNET_OK) 859 of the record if needed */
860 name = record->name;
861 if ( (GNUNET_DNSPARSER_TYPE_SRV == record->type) &&
862 (NULL == name) )
863 GNUNET_asprintf (&name,
864 "_%s._%s.%s",
865 record->data.srv->service,
866 record->data.srv->proto,
867 record->data.srv->domain_name);
868 ret = add_name (dst, dst_len - sizeof (struct record_line), off, name);
869 if (name != record->name)
870 GNUNET_free (name);
871 if (GNUNET_OK != ret)
755 return ret; 872 return ret;
756 /* '*off' is now the position where we will need to write the record line */ 873 /* '*off' is now the position where we will need to write the record line */
757 874
@@ -769,6 +886,9 @@ add_record (char *dst,
769 case GNUNET_DNSPARSER_TYPE_PTR: 886 case GNUNET_DNSPARSER_TYPE_PTR:
770 ret = add_name (dst, dst_len, &pos, record->data.hostname); 887 ret = add_name (dst, dst_len, &pos, record->data.hostname);
771 break; 888 break;
889 case GNUNET_DNSPARSER_TYPE_SRV:
890 ret = add_srv (dst, dst_len, &pos, record->data.srv);
891 break;
772 default: 892 default:
773 if (pos + record->data.raw.data_len > dst_len) 893 if (pos + record->data.raw.data_len > dst_len)
774 { 894 {
@@ -780,7 +900,7 @@ add_record (char *dst,
780 ret = GNUNET_OK; 900 ret = GNUNET_OK;
781 break; 901 break;
782 } 902 }
783 if (ret != GNUNET_OK) 903 if (GNUNET_OK != ret)
784 { 904 {
785 *off = start; 905 *off = start;
786 return GNUNET_NO; 906 return GNUNET_NO;