File: | src/usr.sbin/nsd/zonec.c |
Warning: | line 1267, column 20 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * zonec.c -- zone compiler. | |||
3 | * | |||
4 | * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. | |||
5 | * | |||
6 | * See LICENSE for the license. | |||
7 | * | |||
8 | */ | |||
9 | ||||
10 | #include "config.h" | |||
11 | ||||
12 | #include <assert.h> | |||
13 | #include <fcntl.h> | |||
14 | #include <ctype.h> | |||
15 | #include <errno(*__errno()).h> | |||
16 | #include <limits.h> | |||
17 | #include <stdio.h> | |||
18 | #include <string.h> | |||
19 | #ifdef HAVE_STRINGS_H1 | |||
20 | #include <strings.h> | |||
21 | #endif | |||
22 | #include <unistd.h> | |||
23 | #include <stdlib.h> | |||
24 | #include <time.h> | |||
25 | #ifdef HAVE_SYS_STAT_H1 | |||
26 | #include <sys/stat.h> | |||
27 | #endif | |||
28 | ||||
29 | #include <netinet/in.h> | |||
30 | ||||
31 | #ifdef HAVE_NETDB_H1 | |||
32 | #include <netdb.h> | |||
33 | #endif | |||
34 | ||||
35 | #include "zonec.h" | |||
36 | ||||
37 | #include "dname.h" | |||
38 | #include "dns.h" | |||
39 | #include "namedb.h" | |||
40 | #include "rdata.h" | |||
41 | #include "region-allocator.h" | |||
42 | #include "util.h" | |||
43 | #include "zparser.h" | |||
44 | #include "options.h" | |||
45 | #include "nsec3.h" | |||
46 | ||||
47 | #define ILNP_MAXDIGITS4 4 | |||
48 | #define ILNP_NUMGROUPS4 4 | |||
49 | #define SVCB_MAX_COMMA_SEPARATED_VALUES1000 1000 | |||
50 | ||||
51 | ||||
52 | const dname_type *error_dname; | |||
53 | domain_type *error_domain; | |||
54 | ||||
55 | static time_t startzonec = 0; | |||
56 | static long int totalrrs = 0; | |||
57 | ||||
58 | extern uint8_t nsecbits[NSEC_WINDOW_COUNT256][NSEC_WINDOW_BITS_SIZE(256 / 8)]; | |||
59 | extern uint16_t nsec_highest_rcode; | |||
60 | ||||
61 | ||||
62 | /* | |||
63 | * Allocate SIZE+sizeof(uint16_t) bytes and store SIZE in the first | |||
64 | * element. Return a pointer to the allocation. | |||
65 | */ | |||
66 | static uint16_t * | |||
67 | alloc_rdata(region_type *region, size_t size) | |||
68 | { | |||
69 | uint16_t *result = region_alloc(region, sizeof(uint16_t) + size); | |||
70 | *result = size; | |||
71 | return result; | |||
72 | } | |||
73 | ||||
74 | uint16_t * | |||
75 | alloc_rdata_init(region_type *region, const void *data, size_t size) | |||
76 | { | |||
77 | uint16_t *result = region_alloc(region, sizeof(uint16_t) + size); | |||
78 | *result = size; | |||
79 | memcpy(result + 1, data, size); | |||
80 | return result; | |||
81 | } | |||
82 | ||||
83 | /* | |||
84 | * These are parser function for generic zone file stuff. | |||
85 | */ | |||
86 | uint16_t * | |||
87 | zparser_conv_hex(region_type *region, const char *hex, size_t len) | |||
88 | { | |||
89 | /* convert a hex value to wireformat */ | |||
90 | uint16_t *r = NULL((void *)0); | |||
91 | uint8_t *t; | |||
92 | int i; | |||
93 | ||||
94 | if(len == 1 && hex[0] == '0') { | |||
95 | /* single 0 represents empty buffer */ | |||
96 | return alloc_rdata(region, 0); | |||
97 | } | |||
98 | if (len % 2 != 0) { | |||
99 | zc_error_prev_line("number of hex digits must be a multiple of 2"); | |||
100 | } else if (len > MAX_RDLENGTH65535 * 2) { | |||
101 | zc_error_prev_line("hex data exceeds maximum rdata length (%d)", | |||
102 | MAX_RDLENGTH65535); | |||
103 | } else { | |||
104 | /* the length part */ | |||
105 | r = alloc_rdata(region, len/2); | |||
106 | t = (uint8_t *)(r + 1); | |||
107 | ||||
108 | /* Now process octet by octet... */ | |||
109 | while (*hex) { | |||
110 | *t = 0; | |||
111 | for (i = 16; i >= 1; i -= 15) { | |||
112 | if (isxdigit((unsigned char)*hex)) { | |||
113 | *t += hexdigit_to_int(*hex) * i; | |||
114 | } else { | |||
115 | zc_error_prev_line( | |||
116 | "illegal hex character '%c'", | |||
117 | (int) *hex); | |||
118 | return NULL((void *)0); | |||
119 | } | |||
120 | ++hex; | |||
121 | } | |||
122 | ++t; | |||
123 | } | |||
124 | } | |||
125 | return r; | |||
126 | } | |||
127 | ||||
128 | /* convert hex, precede by a 1-byte length */ | |||
129 | uint16_t * | |||
130 | zparser_conv_hex_length(region_type *region, const char *hex, size_t len) | |||
131 | { | |||
132 | uint16_t *r = NULL((void *)0); | |||
133 | uint8_t *t; | |||
134 | int i; | |||
135 | if (len % 2 != 0) { | |||
136 | zc_error_prev_line("number of hex digits must be a multiple of 2"); | |||
137 | } else if (len > 255 * 2) { | |||
138 | zc_error_prev_line("hex data exceeds 255 bytes"); | |||
139 | } else { | |||
140 | uint8_t *l; | |||
141 | ||||
142 | /* the length part */ | |||
143 | r = alloc_rdata(region, len/2+1); | |||
144 | t = (uint8_t *)(r + 1); | |||
145 | ||||
146 | l = t++; | |||
147 | *l = '\0'; | |||
148 | ||||
149 | /* Now process octet by octet... */ | |||
150 | while (*hex) { | |||
151 | *t = 0; | |||
152 | for (i = 16; i >= 1; i -= 15) { | |||
153 | if (isxdigit((unsigned char)*hex)) { | |||
154 | *t += hexdigit_to_int(*hex) * i; | |||
155 | } else { | |||
156 | zc_error_prev_line( | |||
157 | "illegal hex character '%c'", | |||
158 | (int) *hex); | |||
159 | return NULL((void *)0); | |||
160 | } | |||
161 | ++hex; | |||
162 | } | |||
163 | ++t; | |||
164 | ++*l; | |||
165 | } | |||
166 | } | |||
167 | return r; | |||
168 | } | |||
169 | ||||
170 | uint16_t * | |||
171 | zparser_conv_time(region_type *region, const char *time) | |||
172 | { | |||
173 | /* convert a time YYHM to wireformat */ | |||
174 | uint16_t *r = NULL((void *)0); | |||
175 | struct tm tm; | |||
176 | ||||
177 | /* Try to scan the time... */ | |||
178 | if (!strptime(time, "%Y%m%d%H%M%S", &tm)) { | |||
179 | zc_error_prev_line("date and time is expected"); | |||
180 | } else { | |||
181 | uint32_t l = htonl(mktime_from_utc(&tm))(__uint32_t)(__builtin_constant_p(mktime_from_utc(&tm)) ? (__uint32_t)(((__uint32_t)(mktime_from_utc(&tm)) & 0xff ) << 24 | ((__uint32_t)(mktime_from_utc(&tm)) & 0xff00) << 8 | ((__uint32_t)(mktime_from_utc(&tm)) & 0xff0000) >> 8 | ((__uint32_t)(mktime_from_utc(& tm)) & 0xff000000) >> 24) : __swap32md(mktime_from_utc (&tm))); | |||
182 | r = alloc_rdata_init(region, &l, sizeof(l)); | |||
183 | } | |||
184 | return r; | |||
185 | } | |||
186 | ||||
187 | uint16_t * | |||
188 | zparser_conv_services(region_type *region, const char *protostr, | |||
189 | char *servicestr) | |||
190 | { | |||
191 | /* | |||
192 | * Convert a protocol and a list of service port numbers | |||
193 | * (separated by spaces) in the rdata to wireformat | |||
194 | */ | |||
195 | uint16_t *r = NULL((void *)0); | |||
196 | uint8_t *p; | |||
197 | uint8_t bitmap[65536/8]; | |||
198 | char sep[] = " "; | |||
199 | char *word; | |||
200 | int max_port = -8; | |||
201 | /* convert a protocol in the rdata to wireformat */ | |||
202 | struct protoent *proto; | |||
203 | ||||
204 | memset(bitmap, 0, sizeof(bitmap)); | |||
205 | ||||
206 | proto = getprotobyname(protostr); | |||
207 | if (!proto) { | |||
208 | proto = getprotobynumber(atoi(protostr)); | |||
209 | } | |||
210 | if (!proto) { | |||
211 | zc_error_prev_line("unknown protocol '%s'", protostr); | |||
212 | return NULL((void *)0); | |||
213 | } | |||
214 | ||||
215 | for (word = strtok(servicestr, sep); word; word = strtok(NULL((void *)0), sep)) { | |||
216 | struct servent *service; | |||
217 | int port; | |||
218 | ||||
219 | service = getservbyname(word, proto->p_name); | |||
220 | if (service) { | |||
221 | /* Note: ntohs not ntohl! Strange but true. */ | |||
222 | port = ntohs((uint16_t) service->s_port)(__uint16_t)(__builtin_constant_p((uint16_t) service->s_port ) ? (__uint16_t)(((__uint16_t)((uint16_t) service->s_port) & 0xffU) << 8 | ((__uint16_t)((uint16_t) service-> s_port) & 0xff00U) >> 8) : __swap16md((uint16_t) service ->s_port)); | |||
223 | } else { | |||
224 | char *end; | |||
225 | port = strtol(word, &end, 10); | |||
226 | if (*end != '\0') { | |||
227 | zc_error_prev_line("unknown service '%s' for protocol '%s'", | |||
228 | word, protostr); | |||
229 | continue; | |||
230 | } | |||
231 | } | |||
232 | ||||
233 | if (port < 0 || port > 65535) { | |||
234 | zc_error_prev_line("bad port number %d", port); | |||
235 | } else { | |||
236 | set_bit(bitmap, port); | |||
237 | if (port > max_port) | |||
238 | max_port = port; | |||
239 | } | |||
240 | } | |||
241 | ||||
242 | r = alloc_rdata(region, sizeof(uint8_t) + max_port / 8 + 1); | |||
243 | p = (uint8_t *) (r + 1); | |||
244 | *p = proto->p_proto; | |||
245 | memcpy(p + 1, bitmap, *r-1); | |||
246 | ||||
247 | return r; | |||
248 | } | |||
249 | ||||
250 | uint16_t * | |||
251 | zparser_conv_serial(region_type *region, const char *serialstr) | |||
252 | { | |||
253 | uint16_t *r = NULL((void *)0); | |||
254 | uint32_t serial; | |||
255 | const char *t; | |||
256 | ||||
257 | serial = strtoserial(serialstr, &t); | |||
258 | if (*t != '\0') { | |||
259 | zc_error_prev_line("serial is expected or serial too big"); | |||
260 | } else { | |||
261 | serial = htonl(serial)(__uint32_t)(__builtin_constant_p(serial) ? (__uint32_t)(((__uint32_t )(serial) & 0xff) << 24 | ((__uint32_t)(serial) & 0xff00) << 8 | ((__uint32_t)(serial) & 0xff0000) >> 8 | ((__uint32_t)(serial) & 0xff000000) >> 24) : __swap32md (serial)); | |||
262 | r = alloc_rdata_init(region, &serial, sizeof(serial)); | |||
263 | } | |||
264 | return r; | |||
265 | } | |||
266 | ||||
267 | uint16_t * | |||
268 | zparser_conv_period(region_type *region, const char *periodstr) | |||
269 | { | |||
270 | /* convert a time period (think TTL's) to wireformat) */ | |||
271 | uint16_t *r = NULL((void *)0); | |||
272 | uint32_t period; | |||
273 | const char *end; | |||
274 | ||||
275 | /* Allocate required space... */ | |||
276 | period = strtottl(periodstr, &end); | |||
277 | if (*end != '\0') { | |||
278 | zc_error_prev_line("time period is expected"); | |||
279 | } else { | |||
280 | period = htonl(period)(__uint32_t)(__builtin_constant_p(period) ? (__uint32_t)(((__uint32_t )(period) & 0xff) << 24 | ((__uint32_t)(period) & 0xff00) << 8 | ((__uint32_t)(period) & 0xff0000) >> 8 | ((__uint32_t)(period) & 0xff000000) >> 24) : __swap32md (period)); | |||
281 | r = alloc_rdata_init(region, &period, sizeof(period)); | |||
282 | } | |||
283 | return r; | |||
284 | } | |||
285 | ||||
286 | uint16_t * | |||
287 | zparser_conv_short(region_type *region, const char *text) | |||
288 | { | |||
289 | uint16_t *r = NULL((void *)0); | |||
290 | uint16_t value; | |||
291 | char *end; | |||
292 | ||||
293 | value = htons((uint16_t) strtol(text, &end, 10))(__uint16_t)(__builtin_constant_p((uint16_t) strtol(text, & end, 10)) ? (__uint16_t)(((__uint16_t)((uint16_t) strtol(text , &end, 10)) & 0xffU) << 8 | ((__uint16_t)((uint16_t ) strtol(text, &end, 10)) & 0xff00U) >> 8) : __swap16md ((uint16_t) strtol(text, &end, 10))); | |||
294 | if (*end != '\0') { | |||
295 | zc_error_prev_line("integer value is expected"); | |||
296 | } else { | |||
297 | r = alloc_rdata_init(region, &value, sizeof(value)); | |||
298 | } | |||
299 | return r; | |||
300 | } | |||
301 | ||||
302 | uint16_t * | |||
303 | zparser_conv_byte(region_type *region, const char *text) | |||
304 | { | |||
305 | uint16_t *r = NULL((void *)0); | |||
306 | uint8_t value; | |||
307 | char *end; | |||
308 | ||||
309 | value = (uint8_t) strtol(text, &end, 10); | |||
310 | if (*end != '\0') { | |||
311 | zc_error_prev_line("integer value is expected"); | |||
312 | } else { | |||
313 | r = alloc_rdata_init(region, &value, sizeof(value)); | |||
314 | } | |||
315 | return r; | |||
316 | } | |||
317 | ||||
318 | uint16_t * | |||
319 | zparser_conv_algorithm(region_type *region, const char *text) | |||
320 | { | |||
321 | const lookup_table_type *alg; | |||
322 | uint8_t id; | |||
323 | ||||
324 | alg = lookup_by_name(dns_algorithms, text); | |||
325 | if (alg) { | |||
326 | id = (uint8_t) alg->id; | |||
327 | } else { | |||
328 | char *end; | |||
329 | id = (uint8_t) strtol(text, &end, 10); | |||
330 | if (*end != '\0') { | |||
331 | zc_error_prev_line("algorithm is expected"); | |||
332 | return NULL((void *)0); | |||
333 | } | |||
334 | } | |||
335 | ||||
336 | return alloc_rdata_init(region, &id, sizeof(id)); | |||
337 | } | |||
338 | ||||
339 | uint16_t * | |||
340 | zparser_conv_certificate_type(region_type *region, const char *text) | |||
341 | { | |||
342 | /* convert an algorithm string to integer */ | |||
343 | const lookup_table_type *type; | |||
344 | uint16_t id; | |||
345 | ||||
346 | type = lookup_by_name(dns_certificate_types, text); | |||
347 | if (type) { | |||
348 | id = htons((uint16_t) type->id)(__uint16_t)(__builtin_constant_p((uint16_t) type->id) ? ( __uint16_t)(((__uint16_t)((uint16_t) type->id) & 0xffU ) << 8 | ((__uint16_t)((uint16_t) type->id) & 0xff00U ) >> 8) : __swap16md((uint16_t) type->id)); | |||
349 | } else { | |||
350 | char *end; | |||
351 | id = htons((uint16_t) strtol(text, &end, 10))(__uint16_t)(__builtin_constant_p((uint16_t) strtol(text, & end, 10)) ? (__uint16_t)(((__uint16_t)((uint16_t) strtol(text , &end, 10)) & 0xffU) << 8 | ((__uint16_t)((uint16_t ) strtol(text, &end, 10)) & 0xff00U) >> 8) : __swap16md ((uint16_t) strtol(text, &end, 10))); | |||
352 | if (*end != '\0') { | |||
353 | zc_error_prev_line("certificate type is expected"); | |||
354 | return NULL((void *)0); | |||
355 | } | |||
356 | } | |||
357 | ||||
358 | return alloc_rdata_init(region, &id, sizeof(id)); | |||
359 | } | |||
360 | ||||
361 | uint16_t * | |||
362 | zparser_conv_a(region_type *region, const char *text) | |||
363 | { | |||
364 | in_addr_t address; | |||
365 | uint16_t *r = NULL((void *)0); | |||
366 | ||||
367 | if (inet_pton(AF_INET2, text, &address) != 1) { | |||
368 | zc_error_prev_line("invalid IPv4 address '%s'", text); | |||
369 | } else { | |||
370 | r = alloc_rdata_init(region, &address, sizeof(address)); | |||
371 | } | |||
372 | return r; | |||
373 | } | |||
374 | ||||
375 | uint16_t * | |||
376 | zparser_conv_aaaa(region_type *region, const char *text) | |||
377 | { | |||
378 | uint8_t address[IP6ADDRLEN(128/8)]; | |||
379 | uint16_t *r = NULL((void *)0); | |||
380 | ||||
381 | if (inet_pton(AF_INET624, text, address) != 1) { | |||
382 | zc_error_prev_line("invalid IPv6 address '%s'", text); | |||
383 | } else { | |||
384 | r = alloc_rdata_init(region, address, sizeof(address)); | |||
385 | } | |||
386 | return r; | |||
387 | } | |||
388 | ||||
389 | ||||
390 | uint16_t * | |||
391 | zparser_conv_ilnp64(region_type *region, const char *text) | |||
392 | { | |||
393 | uint16_t *r = NULL((void *)0); | |||
394 | int ngroups, num; | |||
395 | unsigned long hex; | |||
396 | const char *ch; | |||
397 | char digits[ILNP_MAXDIGITS4+1]; | |||
398 | unsigned int ui[ILNP_NUMGROUPS4]; | |||
399 | uint16_t a[ILNP_NUMGROUPS4]; | |||
400 | ||||
401 | ngroups = 1; /* Always at least one group */ | |||
402 | num = 0; | |||
403 | for (ch = text; *ch != '\0'; ch++) { | |||
404 | if (*ch == ':') { | |||
405 | if (num <= 0) { | |||
406 | zc_error_prev_line("ilnp64: empty group of " | |||
407 | "digits is not allowed"); | |||
408 | return NULL((void *)0); | |||
409 | } | |||
410 | digits[num] = '\0'; | |||
411 | hex = (unsigned long) strtol(digits, NULL((void *)0), 16); | |||
412 | num = 0; | |||
413 | ui[ngroups - 1] = hex; | |||
414 | if (ngroups >= ILNP_NUMGROUPS4) { | |||
415 | zc_error_prev_line("ilnp64: more than %d groups " | |||
416 | "of digits", ILNP_NUMGROUPS4); | |||
417 | return NULL((void *)0); | |||
418 | } | |||
419 | ngroups++; | |||
420 | } else { | |||
421 | /* Our grammar is stricter than the one accepted by | |||
422 | * strtol. */ | |||
423 | if (!isxdigit((unsigned char)*ch)) { | |||
424 | zc_error_prev_line("ilnp64: invalid " | |||
425 | "(non-hexadecimal) character %c", *ch); | |||
426 | return NULL((void *)0); | |||
427 | } | |||
428 | if (num >= ILNP_MAXDIGITS4) { | |||
429 | zc_error_prev_line("ilnp64: more than %d digits " | |||
430 | "in a group", ILNP_MAXDIGITS4); | |||
431 | return NULL((void *)0); | |||
432 | } | |||
433 | digits[num++] = *ch; | |||
434 | } | |||
435 | } | |||
436 | if (num <= 0) { | |||
437 | zc_error_prev_line("ilnp64: empty group of digits is not " | |||
438 | "allowed"); | |||
439 | return NULL((void *)0); | |||
440 | } | |||
441 | digits[num] = '\0'; | |||
442 | hex = (unsigned long) strtol(digits, NULL((void *)0), 16); | |||
443 | ui[ngroups - 1] = hex; | |||
444 | if (ngroups < 4) { | |||
445 | zc_error_prev_line("ilnp64: less than %d groups of digits", | |||
446 | ILNP_NUMGROUPS4); | |||
447 | return NULL((void *)0); | |||
448 | } | |||
449 | ||||
450 | a[0] = htons(ui[0])(__uint16_t)(__builtin_constant_p(ui[0]) ? (__uint16_t)(((__uint16_t )(ui[0]) & 0xffU) << 8 | ((__uint16_t)(ui[0]) & 0xff00U) >> 8) : __swap16md(ui[0])); | |||
451 | a[1] = htons(ui[1])(__uint16_t)(__builtin_constant_p(ui[1]) ? (__uint16_t)(((__uint16_t )(ui[1]) & 0xffU) << 8 | ((__uint16_t)(ui[1]) & 0xff00U) >> 8) : __swap16md(ui[1])); | |||
452 | a[2] = htons(ui[2])(__uint16_t)(__builtin_constant_p(ui[2]) ? (__uint16_t)(((__uint16_t )(ui[2]) & 0xffU) << 8 | ((__uint16_t)(ui[2]) & 0xff00U) >> 8) : __swap16md(ui[2])); | |||
453 | a[3] = htons(ui[3])(__uint16_t)(__builtin_constant_p(ui[3]) ? (__uint16_t)(((__uint16_t )(ui[3]) & 0xffU) << 8 | ((__uint16_t)(ui[3]) & 0xff00U) >> 8) : __swap16md(ui[3])); | |||
454 | r = alloc_rdata_init(region, a, sizeof(a)); | |||
455 | return r; | |||
456 | } | |||
457 | ||||
458 | static uint16_t * | |||
459 | zparser_conv_eui48(region_type *region, const char *text) | |||
460 | { | |||
461 | uint8_t nums[6]; | |||
462 | uint16_t *r = NULL((void *)0); | |||
463 | unsigned int a, b, c, d, e, f; | |||
464 | int l; | |||
465 | ||||
466 | if (sscanf(text, "%2x-%2x-%2x-%2x-%2x-%2x%n", | |||
467 | &a, &b, &c, &d, &e, &f, &l) != 6 || | |||
468 | l != (int)strlen(text)){ | |||
469 | zc_error_prev_line("eui48: invalid rr"); | |||
470 | return NULL((void *)0); | |||
471 | } | |||
472 | nums[0] = (uint8_t)a; | |||
473 | nums[1] = (uint8_t)b; | |||
474 | nums[2] = (uint8_t)c; | |||
475 | nums[3] = (uint8_t)d; | |||
476 | nums[4] = (uint8_t)e; | |||
477 | nums[5] = (uint8_t)f; | |||
478 | r = alloc_rdata_init(region, nums, sizeof(nums)); | |||
479 | return r; | |||
480 | } | |||
481 | ||||
482 | static uint16_t * | |||
483 | zparser_conv_eui64(region_type *region, const char *text) | |||
484 | { | |||
485 | uint8_t nums[8]; | |||
486 | uint16_t *r = NULL((void *)0); | |||
487 | unsigned int a, b, c, d, e, f, g, h; | |||
488 | int l; | |||
489 | if (sscanf(text, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", | |||
490 | &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || | |||
491 | l != (int)strlen(text)) { | |||
492 | zc_error_prev_line("eui64: invalid rr"); | |||
493 | return NULL((void *)0); | |||
494 | } | |||
495 | nums[0] = (uint8_t)a; | |||
496 | nums[1] = (uint8_t)b; | |||
497 | nums[2] = (uint8_t)c; | |||
498 | nums[3] = (uint8_t)d; | |||
499 | nums[4] = (uint8_t)e; | |||
500 | nums[5] = (uint8_t)f; | |||
501 | nums[6] = (uint8_t)g; | |||
502 | nums[7] = (uint8_t)h; | |||
503 | r = alloc_rdata_init(region, nums, sizeof(nums)); | |||
504 | return r; | |||
505 | } | |||
506 | ||||
507 | uint16_t * | |||
508 | zparser_conv_eui(region_type *region, const char *text, size_t len) | |||
509 | { | |||
510 | uint16_t *r = NULL((void *)0); | |||
511 | int nnum, num; | |||
512 | const char* ch; | |||
513 | ||||
514 | nnum = len/8; | |||
515 | num = 1; | |||
516 | for (ch = text; *ch != '\0'; ch++) { | |||
517 | if (*ch == '-') { | |||
518 | num++; | |||
519 | } else if (!isxdigit((unsigned char)*ch)) { | |||
520 | zc_error_prev_line("eui%u: invalid (non-hexadecimal) " | |||
521 | "character %c", (unsigned) len, *ch); | |||
522 | return NULL((void *)0); | |||
523 | } | |||
524 | } | |||
525 | if (num != nnum) { | |||
526 | zc_error_prev_line("eui%u: wrong number of hex numbers", | |||
527 | (unsigned) len); | |||
528 | return NULL((void *)0); | |||
529 | } | |||
530 | ||||
531 | switch (len) { | |||
532 | case 48: | |||
533 | r = zparser_conv_eui48(region, text); | |||
534 | break; | |||
535 | case 64: | |||
536 | r = zparser_conv_eui64(region, text); | |||
537 | break; | |||
538 | default: | |||
539 | zc_error_prev_line("eui%u: invalid length", | |||
540 | (unsigned) len); | |||
541 | return NULL((void *)0); | |||
542 | break; | |||
543 | } | |||
544 | return r; | |||
545 | } | |||
546 | ||||
547 | uint16_t * | |||
548 | zparser_conv_text(region_type *region, const char *text, size_t len) | |||
549 | { | |||
550 | uint16_t *r = NULL((void *)0); | |||
551 | uint8_t *p; | |||
552 | ||||
553 | if (len > 255) { | |||
554 | zc_error_prev_line("text string is longer than 255 characters," | |||
555 | " try splitting it into multiple parts"); | |||
556 | len = 255; | |||
557 | } | |||
558 | r = alloc_rdata(region, len + 1); | |||
559 | p = (uint8_t *) (r + 1); | |||
560 | *p = len; | |||
561 | memcpy(p + 1, text, len); | |||
562 | return r; | |||
563 | } | |||
564 | ||||
565 | /* for CAA Value [RFC 6844] */ | |||
566 | uint16_t * | |||
567 | zparser_conv_long_text(region_type *region, const char *text, size_t len) | |||
568 | { | |||
569 | uint16_t *r = NULL((void *)0); | |||
570 | if (len > MAX_RDLENGTH65535) { | |||
571 | zc_error_prev_line("text string is longer than max rdlen"); | |||
572 | return NULL((void *)0); | |||
573 | } | |||
574 | r = alloc_rdata_init(region, text, len); | |||
575 | return r; | |||
576 | } | |||
577 | ||||
578 | /* for CAA Tag [RFC 6844] */ | |||
579 | uint16_t * | |||
580 | zparser_conv_tag(region_type *region, const char *text, size_t len) | |||
581 | { | |||
582 | uint16_t *r = NULL((void *)0); | |||
583 | uint8_t *p; | |||
584 | const char* ptr; | |||
585 | ||||
586 | if (len < 1) { | |||
587 | zc_error_prev_line("invalid tag: zero length"); | |||
588 | return NULL((void *)0); | |||
589 | } | |||
590 | if (len > 15) { | |||
591 | zc_error_prev_line("invalid tag %s: longer than 15 characters (%u)", | |||
592 | text, (unsigned) len); | |||
593 | return NULL((void *)0); | |||
594 | } | |||
595 | for (ptr = text; *ptr; ptr++) { | |||
596 | if (!isdigit((unsigned char)*ptr) && !islower((unsigned char)*ptr)) { | |||
597 | zc_error_prev_line("invalid tag %s: contains invalid char %c", | |||
598 | text, *ptr); | |||
599 | return NULL((void *)0); | |||
600 | } | |||
601 | } | |||
602 | r = alloc_rdata(region, len + 1); | |||
603 | p = (uint8_t *) (r + 1); | |||
604 | *p = len; | |||
605 | memmove(p + 1, text, len); | |||
606 | return r; | |||
607 | } | |||
608 | ||||
609 | uint16_t * | |||
610 | zparser_conv_dns_name(region_type *region, const uint8_t* name, size_t len) | |||
611 | { | |||
612 | uint16_t* r = NULL((void *)0); | |||
613 | uint8_t* p = NULL((void *)0); | |||
614 | r = alloc_rdata(region, len); | |||
615 | p = (uint8_t *) (r + 1); | |||
616 | memcpy(p, name, len); | |||
617 | ||||
618 | return r; | |||
619 | } | |||
620 | ||||
621 | uint16_t * | |||
622 | zparser_conv_b32(region_type *region, const char *b32) | |||
623 | { | |||
624 | uint8_t buffer[B64BUFSIZE65535]; | |||
625 | uint16_t *r = NULL((void *)0); | |||
626 | int i; | |||
627 | ||||
628 | if(strcmp(b32, "-") == 0) { | |||
629 | return alloc_rdata_init(region, "", 1); | |||
630 | } | |||
631 | i = b32_pton(b32, buffer+1, B64BUFSIZE65535-1); | |||
632 | if (i == -1 || i > 255) { | |||
633 | zc_error_prev_line("invalid base32 data"); | |||
634 | } else { | |||
635 | buffer[0] = i; /* store length byte */ | |||
636 | r = alloc_rdata_init(region, buffer, i+1); | |||
637 | } | |||
638 | return r; | |||
639 | } | |||
640 | ||||
641 | uint16_t * | |||
642 | zparser_conv_b64(region_type *region, const char *b64) | |||
643 | { | |||
644 | uint8_t buffer[B64BUFSIZE65535]; | |||
645 | uint16_t *r = NULL((void *)0); | |||
646 | int i; | |||
647 | ||||
648 | if(strcmp(b64, "0") == 0) { | |||
649 | /* single 0 represents empty buffer */ | |||
650 | return alloc_rdata(region, 0); | |||
651 | } | |||
652 | i = __b64_pton(b64, buffer, B64BUFSIZE65535); | |||
653 | if (i == -1) { | |||
654 | zc_error_prev_line("invalid base64 data"); | |||
655 | } else { | |||
656 | r = alloc_rdata_init(region, buffer, i); | |||
657 | } | |||
658 | return r; | |||
659 | } | |||
660 | ||||
661 | uint16_t * | |||
662 | zparser_conv_rrtype(region_type *region, const char *text) | |||
663 | { | |||
664 | uint16_t *r = NULL((void *)0); | |||
665 | uint16_t type = rrtype_from_string(text); | |||
666 | ||||
667 | if (type == 0) { | |||
668 | zc_error_prev_line("unrecognized RR type '%s'", text); | |||
669 | } else { | |||
670 | type = htons(type)(__uint16_t)(__builtin_constant_p(type) ? (__uint16_t)(((__uint16_t )(type) & 0xffU) << 8 | ((__uint16_t)(type) & 0xff00U ) >> 8) : __swap16md(type)); | |||
671 | r = alloc_rdata_init(region, &type, sizeof(type)); | |||
672 | } | |||
673 | return r; | |||
674 | } | |||
675 | ||||
676 | uint16_t * | |||
677 | zparser_conv_nxt(region_type *region, uint8_t nxtbits[]) | |||
678 | { | |||
679 | /* nxtbits[] consists of 16 bytes with some zero's in it | |||
680 | * copy every byte with zero to r and write the length in | |||
681 | * the first byte | |||
682 | */ | |||
683 | uint16_t i; | |||
684 | uint16_t last = 0; | |||
685 | ||||
686 | for (i = 0; i < 16; i++) { | |||
687 | if (nxtbits[i] != 0) | |||
688 | last = i + 1; | |||
689 | } | |||
690 | ||||
691 | return alloc_rdata_init(region, nxtbits, last); | |||
692 | } | |||
693 | ||||
694 | ||||
695 | /* we potentially have 256 windows, each one is numbered. empty ones | |||
696 | * should be discarded | |||
697 | */ | |||
698 | uint16_t * | |||
699 | zparser_conv_nsec(region_type *region, | |||
700 | uint8_t nsecbits[NSEC_WINDOW_COUNT256][NSEC_WINDOW_BITS_SIZE(256 / 8)]) | |||
701 | { | |||
702 | /* nsecbits contains up to 64K of bits which represent the | |||
703 | * types available for a name. Walk the bits according to | |||
704 | * nsec++ draft from jakob | |||
705 | */ | |||
706 | uint16_t *r; | |||
707 | uint8_t *ptr; | |||
708 | size_t i,j; | |||
709 | uint16_t window_count = 0; | |||
710 | uint16_t total_size = 0; | |||
711 | uint16_t window_max = 0; | |||
712 | ||||
713 | /* The used windows. */ | |||
714 | int used[NSEC_WINDOW_COUNT256]; | |||
715 | /* The last byte used in each the window. */ | |||
716 | int size[NSEC_WINDOW_COUNT256]; | |||
717 | ||||
718 | window_max = 1 + (nsec_highest_rcode / 256); | |||
719 | ||||
720 | /* used[i] is the i-th window included in the nsec | |||
721 | * size[used[0]] is the size of window 0 | |||
722 | */ | |||
723 | ||||
724 | /* walk through the 256 windows */ | |||
725 | for (i = 0; i < window_max; ++i) { | |||
726 | int empty_window = 1; | |||
727 | /* check each of the 32 bytes */ | |||
728 | for (j = 0; j < NSEC_WINDOW_BITS_SIZE(256 / 8); ++j) { | |||
729 | if (nsecbits[i][j] != 0) { | |||
730 | size[i] = j + 1; | |||
731 | empty_window = 0; | |||
732 | } | |||
733 | } | |||
734 | if (!empty_window) { | |||
735 | used[window_count] = i; | |||
736 | window_count++; | |||
737 | } | |||
738 | } | |||
739 | ||||
740 | for (i = 0; i < window_count; ++i) { | |||
741 | total_size += sizeof(uint16_t) + size[used[i]]; | |||
742 | } | |||
743 | ||||
744 | r = alloc_rdata(region, total_size); | |||
745 | ptr = (uint8_t *) (r + 1); | |||
746 | ||||
747 | /* now walk used and copy it */ | |||
748 | for (i = 0; i < window_count; ++i) { | |||
749 | ptr[0] = used[i]; | |||
750 | ptr[1] = size[used[i]]; | |||
751 | memcpy(ptr + 2, &nsecbits[used[i]], size[used[i]]); | |||
752 | ptr += size[used[i]] + 2; | |||
753 | } | |||
754 | ||||
755 | return r; | |||
756 | } | |||
757 | ||||
758 | static uint16_t | |||
759 | svcbparam_lookup_key(const char *key, size_t key_len) | |||
760 | { | |||
761 | char buf[64]; | |||
762 | char *endptr; | |||
763 | unsigned long int key_value; | |||
764 | ||||
765 | if (key_len >= 4 && key_len <= 8 && !strncmp(key, "key", 3)) { | |||
766 | memcpy(buf, key + 3, key_len - 3); | |||
767 | buf[key_len - 3] = 0; | |||
768 | key_value = strtoul(buf, &endptr, 10); | |||
769 | if (endptr > buf /* digits seen */ | |||
770 | && *endptr == 0 /* no non-digit chars after digits */ | |||
771 | && key_value <= 65535) /* no overflow */ | |||
772 | return key_value; | |||
773 | ||||
774 | } else switch (key_len) { | |||
775 | case sizeof("mandatory")-1: | |||
776 | if (!strncmp(key, "mandatory", sizeof("mandatory")-1)) | |||
777 | return SVCB_KEY_MANDATORY0; | |||
778 | if (!strncmp(key, "echconfig", sizeof("echconfig")-1)) | |||
779 | return SVCB_KEY_ECH5; /* allow "echconfig" as well as "ech" */ | |||
780 | break; | |||
781 | ||||
782 | case sizeof("alpn")-1: | |||
783 | if (!strncmp(key, "alpn", sizeof("alpn")-1)) | |||
784 | return SVCB_KEY_ALPN1; | |||
785 | if (!strncmp(key, "port", sizeof("port")-1)) | |||
786 | return SVCB_KEY_PORT3; | |||
787 | break; | |||
788 | ||||
789 | case sizeof("no-default-alpn")-1: | |||
790 | if (!strncmp( key , "no-default-alpn" | |||
791 | , sizeof("no-default-alpn")-1)) | |||
792 | return SVCB_KEY_NO_DEFAULT_ALPN2; | |||
793 | break; | |||
794 | ||||
795 | case sizeof("ipv4hint")-1: | |||
796 | if (!strncmp(key, "ipv4hint", sizeof("ipv4hint")-1)) | |||
797 | return SVCB_KEY_IPV4HINT4; | |||
798 | if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1)) | |||
799 | return SVCB_KEY_IPV6HINT6; | |||
800 | break; | |||
801 | case sizeof("dohpath")-1: | |||
802 | if (!strncmp(key, "dohpath", sizeof("dohpath")-1)) | |||
803 | return SVCB_KEY_DOHPATH7; | |||
804 | break; | |||
805 | case sizeof("ech")-1: | |||
806 | if (!strncmp(key, "ech", sizeof("ech")-1)) | |||
807 | return SVCB_KEY_ECH5; | |||
808 | break; | |||
809 | default: | |||
810 | break; | |||
811 | } | |||
812 | if (key_len > sizeof(buf) - 1) | |||
813 | zc_error_prev_line("Unknown SvcParamKey"); | |||
814 | else { | |||
815 | memcpy(buf, key, key_len); | |||
816 | buf[key_len] = 0; | |||
817 | zc_error_prev_line("Unknown SvcParamKey: %s", buf); | |||
818 | } | |||
819 | /* Although the returned value might be used by the caller, | |||
820 | * the parser has erred, so the zone will not be loaded. | |||
821 | */ | |||
822 | return -1; | |||
823 | } | |||
824 | ||||
825 | static uint16_t * | |||
826 | zparser_conv_svcbparam_port_value(region_type *region, const char *val) | |||
827 | { | |||
828 | unsigned long int port; | |||
829 | char *endptr; | |||
830 | uint16_t *r; | |||
831 | ||||
832 | port = strtoul(val, &endptr, 10); | |||
833 | if (endptr > val /* digits seen */ | |||
834 | && *endptr == 0 /* no non-digit chars after digits */ | |||
835 | && port <= 65535) { /* no overflow */ | |||
836 | ||||
837 | r = alloc_rdata(region, 3 * sizeof(uint16_t)); | |||
838 | r[1] = htons(SVCB_KEY_PORT)(__uint16_t)(__builtin_constant_p(3) ? (__uint16_t)(((__uint16_t )(3) & 0xffU) << 8 | ((__uint16_t)(3) & 0xff00U ) >> 8) : __swap16md(3)); | |||
839 | r[2] = htons(sizeof(uint16_t))(__uint16_t)(__builtin_constant_p(sizeof(uint16_t)) ? (__uint16_t )(((__uint16_t)(sizeof(uint16_t)) & 0xffU) << 8 | ( (__uint16_t)(sizeof(uint16_t)) & 0xff00U) >> 8) : __swap16md (sizeof(uint16_t))); | |||
840 | r[3] = htons(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t )(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U ) >> 8) : __swap16md(port)); | |||
841 | return r; | |||
842 | } | |||
843 | zc_error_prev_line("Could not parse port SvcParamValue: \"%s\"", val); | |||
844 | return NULL((void *)0); | |||
845 | } | |||
846 | ||||
847 | static uint16_t * | |||
848 | zparser_conv_svcbparam_ipv4hint_value(region_type *region, const char *val) | |||
849 | { | |||
850 | uint16_t *r; | |||
851 | int count; | |||
852 | char ip_str[INET_ADDRSTRLEN16+1]; | |||
853 | char *next_ip_str; | |||
854 | uint32_t *ip_wire_dst; | |||
855 | size_t i; | |||
856 | ||||
857 | for (i = 0, count = 1; val[i]; i++) { | |||
858 | if (val[i] == ',') | |||
859 | count += 1; | |||
860 | if (count > SVCB_MAX_COMMA_SEPARATED_VALUES1000) { | |||
861 | zc_error_prev_line("Too many IPV4 addresses in ipv4hint"); | |||
862 | return NULL((void *)0); | |||
863 | } | |||
864 | } | |||
865 | ||||
866 | /* count == number of comma's in val + 1, so the actual number of IPv4 | |||
867 | * addresses in val | |||
868 | */ | |||
869 | r = alloc_rdata(region, 2 * sizeof(uint16_t) + IP4ADDRLEN(32/8) * count); | |||
870 | r[1] = htons(SVCB_KEY_IPV4HINT)(__uint16_t)(__builtin_constant_p(4) ? (__uint16_t)(((__uint16_t )(4) & 0xffU) << 8 | ((__uint16_t)(4) & 0xff00U ) >> 8) : __swap16md(4)); | |||
871 | r[2] = htons(IP4ADDRLEN * count)(__uint16_t)(__builtin_constant_p((32/8) * count) ? (__uint16_t )(((__uint16_t)((32/8) * count) & 0xffU) << 8 | ((__uint16_t )((32/8) * count) & 0xff00U) >> 8) : __swap16md((32 /8) * count)); | |||
872 | ip_wire_dst = (void *)&r[3]; | |||
873 | ||||
874 | while (count) { | |||
875 | if (!(next_ip_str = strchr(val, ','))) { | |||
876 | if (inet_pton(AF_INET2, val, ip_wire_dst) != 1) | |||
877 | break; | |||
878 | ||||
879 | assert(count == 1)((void)0); | |||
880 | ||||
881 | } else if (next_ip_str - val >= (int)sizeof(ip_str)) | |||
882 | break; | |||
883 | ||||
884 | else { | |||
885 | memcpy(ip_str, val, next_ip_str - val); | |||
886 | ip_str[next_ip_str - val] = 0; | |||
887 | if (inet_pton(AF_INET2, ip_str, ip_wire_dst) != 1) { | |||
888 | val = ip_str; /* to use in error reporting below */ | |||
889 | break; | |||
890 | } | |||
891 | ||||
892 | val = next_ip_str + 1; | |||
893 | } | |||
894 | ip_wire_dst++; | |||
895 | count--; | |||
896 | } | |||
897 | if (count) | |||
898 | zc_error_prev_line("Could not parse ipv4hint SvcParamValue: %s", val); | |||
899 | ||||
900 | return r; | |||
901 | } | |||
902 | ||||
903 | static uint16_t * | |||
904 | zparser_conv_svcbparam_ipv6hint_value(region_type *region, const char *val) | |||
905 | { | |||
906 | uint16_t *r; | |||
907 | int i, count; | |||
908 | char ip6_str[INET6_ADDRSTRLEN46+1]; | |||
909 | char *next_ip6_str; | |||
910 | uint8_t *ipv6_wire_dst; | |||
911 | ||||
912 | for (i = 0, count = 1; val[i]; i++) { | |||
913 | if (val[i] == ',') | |||
914 | count += 1; | |||
915 | if (count > SVCB_MAX_COMMA_SEPARATED_VALUES1000) { | |||
916 | zc_error_prev_line("Too many IPV6 addresses in ipv6hint"); | |||
917 | return NULL((void *)0); | |||
918 | } | |||
919 | } | |||
920 | ||||
921 | /* count == number of comma's in val + 1 | |||
922 | * so actually the number of IPv6 addresses in val | |||
923 | */ | |||
924 | r = alloc_rdata(region, 2 * sizeof(uint16_t) + IP6ADDRLEN(128/8) * count); | |||
925 | r[1] = htons(SVCB_KEY_IPV6HINT)(__uint16_t)(__builtin_constant_p(6) ? (__uint16_t)(((__uint16_t )(6) & 0xffU) << 8 | ((__uint16_t)(6) & 0xff00U ) >> 8) : __swap16md(6)); | |||
926 | r[2] = htons(IP6ADDRLEN * count)(__uint16_t)(__builtin_constant_p((128/8) * count) ? (__uint16_t )(((__uint16_t)((128/8) * count) & 0xffU) << 8 | (( __uint16_t)((128/8) * count) & 0xff00U) >> 8) : __swap16md ((128/8) * count)); | |||
927 | ipv6_wire_dst = (void *)&r[3]; | |||
928 | ||||
929 | while (count) { | |||
930 | if (!(next_ip6_str = strchr(val, ','))) { | |||
931 | if ((inet_pton(AF_INET624, val, ipv6_wire_dst) != 1)) | |||
932 | break; | |||
933 | ||||
934 | assert(count == 1)((void)0); | |||
935 | ||||
936 | } else if (next_ip6_str - val >= (int)sizeof(ip6_str)) | |||
937 | break; | |||
938 | ||||
939 | else { | |||
940 | memcpy(ip6_str, val, next_ip6_str - val); | |||
941 | ip6_str[next_ip6_str - val] = 0; | |||
942 | if (inet_pton(AF_INET624, ip6_str, ipv6_wire_dst) != 1) { | |||
943 | val = ip6_str; /* for error reporting below */ | |||
944 | break; | |||
945 | } | |||
946 | ||||
947 | val = next_ip6_str + 1; /* skip the comma */ | |||
948 | } | |||
949 | ipv6_wire_dst += IP6ADDRLEN(128/8); | |||
950 | count--; | |||
951 | } | |||
952 | if (count) | |||
953 | zc_error_prev_line("Could not parse ipv6hint SvcParamValue: %s", val); | |||
954 | ||||
955 | return r; | |||
956 | } | |||
957 | ||||
958 | static int | |||
959 | network_uint16_cmp(const void *a, const void *b) | |||
960 | { | |||
961 | return ((int)read_uint16(a)) - ((int)read_uint16(b)); | |||
962 | } | |||
963 | ||||
964 | static uint16_t * | |||
965 | zparser_conv_svcbparam_mandatory_value(region_type *region, | |||
966 | const char *val, size_t val_len) | |||
967 | { | |||
968 | uint16_t *r; | |||
969 | size_t i, count; | |||
970 | char* next_key; | |||
971 | uint16_t* key_dst; | |||
972 | ||||
973 | for (i = 0, count = 1; val[i]; i++) { | |||
974 | if (val[i] == ',') | |||
975 | count += 1; | |||
976 | if (count > SVCB_MAX_COMMA_SEPARATED_VALUES1000) { | |||
977 | zc_error_prev_line("Too many keys in mandatory"); | |||
978 | return NULL((void *)0); | |||
979 | } | |||
980 | } | |||
981 | ||||
982 | r = alloc_rdata(region, (2 + count) * sizeof(uint16_t)); | |||
983 | r[1] = htons(SVCB_KEY_MANDATORY)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t )(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U ) >> 8) : __swap16md(0)); | |||
984 | r[2] = htons(sizeof(uint16_t) * count)(__uint16_t)(__builtin_constant_p(sizeof(uint16_t) * count) ? (__uint16_t)(((__uint16_t)(sizeof(uint16_t) * count) & 0xffU ) << 8 | ((__uint16_t)(sizeof(uint16_t) * count) & 0xff00U ) >> 8) : __swap16md(sizeof(uint16_t) * count)); | |||
985 | key_dst = (void *)&r[3]; | |||
986 | ||||
987 | for(;;) { | |||
988 | if (!(next_key = strchr(val, ','))) { | |||
989 | *key_dst = htons(svcbparam_lookup_key(val, val_len))(__uint16_t)(__builtin_constant_p(svcbparam_lookup_key(val, val_len )) ? (__uint16_t)(((__uint16_t)(svcbparam_lookup_key(val, val_len )) & 0xffU) << 8 | ((__uint16_t)(svcbparam_lookup_key (val, val_len)) & 0xff00U) >> 8) : __swap16md(svcbparam_lookup_key (val, val_len))); | |||
990 | break; | |||
991 | } else { | |||
992 | *key_dst = htons(svcbparam_lookup_key(val, next_key - val))(__uint16_t)(__builtin_constant_p(svcbparam_lookup_key(val, next_key - val)) ? (__uint16_t)(((__uint16_t)(svcbparam_lookup_key(val , next_key - val)) & 0xffU) << 8 | ((__uint16_t)(svcbparam_lookup_key (val, next_key - val)) & 0xff00U) >> 8) : __swap16md (svcbparam_lookup_key(val, next_key - val))); | |||
993 | } | |||
994 | ||||
995 | val_len -= next_key - val + 1; | |||
996 | val = next_key + 1; /* skip the comma */ | |||
997 | key_dst += 1; | |||
998 | } | |||
999 | ||||
1000 | /* In draft-ietf-dnsop-svcb-https-04 Section 7: | |||
1001 | * | |||
1002 | * In wire format, the keys are represented by their numeric | |||
1003 | * values in network byte order, concatenated in ascending order. | |||
1004 | */ | |||
1005 | qsort((void *)&r[3], count, sizeof(uint16_t), network_uint16_cmp); | |||
1006 | ||||
1007 | return r; | |||
1008 | } | |||
1009 | ||||
1010 | static uint16_t * | |||
1011 | zparser_conv_svcbparam_ech_value(region_type *region, const char *b64) | |||
1012 | { | |||
1013 | uint8_t buffer[B64BUFSIZE65535]; | |||
1014 | uint16_t *r = NULL((void *)0); | |||
1015 | int wire_len; | |||
1016 | ||||
1017 | if(strcmp(b64, "0") == 0) { | |||
1018 | /* single 0 represents empty buffer */ | |||
1019 | return alloc_rdata(region, 0); | |||
1020 | } | |||
1021 | wire_len = __b64_pton(b64, buffer, B64BUFSIZE65535); | |||
1022 | if (wire_len == -1) { | |||
1023 | zc_error_prev_line("invalid base64 data in ech"); | |||
1024 | } else { | |||
1025 | r = alloc_rdata(region, 2 * sizeof(uint16_t) + wire_len); | |||
1026 | r[1] = htons(SVCB_KEY_ECH)(__uint16_t)(__builtin_constant_p(5) ? (__uint16_t)(((__uint16_t )(5) & 0xffU) << 8 | ((__uint16_t)(5) & 0xff00U ) >> 8) : __swap16md(5)); | |||
1027 | r[2] = htons(wire_len)(__uint16_t)(__builtin_constant_p(wire_len) ? (__uint16_t)((( __uint16_t)(wire_len) & 0xffU) << 8 | ((__uint16_t) (wire_len) & 0xff00U) >> 8) : __swap16md(wire_len)); | |||
1028 | memcpy(&r[3], buffer, wire_len); | |||
1029 | } | |||
1030 | ||||
1031 | return r; | |||
1032 | } | |||
1033 | ||||
1034 | static const char* parse_alpn_next_unescaped_comma(const char *val) | |||
1035 | { | |||
1036 | while (*val) { | |||
1037 | /* Only return when the comma is not escaped*/ | |||
1038 | if (*val == '\\'){ | |||
1039 | ++val; | |||
1040 | if (!*val) | |||
1041 | break; | |||
1042 | } else if (*val == ',') | |||
1043 | return val; | |||
1044 | ||||
1045 | val++; | |||
1046 | } | |||
1047 | return NULL((void *)0); | |||
1048 | } | |||
1049 | ||||
1050 | static size_t | |||
1051 | parse_alpn_copy_unescaped(uint8_t *dst, const char *src, size_t len) | |||
1052 | { | |||
1053 | uint8_t *orig_dst = dst; | |||
1054 | ||||
1055 | while (len) { | |||
1056 | if (*src == '\\') { | |||
1057 | src++; | |||
1058 | len--; | |||
1059 | if (!len) | |||
1060 | break; | |||
1061 | } | |||
1062 | *dst++ = *src++; | |||
1063 | len--; | |||
1064 | } | |||
1065 | return (size_t)(dst - orig_dst); | |||
1066 | } | |||
1067 | ||||
1068 | static uint16_t * | |||
1069 | zparser_conv_svcbparam_alpn_value(region_type *region, | |||
1070 | const char *val, size_t val_len) | |||
1071 | { | |||
1072 | uint8_t unescaped_dst[65536]; | |||
1073 | uint8_t *dst = unescaped_dst; | |||
1074 | const char *next_str; | |||
1075 | size_t str_len; | |||
1076 | size_t dst_len; | |||
1077 | uint16_t *r = NULL((void *)0); | |||
1078 | ||||
1079 | if (val_len > sizeof(unescaped_dst)) { | |||
1080 | zc_error_prev_line("invalid alpn"); | |||
1081 | return r; | |||
1082 | } | |||
1083 | while (val_len) { | |||
1084 | size_t dst_len; | |||
1085 | ||||
1086 | str_len = (next_str = parse_alpn_next_unescaped_comma(val)) | |||
1087 | ? (size_t)(next_str - val) : val_len; | |||
1088 | ||||
1089 | if (str_len > 255) { | |||
1090 | zc_error_prev_line("alpn strings need to be" | |||
1091 | " smaller than 255 chars"); | |||
1092 | return r; | |||
1093 | } | |||
1094 | dst_len = parse_alpn_copy_unescaped(dst + 1, val, str_len); | |||
1095 | *dst++ = dst_len; | |||
1096 | dst += dst_len; | |||
1097 | ||||
1098 | if (!next_str) | |||
1099 | break; | |||
1100 | ||||
1101 | /* skip the comma for the next iteration */ | |||
1102 | val_len -= next_str - val + 1; | |||
1103 | val = next_str + 1; | |||
1104 | } | |||
1105 | dst_len = dst - unescaped_dst; | |||
1106 | r = alloc_rdata(region, 2 * sizeof(uint16_t) + dst_len); | |||
1107 | r[1] = htons(SVCB_KEY_ALPN)(__uint16_t)(__builtin_constant_p(1) ? (__uint16_t)(((__uint16_t )(1) & 0xffU) << 8 | ((__uint16_t)(1) & 0xff00U ) >> 8) : __swap16md(1)); | |||
1108 | r[2] = htons(dst_len)(__uint16_t)(__builtin_constant_p(dst_len) ? (__uint16_t)(((__uint16_t )(dst_len) & 0xffU) << 8 | ((__uint16_t)(dst_len) & 0xff00U) >> 8) : __swap16md(dst_len)); | |||
1109 | memcpy(&r[3], unescaped_dst, dst_len); | |||
1110 | return r; | |||
1111 | } | |||
1112 | ||||
1113 | static uint16_t * | |||
1114 | zparser_conv_svcbparam_key_value(region_type *region, | |||
1115 | const char *key, size_t key_len, const char *val, size_t val_len) | |||
1116 | { | |||
1117 | uint16_t svcparamkey = svcbparam_lookup_key(key, key_len); | |||
1118 | uint16_t *r; | |||
1119 | ||||
1120 | switch (svcparamkey) { | |||
1121 | case SVCB_KEY_PORT3: | |||
1122 | return zparser_conv_svcbparam_port_value(region, val); | |||
1123 | case SVCB_KEY_IPV4HINT4: | |||
1124 | return zparser_conv_svcbparam_ipv4hint_value(region, val); | |||
1125 | case SVCB_KEY_IPV6HINT6: | |||
1126 | return zparser_conv_svcbparam_ipv6hint_value(region, val); | |||
1127 | case SVCB_KEY_MANDATORY0: | |||
1128 | return zparser_conv_svcbparam_mandatory_value(region, val, val_len); | |||
1129 | case SVCB_KEY_NO_DEFAULT_ALPN2: | |||
1130 | if(zone_is_slave(parser->current_zone->opts)) | |||
1131 | zc_warning_prev_line("no-default-alpn should not have a value"); | |||
1132 | else | |||
1133 | zc_error_prev_line("no-default-alpn should not have a value"); | |||
1134 | break; | |||
1135 | case SVCB_KEY_ECH5: | |||
1136 | return zparser_conv_svcbparam_ech_value(region, val); | |||
1137 | case SVCB_KEY_ALPN1: | |||
1138 | return zparser_conv_svcbparam_alpn_value(region, val, val_len); | |||
1139 | case SVCB_KEY_DOHPATH7: | |||
1140 | /* fallthrough */ | |||
1141 | default: | |||
1142 | break; | |||
1143 | } | |||
1144 | r = alloc_rdata(region, 2 * sizeof(uint16_t) + val_len); | |||
1145 | r[1] = htons(svcparamkey)(__uint16_t)(__builtin_constant_p(svcparamkey) ? (__uint16_t) (((__uint16_t)(svcparamkey) & 0xffU) << 8 | ((__uint16_t )(svcparamkey) & 0xff00U) >> 8) : __swap16md(svcparamkey )); | |||
1146 | r[2] = htons(val_len)(__uint16_t)(__builtin_constant_p(val_len) ? (__uint16_t)(((__uint16_t )(val_len) & 0xffU) << 8 | ((__uint16_t)(val_len) & 0xff00U) >> 8) : __swap16md(val_len)); | |||
1147 | memcpy(r + 3, val, val_len); | |||
1148 | return r; | |||
1149 | } | |||
1150 | ||||
1151 | uint16_t * | |||
1152 | zparser_conv_svcbparam(region_type *region, const char *key, size_t key_len | |||
1153 | , const char *val, size_t val_len) | |||
1154 | { | |||
1155 | const char *eq; | |||
1156 | uint16_t *r; | |||
1157 | uint16_t svcparamkey; | |||
1158 | ||||
1159 | /* Form <key>="<value>" (or at least with quoted value) */ | |||
1160 | if (val && val_len) { | |||
1161 | /* Does key end with '=' */ | |||
1162 | if (key_len && key[key_len - 1] == '=') | |||
1163 | return zparser_conv_svcbparam_key_value( | |||
1164 | region, key, key_len - 1, val, val_len); | |||
1165 | ||||
1166 | zc_error_prev_line( "SvcParam syntax error in param: %s\"%s\"" | |||
1167 | , key, val); | |||
1168 | } | |||
1169 | assert(val == NULL)((void)0); | |||
1170 | if ((eq = memchr(key, '=', key_len))) { | |||
1171 | size_t new_key_len = eq - key; | |||
1172 | ||||
1173 | if (key_len - new_key_len - 1 > 0) | |||
1174 | return zparser_conv_svcbparam_key_value(region, | |||
1175 | key, new_key_len, eq+1, key_len - new_key_len - 1); | |||
1176 | key_len = new_key_len; | |||
1177 | } | |||
1178 | /* Some SvcParamKeys require values */ | |||
1179 | svcparamkey = svcbparam_lookup_key(key, key_len); | |||
1180 | switch (svcparamkey) { | |||
1181 | case SVCB_KEY_MANDATORY0: | |||
1182 | case SVCB_KEY_ALPN1: | |||
1183 | case SVCB_KEY_PORT3: | |||
1184 | case SVCB_KEY_IPV4HINT4: | |||
1185 | case SVCB_KEY_IPV6HINT6: | |||
1186 | case SVCB_KEY_DOHPATH7: | |||
1187 | if(zone_is_slave(parser->current_zone->opts)) | |||
1188 | zc_warning_prev_line("value expected for SvcParam: %s", key); | |||
1189 | else | |||
1190 | zc_error_prev_line("value expected for SvcParam: %s", key); | |||
1191 | break; | |||
1192 | default: | |||
1193 | break; | |||
1194 | } | |||
1195 | /* SvcParam is only a SvcParamKey */ | |||
1196 | r = alloc_rdata(region, 2 * sizeof(uint16_t)); | |||
1197 | r[1] = htons(svcparamkey)(__uint16_t)(__builtin_constant_p(svcparamkey) ? (__uint16_t) (((__uint16_t)(svcparamkey) & 0xffU) << 8 | ((__uint16_t )(svcparamkey) & 0xff00U) >> 8) : __swap16md(svcparamkey )); | |||
1198 | r[2] = 0; | |||
1199 | return r; | |||
1200 | } | |||
1201 | ||||
1202 | /* Parse an int terminated in the specified range. */ | |||
1203 | static int | |||
1204 | parse_int(const char *str, | |||
1205 | char **end, | |||
1206 | int *result, | |||
1207 | const char *name, | |||
1208 | int min, | |||
1209 | int max) | |||
1210 | { | |||
1211 | *result = (int) strtol(str, end, 10); | |||
1212 | if (*result < min || *result > max) { | |||
1213 | zc_error_prev_line("%s must be within the range [%d .. %d]", | |||
1214 | name, | |||
1215 | min, | |||
1216 | max); | |||
1217 | return 0; | |||
1218 | } else { | |||
1219 | return 1; | |||
1220 | } | |||
1221 | } | |||
1222 | ||||
1223 | /* RFC1876 conversion routines */ | |||
1224 | static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, | |||
1225 | 1000000,10000000,100000000,1000000000}; | |||
1226 | ||||
1227 | /* | |||
1228 | * Converts ascii size/precision X * 10**Y(cm) to 0xXY. | |||
1229 | * Sets the given pointer to the last used character. | |||
1230 | * | |||
1231 | */ | |||
1232 | static uint8_t | |||
1233 | precsize_aton (char *cp, char **endptr) | |||
1234 | { | |||
1235 | unsigned int mval = 0, cmval = 0; | |||
1236 | uint8_t retval = 0; | |||
1237 | int exponent; | |||
1238 | int mantissa; | |||
1239 | ||||
1240 | while (isdigit((unsigned char)*cp)) | |||
1241 | mval = mval * 10 + hexdigit_to_int(*cp++); | |||
1242 | ||||
1243 | if (*cp == '.') { /* centimeters */ | |||
1244 | cp++; | |||
1245 | if (isdigit((unsigned char)*cp)) { | |||
1246 | cmval = hexdigit_to_int(*cp++) * 10; | |||
1247 | if (isdigit((unsigned char)*cp)) { | |||
1248 | cmval += hexdigit_to_int(*cp++); | |||
1249 | } | |||
1250 | } | |||
1251 | } | |||
1252 | ||||
1253 | if(mval >= poweroften[7]) { | |||
1254 | assert(poweroften[7] != 0)((void)0); | |||
1255 | /* integer overflow possible for *100 */ | |||
1256 | mantissa = mval / poweroften[7]; | |||
1257 | exponent = 9; /* max */ | |||
1258 | } | |||
1259 | else { | |||
1260 | cmval = (mval * 100) + cmval; | |||
1261 | ||||
1262 | for (exponent = 0; exponent < 9; exponent++) | |||
1263 | if (cmval < poweroften[exponent+1]) | |||
1264 | break; | |||
1265 | ||||
1266 | assert(poweroften[exponent] != 0)((void)0); | |||
1267 | mantissa = cmval / poweroften[exponent]; | |||
| ||||
1268 | } | |||
1269 | if (mantissa > 9) | |||
1270 | mantissa = 9; | |||
1271 | ||||
1272 | retval = (mantissa << 4) | exponent; | |||
1273 | ||||
1274 | if (*cp == 'm') cp++; | |||
1275 | ||||
1276 | *endptr = cp; | |||
1277 | ||||
1278 | return (retval); | |||
1279 | } | |||
1280 | ||||
1281 | /* | |||
1282 | * Parses a specific part of rdata. | |||
1283 | * | |||
1284 | * Returns: | |||
1285 | * | |||
1286 | * number of elements parsed | |||
1287 | * zero on error | |||
1288 | * | |||
1289 | */ | |||
1290 | uint16_t * | |||
1291 | zparser_conv_loc(region_type *region, char *str) | |||
1292 | { | |||
1293 | uint16_t *r; | |||
1294 | uint32_t *p; | |||
1295 | int i; | |||
1296 | int deg, min, secs; /* Secs is stored times 1000. */ | |||
1297 | uint32_t lat = 0, lon = 0, alt = 0; | |||
1298 | /* encoded defaults: version=0 sz=1m hp=10000m vp=10m */ | |||
1299 | uint8_t vszhpvp[4] = {0, 0x12, 0x16, 0x13}; | |||
1300 | char *start; | |||
1301 | double d; | |||
1302 | ||||
1303 | for(;;) { | |||
| ||||
1304 | deg = min = secs = 0; | |||
1305 | ||||
1306 | /* Degrees */ | |||
1307 | if (*str == '\0') { | |||
1308 | zc_error_prev_line("unexpected end of LOC data"); | |||
1309 | return NULL((void *)0); | |||
1310 | } | |||
1311 | ||||
1312 | if (!parse_int(str, &str, °, "degrees", 0, 180)) | |||
1313 | return NULL((void *)0); | |||
1314 | if (!isspace((unsigned char)*str)) { | |||
1315 | zc_error_prev_line("space expected after degrees"); | |||
1316 | return NULL((void *)0); | |||
1317 | } | |||
1318 | ++str; | |||
1319 | ||||
1320 | /* Minutes? */ | |||
1321 | if (isdigit((unsigned char)*str)) { | |||
1322 | if (!parse_int(str, &str, &min, "minutes", 0, 60)) | |||
1323 | return NULL((void *)0); | |||
1324 | if (!isspace((unsigned char)*str)) { | |||
1325 | zc_error_prev_line("space expected after minutes"); | |||
1326 | return NULL((void *)0); | |||
1327 | } | |||
1328 | ++str; | |||
1329 | } | |||
1330 | ||||
1331 | /* Seconds? */ | |||
1332 | if (isdigit((unsigned char)*str)) { | |||
1333 | start = str; | |||
1334 | if (!parse_int(str, &str, &i, "seconds", 0, 60)) { | |||
1335 | return NULL((void *)0); | |||
1336 | } | |||
1337 | ||||
1338 | if (*str == '.' && !parse_int(str + 1, &str, &i, "seconds fraction", 0, 999)) { | |||
1339 | return NULL((void *)0); | |||
1340 | } | |||
1341 | ||||
1342 | if (!isspace((unsigned char)*str)) { | |||
1343 | zc_error_prev_line("space expected after seconds"); | |||
1344 | return NULL((void *)0); | |||
1345 | } | |||
1346 | /* No need for precision specifiers, it's a double */ | |||
1347 | if (sscanf(start, "%lf", &d) != 1) { | |||
1348 | zc_error_prev_line("error parsing seconds"); | |||
1349 | } | |||
1350 | ||||
1351 | if (d < 0.0 || d > 60.0) { | |||
1352 | zc_error_prev_line("seconds not in range 0.0 .. 60.0"); | |||
1353 | } | |||
1354 | ||||
1355 | secs = (int) (d * 1000.0 + 0.5); | |||
1356 | ++str; | |||
1357 | } | |||
1358 | ||||
1359 | switch(*str) { | |||
1360 | case 'N': | |||
1361 | case 'n': | |||
1362 | lat = ((uint32_t)1<<31) + (deg * 3600000 + min * 60000 + secs); | |||
1363 | break; | |||
1364 | case 'E': | |||
1365 | case 'e': | |||
1366 | lon = ((uint32_t)1<<31) + (deg * 3600000 + min * 60000 + secs); | |||
1367 | break; | |||
1368 | case 'S': | |||
1369 | case 's': | |||
1370 | lat = ((uint32_t)1<<31) - (deg * 3600000 + min * 60000 + secs); | |||
1371 | break; | |||
1372 | case 'W': | |||
1373 | case 'w': | |||
1374 | lon = ((uint32_t)1<<31) - (deg * 3600000 + min * 60000 + secs); | |||
1375 | break; | |||
1376 | default: | |||
1377 | zc_error_prev_line("invalid latitude/longtitude: '%c'", *str); | |||
1378 | return NULL((void *)0); | |||
1379 | } | |||
1380 | ++str; | |||
1381 | ||||
1382 | if (lat
| |||
1383 | break; | |||
1384 | ||||
1385 | if (!isspace((unsigned char)*str)) { | |||
1386 | zc_error_prev_line("space expected after latitude/longitude"); | |||
1387 | return NULL((void *)0); | |||
1388 | } | |||
1389 | ++str; | |||
1390 | } | |||
1391 | ||||
1392 | /* Altitude */ | |||
1393 | if (*str == '\0') { | |||
1394 | zc_error_prev_line("unexpected end of LOC data"); | |||
1395 | return NULL((void *)0); | |||
1396 | } | |||
1397 | ||||
1398 | if (!isspace((unsigned char)*str)) { | |||
1399 | zc_error_prev_line("space expected before altitude"); | |||
1400 | return NULL((void *)0); | |||
1401 | } | |||
1402 | ++str; | |||
1403 | ||||
1404 | start = str; | |||
1405 | ||||
1406 | /* Sign */ | |||
1407 | if (*str == '+' || *str == '-') { | |||
1408 | ++str; | |||
1409 | } | |||
1410 | ||||
1411 | /* Meters of altitude... */ | |||
1412 | if(strtol(str, &str, 10) == LONG_MAX0x7fffffffffffffffL) { | |||
1413 | zc_error_prev_line("altitude too large, number overflow"); | |||
1414 | return NULL((void *)0); | |||
1415 | } | |||
1416 | switch(*str) { | |||
1417 | case ' ': | |||
1418 | case '\0': | |||
1419 | case 'm': | |||
1420 | break; | |||
1421 | case '.': | |||
1422 | if (!parse_int(str + 1, &str, &i, "altitude fraction", 0, 99)) { | |||
1423 | return NULL((void *)0); | |||
1424 | } | |||
1425 | if (!isspace((unsigned char)*str) && *str != '\0' && *str != 'm') { | |||
1426 | zc_error_prev_line("altitude fraction must be a number"); | |||
1427 | return NULL((void *)0); | |||
1428 | } | |||
1429 | break; | |||
1430 | default: | |||
1431 | zc_error_prev_line("altitude must be expressed in meters"); | |||
1432 | return NULL((void *)0); | |||
1433 | } | |||
1434 | if (!isspace((unsigned char)*str) && *str != '\0') | |||
1435 | ++str; | |||
1436 | ||||
1437 | if (sscanf(start, "%lf", &d) != 1) { | |||
1438 | zc_error_prev_line("error parsing altitude"); | |||
1439 | } | |||
1440 | ||||
1441 | alt = (uint32_t) (10000000.0 + d * 100 + 0.5); | |||
1442 | ||||
1443 | if (!isspace((unsigned char)*str) && *str != '\0') { | |||
1444 | zc_error_prev_line("unexpected character after altitude"); | |||
1445 | return NULL((void *)0); | |||
1446 | } | |||
1447 | ||||
1448 | /* Now parse size, horizontal precision and vertical precision if any */ | |||
1449 | for(i = 1; isspace((unsigned char)*str) && i <= 3; i++) { | |||
1450 | vszhpvp[i] = precsize_aton(str + 1, &str); | |||
1451 | ||||
1452 | if (!isspace((unsigned char)*str) && *str != '\0') { | |||
1453 | zc_error_prev_line("invalid size or precision"); | |||
1454 | return NULL((void *)0); | |||
1455 | } | |||
1456 | } | |||
1457 | ||||
1458 | /* Allocate required space... */ | |||
1459 | r = alloc_rdata(region, 16); | |||
1460 | p = (uint32_t *) (r + 1); | |||
1461 | ||||
1462 | memmove(p, vszhpvp, 4); | |||
1463 | write_uint32(p + 1, lat); | |||
1464 | write_uint32(p + 2, lon); | |||
1465 | write_uint32(p + 3, alt); | |||
1466 | ||||
1467 | return r; | |||
1468 | } | |||
1469 | ||||
1470 | /* | |||
1471 | * Convert an APL RR RDATA element. | |||
1472 | */ | |||
1473 | uint16_t * | |||
1474 | zparser_conv_apl_rdata(region_type *region, char *str) | |||
1475 | { | |||
1476 | int negated = 0; | |||
1477 | uint16_t address_family; | |||
1478 | uint8_t prefix; | |||
1479 | uint8_t maximum_prefix; | |||
1480 | uint8_t length; | |||
1481 | uint8_t address[IP6ADDRLEN(128/8)]; | |||
1482 | char *colon = strchr(str, ':'); | |||
1483 | char *slash = strchr(str, '/'); | |||
1484 | int af; | |||
1485 | int rc; | |||
1486 | uint16_t rdlength; | |||
1487 | uint16_t *r; | |||
1488 | uint8_t *t; | |||
1489 | char *end; | |||
1490 | long p; | |||
1491 | ||||
1492 | if (!colon) { | |||
1493 | zc_error("address family separator is missing"); | |||
1494 | return NULL((void *)0); | |||
1495 | } | |||
1496 | if (!slash) { | |||
1497 | zc_error("prefix separator is missing"); | |||
1498 | return NULL((void *)0); | |||
1499 | } | |||
1500 | ||||
1501 | *colon = '\0'; | |||
1502 | *slash = '\0'; | |||
1503 | ||||
1504 | if (*str == '!') { | |||
1505 | negated = 1; | |||
1506 | ++str; | |||
1507 | } | |||
1508 | ||||
1509 | if (strcmp(str, "1") == 0) { | |||
1510 | address_family = htons(1)(__uint16_t)(__builtin_constant_p(1) ? (__uint16_t)(((__uint16_t )(1) & 0xffU) << 8 | ((__uint16_t)(1) & 0xff00U ) >> 8) : __swap16md(1)); | |||
1511 | af = AF_INET2; | |||
1512 | length = sizeof(in_addr_t); | |||
1513 | maximum_prefix = length * 8; | |||
1514 | } else if (strcmp(str, "2") == 0) { | |||
1515 | address_family = htons(2)(__uint16_t)(__builtin_constant_p(2) ? (__uint16_t)(((__uint16_t )(2) & 0xffU) << 8 | ((__uint16_t)(2) & 0xff00U ) >> 8) : __swap16md(2)); | |||
1516 | af = AF_INET624; | |||
1517 | length = IP6ADDRLEN(128/8); | |||
1518 | maximum_prefix = length * 8; | |||
1519 | } else { | |||
1520 | zc_error("invalid address family '%s'", str); | |||
1521 | return NULL((void *)0); | |||
1522 | } | |||
1523 | ||||
1524 | rc = inet_pton(af, colon + 1, address); | |||
1525 | if (rc == 0) { | |||
1526 | zc_error("invalid address '%s'", colon + 1); | |||
1527 | return NULL((void *)0); | |||
1528 | } else if (rc == -1) { | |||
1529 | zc_error("inet_pton failed: %s", strerror(errno(*__errno()))); | |||
1530 | return NULL((void *)0); | |||
1531 | } | |||
1532 | ||||
1533 | /* Strip trailing zero octets. */ | |||
1534 | while (length > 0 && address[length - 1] == 0) | |||
1535 | --length; | |||
1536 | ||||
1537 | ||||
1538 | p = strtol(slash + 1, &end, 10); | |||
1539 | if (p < 0 || p > maximum_prefix) { | |||
1540 | zc_error("prefix not in the range 0 .. %d", maximum_prefix); | |||
1541 | return NULL((void *)0); | |||
1542 | } else if (*end != '\0') { | |||
1543 | zc_error("invalid prefix '%s'", slash + 1); | |||
1544 | return NULL((void *)0); | |||
1545 | } | |||
1546 | prefix = (uint8_t) p; | |||
1547 | ||||
1548 | rdlength = (sizeof(address_family) + sizeof(prefix) + sizeof(length) | |||
1549 | + length); | |||
1550 | r = alloc_rdata(region, rdlength); | |||
1551 | t = (uint8_t *) (r + 1); | |||
1552 | ||||
1553 | memcpy(t, &address_family, sizeof(address_family)); | |||
1554 | t += sizeof(address_family); | |||
1555 | memcpy(t, &prefix, sizeof(prefix)); | |||
1556 | t += sizeof(prefix); | |||
1557 | memcpy(t, &length, sizeof(length)); | |||
1558 | if (negated) { | |||
1559 | *t |= APL_NEGATION_MASK0x80U; | |||
1560 | } | |||
1561 | t += sizeof(length); | |||
1562 | memcpy(t, address, length); | |||
1563 | ||||
1564 | return r; | |||
1565 | } | |||
1566 | ||||
1567 | /* | |||
1568 | * Below some function that also convert but not to wireformat | |||
1569 | * but to "normal" (int,long,char) types | |||
1570 | */ | |||
1571 | ||||
1572 | uint32_t | |||
1573 | zparser_ttl2int(const char *ttlstr, int* error) | |||
1574 | { | |||
1575 | /* convert a ttl value to a integer | |||
1576 | * return the ttl in a int | |||
1577 | * -1 on error | |||
1578 | */ | |||
1579 | ||||
1580 | uint32_t ttl; | |||
1581 | const char *t; | |||
1582 | ||||
1583 | ttl = strtottl(ttlstr, &t); | |||
1584 | if (*t != 0) { | |||
1585 | zc_error_prev_line("invalid TTL value: %s",ttlstr); | |||
1586 | *error = 1; | |||
1587 | } | |||
1588 | ||||
1589 | return ttl; | |||
1590 | } | |||
1591 | ||||
1592 | ||||
1593 | void | |||
1594 | zadd_rdata_wireformat(uint16_t *data) | |||
1595 | { | |||
1596 | if (parser->current_rr.rdata_count >= MAXRDATALEN64) { | |||
1597 | zc_error_prev_line("too many rdata elements"); | |||
1598 | } else { | |||
1599 | parser->current_rr.rdatas[parser->current_rr.rdata_count].data | |||
1600 | = data; | |||
1601 | ++parser->current_rr.rdata_count; | |||
1602 | } | |||
1603 | } | |||
1604 | ||||
1605 | /** | |||
1606 | * Used for TXT RR's to grow with undefined number of strings. | |||
1607 | */ | |||
1608 | void | |||
1609 | zadd_rdata_txt_wireformat(uint16_t *data, int first) | |||
1610 | { | |||
1611 | rdata_atom_type *rd; | |||
1612 | if (parser->current_rr.rdata_count >= MAXRDATALEN64) { | |||
1613 | zc_error_prev_line("too many rdata txt elements"); | |||
1614 | return; | |||
1615 | } | |||
1616 | ||||
1617 | /* First STR in str_seq, allocate 65K in first unused rdata | |||
1618 | * else find last used rdata */ | |||
1619 | if (first) { | |||
1620 | rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count]; | |||
1621 | if ((rd->data = (uint16_t *) region_alloc(parser->rr_region, | |||
1622 | sizeof(uint16_t) + 65535 * sizeof(uint8_t))) == NULL((void *)0)) { | |||
1623 | zc_error_prev_line("Could not allocate memory for TXT RR"); | |||
1624 | return; | |||
1625 | } | |||
1626 | parser->current_rr.rdata_count++; | |||
1627 | rd->data[0] = 0; | |||
1628 | } | |||
1629 | else | |||
1630 | rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1]; | |||
1631 | ||||
1632 | if ((size_t)rd->data[0] + (size_t)data[0] > 65535) { | |||
1633 | zc_error_prev_line("too large rdata element"); | |||
1634 | return; | |||
1635 | } | |||
1636 | ||||
1637 | memcpy((uint8_t *)rd->data + 2 + rd->data[0], data + 1, data[0]); | |||
1638 | rd->data[0] += data[0]; | |||
1639 | } | |||
1640 | ||||
1641 | /** | |||
1642 | * Clean up after last call of zadd_rdata_txt_wireformat | |||
1643 | */ | |||
1644 | void | |||
1645 | zadd_rdata_txt_clean_wireformat() | |||
1646 | { | |||
1647 | uint16_t *tmp_data; | |||
1648 | rdata_atom_type *rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1]; | |||
1649 | if(!rd || !rd->data) | |||
1650 | return; /* previous syntax failure */ | |||
1651 | if ((tmp_data = (uint16_t *) region_alloc(parser->region, | |||
1652 | ((size_t)rd->data[0]) + ((size_t)2))) != NULL((void *)0)) { | |||
1653 | memcpy(tmp_data, rd->data, rd->data[0] + 2); | |||
1654 | /* rd->data of u16+65535 freed when rr_region is freed */ | |||
1655 | rd->data = tmp_data; | |||
1656 | } | |||
1657 | else { | |||
1658 | /* We could not get memory in non-volatile region */ | |||
1659 | zc_error_prev_line("could not allocate memory for rdata"); | |||
1660 | return; | |||
1661 | } | |||
1662 | } | |||
1663 | ||||
1664 | static int | |||
1665 | svcparam_key_cmp(const void *a, const void *b) | |||
1666 | { | |||
1667 | return ((int)read_uint16(rdata_atom_data(*(rdata_atom_type *)a))) | |||
1668 | - ((int)read_uint16(rdata_atom_data(*(rdata_atom_type *)b))); | |||
1669 | } | |||
1670 | ||||
1671 | void | |||
1672 | zadd_rdata_svcb_check_wireformat() | |||
1673 | { | |||
1674 | size_t i; | |||
1675 | uint8_t paramkeys[65536]; | |||
1676 | int prev_key = - 1; | |||
1677 | int key = 0; | |||
1678 | size_t size; | |||
1679 | uint16_t *mandatory_values; | |||
1680 | ||||
1681 | if (parser->current_rr.rdata_count <= 2) { | |||
1682 | if (!parser->error_occurred) | |||
1683 | zc_error_prev_line("invalid SVCB or HTTPS rdata"); | |||
1684 | return; | |||
1685 | } else for (i = 2; i < parser->current_rr.rdata_count; i++) { | |||
1686 | if (parser->current_rr.rdatas[i].data == NULL((void *)0) | |||
1687 | || rdata_atom_data(parser->current_rr.rdatas[i]) == NULL((void *)0) | |||
1688 | || rdata_atom_size(parser->current_rr.rdatas[i]) < 4) { | |||
1689 | if (!parser->error_occurred) | |||
1690 | zc_error_prev_line("invalid SVCB or HTTPS rdata"); | |||
1691 | return; | |||
1692 | } | |||
1693 | } | |||
1694 | /* After this point, all rdatas do have data larger than 4 bytes. | |||
1695 | * So we may assume a uint16_t SVCB key followed by uint16_t length | |||
1696 | * in each rdata in the remainder of this function. | |||
1697 | */ | |||
1698 | memset(paramkeys, 0, sizeof(paramkeys)); | |||
1699 | /* | |||
1700 | * In draft-ietf-dnsop-svcb-https-04 Section 7: | |||
1701 | * In wire format, the keys are represented by their numeric values in | |||
1702 | * network byte order, concatenated in ascending order. | |||
1703 | * | |||
1704 | * svcparam_key_cmp assumes the rdatas to have a SVCB key, which is | |||
1705 | * safe because we checked. | |||
1706 | * | |||
1707 | */ | |||
1708 | qsort( (void *)&parser->current_rr.rdatas[2] | |||
1709 | , parser->current_rr.rdata_count - 2 | |||
1710 | , sizeof(rdata_atom_type) | |||
1711 | , svcparam_key_cmp | |||
1712 | ); | |||
1713 | ||||
1714 | for (i = 2; i < parser->current_rr.rdata_count; i++) { | |||
1715 | assert(parser->current_rr.rdatas[i].data)((void)0); | |||
1716 | assert(rdata_atom_data(parser->current_rr.rdatas[i]))((void)0); | |||
1717 | assert(rdata_atom_size(parser->current_rr.rdatas[i]) >= sizeof(uint16_t))((void)0); | |||
1718 | ||||
1719 | key = read_uint16(rdata_atom_data(parser->current_rr.rdatas[i])); | |||
1720 | ||||
1721 | /* In draft-ietf-dnsop-svcb-https-04 Section 7: | |||
1722 | * | |||
1723 | * Keys (...) MUST NOT appear more than once. | |||
1724 | * | |||
1725 | * If they key has already been seen, we have a duplicate | |||
1726 | */ | |||
1727 | if (!paramkeys[key]) | |||
1728 | /* keep track of keys that are present */ | |||
1729 | paramkeys[key] = 1; | |||
1730 | ||||
1731 | else if (key < SVCPARAMKEY_COUNT8) { | |||
1732 | if(zone_is_slave(parser->current_zone->opts)) | |||
1733 | zc_warning_prev_line( | |||
1734 | "Duplicate key found: %s", | |||
1735 | svcparamkey_strs[key]); | |||
1736 | else { | |||
1737 | zc_error_prev_line( | |||
1738 | "Duplicate key found: %s", | |||
1739 | svcparamkey_strs[key]); | |||
1740 | } | |||
1741 | } else if(zone_is_slave(parser->current_zone->opts)) | |||
1742 | zc_warning_prev_line( | |||
1743 | "Duplicate key found: key%d", key); | |||
1744 | else | |||
1745 | zc_error_prev_line( | |||
1746 | "Duplicate key found: key%d", key); | |||
1747 | } | |||
1748 | /* Checks when a mandatory key is present */ | |||
1749 | if (!paramkeys[SVCB_KEY_MANDATORY0]) | |||
1750 | return; | |||
1751 | ||||
1752 | size = rdata_atom_size(parser->current_rr.rdatas[2]); | |||
1753 | assert(size >= 4)((void)0); | |||
1754 | mandatory_values = (void*)rdata_atom_data(parser->current_rr.rdatas[2]); | |||
1755 | mandatory_values += 2; /* skip the key type and length */ | |||
1756 | ||||
1757 | if (size % 2) | |||
1758 | zc_error_prev_line("mandatory rdata must be a multiple of shorts"); | |||
1759 | ||||
1760 | else for (i = 0; i < (size - 4)/2; i++) { | |||
1761 | key = ntohs(mandatory_values[i])(__uint16_t)(__builtin_constant_p(mandatory_values[i]) ? (__uint16_t )(((__uint16_t)(mandatory_values[i]) & 0xffU) << 8 | ((__uint16_t)(mandatory_values[i]) & 0xff00U) >> 8 ) : __swap16md(mandatory_values[i])); | |||
1762 | ||||
1763 | if (paramkeys[key]) | |||
1764 | ; /* pass */ | |||
1765 | ||||
1766 | else if (key < SVCPARAMKEY_COUNT8) { | |||
1767 | if(zone_is_slave(parser->current_zone->opts)) | |||
1768 | zc_warning_prev_line("mandatory SvcParamKey: %s is missing " | |||
1769 | "the record", svcparamkey_strs[key]); | |||
1770 | else | |||
1771 | zc_error_prev_line("mandatory SvcParamKey: %s is missing " | |||
1772 | "the record", svcparamkey_strs[key]); | |||
1773 | } else { | |||
1774 | if(zone_is_slave(parser->current_zone->opts)) | |||
1775 | zc_warning_prev_line("mandatory SvcParamKey: key%d is missing " | |||
1776 | "the record", key); | |||
1777 | else | |||
1778 | zc_error_prev_line("mandatory SvcParamKey: key%d is missing " | |||
1779 | "the record", key); | |||
1780 | } | |||
1781 | ||||
1782 | /* In draft-ietf-dnsop-svcb-https-04 Section 8 | |||
1783 | * automatically mandatory MUST NOT appear in its own value-list | |||
1784 | */ | |||
1785 | if (key == SVCB_KEY_MANDATORY0) { | |||
1786 | if(zone_is_slave(parser->current_zone->opts)) | |||
1787 | zc_warning_prev_line("mandatory MUST not be included" | |||
1788 | " as mandatory parameter"); | |||
1789 | else | |||
1790 | zc_error_prev_line("mandatory MUST not be included" | |||
1791 | " as mandatory parameter"); | |||
1792 | } | |||
1793 | if (key == prev_key) { | |||
1794 | if(zone_is_slave(parser->current_zone->opts)) | |||
1795 | zc_warning_prev_line("Keys inSvcParam mandatory " | |||
1796 | "MUST NOT appear more than once."); | |||
1797 | else | |||
1798 | zc_error_prev_line("Keys in SvcParam mandatory " | |||
1799 | "MUST NOT appear more than once."); | |||
1800 | } | |||
1801 | prev_key = key; | |||
1802 | } | |||
1803 | } | |||
1804 | ||||
1805 | void | |||
1806 | zadd_rdata_domain(domain_type *domain) | |||
1807 | { | |||
1808 | if (parser->current_rr.rdata_count >= MAXRDATALEN64) { | |||
1809 | zc_error_prev_line("too many rdata elements"); | |||
1810 | } else { | |||
1811 | parser->current_rr.rdatas[parser->current_rr.rdata_count].domain | |||
1812 | = domain; | |||
1813 | domain->usage ++; /* new reference to domain */ | |||
1814 | ++parser->current_rr.rdata_count; | |||
1815 | } | |||
1816 | } | |||
1817 | ||||
1818 | void | |||
1819 | parse_unknown_rdata(uint16_t type, uint16_t *wireformat) | |||
1820 | { | |||
1821 | buffer_type packet; | |||
1822 | uint16_t size; | |||
1823 | ssize_t rdata_count; | |||
1824 | ssize_t i; | |||
1825 | rdata_atom_type *rdatas; | |||
1826 | ||||
1827 | if (wireformat) { | |||
1828 | size = *wireformat; | |||
1829 | } else { | |||
1830 | return; | |||
1831 | } | |||
1832 | ||||
1833 | buffer_create_from(&packet, wireformat + 1, *wireformat); | |||
1834 | rdata_count = rdata_wireformat_to_rdata_atoms(parser->region, | |||
1835 | parser->db->domains, | |||
1836 | type, | |||
1837 | size, | |||
1838 | &packet, | |||
1839 | &rdatas); | |||
1840 | if (rdata_count == -1) { | |||
1841 | zc_error_prev_line("bad unknown RDATA"); | |||
1842 | return; | |||
1843 | } | |||
1844 | ||||
1845 | for (i = 0; i < rdata_count; ++i) { | |||
1846 | if (rdata_atom_is_domain(type, i)) { | |||
1847 | zadd_rdata_domain(rdatas[i].domain); | |||
1848 | } else { | |||
1849 | zadd_rdata_wireformat(rdatas[i].data); | |||
1850 | } | |||
1851 | } | |||
1852 | region_recycle(parser->region, rdatas, | |||
1853 | rdata_count*sizeof(rdata_atom_type)); | |||
1854 | } | |||
1855 | ||||
1856 | ||||
1857 | /* | |||
1858 | * Compares two rdata arrays. | |||
1859 | * | |||
1860 | * Returns: | |||
1861 | * | |||
1862 | * zero if they are equal | |||
1863 | * non-zero if not | |||
1864 | * | |||
1865 | */ | |||
1866 | static int | |||
1867 | zrdatacmp(uint16_t type, rr_type *a, rr_type *b) | |||
1868 | { | |||
1869 | int i = 0; | |||
1870 | ||||
1871 | assert(a)((void)0); | |||
1872 | assert(b)((void)0); | |||
1873 | ||||
1874 | /* One is shorter than another */ | |||
1875 | if (a->rdata_count != b->rdata_count) | |||
1876 | return 1; | |||
1877 | ||||
1878 | /* Compare element by element */ | |||
1879 | for (i = 0; i < a->rdata_count; ++i) { | |||
1880 | if (rdata_atom_is_domain(type, i)) { | |||
1881 | if (rdata_atom_domain(a->rdatas[i]) | |||
1882 | != rdata_atom_domain(b->rdatas[i])) | |||
1883 | { | |||
1884 | return 1; | |||
1885 | } | |||
1886 | } else if(rdata_atom_is_literal_domain(type, i)) { | |||
1887 | if (rdata_atom_size(a->rdatas[i]) | |||
1888 | != rdata_atom_size(b->rdatas[i])) | |||
1889 | return 1; | |||
1890 | if (!dname_equal_nocase(rdata_atom_data(a->rdatas[i]), | |||
1891 | rdata_atom_data(b->rdatas[i]), | |||
1892 | rdata_atom_size(a->rdatas[i]))) | |||
1893 | return 1; | |||
1894 | } else { | |||
1895 | if (rdata_atom_size(a->rdatas[i]) | |||
1896 | != rdata_atom_size(b->rdatas[i])) | |||
1897 | { | |||
1898 | return 1; | |||
1899 | } | |||
1900 | if (memcmp(rdata_atom_data(a->rdatas[i]), | |||
1901 | rdata_atom_data(b->rdatas[i]), | |||
1902 | rdata_atom_size(a->rdatas[i])) != 0) | |||
1903 | { | |||
1904 | return 1; | |||
1905 | } | |||
1906 | } | |||
1907 | } | |||
1908 | ||||
1909 | /* Otherwise they are equal */ | |||
1910 | return 0; | |||
1911 | } | |||
1912 | ||||
1913 | /* | |||
1914 | * | |||
1915 | * Opens a zone file. | |||
1916 | * | |||
1917 | * Returns: | |||
1918 | * | |||
1919 | * - pointer to the parser structure | |||
1920 | * - NULL on error and errno set | |||
1921 | * | |||
1922 | */ | |||
1923 | static int | |||
1924 | zone_open(const char *filename, uint32_t ttl, uint16_t klass, | |||
1925 | const dname_type *origin) | |||
1926 | { | |||
1927 | /* Open the zone file... */ | |||
1928 | if (strcmp(filename, "-") == 0) { | |||
1929 | yyin = stdin(&__sF[0]); | |||
1930 | filename = "<stdin>"; | |||
1931 | warn_if_directory("zonefile from stdin", yyin, filename); | |||
1932 | } else { | |||
1933 | if (!(yyin = fopen(filename, "r"))) { | |||
1934 | return 0; | |||
1935 | } | |||
1936 | warn_if_directory("zonefile", yyin, filename); | |||
1937 | } | |||
1938 | ||||
1939 | zparser_init(filename, ttl, klass, origin); | |||
1940 | ||||
1941 | return 1; | |||
1942 | } | |||
1943 | ||||
1944 | ||||
1945 | void | |||
1946 | set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT256][NSEC_WINDOW_BITS_SIZE(256 / 8)], | |||
1947 | uint16_t index) | |||
1948 | { | |||
1949 | /* | |||
1950 | * The bits are counted from left to right, so bit #0 is the | |||
1951 | * left most bit. | |||
1952 | */ | |||
1953 | uint8_t window = index / 256; | |||
1954 | uint8_t bit = index % 256; | |||
1955 | ||||
1956 | bits[window][bit / 8] |= (1 << (7 - bit % 8)); | |||
1957 | } | |||
1958 | ||||
1959 | ||||
1960 | static int | |||
1961 | has_soa(domain_type* domain) | |||
1962 | { | |||
1963 | rrset_type* p = NULL((void *)0); | |||
1964 | if(!domain) return 0; | |||
1965 | for(p = domain->rrsets; p; p = p->next) | |||
1966 | if(rrset_rrtype(p) == TYPE_SOA6) | |||
1967 | return 1; | |||
1968 | return 0; | |||
1969 | } | |||
1970 | ||||
1971 | int | |||
1972 | process_rr(void) | |||
1973 | { | |||
1974 | zone_type *zone = parser->current_zone; | |||
1975 | rr_type *rr = &parser->current_rr; | |||
1976 | rrset_type *rrset; | |||
1977 | size_t max_rdlength; | |||
1978 | int i; | |||
1979 | rrtype_descriptor_type *descriptor | |||
1980 | = rrtype_descriptor_by_type(rr->type); | |||
1981 | ||||
1982 | /* We only support IN class */ | |||
1983 | if (rr->klass != CLASS_IN1) { | |||
1984 | if(zone_is_slave(zone->opts)) | |||
1985 | zc_warning_prev_line("only class IN is supported"); | |||
1986 | else | |||
1987 | zc_error_prev_line("only class IN is supported"); | |||
1988 | return 0; | |||
1989 | } | |||
1990 | ||||
1991 | /* Make sure the maximum RDLENGTH does not exceed 65535 bytes. */ | |||
1992 | max_rdlength = rdata_maximum_wireformat_size( | |||
1993 | descriptor, rr->rdata_count, rr->rdatas); | |||
1994 | ||||
1995 | if (max_rdlength > MAX_RDLENGTH65535) { | |||
1996 | zc_error_prev_line("maximum rdata length exceeds %d octets", MAX_RDLENGTH65535); | |||
1997 | return 0; | |||
1998 | } | |||
1999 | ||||
2000 | /* We cannot print invalid owner names, | |||
2001 | * so error on that before it is used in printing other errors. | |||
2002 | */ | |||
2003 | if (rr->owner == error_domain | |||
2004 | || domain_dname(rr->owner) == error_dname) { | |||
2005 | zc_error_prev_line("invalid owner name"); | |||
2006 | return 0; | |||
2007 | } | |||
2008 | ||||
2009 | /* we have the zone already */ | |||
2010 | assert(zone)((void)0); | |||
2011 | if (rr->type == TYPE_SOA6) { | |||
2012 | if (rr->owner != zone->apex) { | |||
2013 | char s[MAXDOMAINLEN255*5]; | |||
2014 | snprintf(s, sizeof(s), "%s", domain_to_string(zone->apex)); | |||
2015 | zc_error_prev_line( | |||
2016 | "SOA record with invalid domain name, '%s' is not '%s'", domain_to_string(rr->owner), s); | |||
2017 | return 0; | |||
2018 | } | |||
2019 | if(has_soa(rr->owner)) { | |||
2020 | if(zone_is_slave(zone->opts)) | |||
2021 | zc_warning_prev_line("this SOA record was already encountered"); | |||
2022 | else | |||
2023 | zc_error_prev_line("this SOA record was already encountered"); | |||
2024 | return 0; | |||
2025 | } | |||
2026 | rr->owner->is_apex = 1; | |||
2027 | } | |||
2028 | ||||
2029 | if (!domain_is_subdomain(rr->owner, zone->apex)) | |||
2030 | { | |||
2031 | char s[MAXDOMAINLEN255*5]; | |||
2032 | snprintf(s, sizeof(s), "%s", domain_to_string(zone->apex)); | |||
2033 | if(zone_is_slave(zone->opts)) | |||
2034 | zc_warning_prev_line("out of zone data: %s is outside the zone for fqdn %s", domain_to_string(rr->owner), s); | |||
2035 | else | |||
2036 | zc_error_prev_line("out of zone data: %s is outside the zone for fqdn %s", domain_to_string(rr->owner), s); | |||
2037 | return 0; | |||
2038 | } | |||
2039 | ||||
2040 | /* Do we have this type of rrset already? */ | |||
2041 | rrset = domain_find_rrset(rr->owner, zone, rr->type); | |||
2042 | if (!rrset) { | |||
2043 | rrset = (rrset_type *) region_alloc(parser->region, | |||
2044 | sizeof(rrset_type)); | |||
2045 | rrset->zone = zone; | |||
2046 | rrset->rr_count = 1; | |||
2047 | rrset->rrs = (rr_type *) region_alloc(parser->region, | |||
2048 | sizeof(rr_type)); | |||
2049 | rrset->rrs[0] = *rr; | |||
2050 | ||||
2051 | /* Add it */ | |||
2052 | domain_add_rrset(rr->owner, rrset); | |||
2053 | } else { | |||
2054 | rr_type* o; | |||
2055 | if (rr->type != TYPE_RRSIG46 && rrset->rrs[0].ttl != rr->ttl) { | |||
2056 | zc_warning_prev_line( | |||
2057 | "%s TTL %u does not match the TTL %u of the %s RRset", | |||
2058 | domain_to_string(rr->owner), (unsigned)rr->ttl, | |||
2059 | (unsigned)rrset->rrs[0].ttl, | |||
2060 | rrtype_to_string(rr->type)); | |||
2061 | } | |||
2062 | ||||
2063 | /* Search for possible duplicates... */ | |||
2064 | for (i = 0; i < rrset->rr_count; i++) { | |||
2065 | if (!zrdatacmp(rr->type, rr, &rrset->rrs[i])) { | |||
2066 | break; | |||
2067 | } | |||
2068 | } | |||
2069 | ||||
2070 | /* Discard the duplicates... */ | |||
2071 | if (i < rrset->rr_count) { | |||
2072 | /* add rdatas to recycle bin. */ | |||
2073 | size_t i; | |||
2074 | for (i = 0; i < rr->rdata_count; i++) { | |||
2075 | if(!rdata_atom_is_domain(rr->type, i)) | |||
2076 | region_recycle(parser->region, rr->rdatas[i].data, | |||
2077 | rdata_atom_size(rr->rdatas[i]) | |||
2078 | + sizeof(uint16_t)); | |||
2079 | } | |||
2080 | region_recycle(parser->region, rr->rdatas, | |||
2081 | sizeof(rdata_atom_type)*rr->rdata_count); | |||
2082 | return 0; | |||
2083 | } | |||
2084 | if(rrset->rr_count == 65535) { | |||
2085 | zc_error_prev_line("too many RRs for domain RRset"); | |||
2086 | return 0; | |||
2087 | } | |||
2088 | ||||
2089 | /* Add it... */ | |||
2090 | o = rrset->rrs; | |||
2091 | rrset->rrs = (rr_type *) region_alloc_array(parser->region, | |||
2092 | (rrset->rr_count + 1), sizeof(rr_type)); | |||
2093 | memcpy(rrset->rrs, o, (rrset->rr_count) * sizeof(rr_type)); | |||
2094 | region_recycle(parser->region, o, | |||
2095 | (rrset->rr_count) * sizeof(rr_type)); | |||
2096 | rrset->rrs[rrset->rr_count] = *rr; | |||
2097 | ++rrset->rr_count; | |||
2098 | } | |||
2099 | ||||
2100 | if(rr->type == TYPE_DNAME39 && rrset->rr_count > 1) { | |||
2101 | if(zone_is_slave(zone->opts)) | |||
2102 | zc_warning_prev_line("multiple DNAMEs at the same name"); | |||
2103 | else | |||
2104 | zc_error_prev_line("multiple DNAMEs at the same name"); | |||
2105 | } | |||
2106 | if(rr->type == TYPE_CNAME5 && rrset->rr_count > 1) { | |||
2107 | if(zone_is_slave(zone->opts)) | |||
2108 | zc_warning_prev_line("multiple CNAMEs at the same name"); | |||
2109 | else | |||
2110 | zc_error_prev_line("multiple CNAMEs at the same name"); | |||
2111 | } | |||
2112 | if((rr->type == TYPE_DNAME39 && domain_find_rrset(rr->owner, zone, TYPE_CNAME5)) | |||
2113 | ||(rr->type == TYPE_CNAME5 && domain_find_rrset(rr->owner, zone, TYPE_DNAME39))) { | |||
2114 | if(zone_is_slave(zone->opts)) | |||
2115 | zc_warning_prev_line("DNAME and CNAME at the same name"); | |||
2116 | else | |||
2117 | zc_error_prev_line("DNAME and CNAME at the same name"); | |||
2118 | } | |||
2119 | if(domain_find_rrset(rr->owner, zone, TYPE_CNAME5) && | |||
2120 | domain_find_non_cname_rrset(rr->owner, zone)) { | |||
2121 | if(zone_is_slave(zone->opts)) | |||
2122 | zc_warning_prev_line("CNAME and other data at the same name"); | |||
2123 | else | |||
2124 | zc_error_prev_line("CNAME and other data at the same name"); | |||
2125 | } | |||
2126 | ||||
2127 | /* Check we have SOA */ | |||
2128 | if(rr->owner == zone->apex) | |||
2129 | apex_rrset_checks(parser->db, rrset, rr->owner); | |||
2130 | ||||
2131 | if(parser->line % ZONEC_PCT_COUNT100000 == 0 && time(NULL((void *)0)) > startzonec + ZONEC_PCT_TIME5) { | |||
2132 | struct stat buf; | |||
2133 | startzonec = time(NULL((void *)0)); | |||
2134 | buf.st_size = 0; | |||
2135 | fstat(fileno(yyin)(!__isthreaded ? ((yyin)->_file) : (fileno)(yyin)), &buf); | |||
2136 | if(buf.st_size == 0) buf.st_size = 1; | |||
2137 | VERBOSITY(1, (LOG_INFO, "parse %s %d %%",do { if ((1) <= verbosity) { log_msg (6, "parse %s %d %%", parser->current_zone->opts->name, (int)((uint64_t)ftell (yyin)*(uint64_t)100/(uint64_t)buf.st_size)) ; } } while (0) | |||
2138 | parser->current_zone->opts->name,do { if ((1) <= verbosity) { log_msg (6, "parse %s %d %%", parser->current_zone->opts->name, (int)((uint64_t)ftell (yyin)*(uint64_t)100/(uint64_t)buf.st_size)) ; } } while (0) | |||
2139 | (int)((uint64_t)ftell(yyin)*(uint64_t)100/(uint64_t)buf.st_size)))do { if ((1) <= verbosity) { log_msg (6, "parse %s %d %%", parser->current_zone->opts->name, (int)((uint64_t)ftell (yyin)*(uint64_t)100/(uint64_t)buf.st_size)) ; } } while (0); | |||
2140 | } | |||
2141 | ++totalrrs; | |||
2142 | return 1; | |||
2143 | } | |||
2144 | ||||
2145 | /* | |||
2146 | * Find rrset type for any zone | |||
2147 | */ | |||
2148 | static rrset_type* | |||
2149 | domain_find_rrset_any(domain_type *domain, uint16_t type) | |||
2150 | { | |||
2151 | rrset_type *result = domain->rrsets; | |||
2152 | while (result) { | |||
2153 | if (rrset_rrtype(result) == type) { | |||
2154 | return result; | |||
2155 | } | |||
2156 | result = result->next; | |||
2157 | } | |||
2158 | return NULL((void *)0); | |||
2159 | } | |||
2160 | ||||
2161 | /* | |||
2162 | * Check for DNAME type. Nothing is allowed below it | |||
2163 | */ | |||
2164 | static void | |||
2165 | check_dname(zone_type* zone) | |||
2166 | { | |||
2167 | domain_type* domain; | |||
2168 | for(domain = zone->apex; domain && domain_is_subdomain(domain, | |||
2169 | zone->apex); domain=domain_next(domain)) | |||
2170 | { | |||
2171 | if(domain->is_existing) { | |||
2172 | /* there may not be DNAMEs above it */ | |||
2173 | domain_type* parent = domain->parent; | |||
2174 | #ifdef NSEC3 | |||
2175 | if(domain_has_only_NSEC3(domain, NULL((void *)0))) | |||
2176 | continue; | |||
2177 | #endif | |||
2178 | while(parent) { | |||
2179 | if(domain_find_rrset_any(parent, TYPE_DNAME39)) { | |||
2180 | zc_error("While checking node %s,", | |||
2181 | domain_to_string(domain)); | |||
2182 | zc_error("DNAME at %s has data below it. " | |||
2183 | "This is not allowed (rfc 2672).", | |||
2184 | domain_to_string(parent)); | |||
2185 | return; | |||
2186 | } | |||
2187 | parent = parent->parent; | |||
2188 | } | |||
2189 | } | |||
2190 | } | |||
2191 | } | |||
2192 | ||||
2193 | /* | |||
2194 | * Reads the specified zone into the memory | |||
2195 | * nsd_options can be NULL if no config file is passed. | |||
2196 | */ | |||
2197 | unsigned int | |||
2198 | zonec_read(const char* name, const char* zonefile, zone_type* zone) | |||
2199 | { | |||
2200 | const dname_type *dname; | |||
2201 | ||||
2202 | totalrrs = 0; | |||
2203 | startzonec = time(NULL((void *)0)); | |||
2204 | parser->errors = 0; | |||
2205 | ||||
2206 | dname = dname_parse(parser->rr_region, name); | |||
2207 | if (!dname) { | |||
2208 | zc_error("incorrect zone name '%s'", name); | |||
2209 | return 1; | |||
2210 | } | |||
2211 | ||||
2212 | /* Open the zone file */ | |||
2213 | if (!zone_open(zonefile, 3600, CLASS_IN1, dname)) { | |||
2214 | zc_error("cannot open '%s': %s", zonefile, strerror(errno(*__errno()))); | |||
2215 | return 1; | |||
2216 | } | |||
2217 | parser->current_zone = zone; | |||
2218 | ||||
2219 | /* Parse and process all RRs. */ | |||
2220 | yyparse(); | |||
2221 | ||||
2222 | /* remove origin if it was unused */ | |||
2223 | if(parser->origin != error_domain) | |||
2224 | domain_table_deldomain(parser->db, parser->origin); | |||
2225 | /* rr_region has been emptied by now */ | |||
2226 | dname = dname_parse(parser->rr_region, name); | |||
2227 | ||||
2228 | /* check if zone file contained a correct SOA record */ | |||
2229 | if (!parser->current_zone) { | |||
2230 | zc_error("zone configured as '%s' has no content.", name); | |||
2231 | } else if(!parser->current_zone->soa_rrset || | |||
2232 | parser->current_zone->soa_rrset->rr_count == 0) { | |||
2233 | zc_error("zone configured as '%s' has no SOA record.", name); | |||
2234 | } else if(dname_compare(domain_dname( | |||
2235 | parser->current_zone->soa_rrset->rrs[0].owner), dname) != 0) { | |||
2236 | zc_error("zone configured as '%s', but SOA has owner '%s'.", | |||
2237 | name, domain_to_string( | |||
2238 | parser->current_zone->soa_rrset->rrs[0].owner)); | |||
2239 | } | |||
2240 | region_free_all(parser->rr_region); | |||
2241 | ||||
2242 | parser_flush(); | |||
2243 | fclose(yyin); | |||
2244 | if(!zone_is_slave(zone->opts)) | |||
2245 | check_dname(zone); | |||
2246 | ||||
2247 | parser->filename = NULL((void *)0); | |||
2248 | return parser->errors; | |||
2249 | } | |||
2250 | ||||
2251 | ||||
2252 | /* | |||
2253 | * setup parse | |||
2254 | */ | |||
2255 | void | |||
2256 | zonec_setup_parser(namedb_type* db) | |||
2257 | { | |||
2258 | region_type* rr_region = region_create(xalloc, free); | |||
2259 | parser = zparser_create(db->region, rr_region, db); | |||
2260 | assert(parser)((void)0); | |||
2261 | /* Unique pointers used to mark errors. */ | |||
2262 | error_dname = (dname_type *) region_alloc(db->region, 1); | |||
2263 | error_domain = (domain_type *) region_alloc(db->region, 1); | |||
2264 | /* Open the network database */ | |||
2265 | setprotoent(1); | |||
2266 | setservent(1); | |||
2267 | } | |||
2268 | ||||
2269 | /** desetup parse */ | |||
2270 | void | |||
2271 | zonec_desetup_parser(void) | |||
2272 | { | |||
2273 | if(parser) { | |||
2274 | endservent(); | |||
2275 | endprotoent(); | |||
2276 | region_destroy(parser->rr_region); | |||
2277 | /* removed when parser->region(=db->region) is destroyed: | |||
2278 | * region_recycle(parser->region, (void*)error_dname, 1); | |||
2279 | * region_recycle(parser->region, (void*)error_domain, 1); */ | |||
2280 | /* clear memory for exit, but this is not portable to | |||
2281 | * other versions of lex. yylex_destroy(); */ | |||
2282 | #ifdef MEMCLEAN /* OS collects memory pages */ | |||
2283 | yylex_destroy(); | |||
2284 | #endif | |||
2285 | } | |||
2286 | } | |||
2287 | ||||
2288 | static domain_table_type* orig_domains = NULL((void *)0); | |||
2289 | static region_type* orig_region = NULL((void *)0); | |||
2290 | static region_type* orig_dbregion = NULL((void *)0); | |||
2291 | ||||
2292 | /** setup for string parse */ | |||
2293 | void | |||
2294 | zonec_setup_string_parser(region_type* region, domain_table_type* domains) | |||
2295 | { | |||
2296 | assert(parser)((void)0); /* global parser must be setup */ | |||
2297 | orig_domains = parser->db->domains; | |||
2298 | orig_region = parser->region; | |||
2299 | orig_dbregion = parser->db->region; | |||
2300 | parser->region = region; | |||
2301 | parser->db->region = region; | |||
2302 | parser->db->domains = domains; | |||
2303 | zparser_init("string", 3600, CLASS_IN1, domain_dname(domains->root)); | |||
2304 | } | |||
2305 | ||||
2306 | /** desetup string parse */ | |||
2307 | void | |||
2308 | zonec_desetup_string_parser(void) | |||
2309 | { | |||
2310 | parser->region = orig_region; | |||
2311 | parser->db->domains = orig_domains; | |||
2312 | parser->db->region = orig_dbregion; | |||
2313 | } | |||
2314 | ||||
2315 | /** parse a string into temporary storage */ | |||
2316 | int | |||
2317 | zonec_parse_string(region_type* region, domain_table_type* domains, | |||
2318 | zone_type* zone, char* str, domain_type** parsed, int* num_rrs) | |||
2319 | { | |||
2320 | int errors; | |||
2321 | zonec_setup_string_parser(region, domains); | |||
2322 | parser->current_zone = zone; | |||
2323 | parser->errors = 0; | |||
2324 | totalrrs = 0; | |||
2325 | startzonec = time(NULL((void *)0))+100000; /* disable */ | |||
2326 | parser_push_stringbuf(str); | |||
2327 | yyparse(); | |||
2328 | parser_pop_stringbuf(); | |||
2329 | errors = parser->errors; | |||
2330 | *num_rrs = totalrrs; | |||
2331 | if(*num_rrs == 0) | |||
2332 | *parsed = NULL((void *)0); | |||
2333 | else *parsed = parser->prev_dname; | |||
2334 | /* remove origin if it was not used during the parse */ | |||
2335 | if(parser->origin != error_domain) | |||
2336 | domain_table_deldomain(parser->db, parser->origin); | |||
2337 | region_free_all(parser->rr_region); | |||
2338 | zonec_desetup_string_parser(); | |||
2339 | parser_flush(); | |||
2340 | return errors; | |||
2341 | } | |||
2342 | ||||
2343 | /** check SSHFP type for failures and emit warnings */ | |||
2344 | void check_sshfp(void) | |||
2345 | { | |||
2346 | uint8_t hash; | |||
2347 | uint16_t size; | |||
2348 | if(parser->current_rr.rdata_count < 3) | |||
2349 | return; /* cannot check it, too few rdata elements */ | |||
2350 | if(!parser->current_rr.rdatas[0].data || | |||
2351 | !parser->current_rr.rdatas[1].data || | |||
2352 | !parser->current_rr.rdatas[2].data || | |||
2353 | !parser->current_rr.owner) | |||
2354 | return; /* cannot check, NULLs (due to earlier errors) */ | |||
2355 | if(rdata_atom_size(parser->current_rr.rdatas[1]) != 1) | |||
2356 | return; /* wrong size of the hash type rdata element */ | |||
2357 | hash = rdata_atom_data(parser->current_rr.rdatas[1])[0]; | |||
2358 | size = rdata_atom_size(parser->current_rr.rdatas[2]); | |||
2359 | if(hash == 1 && size != 20) { | |||
2360 | zc_warning_prev_line("SSHFP %s of type SHA1 has hash of " | |||
2361 | "wrong length, %d bytes, should be 20", | |||
2362 | domain_to_string(parser->current_rr.owner), | |||
2363 | (int)size); | |||
2364 | } else if(hash == 2 && size != 32) { | |||
2365 | zc_warning_prev_line("SSHFP %s of type SHA256 has hash of " | |||
2366 | "wrong length, %d bytes, should be 32", | |||
2367 | domain_to_string(parser->current_rr.owner), | |||
2368 | (int)size); | |||
2369 | } | |||
2370 | } | |||
2371 | ||||
2372 | void | |||
2373 | apex_rrset_checks(namedb_type* db, rrset_type* rrset, domain_type* domain) | |||
2374 | { | |||
2375 | uint32_t soa_minimum; | |||
2376 | unsigned i; | |||
2377 | zone_type* zone = rrset->zone; | |||
2378 | assert(domain == zone->apex)((void)0); | |||
2379 | (void)domain; | |||
2380 | if (rrset_rrtype(rrset) == TYPE_SOA6) { | |||
2381 | zone->soa_rrset = rrset; | |||
2382 | ||||
2383 | /* BUG #103 add another soa with a tweaked ttl */ | |||
2384 | if(zone->soa_nx_rrset == 0) { | |||
2385 | zone->soa_nx_rrset = region_alloc(db->region, | |||
2386 | sizeof(rrset_type)); | |||
2387 | zone->soa_nx_rrset->rr_count = 1; | |||
2388 | zone->soa_nx_rrset->next = 0; | |||
2389 | zone->soa_nx_rrset->zone = zone; | |||
2390 | zone->soa_nx_rrset->rrs = region_alloc(db->region, | |||
2391 | sizeof(rr_type)); | |||
2392 | } | |||
2393 | memcpy(zone->soa_nx_rrset->rrs, rrset->rrs, sizeof(rr_type)); | |||
2394 | ||||
2395 | /* check the ttl and MINIMUM value and set accordingly */ | |||
2396 | memcpy(&soa_minimum, rdata_atom_data(rrset->rrs->rdatas[6]), | |||
2397 | rdata_atom_size(rrset->rrs->rdatas[6])); | |||
2398 | if (rrset->rrs->ttl > ntohl(soa_minimum)(__uint32_t)(__builtin_constant_p(soa_minimum) ? (__uint32_t) (((__uint32_t)(soa_minimum) & 0xff) << 24 | ((__uint32_t )(soa_minimum) & 0xff00) << 8 | ((__uint32_t)(soa_minimum ) & 0xff0000) >> 8 | ((__uint32_t)(soa_minimum) & 0xff000000) >> 24) : __swap32md(soa_minimum))) { | |||
2399 | zone->soa_nx_rrset->rrs[0].ttl = ntohl(soa_minimum)(__uint32_t)(__builtin_constant_p(soa_minimum) ? (__uint32_t) (((__uint32_t)(soa_minimum) & 0xff) << 24 | ((__uint32_t )(soa_minimum) & 0xff00) << 8 | ((__uint32_t)(soa_minimum ) & 0xff0000) >> 8 | ((__uint32_t)(soa_minimum) & 0xff000000) >> 24) : __swap32md(soa_minimum)); | |||
2400 | } | |||
2401 | } else if (rrset_rrtype(rrset) == TYPE_NS2) { | |||
2402 | zone->ns_rrset = rrset; | |||
2403 | } else if (rrset_rrtype(rrset) == TYPE_RRSIG46) { | |||
2404 | for (i = 0; i < rrset->rr_count; ++i) { | |||
2405 | if(rr_rrsig_type_covered(&rrset->rrs[i])==TYPE_DNSKEY48){ | |||
2406 | zone->is_secure = 1; | |||
2407 | break; | |||
2408 | } | |||
2409 | } | |||
2410 | } | |||
2411 | } |