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