Commit | Line | Data |
---|---|---|
825eb42b JL |
1 | /* |
2 | * str2host.c | |
3 | * | |
4 | * conversion routines from the presentation format | |
5 | * to the host format | |
6 | * | |
7 | * a Net::DNS like library for C | |
8 | * | |
9 | * (c) NLnet Labs, 2004-2006 | |
10 | * | |
11 | * See the file LICENSE for the license | |
12 | */ | |
13 | #include <ldns/config.h> | |
14 | ||
15 | #include <ldns/ldns.h> | |
16 | ||
17 | #ifdef HAVE_SYS_SOCKET_H | |
18 | #include <sys/socket.h> | |
19 | #endif | |
20 | #ifdef HAVE_ARPA_INET_H | |
21 | #include <arpa/inet.h> | |
22 | #endif | |
23 | #include <time.h> | |
24 | ||
25 | #include <errno.h> | |
26 | #ifdef HAVE_NETDB_H | |
27 | #include <netdb.h> | |
28 | #endif | |
29 | ||
30 | #include <limits.h> | |
31 | #ifdef HAVE_SYS_PARAM_H | |
32 | #include <sys/param.h> | |
33 | #endif | |
34 | ||
35 | ldns_status | |
36 | ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) | |
37 | { | |
38 | char *end = NULL; | |
39 | uint16_t *r; | |
40 | r = LDNS_MALLOC(uint16_t); | |
41 | ||
42 | *r = htons((uint16_t)strtol((char *)shortstr, &end, 10)); | |
43 | ||
44 | if(*end != 0) { | |
45 | LDNS_FREE(r); | |
46 | return LDNS_STATUS_INVALID_INT; | |
47 | } else { | |
48 | *rd = ldns_rdf_new_frm_data( | |
49 | LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r); | |
50 | LDNS_FREE(r); | |
51 | return LDNS_STATUS_OK; | |
52 | } | |
53 | } | |
54 | ||
55 | ldns_status | |
56 | ldns_str2rdf_time(ldns_rdf **rd, const char *time) | |
57 | { | |
58 | /* convert a time YYYYDDMMHHMMSS to wireformat */ | |
59 | uint16_t *r = NULL; | |
60 | struct tm tm; | |
61 | uint32_t l; | |
62 | char *end; | |
63 | ||
64 | /* Try to scan the time... */ | |
65 | r = (uint16_t*)LDNS_MALLOC(uint32_t); | |
66 | ||
67 | memset(&tm, 0, sizeof(tm)); | |
68 | ||
69 | if (strlen(time) == 14 && | |
70 | sscanf(time, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6 | |
71 | ) { | |
72 | tm.tm_year -= 1900; | |
73 | tm.tm_mon--; | |
74 | /* Check values */ | |
75 | if (tm.tm_year < 70) { | |
76 | goto bad_format; | |
77 | } | |
78 | if (tm.tm_mon < 0 || tm.tm_mon > 11) { | |
79 | goto bad_format; | |
80 | } | |
81 | if (tm.tm_mday < 1 || tm.tm_mday > 31) { | |
82 | goto bad_format; | |
83 | } | |
84 | ||
85 | if (tm.tm_hour < 0 || tm.tm_hour > 23) { | |
86 | goto bad_format; | |
87 | } | |
88 | ||
89 | if (tm.tm_min < 0 || tm.tm_min > 59) { | |
90 | goto bad_format; | |
91 | } | |
92 | ||
93 | if (tm.tm_sec < 0 || tm.tm_sec > 59) { | |
94 | goto bad_format; | |
95 | } | |
96 | ||
97 | l = htonl(mktime_from_utc(&tm)); | |
98 | memcpy(r, &l, sizeof(uint32_t)); | |
99 | *rd = ldns_rdf_new_frm_data( | |
100 | LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); | |
101 | LDNS_FREE(r); | |
102 | return LDNS_STATUS_OK; | |
103 | } else { | |
104 | /* handle it as 32 bits timestamp */ | |
105 | l = htonl((uint32_t)strtol((char*)time, &end, 10)); | |
106 | if(*end != 0) { | |
107 | LDNS_FREE(r); | |
108 | return LDNS_STATUS_ERR; | |
109 | } else { | |
110 | memcpy(r, &l, sizeof(uint32_t)); | |
111 | *rd = ldns_rdf_new_frm_data( | |
112 | LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); | |
113 | LDNS_FREE(r); | |
114 | return LDNS_STATUS_OK; | |
115 | } | |
116 | } | |
117 | ||
118 | bad_format: | |
119 | LDNS_FREE(r); | |
120 | return LDNS_STATUS_INVALID_TIME; | |
121 | } | |
122 | ||
123 | ldns_status | |
124 | ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) | |
125 | { | |
126 | uint8_t salt_length; | |
127 | int c; | |
128 | int salt_length_str; | |
129 | ||
130 | uint8_t *salt; | |
131 | uint8_t *data; | |
132 | ||
133 | salt_length_str = strlen(salt_str); | |
134 | if (salt_length_str == 1 && salt_str[0] == '-') { | |
135 | salt_length_str = 0; | |
136 | } else if (salt_length_str % 2 != 0) { | |
137 | return LDNS_STATUS_INVALID_HEX; | |
138 | } | |
139 | if (salt_length_str > 512) { | |
140 | return LDNS_STATUS_INVALID_HEX; | |
141 | } | |
142 | ||
143 | salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2); | |
144 | for (c = 0; c < salt_length_str; c += 2) { | |
145 | if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { | |
146 | salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + | |
147 | ldns_hexdigit_to_int(salt_str[c+1]); | |
148 | } else { | |
149 | LDNS_FREE(salt); | |
150 | return LDNS_STATUS_INVALID_HEX; | |
151 | } | |
152 | } | |
153 | salt_length = (uint8_t) (salt_length_str / 2); | |
154 | ||
155 | data = LDNS_XMALLOC(uint8_t, 1 + salt_length); | |
156 | data[0] = salt_length; | |
157 | memcpy(&data[1], salt, salt_length); | |
158 | *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data); | |
159 | LDNS_FREE(data); | |
160 | LDNS_FREE(salt); | |
161 | ||
162 | return LDNS_STATUS_OK; | |
163 | } | |
164 | ||
165 | ldns_status | |
166 | ldns_str2rdf_period(ldns_rdf **rd,const char *period) | |
167 | { | |
168 | uint32_t p; | |
169 | const char *end; | |
170 | ||
171 | /* Allocate required space... */ | |
172 | p = ldns_str2period(period, &end); | |
173 | ||
174 | if (*end != 0) { | |
175 | return LDNS_STATUS_ERR; | |
176 | } else { | |
177 | p = (uint32_t) htonl(p); | |
178 | *rd = ldns_rdf_new_frm_data( | |
179 | LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p); | |
180 | } | |
181 | return LDNS_STATUS_OK; | |
182 | } | |
183 | ||
184 | ldns_status | |
185 | ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) | |
186 | { | |
187 | char *end; | |
188 | uint16_t *r = NULL; | |
189 | uint32_t l; | |
190 | ||
191 | r = (uint16_t*)LDNS_MALLOC(uint32_t); | |
192 | errno = 0; /* must set to zero before call, | |
193 | note race condition on errno */ | |
194 | if(*longstr == '-') | |
195 | l = htonl((uint32_t)strtol((char*)longstr, &end, 10)); | |
196 | else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10)); | |
197 | ||
198 | if(*end != 0) { | |
199 | LDNS_FREE(r); | |
200 | return LDNS_STATUS_ERR; | |
201 | } else { | |
202 | if (errno == ERANGE) { | |
203 | LDNS_FREE(r); | |
204 | return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; | |
205 | } | |
206 | memcpy(r, &l, sizeof(uint32_t)); | |
207 | *rd = ldns_rdf_new_frm_data( | |
208 | LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); | |
209 | LDNS_FREE(r); | |
210 | return LDNS_STATUS_OK; | |
211 | } | |
212 | } | |
213 | ||
214 | ldns_status | |
215 | ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) | |
216 | { | |
217 | char *end; | |
218 | uint8_t *r = NULL; | |
219 | ||
220 | r = LDNS_MALLOC(uint8_t); | |
221 | ||
222 | *r = (uint8_t)strtol((char*)bytestr, &end, 10); | |
223 | ||
224 | if(*end != 0) { | |
225 | LDNS_FREE(r); | |
226 | return LDNS_STATUS_ERR; | |
227 | } else { | |
228 | *rd = ldns_rdf_new_frm_data( | |
229 | LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r); | |
230 | LDNS_FREE(r); | |
231 | return LDNS_STATUS_OK; | |
232 | } | |
233 | } | |
234 | ||
235 | ||
236 | /* | |
237 | * Checks whether the escaped value at **s is an octal value or | |
238 | * a 'normally' escaped character (and not eos) | |
239 | * | |
240 | * The string pointer at *s is increased by either 0 (on error), 1 (on | |
241 | * normal escapes), or 3 (on octals) | |
242 | * | |
243 | * Returns the number of bytes read from the escaped string, or | |
244 | * 0 on error | |
245 | */ | |
246 | static int | |
247 | parse_escape(uint8_t *s, uint8_t *q) { | |
248 | uint8_t val; | |
249 | if (strlen((char *)s) > 3 && | |
250 | isdigit((int) s[1]) && | |
251 | isdigit((int) s[2]) && | |
252 | isdigit((int) s[3])) { | |
253 | /* cast this so it fits */ | |
254 | val = (uint8_t) ldns_hexdigit_to_int((char) s[1]) * 100 + | |
255 | ldns_hexdigit_to_int((char) s[2]) * 10 + | |
256 | ldns_hexdigit_to_int((char) s[3]); | |
257 | *q = val; | |
258 | return 3; | |
259 | } else { | |
260 | s++; | |
ac996e71 | 261 | if (*s == '\0' || isdigit((int) *s)) { |
825eb42b | 262 | /* apparently the string terminator |
ac996e71 | 263 | * or a digit has been escaped... |
825eb42b JL |
264 | */ |
265 | return 0; | |
266 | } | |
267 | *q = *s; | |
268 | return 1; | |
269 | } | |
270 | } | |
271 | ||
272 | /* | |
273 | * No special care is taken, all dots are translated into | |
274 | * label seperators. | |
275 | * Could be made more efficient....we do 3 memcpy's in total... | |
276 | */ | |
277 | ldns_status | |
278 | ldns_str2rdf_dname(ldns_rdf **d, const char *str) | |
279 | { | |
280 | size_t len; | |
281 | ||
282 | int esc; | |
ac996e71 | 283 | uint8_t *s, *q, *pq, label_len; |
825eb42b JL |
284 | uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; |
285 | *d = NULL; | |
286 | ||
287 | len = strlen((char*)str); | |
288 | /* octet representation can make strings a lot longer than actual length */ | |
289 | if (len > LDNS_MAX_DOMAINLEN * 4) { | |
290 | return LDNS_STATUS_DOMAINNAME_OVERFLOW; | |
291 | } | |
292 | if (0 == len) { | |
293 | return LDNS_STATUS_DOMAINNAME_UNDERFLOW; | |
294 | } | |
295 | ||
296 | /* root label */ | |
297 | if (1 == len && *str == '.') { | |
298 | *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); | |
299 | return LDNS_STATUS_OK; | |
300 | } | |
301 | ||
302 | /* get on with the rest */ | |
303 | ||
ac996e71 JL |
304 | /* s is on the current character in the string |
305 | * pq points to where the labellength is going to go | |
306 | * label_len keeps track of the current label's length | |
307 | * q builds the dname inside the buf array | |
825eb42b JL |
308 | */ |
309 | len = 0; | |
310 | q = buf+1; | |
311 | pq = buf; | |
312 | label_len = 0; | |
ac996e71 | 313 | for (s = (uint8_t *)str; *s; s++, q++) { |
825eb42b JL |
314 | if (q > buf + LDNS_MAX_DOMAINLEN) { |
315 | return LDNS_STATUS_DOMAINNAME_OVERFLOW; | |
316 | } | |
317 | *q = 0; | |
318 | switch (*s) { | |
319 | case '.': | |
320 | if (label_len > LDNS_MAX_LABELLEN) { | |
321 | return LDNS_STATUS_LABEL_OVERFLOW; | |
322 | } | |
323 | if (label_len == 0) { | |
324 | return LDNS_STATUS_EMPTY_LABEL; | |
325 | } | |
326 | len += label_len + 1; | |
327 | *pq = label_len; | |
328 | label_len = 0; | |
329 | pq = q; | |
825eb42b JL |
330 | break; |
331 | case '\\': | |
332 | /* octet value or literal char */ | |
333 | esc = parse_escape(s, q); | |
334 | if (esc > 0) { | |
335 | s += esc; | |
336 | label_len++; | |
337 | } else { | |
338 | return LDNS_STATUS_SYNTAX_BAD_ESCAPE; | |
339 | } | |
340 | break; | |
341 | default: | |
342 | *q = *s; | |
343 | label_len++; | |
344 | } | |
345 | } | |
346 | ||
347 | /* add root label if last char was not '.' */ | |
348 | if (!ldns_dname_str_absolute(str)) { | |
349 | if (q > buf + LDNS_MAX_DOMAINLEN) { | |
350 | return LDNS_STATUS_DOMAINNAME_OVERFLOW; | |
351 | } | |
ac996e71 JL |
352 | if (label_len > LDNS_MAX_LABELLEN) { |
353 | return LDNS_STATUS_LABEL_OVERFLOW; | |
354 | } | |
355 | if (label_len == 0) { /* label_len 0 but not . at end? */ | |
356 | return LDNS_STATUS_EMPTY_LABEL; | |
357 | } | |
825eb42b JL |
358 | len += label_len + 1; |
359 | *pq = label_len; | |
360 | *q = 0; | |
361 | } | |
362 | len++; | |
363 | ||
364 | *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); | |
365 | return LDNS_STATUS_OK; | |
366 | } | |
367 | ||
368 | ldns_status | |
369 | ldns_str2rdf_a(ldns_rdf **rd, const char *str) | |
370 | { | |
371 | in_addr_t address; | |
372 | if (inet_pton(AF_INET, (char*)str, &address) != 1) { | |
373 | return LDNS_STATUS_INVALID_IP4; | |
374 | } else { | |
375 | *rd = ldns_rdf_new_frm_data( | |
376 | LDNS_RDF_TYPE_A, sizeof(address), &address); | |
377 | } | |
378 | return LDNS_STATUS_OK; | |
379 | } | |
380 | ||
381 | ldns_status | |
382 | ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) | |
383 | { | |
384 | uint8_t address[LDNS_IP6ADDRLEN + 1]; | |
385 | ||
386 | if (inet_pton(AF_INET6, (char*)str, address) != 1) { | |
387 | return LDNS_STATUS_INVALID_IP6; | |
388 | } else { | |
389 | *rd = ldns_rdf_new_frm_data( | |
390 | LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); | |
391 | } | |
392 | return LDNS_STATUS_OK; | |
393 | } | |
394 | ||
395 | ldns_status | |
396 | ldns_str2rdf_str(ldns_rdf **rd, const char *str) | |
397 | { | |
398 | uint8_t *data; | |
ac996e71 | 399 | size_t i, str_i, esc_i; |
825eb42b JL |
400 | |
401 | if (strlen(str) > 255) { | |
402 | return LDNS_STATUS_INVALID_STR; | |
403 | } | |
404 | ||
405 | data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); | |
406 | i = 1; | |
407 | for (str_i = 0; str_i < strlen(str); str_i++) { | |
408 | if (str[str_i] == '\\') { | |
409 | /* octet value or literal char */ | |
ac996e71 JL |
410 | esc_i = (size_t) parse_escape((uint8_t*) &str[str_i], (uint8_t*) &data[i]); |
411 | if (esc_i == 0) { | |
412 | LDNS_FREE(data); | |
413 | return LDNS_STATUS_SYNTAX_BAD_ESCAPE; | |
414 | } | |
415 | str_i += esc_i; | |
825eb42b JL |
416 | } else { |
417 | data[i] = (uint8_t) str[str_i]; | |
418 | } | |
419 | i++; | |
420 | } | |
421 | data[0] = i - 1; | |
422 | *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_STR, i, data); | |
423 | LDNS_FREE(data); | |
424 | return LDNS_STATUS_OK; | |
425 | } | |
426 | ||
427 | ldns_status | |
428 | ldns_str2rdf_apl(ldns_rdf **rd, const char *str) | |
429 | { | |
430 | const char *my_str = str; | |
431 | ||
432 | char *my_ip_str; | |
433 | size_t ip_str_len; | |
434 | ||
435 | uint16_t family; | |
436 | bool negation; | |
437 | uint8_t afdlength = 0; | |
438 | uint8_t *afdpart; | |
439 | uint8_t prefix; | |
440 | ||
441 | uint8_t *data; | |
442 | ||
443 | size_t i = 0; | |
444 | ||
445 | /* [!]afi:address/prefix */ | |
446 | if (strlen(my_str) < 2) { | |
447 | return LDNS_STATUS_INVALID_STR; | |
448 | } | |
449 | ||
450 | if (my_str[0] == '!') { | |
451 | negation = true; | |
452 | my_str += 1; | |
453 | } else { | |
454 | negation = false; | |
455 | } | |
456 | ||
457 | family = (uint16_t) atoi(my_str); | |
458 | ||
459 | my_str = strchr(my_str, ':') + 1; | |
460 | ||
461 | /* need ip addr and only ip addr for inet_pton */ | |
462 | ip_str_len = (size_t) (strchr(my_str, '/') - my_str); | |
463 | my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); | |
464 | strncpy(my_ip_str, my_str, ip_str_len + 1); | |
465 | my_ip_str[ip_str_len] = '\0'; | |
466 | ||
467 | if (family == 1) { | |
468 | /* ipv4 */ | |
469 | afdpart = LDNS_XMALLOC(uint8_t, 4); | |
470 | if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { | |
471 | return LDNS_STATUS_INVALID_STR; | |
472 | } | |
473 | for (i = 0; i < 4; i++) { | |
474 | if (afdpart[i] != 0) { | |
475 | afdlength = i + 1; | |
476 | } | |
477 | } | |
478 | } else if (family == 2) { | |
479 | /* ipv6 */ | |
480 | afdpart = LDNS_XMALLOC(uint8_t, 16); | |
481 | if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { | |
482 | return LDNS_STATUS_INVALID_STR; | |
483 | } | |
484 | for (i = 0; i < 16; i++) { | |
485 | if (afdpart[i] != 0) { | |
486 | afdlength = i + 1; | |
487 | } | |
488 | } | |
489 | } else { | |
490 | /* unknown family */ | |
491 | LDNS_FREE(my_ip_str); | |
492 | return LDNS_STATUS_INVALID_STR; | |
493 | } | |
494 | ||
495 | my_str = strchr(my_str, '/') + 1; | |
496 | prefix = (uint8_t) atoi(my_str); | |
497 | ||
498 | data = LDNS_XMALLOC(uint8_t, 4 + afdlength); | |
499 | ldns_write_uint16(data, family); | |
500 | data[2] = prefix; | |
501 | data[3] = afdlength; | |
502 | if (negation) { | |
503 | /* set bit 1 of byte 3 */ | |
504 | data[3] = data[3] | 0x80; | |
505 | } | |
506 | ||
507 | memcpy(data + 4, afdpart, afdlength); | |
508 | ||
509 | *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); | |
510 | LDNS_FREE(afdpart); | |
511 | LDNS_FREE(data); | |
512 | LDNS_FREE(my_ip_str); | |
513 | ||
514 | return LDNS_STATUS_OK; | |
515 | } | |
516 | ||
517 | ldns_status | |
518 | ldns_str2rdf_b64(ldns_rdf **rd, const char *str) | |
519 | { | |
520 | uint8_t *buffer; | |
521 | int16_t i; | |
522 | ||
523 | buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); | |
524 | ||
525 | i = (uint16_t)ldns_b64_pton((const char*)str, buffer, | |
526 | ldns_b64_ntop_calculate_size(strlen(str))); | |
527 | if (-1 == i) { | |
528 | LDNS_FREE(buffer); | |
529 | return LDNS_STATUS_INVALID_B64; | |
530 | } else { | |
531 | *rd = ldns_rdf_new_frm_data( | |
532 | LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); | |
533 | } | |
534 | LDNS_FREE(buffer); | |
535 | ||
536 | return LDNS_STATUS_OK; | |
537 | } | |
538 | ||
539 | ldns_status | |
540 | ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) | |
541 | { | |
542 | uint8_t *buffer; | |
543 | int i; | |
544 | /* first byte contains length of actual b32 data */ | |
545 | uint8_t len = ldns_b32_pton_calculate_size(strlen(str)); | |
546 | buffer = LDNS_XMALLOC(uint8_t, len + 1); | |
547 | buffer[0] = len; | |
548 | ||
549 | i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1, | |
550 | ldns_b32_ntop_calculate_size(strlen(str))); | |
551 | if (i < 0) { | |
552 | return LDNS_STATUS_INVALID_B32_EXT; | |
553 | } else { | |
554 | *rd = ldns_rdf_new_frm_data( | |
555 | LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); | |
556 | } | |
557 | LDNS_FREE(buffer); | |
558 | ||
559 | return LDNS_STATUS_OK; | |
560 | } | |
561 | ||
562 | ldns_status | |
563 | ldns_str2rdf_hex(ldns_rdf **rd, const char *str) | |
564 | { | |
565 | uint8_t *t, *t_orig; | |
566 | int i; | |
567 | size_t len; | |
568 | ||
569 | len = strlen(str); | |
570 | ||
571 | if (len > LDNS_MAX_RDFLEN * 2) { | |
572 | return LDNS_STATUS_LABEL_OVERFLOW; | |
573 | } else { | |
574 | t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); | |
575 | t_orig = t; | |
576 | /* Now process octet by octet... */ | |
577 | while (*str) { | |
578 | *t = 0; | |
579 | if (isspace((int) *str)) { | |
580 | str++; | |
581 | } else { | |
582 | for (i = 16; i >= 1; i -= 15) { | |
583 | while (*str && isspace((int) *str)) { str++; } | |
584 | if (*str) { | |
585 | if (isxdigit((int) *str)) { | |
586 | *t += ldns_hexdigit_to_int(*str) * i; | |
587 | } else { | |
588 | return LDNS_STATUS_ERR; | |
589 | } | |
590 | ++str; | |
591 | } | |
592 | } | |
593 | ++t; | |
594 | } | |
595 | } | |
596 | *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, | |
597 | (size_t) (t - t_orig), | |
598 | t_orig); | |
599 | LDNS_FREE(t_orig); | |
600 | } | |
601 | return LDNS_STATUS_OK; | |
602 | } | |
603 | ||
604 | ldns_status | |
605 | ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) | |
606 | { | |
607 | const char *delimiters = "\n\t "; | |
608 | char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); | |
609 | ldns_buffer *str_buf; | |
610 | ssize_t c; | |
611 | uint16_t cur_type; | |
612 | size_t type_count = 0; | |
613 | ldns_rr_type type_list[1024]; | |
ac996e71 JL |
614 | if(!token) return LDNS_STATUS_MEM_ERR; |
615 | if(rd == NULL) { | |
616 | LDNS_FREE(token); | |
617 | return LDNS_STATUS_NULL; | |
618 | } | |
825eb42b JL |
619 | |
620 | str_buf = LDNS_MALLOC(ldns_buffer); | |
ac996e71 JL |
621 | if(!str_buf) { |
622 | LDNS_FREE(token); | |
623 | return LDNS_STATUS_MEM_ERR; | |
624 | } | |
825eb42b | 625 | ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); |
ac996e71 JL |
626 | if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { |
627 | LDNS_FREE(str_buf); | |
628 | LDNS_FREE(token); | |
629 | return LDNS_STATUS_MEM_ERR; | |
630 | } | |
825eb42b | 631 | |
ac996e71 | 632 | while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { |
825eb42b JL |
633 | cur_type = ldns_get_rr_type_by_name(token); |
634 | type_list[type_count] = cur_type; | |
635 | type_count++; | |
636 | } | |
637 | ||
638 | *rd = ldns_dnssec_create_nsec_bitmap(type_list, | |
639 | type_count, | |
640 | LDNS_RR_TYPE_NSEC); | |
641 | ||
ac996e71 | 642 | LDNS_FREE(token); |
825eb42b JL |
643 | ldns_buffer_free(str_buf); |
644 | return LDNS_STATUS_OK; | |
645 | } | |
646 | ||
647 | ldns_status | |
648 | ldns_str2rdf_type(ldns_rdf **rd, const char *str) | |
649 | { | |
650 | uint16_t type; | |
651 | type = htons(ldns_get_rr_type_by_name(str)); | |
652 | /* ldns_rr_type is a 16 bit value */ | |
653 | *rd = ldns_rdf_new_frm_data( | |
654 | LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); | |
655 | return LDNS_STATUS_OK; | |
656 | } | |
657 | ||
658 | ldns_status | |
659 | ldns_str2rdf_class(ldns_rdf **rd, const char *str) | |
660 | { | |
661 | uint16_t klass; | |
662 | klass = htons(ldns_get_rr_class_by_name(str)); | |
663 | /* class is 16 bit */ | |
664 | *rd = ldns_rdf_new_frm_data( | |
665 | LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); | |
666 | return LDNS_STATUS_OK; | |
667 | } | |
668 | ||
669 | /* An certificate alg field can either be specified as a 8 bits number | |
670 | * or by its symbolic name. Handle both | |
671 | */ | |
672 | ldns_status | |
673 | ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) | |
674 | { | |
675 | ldns_lookup_table *lt; | |
676 | ldns_status st; | |
677 | uint8_t idd[2]; | |
678 | lt = ldns_lookup_by_name(ldns_cert_algorithms, str); | |
679 | st = LDNS_STATUS_OK; | |
680 | ||
681 | if (lt) { | |
682 | ldns_write_uint16(idd, (uint16_t) lt->id); | |
683 | *rd = ldns_rdf_new_frm_data( | |
684 | LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); | |
685 | if (!*rd) { | |
686 | st = LDNS_STATUS_ERR; | |
687 | } | |
688 | } else { | |
689 | /* try as-is (a number) */ | |
690 | st = ldns_str2rdf_int16(rd, str); | |
691 | if (st == LDNS_STATUS_OK && | |
692 | ldns_rdf2native_int16(*rd) == 0) { | |
693 | st = LDNS_STATUS_CERT_BAD_ALGORITHM; | |
694 | } | |
695 | } | |
696 | ||
697 | return st; | |
698 | } | |
699 | ||
700 | /* An alg field can either be specified as a 8 bits number | |
701 | * or by its symbolic name. Handle both | |
702 | */ | |
703 | ldns_status | |
704 | ldns_str2rdf_alg(ldns_rdf **rd, const char *str) | |
705 | { | |
706 | ldns_lookup_table *lt; | |
707 | ldns_status st; | |
708 | ||
709 | lt = ldns_lookup_by_name(ldns_algorithms, str); | |
710 | st = LDNS_STATUS_OK; | |
711 | ||
712 | if (lt) { | |
713 | /* it was given as a integer */ | |
714 | *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); | |
715 | if (!*rd) { | |
716 | st = LDNS_STATUS_ERR; | |
717 | } | |
718 | } else { | |
719 | /* try as-is (a number) */ | |
720 | st = ldns_str2rdf_int8(rd, str); | |
721 | } | |
722 | return st; | |
723 | } | |
724 | ||
725 | ldns_status | |
726 | ldns_str2rdf_unknown(ldns_rdf **rd, const char *str) | |
727 | { | |
728 | /* this should be caught in an earlier time (general str2host for | |
729 | rr's */ | |
730 | rd = rd; | |
731 | str = str; | |
732 | return LDNS_STATUS_NOT_IMPL; | |
733 | } | |
734 | ||
735 | ldns_status | |
736 | ldns_str2rdf_tsig(ldns_rdf **rd, const char *str) | |
737 | { | |
738 | /* there is no strign representation for TSIG rrs */ | |
739 | rd = rd; | |
740 | str = str; | |
741 | return LDNS_STATUS_NOT_IMPL; | |
742 | } | |
743 | ||
744 | ldns_status | |
745 | ldns_str2rdf_service(ldns_rdf **rd, const char *str) | |
746 | { | |
747 | /* is this used? is this actually WKS? or SRV? */ | |
748 | rd = rd; | |
749 | str = str; | |
750 | return LDNS_STATUS_NOT_IMPL; | |
751 | } | |
752 | ||
753 | static int | |
754 | loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) | |
755 | { | |
756 | /* read <digits>[.<digits>][mM] */ | |
757 | /* into mantissa exponent format for LOC type */ | |
758 | uint32_t meters = 0, cm = 0, val; | |
759 | while (isblank(*my_str)) { | |
760 | my_str++; | |
761 | } | |
762 | meters = (uint32_t)strtol(my_str, &my_str, 10); | |
763 | if (*my_str == '.') { | |
764 | my_str++; | |
765 | cm = (uint32_t)strtol(my_str, &my_str, 10); | |
766 | } | |
767 | if (meters >= 1) { | |
768 | *e = 2; | |
769 | val = meters; | |
770 | } else { | |
771 | *e = 0; | |
772 | val = cm; | |
773 | } | |
774 | while(val >= 10) { | |
775 | (*e)++; | |
776 | val /= 10; | |
777 | } | |
778 | *m = (uint8_t)val; | |
779 | ||
780 | if (*e > 9) | |
781 | return 0; | |
782 | if (*my_str == 'm' || *my_str == 'M') { | |
783 | my_str++; | |
784 | } | |
785 | *endstr = my_str; | |
786 | return 1; | |
787 | } | |
788 | ||
789 | ldns_status | |
790 | ldns_str2rdf_loc(ldns_rdf **rd, const char *str) | |
791 | { | |
792 | uint32_t latitude = 0; | |
793 | uint32_t longitude = 0; | |
794 | uint32_t altitude = 0; | |
795 | ||
796 | uint8_t *data; | |
797 | uint32_t equator = (uint32_t) ldns_power(2, 31); | |
798 | ||
799 | uint32_t h = 0; | |
800 | uint32_t m = 0; | |
801 | uint8_t size_b = 1, size_e = 2; | |
802 | uint8_t horiz_pre_b = 1, horiz_pre_e = 6; | |
803 | uint8_t vert_pre_b = 1, vert_pre_e = 3; | |
804 | ||
805 | double s = 0.0; | |
806 | bool northerness; | |
807 | bool easterness; | |
808 | ||
809 | char *my_str = (char *) str; | |
810 | ||
811 | /* only support version 0 */ | |
812 | if (isdigit((int) *my_str)) { | |
813 | h = (uint32_t) strtol(my_str, &my_str, 10); | |
814 | } else { | |
815 | return LDNS_STATUS_INVALID_STR; | |
816 | } | |
817 | ||
818 | while (isblank((int) *my_str)) { | |
819 | my_str++; | |
820 | } | |
821 | ||
822 | if (isdigit((int) *my_str)) { | |
823 | m = (uint32_t) strtol(my_str, &my_str, 10); | |
824 | } else if (*my_str == 'N' || *my_str == 'S') { | |
825 | goto north; | |
826 | } else { | |
827 | return LDNS_STATUS_INVALID_STR; | |
828 | } | |
829 | ||
830 | while (isblank((int) *my_str)) { | |
831 | my_str++; | |
832 | } | |
833 | ||
834 | if (isdigit((int) *my_str)) { | |
835 | s = strtod(my_str, &my_str); | |
836 | } | |
837 | north: | |
838 | while (isblank((int) *my_str)) { | |
839 | my_str++; | |
840 | } | |
841 | ||
842 | if (*my_str == 'N') { | |
843 | northerness = true; | |
844 | } else if (*my_str == 'S') { | |
845 | northerness = false; | |
846 | } else { | |
847 | return LDNS_STATUS_INVALID_STR; | |
848 | } | |
849 | ||
850 | my_str++; | |
851 | ||
852 | /* store number */ | |
853 | s = 1000.0 * s; | |
854 | /* add a little to make floor in conversion a round */ | |
855 | s += 0.0005; | |
856 | latitude = (uint32_t) s; | |
857 | latitude += 1000 * 60 * m; | |
858 | latitude += 1000 * 60 * 60 * h; | |
859 | if (northerness) { | |
860 | latitude = equator + latitude; | |
861 | } else { | |
862 | latitude = equator - latitude; | |
863 | } | |
864 | while (isblank(*my_str)) { | |
865 | my_str++; | |
866 | } | |
867 | ||
868 | if (isdigit((int) *my_str)) { | |
869 | h = (uint32_t) strtol(my_str, &my_str, 10); | |
870 | } else { | |
871 | return LDNS_STATUS_INVALID_STR; | |
872 | } | |
873 | ||
874 | while (isblank((int) *my_str)) { | |
875 | my_str++; | |
876 | } | |
877 | ||
878 | if (isdigit((int) *my_str)) { | |
879 | m = (uint32_t) strtol(my_str, &my_str, 10); | |
880 | } else if (*my_str == 'E' || *my_str == 'W') { | |
881 | goto east; | |
882 | } else { | |
883 | return LDNS_STATUS_INVALID_STR; | |
884 | } | |
885 | ||
886 | while (isblank(*my_str)) { | |
887 | my_str++; | |
888 | } | |
889 | ||
890 | if (isdigit((int) *my_str)) { | |
891 | s = strtod(my_str, &my_str); | |
892 | } | |
893 | ||
894 | east: | |
895 | while (isblank(*my_str)) { | |
896 | my_str++; | |
897 | } | |
898 | ||
899 | if (*my_str == 'E') { | |
900 | easterness = true; | |
901 | } else if (*my_str == 'W') { | |
902 | easterness = false; | |
903 | } else { | |
904 | return LDNS_STATUS_INVALID_STR; | |
905 | } | |
906 | ||
907 | my_str++; | |
908 | ||
909 | /* store number */ | |
910 | s *= 1000.0; | |
911 | /* add a little to make floor in conversion a round */ | |
912 | s += 0.0005; | |
913 | longitude = (uint32_t) s; | |
914 | longitude += 1000 * 60 * m; | |
915 | longitude += 1000 * 60 * 60 * h; | |
916 | ||
917 | if (easterness) { | |
918 | longitude += equator; | |
919 | } else { | |
920 | longitude = equator - longitude; | |
921 | } | |
922 | ||
923 | altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + | |
924 | 10000000.0 + 0.5); | |
925 | if (*my_str == 'm' || *my_str == 'M') { | |
926 | my_str++; | |
927 | } | |
928 | ||
929 | if (strlen(my_str) > 0) { | |
930 | if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) | |
931 | return LDNS_STATUS_INVALID_STR; | |
932 | } | |
933 | ||
934 | if (strlen(my_str) > 0) { | |
935 | if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) | |
936 | return LDNS_STATUS_INVALID_STR; | |
937 | } | |
938 | ||
939 | if (strlen(my_str) > 0) { | |
940 | if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) | |
941 | return LDNS_STATUS_INVALID_STR; | |
942 | } | |
943 | ||
944 | data = LDNS_XMALLOC(uint8_t, 16); | |
945 | data[0] = 0; | |
946 | data[1] = 0; | |
947 | data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); | |
948 | data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); | |
949 | data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); | |
950 | ldns_write_uint32(data + 4, latitude); | |
951 | ldns_write_uint32(data + 8, longitude); | |
952 | ldns_write_uint32(data + 12, altitude); | |
953 | ||
954 | *rd = ldns_rdf_new_frm_data( | |
955 | LDNS_RDF_TYPE_LOC, 16, data); | |
956 | ||
957 | LDNS_FREE(data); | |
958 | return LDNS_STATUS_OK; | |
959 | } | |
960 | ||
961 | ldns_status | |
962 | ldns_str2rdf_wks(ldns_rdf **rd, const char *str) | |
963 | { | |
964 | uint8_t *bitmap = NULL; | |
965 | uint8_t *data; | |
966 | int bm_len = 0; | |
967 | ||
968 | struct protoent *proto = NULL; | |
969 | struct servent *serv = NULL; | |
970 | int serv_port; | |
971 | ||
972 | ldns_buffer *str_buf; | |
973 | ||
974 | char *proto_str = NULL; | |
ac996e71 JL |
975 | char *token; |
976 | if(strlen(str) == 0) | |
977 | token = LDNS_XMALLOC(char, 50); | |
978 | else token = LDNS_XMALLOC(char, strlen(str)+2); | |
979 | if(!token) return LDNS_STATUS_MEM_ERR; | |
825eb42b JL |
980 | |
981 | str_buf = LDNS_MALLOC(ldns_buffer); | |
ac996e71 | 982 | if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} |
825eb42b | 983 | ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); |
ac996e71 JL |
984 | if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { |
985 | LDNS_FREE(str_buf); | |
986 | LDNS_FREE(token); | |
987 | return LDNS_STATUS_MEM_ERR; | |
988 | } | |
825eb42b JL |
989 | |
990 | while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { | |
991 | if (!proto_str) { | |
992 | proto_str = strdup(token); | |
993 | if (!proto_str) { | |
ac996e71 | 994 | LDNS_FREE(bitmap); |
825eb42b | 995 | LDNS_FREE(token); |
ac996e71 | 996 | ldns_buffer_free(str_buf); |
825eb42b JL |
997 | return LDNS_STATUS_INVALID_STR; |
998 | } | |
999 | } else { | |
1000 | serv = getservbyname(token, proto_str); | |
1001 | if (serv) { | |
1002 | serv_port = (int) ntohs((uint16_t) serv->s_port); | |
1003 | } else { | |
1004 | serv_port = atoi(token); | |
1005 | } | |
1006 | if (serv_port / 8 >= bm_len) { | |
ac996e71 JL |
1007 | uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); |
1008 | if(!b2) { | |
1009 | LDNS_FREE(bitmap); | |
1010 | LDNS_FREE(token); | |
1011 | ldns_buffer_free(str_buf); | |
1012 | free(proto_str); | |
1013 | return LDNS_STATUS_INVALID_STR; | |
1014 | } | |
1015 | bitmap = b2; | |
825eb42b JL |
1016 | /* set to zero to be sure */ |
1017 | for (; bm_len <= serv_port / 8; bm_len++) { | |
1018 | bitmap[bm_len] = 0; | |
1019 | } | |
1020 | } | |
1021 | ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); | |
1022 | } | |
1023 | } | |
1024 | ||
ac996e71 JL |
1025 | if (!proto_str || !bitmap) { |
1026 | LDNS_FREE(bitmap); | |
825eb42b | 1027 | LDNS_FREE(token); |
ac996e71 JL |
1028 | ldns_buffer_free(str_buf); |
1029 | free(proto_str); | |
825eb42b JL |
1030 | return LDNS_STATUS_INVALID_STR; |
1031 | } | |
1032 | ||
1033 | data = LDNS_XMALLOC(uint8_t, bm_len + 1); | |
ac996e71 JL |
1034 | if(!data) { |
1035 | LDNS_FREE(token); | |
1036 | ldns_buffer_free(str_buf); | |
1037 | LDNS_FREE(bitmap); | |
1038 | free(proto_str); | |
1039 | return LDNS_STATUS_INVALID_STR; | |
1040 | } | |
825eb42b JL |
1041 | if (proto_str) |
1042 | proto = getprotobyname(proto_str); | |
1043 | if (proto) { | |
1044 | data[0] = (uint8_t) proto->p_proto; | |
1045 | } else if (proto_str) { | |
1046 | data[0] = (uint8_t) atoi(proto_str); | |
1047 | } else { | |
1048 | data[0] = 0; | |
1049 | } | |
1050 | memcpy(data + 1, bitmap, (size_t) bm_len); | |
1051 | ||
1052 | *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); | |
1053 | ||
1054 | LDNS_FREE(data); | |
1055 | LDNS_FREE(token); | |
1056 | ldns_buffer_free(str_buf); | |
1057 | LDNS_FREE(bitmap); | |
1058 | free(proto_str); | |
1059 | #ifdef HAVE_ENDSERVENT | |
1060 | endservent(); | |
1061 | #endif | |
1062 | #ifdef HAVE_ENDPROTOENT | |
1063 | endprotoent(); | |
1064 | #endif | |
1065 | ||
ac996e71 JL |
1066 | if(!*rd) return LDNS_STATUS_MEM_ERR; |
1067 | ||
825eb42b JL |
1068 | return LDNS_STATUS_OK; |
1069 | } | |
1070 | ||
1071 | ldns_status | |
1072 | ldns_str2rdf_nsap(ldns_rdf **rd, const char *str) | |
1073 | { | |
1074 | size_t len, i; | |
1075 | char* nsap_str = (char*) str; | |
1076 | ||
1077 | /* just a hex string with optional dots? */ | |
1078 | if (str[0] != '0' || str[1] != 'x') { | |
1079 | return LDNS_STATUS_INVALID_STR; | |
1080 | } else { | |
1081 | len = strlen(str); | |
1082 | for (i=0; i < len; i++) { | |
1083 | if (nsap_str[i] == '.') | |
1084 | nsap_str[i] = ' '; | |
1085 | } | |
1086 | return ldns_str2rdf_hex(rd, str+2); | |
1087 | } | |
1088 | } | |
1089 | ||
1090 | ldns_status | |
1091 | ldns_str2rdf_atma(ldns_rdf **rd, const char *str) | |
1092 | { | |
1093 | size_t len, i; | |
1094 | char* atma_str = (char*) str; | |
1095 | ldns_status status; | |
1096 | ||
1097 | /* just a hex string with optional dots? */ | |
1098 | len = strlen(str); | |
1099 | for (i=0; i < len; i++) { | |
1100 | if (atma_str[i] == '.') | |
1101 | atma_str[i] = ' '; | |
1102 | } | |
1103 | status = ldns_str2rdf_hex(rd, str); | |
1104 | if (status != LDNS_STATUS_OK) { | |
1105 | ; /* probably in e.164 format than */ | |
1106 | } | |
1107 | return status; | |
1108 | } | |
1109 | ||
1110 | ldns_status | |
1111 | ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) | |
1112 | { | |
1113 | uint8_t precedence = 0; | |
1114 | uint8_t gateway_type = 0; | |
1115 | uint8_t algorithm = 0; | |
1116 | char* gateway = NULL; | |
1117 | char* publickey = NULL; | |
1118 | uint8_t *data; | |
1119 | ldns_buffer *str_buf; | |
ac996e71 | 1120 | char *token; |
825eb42b JL |
1121 | int token_count = 0; |
1122 | int ipseckey_len = 0; | |
1123 | ldns_rdf* gateway_rdf = NULL; | |
1124 | ldns_rdf* publickey_rdf = NULL; | |
1125 | ldns_status status = LDNS_STATUS_OK; | |
ac996e71 JL |
1126 | |
1127 | if(strlen(str) == 0) | |
1128 | token = LDNS_XMALLOC(char, 256); | |
1129 | else token = LDNS_XMALLOC(char, strlen(str)+2); | |
1130 | if(!token) return LDNS_STATUS_MEM_ERR; | |
825eb42b JL |
1131 | |
1132 | str_buf = LDNS_MALLOC(ldns_buffer); | |
ac996e71 | 1133 | if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} |
825eb42b | 1134 | ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); |
ac996e71 JL |
1135 | if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { |
1136 | LDNS_FREE(str_buf); | |
1137 | LDNS_FREE(token); | |
1138 | return LDNS_STATUS_MEM_ERR; | |
1139 | } | |
825eb42b JL |
1140 | while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { |
1141 | switch (token_count) { | |
1142 | case 0: | |
1143 | precedence = atoi(token); | |
1144 | break; | |
1145 | case 1: | |
1146 | gateway_type = atoi(token); | |
1147 | break; | |
1148 | case 2: | |
1149 | algorithm = atoi(token); | |
1150 | break; | |
1151 | case 3: | |
1152 | gateway = strdup(token); | |
1153 | if (!gateway || (gateway_type == 0 && | |
1154 | (token[0] != '.' || token[1] != '\0'))) { | |
1155 | LDNS_FREE(gateway); | |
1156 | LDNS_FREE(token); | |
ac996e71 | 1157 | ldns_buffer_free(str_buf); |
825eb42b JL |
1158 | return LDNS_STATUS_INVALID_STR; |
1159 | } | |
1160 | break; | |
1161 | case 4: | |
1162 | publickey = strdup(token); | |
1163 | break; | |
1164 | default: | |
1165 | LDNS_FREE(token); | |
ac996e71 | 1166 | ldns_buffer_free(str_buf); |
825eb42b JL |
1167 | return LDNS_STATUS_INVALID_STR; |
1168 | break; | |
1169 | } | |
1170 | token_count++; | |
1171 | } | |
1172 | ||
1173 | if (!gateway || !publickey) { | |
1174 | if (gateway) | |
1175 | LDNS_FREE(gateway); | |
1176 | if (publickey) | |
1177 | LDNS_FREE(publickey); | |
1178 | LDNS_FREE(token); | |
ac996e71 | 1179 | ldns_buffer_free(str_buf); |
825eb42b JL |
1180 | return LDNS_STATUS_INVALID_STR; |
1181 | } | |
1182 | ||
1183 | if (gateway_type == 1) { | |
1184 | status = ldns_str2rdf_a(&gateway_rdf, gateway); | |
1185 | } else if (gateway_type == 2) { | |
1186 | status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); | |
1187 | } else if (gateway_type == 3) { | |
1188 | status = ldns_str2rdf_dname(&gateway_rdf, gateway); | |
1189 | } | |
1190 | ||
1191 | if (status != LDNS_STATUS_OK) { | |
1192 | if (gateway) | |
1193 | LDNS_FREE(gateway); | |
1194 | if (publickey) | |
1195 | LDNS_FREE(publickey); | |
1196 | LDNS_FREE(token); | |
ac996e71 | 1197 | ldns_buffer_free(str_buf); |
825eb42b JL |
1198 | return LDNS_STATUS_INVALID_STR; |
1199 | } | |
1200 | ||
1201 | status = ldns_str2rdf_b64(&publickey_rdf, publickey); | |
1202 | ||
1203 | if (status != LDNS_STATUS_OK) { | |
1204 | if (gateway) | |
1205 | LDNS_FREE(gateway); | |
1206 | if (publickey) | |
1207 | LDNS_FREE(publickey); | |
1208 | LDNS_FREE(token); | |
ac996e71 JL |
1209 | ldns_buffer_free(str_buf); |
1210 | if (gateway_rdf) ldns_rdf_free(gateway_rdf); | |
825eb42b JL |
1211 | return LDNS_STATUS_INVALID_STR; |
1212 | } | |
1213 | ||
1214 | /* now copy all into one ipseckey rdf */ | |
1215 | if (gateway_type) | |
1216 | ipseckey_len = 3 + ldns_rdf_size(gateway_rdf) + ldns_rdf_size(publickey_rdf); | |
1217 | else | |
1218 | ipseckey_len = 3 + ldns_rdf_size(publickey_rdf); | |
1219 | ||
1220 | data = LDNS_XMALLOC(uint8_t, ipseckey_len); | |
ac996e71 JL |
1221 | if(!data) { |
1222 | if (gateway) | |
1223 | LDNS_FREE(gateway); | |
1224 | if (publickey) | |
1225 | LDNS_FREE(publickey); | |
1226 | LDNS_FREE(token); | |
1227 | ldns_buffer_free(str_buf); | |
1228 | if (gateway_rdf) ldns_rdf_free(gateway_rdf); | |
1229 | if (publickey_rdf) ldns_rdf_free(publickey_rdf); | |
1230 | return LDNS_STATUS_MEM_ERR; | |
1231 | } | |
825eb42b JL |
1232 | |
1233 | data[0] = precedence; | |
1234 | data[1] = gateway_type; | |
1235 | data[2] = algorithm; | |
1236 | ||
1237 | if (gateway_type) { | |
1238 | memcpy(data + 3, | |
1239 | ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); | |
1240 | memcpy(data + 3 + ldns_rdf_size(gateway_rdf), | |
1241 | ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); | |
1242 | } else { | |
1243 | memcpy(data + 3, | |
1244 | ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); | |
1245 | } | |
1246 | ||
1247 | *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); | |
1248 | ||
1249 | if (gateway) | |
1250 | LDNS_FREE(gateway); | |
1251 | if (publickey) | |
1252 | LDNS_FREE(publickey); | |
1253 | LDNS_FREE(token); | |
1254 | ldns_buffer_free(str_buf); | |
1255 | ldns_rdf_free(gateway_rdf); | |
1256 | ldns_rdf_free(publickey_rdf); | |
1257 | LDNS_FREE(data); | |
ac996e71 | 1258 | if(!*rd) return LDNS_STATUS_MEM_ERR; |
825eb42b JL |
1259 | return LDNS_STATUS_OK; |
1260 | } |