diff options
Diffstat (limited to 'src/dns')
-rw-r--r-- | src/dns/dnsparser.c | 111 |
1 files changed, 105 insertions, 6 deletions
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c index 2f9fba0a6..d4306c374 100644 --- a/src/dns/dnsparser.c +++ b/src/dns/dnsparser.c | |||
@@ -118,6 +118,21 @@ GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa) | |||
118 | 118 | ||
119 | 119 | ||
120 | /** | 120 | /** |
121 | * Free CERT information record. | ||
122 | * | ||
123 | * @param cert record to free | ||
124 | */ | ||
125 | void | ||
126 | GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert) | ||
127 | { | ||
128 | if (NULL == cert) | ||
129 | return; | ||
130 | GNUNET_free_non_null (cert->certificate_data); | ||
131 | GNUNET_free (cert); | ||
132 | } | ||
133 | |||
134 | |||
135 | /** | ||
121 | * Free SRV information record. | 136 | * Free SRV information record. |
122 | * | 137 | * |
123 | * @param srv record to free | 138 | * @param srv record to free |
@@ -170,6 +185,9 @@ GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r) | |||
170 | case GNUNET_DNSPARSER_TYPE_SRV: | 185 | case GNUNET_DNSPARSER_TYPE_SRV: |
171 | GNUNET_DNSPARSER_free_srv (r->data.srv); | 186 | GNUNET_DNSPARSER_free_srv (r->data.srv); |
172 | break; | 187 | break; |
188 | case GNUNET_DNSPARSER_TYPE_CERT: | ||
189 | GNUNET_DNSPARSER_free_cert (r->data.cert); | ||
190 | break; | ||
173 | case GNUNET_DNSPARSER_TYPE_NS: | 191 | case GNUNET_DNSPARSER_TYPE_NS: |
174 | case GNUNET_DNSPARSER_TYPE_CNAME: | 192 | case GNUNET_DNSPARSER_TYPE_CNAME: |
175 | case GNUNET_DNSPARSER_TYPE_PTR: | 193 | case GNUNET_DNSPARSER_TYPE_PTR: |
@@ -545,6 +563,44 @@ GNUNET_DNSPARSER_parse_srv (const char *r_name, | |||
545 | 563 | ||
546 | 564 | ||
547 | /** | 565 | /** |
566 | * Parse a DNS CERT record. | ||
567 | * | ||
568 | * @param udp_payload reference to UDP packet | ||
569 | * @param udp_payload_length length of @a udp_payload | ||
570 | * @param off pointer to the offset of the query to parse in the CERT record (to be | ||
571 | * incremented by the size of the record), unchanged on error | ||
572 | * @return the parsed CERT record, NULL on error | ||
573 | */ | ||
574 | struct GNUNET_DNSPARSER_CertRecord * | ||
575 | GNUNET_DNSPARSER_parse_cert (const char *udp_payload, | ||
576 | size_t udp_payload_length, | ||
577 | size_t *off) | ||
578 | { | ||
579 | struct GNUNET_DNSPARSER_CertRecord *cert; | ||
580 | struct GNUNET_TUN_DnsCertRecord dcert; | ||
581 | |||
582 | if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) >= udp_payload_length) | ||
583 | { | ||
584 | GNUNET_break_op (0); | ||
585 | return NULL; | ||
586 | } | ||
587 | memcpy (&dcert, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsCertRecord)); | ||
588 | (*off) += sizeof (sizeof (struct GNUNET_TUN_DnsCertRecord)); | ||
589 | cert = GNUNET_new (struct GNUNET_DNSPARSER_CertRecord); | ||
590 | cert->cert_type = ntohs (dcert.cert_type); | ||
591 | cert->cert_tag = ntohs (dcert.cert_tag); | ||
592 | cert->algorithm = dcert.algorithm; | ||
593 | cert->certificate_size = udp_payload_length - (*off); | ||
594 | cert->certificate_data = GNUNET_malloc (cert->certificate_size); | ||
595 | memcpy (cert->certificate_data, | ||
596 | &udp_payload[*off], | ||
597 | cert->certificate_size); | ||
598 | (*off) += cert->certificate_size; | ||
599 | return cert; | ||
600 | } | ||
601 | |||
602 | |||
603 | /** | ||
548 | * Parse a DNS record entry. | 604 | * Parse a DNS record entry. |
549 | * | 605 | * |
550 | * @param udp_payload entire UDP payload | 606 | * @param udp_payload entire UDP payload |
@@ -905,6 +961,46 @@ GNUNET_DNSPARSER_builder_add_mx (char *dst, | |||
905 | 961 | ||
906 | 962 | ||
907 | /** | 963 | /** |
964 | * Add a CERT record to the UDP packet at the given location. | ||
965 | * | ||
966 | * @param dst where to write the CERT record | ||
967 | * @param dst_len number of bytes in @a dst | ||
968 | * @param off pointer to offset where to write the CERT information (increment by bytes used); | ||
969 | * can also change if there was an error | ||
970 | * @param cert CERT information to write | ||
971 | * @return #GNUNET_SYSERR if @a cert is invalid | ||
972 | * #GNUNET_NO if @a cert did not fit | ||
973 | * #GNUNET_OK if @a cert was added to @a dst | ||
974 | */ | ||
975 | int | ||
976 | GNUNET_DNSPARSER_builder_add_cert (char *dst, | ||
977 | size_t dst_len, | ||
978 | size_t *off, | ||
979 | const struct GNUNET_DNSPARSER_CertRecord *cert) | ||
980 | { | ||
981 | struct GNUNET_TUN_DnsCertRecord dcert; | ||
982 | |||
983 | if ( (cert->cert_type > UINT16_MAX) || | ||
984 | (cert->cert_tag > UINT16_MAX) || | ||
985 | (cert->algorithm > UINT8_MAX) ) | ||
986 | { | ||
987 | GNUNET_break (0); | ||
988 | return GNUNET_SYSERR; | ||
989 | } | ||
990 | if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) + cert->certificate_size > dst_len) | ||
991 | return GNUNET_NO; | ||
992 | dcert.cert_type = htons ((uint16_t) cert->cert_type); | ||
993 | dcert.cert_tag = htons ((uint16_t) cert->cert_tag); | ||
994 | dcert.algorithm = (uint8_t) cert->algorithm; | ||
995 | memcpy (&dst[*off], &dcert, sizeof (dcert)); | ||
996 | (*off) += sizeof (dcert); | ||
997 | memcpy (&dst[*off], cert->certificate_data, cert->certificate_size); | ||
998 | (*off) += cert->certificate_size; | ||
999 | return GNUNET_OK; | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /** | ||
908 | * Add an SOA record to the UDP packet at the given location. | 1004 | * Add an SOA record to the UDP packet at the given location. |
909 | * | 1005 | * |
910 | * @param dst where to write the SOA record | 1006 | * @param dst where to write the SOA record |
@@ -926,13 +1022,13 @@ GNUNET_DNSPARSER_builder_add_soa (char *dst, | |||
926 | int ret; | 1022 | int ret; |
927 | 1023 | ||
928 | if ( (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst, | 1024 | if ( (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst, |
929 | dst_len, | 1025 | dst_len, |
930 | off, | 1026 | off, |
931 | soa->mname))) || | 1027 | soa->mname))) || |
932 | (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst, | 1028 | (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst, |
933 | dst_len, | 1029 | dst_len, |
934 | off, | 1030 | off, |
935 | soa->rname)) ) ) | 1031 | soa->rname)) ) ) |
936 | return ret; | 1032 | return ret; |
937 | if (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > dst_len) | 1033 | if (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > dst_len) |
938 | return GNUNET_NO; | 1034 | return GNUNET_NO; |
@@ -1032,6 +1128,9 @@ add_record (char *dst, | |||
1032 | case GNUNET_DNSPARSER_TYPE_MX: | 1128 | case GNUNET_DNSPARSER_TYPE_MX: |
1033 | ret = GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &pos, record->data.mx); | 1129 | ret = GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &pos, record->data.mx); |
1034 | break; | 1130 | break; |
1131 | case GNUNET_DNSPARSER_TYPE_CERT: | ||
1132 | ret = GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &pos, record->data.cert); | ||
1133 | break; | ||
1035 | case GNUNET_DNSPARSER_TYPE_SOA: | 1134 | case GNUNET_DNSPARSER_TYPE_SOA: |
1036 | ret = GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &pos, record->data.soa); | 1135 | ret = GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &pos, record->data.soa); |
1037 | break; | 1136 | break; |