1 wdns_res
wdns_downcase_rdata(wdns_rdata_t * rdata,uint16_t rrtype,uint16_t rrclass)2 wdns_downcase_rdata(wdns_rdata_t *rdata, uint16_t rrtype, uint16_t rrclass)
3 {
4 
5 #define advance_bytes(x) do { \
6 	if (bytes_remaining < (x)) \
7 		return (wdns_res_parse_error); \
8 	p += (x); \
9 	bytes_remaining -= (x); \
10 } while(0)
11 
12 	const record_descr *descr;
13 	const uint8_t *t;
14 	size_t bytes_remaining = rdata->len;
15 	uint8_t oclen;
16 	uint8_t *p = rdata->data;
17 
18 	if (rrtype < record_descr_len) {
19 		descr = &record_descr_array[rrtype];
20 		if (descr->types[0] == rdf_unknown)
21 			return (wdns_res_success);
22 	} else {
23 		return (wdns_res_success);
24 	}
25 
26 	/* only downcase rrtypes specified by RFC 4034 section 6.2
27 	 * and draft-ietf-dnsext-dnssec-bis-updates-11 section 5.1 */
28 	switch (rrtype) {
29 	case WDNS_TYPE_A6:
30 	case WDNS_TYPE_AFSDB:
31 	case WDNS_TYPE_CNAME:
32 	case WDNS_TYPE_DNAME:
33 	case WDNS_TYPE_KX:
34 	case WDNS_TYPE_MB:
35 	case WDNS_TYPE_MD:
36 	case WDNS_TYPE_MF:
37 	case WDNS_TYPE_MG:
38 	case WDNS_TYPE_MINFO:
39 	case WDNS_TYPE_MR:
40 	case WDNS_TYPE_MX:
41 	case WDNS_TYPE_NAPTR:
42 	case WDNS_TYPE_NS:
43 	case WDNS_TYPE_NXT:
44 	case WDNS_TYPE_PTR:
45 	case WDNS_TYPE_PX:
46 	case WDNS_TYPE_RP:
47 	case WDNS_TYPE_RT:
48 	case WDNS_TYPE_SIG:
49 	case WDNS_TYPE_SOA:
50 	case WDNS_TYPE_SRV:
51 		break;
52 	default:
53 		return (wdns_res_success);
54 	}
55 
56 	if (descr->record_class == class_un ||
57 	    descr->record_class == rrclass)
58 	{
59 		for (t = &descr->types[0]; *t != rdf_end; t++) {
60 			if (bytes_remaining == 0)
61 				break;
62 
63 			switch (*t) {
64 			case rdf_name:
65 			case rdf_uname:
66 				while (bytes_remaining-- != 0) {
67 					if (*p == 0) {
68 						p++;
69 						break;
70 					}
71 					if (*p >= 'A' && *p <= 'Z')
72 						*p |= 0x20;
73 					p++;
74 				}
75 				break;
76 
77 			case rdf_repstring:
78 			case rdf_bytes:
79 			case rdf_bytes_b64:
80 			case rdf_bytes_str:
81 			case rdf_type_bitmap:
82 				return (wdns_res_success);
83 
84 			case rdf_int8:
85 				advance_bytes(1U);
86 				break;
87 
88 			case rdf_int16:
89 			case rdf_rrtype:
90 				advance_bytes(2U);
91 				break;
92 
93 			case rdf_int32:
94 			case rdf_ipv4:
95 				advance_bytes(4U);
96 				break;
97 
98 			case rdf_ipv6:
99 				advance_bytes(16U);
100 				break;
101 
102 			case rdf_eui48:
103 				advance_bytes(6U);
104 				break;
105 
106 			case rdf_eui64:
107 				advance_bytes(8U);
108 
109 			case rdf_string:
110 			case rdf_salt:
111 			case rdf_hash:
112 				oclen = *p;
113 				advance_bytes(oclen + 1U);
114 				break;
115 
116 			case rdf_ipv6prefix:
117 				oclen = *p;
118 				if (oclen > 16U)
119 					return (wdns_res_parse_error);
120 				advance_bytes(oclen + 1U);
121 				break;
122 
123 			default:
124 				fprintf(stderr, "ERROR: unhandled rdf type %u\n", *t);
125 				abort();
126 			}
127 
128 		}
129 		if (bytes_remaining != 0) {
130 			return (wdns_res_parse_error);
131 		}
132 	}
133 
134 	return (wdns_res_success);
135 }
136