str2host.c
Go to the documentation of this file.
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 
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  if(!r) return LDNS_STATUS_MEM_ERR;
42 
43  *r = htons((uint16_t)strtol((char *)shortstr, &end, 10));
44 
45  if(*end != 0) {
46  LDNS_FREE(r);
48  } else {
50  LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r);
51  LDNS_FREE(r);
53  }
54 }
55 
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);
67  if(!r) return LDNS_STATUS_MEM_ERR;
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 
99  l = htonl(ldns_mktime_from_utc(&tm));
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);
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);
117  }
118  }
119 
120  bad_format:
121  LDNS_FREE(r);
123 }
124 
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;
134  if(rd == NULL) {
135  return LDNS_STATUS_NULL;
136  }
137 
138  salt_length_str = (int)strlen(salt_str);
139  if (salt_length_str == 1 && salt_str[0] == '-') {
140  salt_length_str = 0;
141  } else if (salt_length_str % 2 != 0) {
143  }
144  if (salt_length_str > 512) {
146  }
147 
148  salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2);
149  if(!salt) {
150  return LDNS_STATUS_MEM_ERR;
151  }
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);
159  }
160  }
161  salt_length = (uint8_t) (salt_length_str / 2);
162 
163  data = LDNS_XMALLOC(uint8_t, 1 + salt_length);
164  if(!data) {
165  LDNS_FREE(salt);
166  return LDNS_STATUS_MEM_ERR;
167  }
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 
175 }
176 
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  }
194 }
195 
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);
204  if(!r) return LDNS_STATUS_MEM_ERR;
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);
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);
224  }
225 }
226 
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);
234  if(!r) return LDNS_STATUS_MEM_ERR;
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);
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) {
262  uint16_t val;
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 */
268  val = (uint16_t) ldns_hexdigit_to_int((char) s[1]) * 100 +
269  ldns_hexdigit_to_int((char) s[2]) * 10 +
270  ldns_hexdigit_to_int((char) s[3]);
271  if (val > 255) {
272  /* outside range */
273  return 0;
274  }
275  *q = (uint8_t) val;
276  return 3;
277  } else {
278  s++;
279  if (*s == '\0' || isdigit((int) *s)) {
280  /* apparently the string terminator
281  * or a digit has been escaped...
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  */
296 ldns_str2rdf_dname(ldns_rdf **d, const char *str)
297 {
298  size_t len;
299 
300  int esc;
301  uint8_t *s, *q, *pq, label_len;
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) {
309  }
310  if (0 == len) {
312  }
313 
314  /* root label */
315  if (1 == len && *str == '.') {
317  return LDNS_STATUS_OK;
318  }
319 
320  /* get on with the rest */
321 
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
326  */
327  len = 0;
328  q = buf+1;
329  pq = buf;
330  label_len = 0;
331  for (s = (uint8_t *)str; *s; s++, q++) {
332  if (q > buf + LDNS_MAX_DOMAINLEN) {
334  }
335  *q = 0;
336  switch (*s) {
337  case '.':
338  if (label_len > LDNS_MAX_LABELLEN) {
340  }
341  if (label_len == 0) {
343  }
344  len += label_len + 1;
345  *pq = label_len;
346  label_len = 0;
347  pq = q;
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 {
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) {
369  }
370  if (label_len > LDNS_MAX_LABELLEN) {
372  }
373  if (label_len == 0) { /* label_len 0 but not . at end? */
375  }
376  len += label_len + 1;
377  *pq = label_len;
378  *q = 0;
379  }
380  len++;
381 
383  return LDNS_STATUS_OK;
384 }
385 
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) {
392  } else {
393  *rd = ldns_rdf_new_frm_data(
394  LDNS_RDF_TYPE_A, sizeof(address), &address);
395  }
397 }
398 
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) {
406  } else {
407  *rd = ldns_rdf_new_frm_data(
408  LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address);
409  }
411 }
412 
414 ldns_str2rdf_str(ldns_rdf **rd, const char *str)
415 {
416  uint8_t *data;
417  size_t i, str_i, esc_i;
418 
419  if (strlen(str) > 255) {
421  }
422 
423  data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
424  if(!data) return LDNS_STATUS_MEM_ERR;
425  i = 1;
426 
427  for (str_i = 0; str_i < strlen(str); str_i++) {
428  if (str[str_i] == '\\') {
429  /* octet value or literal char */
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);
434  }
435  str_i += esc_i;
436  } else {
437  data[i] = (uint8_t) str[str_i];
438  }
439  i++;
440  }
441  data[0] = i - 1;
443 
444  LDNS_FREE(data);
446 }
447 
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 */
467  if (strlen(my_str) < 2
468  || strchr(my_str, ':') == NULL
469  || strchr(my_str, '/') == NULL
470  || strchr(my_str, ':') > strchr(my_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);
488  if(!my_ip_str) return LDNS_STATUS_MEM_ERR;
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);
495  if(!afdpart) {
496  LDNS_FREE(my_ip_str);
497  return LDNS_STATUS_MEM_ERR;
498  }
499  if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
500  LDNS_FREE(my_ip_str);
501  LDNS_FREE(afdpart);
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);
512  if(!afdpart) {
513  LDNS_FREE(my_ip_str);
514  return LDNS_STATUS_MEM_ERR;
515  }
516  if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
517  LDNS_FREE(my_ip_str);
518  LDNS_FREE(afdpart);
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);
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);
536  if(!data) {
537  LDNS_FREE(afdpart);
538  LDNS_FREE(my_ip_str);
540  }
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 
557 }
558 
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)));
566  if(!buffer) {
567  return LDNS_STATUS_MEM_ERR;
568  }
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);
575  } else {
576  *rd = ldns_rdf_new_frm_data(
577  LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
578  }
579  LDNS_FREE(buffer);
580 
582 }
583 
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);
592  if(!buffer) {
593  return LDNS_STATUS_MEM_ERR;
594  }
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) {
600  LDNS_FREE(buffer);
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 
609 }
610 
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) {
622  } else {
623  t = LDNS_XMALLOC(uint8_t, (len / 2) + 1);
624  if(!t) {
625  return LDNS_STATUS_MEM_ERR;
626  }
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 {
640  LDNS_FREE(t_orig);
641  return LDNS_STATUS_ERR;
642  }
643  ++str;
644  }
645  }
646  ++t;
647  }
648  }
650  (size_t) (t - t_orig),
651  t_orig);
652  LDNS_FREE(t_orig);
653  }
655 }
656 
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;
666  ldns_rr_type type_list[65536];
667  if(!token) return LDNS_STATUS_MEM_ERR;
668  if(rd == NULL) {
669  LDNS_FREE(token);
670  return LDNS_STATUS_NULL;
671  }
672 
673  str_buf = LDNS_MALLOC(ldns_buffer);
674  if(!str_buf) {
675  LDNS_FREE(token);
676  return LDNS_STATUS_MEM_ERR;
677  }
678  ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
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  }
684 
685  while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) {
686  if(type_count >= sizeof(type_list)) {
687  LDNS_FREE(str_buf);
688  LDNS_FREE(token);
689  return LDNS_STATUS_ERR;
690  }
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,
699 
700  LDNS_FREE(token);
701  ldns_buffer_free(str_buf);
703 }
704 
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);
714 }
715 
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);
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  */
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];
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) {
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  */
762 ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
763 {
764  ldns_lookup_table *lt;
765  ldns_status st;
766 
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 
785  , ATTR_UNUSED(const char *str)
786  )
787 {
788  /* this should be caught in an earlier time (general str2host for
789  rr's */
790  return LDNS_STATUS_NOT_IMPL;
791 }
792 
795  , ATTR_UNUSED(const char *str)
796  )
797 {
798  /* there is no string representation for TSIG rrs */
799  return LDNS_STATUS_NOT_IMPL;
800 }
801 
804  , ATTR_UNUSED(const char *str)
805  )
806 {
807  /* is this used? is this actually WKS? or SRV? */
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 
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 {
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 {
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 {
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 {
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 {
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 {
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))
990  }
991 
992  if (strlen(my_str) > 0) {
993  if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
995  }
996 
997  if (strlen(my_str) > 0) {
998  if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
1000  }
1001 
1002  data = LDNS_XMALLOC(uint8_t, 16);
1003  if(!data) {
1004  return LDNS_STATUS_MEM_ERR;
1005  }
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);
1020 }
1021 
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;
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;
1041 
1042  str_buf = LDNS_MALLOC(ldns_buffer);
1043  if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1044  ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
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  }
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) {
1055  LDNS_FREE(bitmap);
1056  LDNS_FREE(token);
1057  ldns_buffer_free(str_buf);
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) {
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;
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 
1086  if (!proto_str || !bitmap) {
1087  LDNS_FREE(bitmap);
1088  LDNS_FREE(token);
1089  ldns_buffer_free(str_buf);
1090  free(proto_str);
1091  return LDNS_STATUS_INVALID_STR;
1092  }
1093 
1094  data = LDNS_XMALLOC(uint8_t, bm_len + 1);
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  }
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);
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 
1125  if(!*rd) return LDNS_STATUS_MEM_ERR;
1126 
1127  return LDNS_STATUS_OK;
1128 }
1129 
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 
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 
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;
1179  char *token;
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;
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;
1190 
1191  str_buf = LDNS_MALLOC(ldns_buffer);
1192  if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1193  ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
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  }
1199  while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
1200  switch (token_count) {
1201  case 0:
1202  precedence = (uint8_t)atoi(token);
1203  break;
1204  case 1:
1205  gateway_type = (uint8_t)atoi(token);
1206  break;
1207  case 2:
1208  algorithm = (uint8_t)atoi(token);
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);
1216  ldns_buffer_free(str_buf);
1217  return LDNS_STATUS_INVALID_STR;
1218  }
1219  break;
1220  case 4:
1221  publickey = strdup(token);
1222  break;
1223  default:
1224  LDNS_FREE(token);
1225  ldns_buffer_free(str_buf);
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);
1238  ldns_buffer_free(str_buf);
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);
1256  ldns_buffer_free(str_buf);
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);
1268  ldns_buffer_free(str_buf);
1269  if (gateway_rdf) ldns_rdf_free(gateway_rdf);
1270  return LDNS_STATUS_INVALID_STR;
1271  }
1272 
1273  /* now copy all into one ipseckey rdf */
1274  if (gateway_type)
1275  ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf);
1276  else
1277  ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf);
1278 
1279  data = LDNS_XMALLOC(uint8_t, ipseckey_len);
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  }
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);
1317  if(!*rd) return LDNS_STATUS_MEM_ERR;
1318  return LDNS_STATUS_OK;
1319 }