rdata.c
Go to the documentation of this file.
1 /*
2  * rdata.c
3  *
4  * rdata implementation
5  *
6  * a Net::DNS like library for C
7  *
8  * (c) NLnet Labs, 2004-2006
9  *
10  * See the file LICENSE for the license
11  */
12 
13 #include <ldns/config.h>
14 
15 #include <ldns/ldns.h>
16 
17 /*
18  * Access functions
19  * do this as functions to get type checking
20  */
21 
22 /* read */
23 size_t
25 {
26  assert(rd != NULL);
27  return rd->_size;
28 }
29 
32 {
33  assert(rd != NULL);
34  return rd->_type;
35 }
36 
37 uint8_t *
39 {
40  assert(rd != NULL);
41  return rd->_data;
42 }
43 
44 /* write */
45 void
46 ldns_rdf_set_size(ldns_rdf *rd, size_t size)
47 {
48  assert(rd != NULL);
49  rd->_size = size;
50 }
51 
52 void
54 {
55  assert(rd != NULL);
56  rd->_type = type;
57 }
58 
59 void
60 ldns_rdf_set_data(ldns_rdf *rd, void *data)
61 {
62  /* only copy the pointer */
63  assert(rd != NULL);
64  rd->_data = data;
65 }
66 
67 /* for types that allow it, return
68  * the native/host order type */
69 uint8_t
71 {
72  uint8_t data;
73 
74  /* only allow 8 bit rdfs */
75  if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
76  return 0;
77  }
78 
79  memcpy(&data, ldns_rdf_data(rd), sizeof(data));
80  return data;
81 }
82 
83 uint16_t
85 {
86  uint16_t data;
87 
88  /* only allow 16 bit rdfs */
89  if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
90  return 0;
91  }
92 
93  memcpy(&data, ldns_rdf_data(rd), sizeof(data));
94  return ntohs(data);
95 }
96 
97 uint32_t
99 {
100  uint32_t data;
101 
102  /* only allow 32 bit rdfs */
104  return 0;
105  }
106 
107  memcpy(&data, ldns_rdf_data(rd), sizeof(data));
108  return ntohl(data);
109 }
110 
111 time_t
113 {
114  uint32_t data;
115 
116  switch(ldns_rdf_get_type(rd)) {
117  case LDNS_RDF_TYPE_TIME:
118  memcpy(&data, ldns_rdf_data(rd), sizeof(data));
119  return (time_t)ntohl(data);
120  default:
121  return 0;
122  }
123 }
124 
125 ldns_rdf *
127 {
128  return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
129 }
130 
131 ldns_rdf *
133 {
134  uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
135  ldns_rdf* rdf;
136  if (!rdf_data) {
137  return NULL;
138  }
139  ldns_write_uint16(rdf_data, value);
140  rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
141  if(!rdf)
142  LDNS_FREE(rdf_data);
143  return rdf;
144 }
145 
146 ldns_rdf *
148 {
149  uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
150  ldns_rdf* rdf;
151  if (!rdf_data) {
152  return NULL;
153  }
154  ldns_write_uint32(rdf_data, value);
155  rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
156  if(!rdf)
157  LDNS_FREE(rdf_data);
158  return rdf;
159 }
160 
161 ldns_rdf *
162 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
163 {
164  uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
165  ldns_rdf* rdf;
166  if (!rdf_data) {
167  return NULL;
168  }
169  ldns_write_uint16(rdf_data, size);
170  memcpy(rdf_data + 2, data, size);
171  rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
172  if(!rdf)
173  LDNS_FREE(rdf_data);
174  return rdf;
175 }
176 
177 /* note: data must be allocated memory */
178 ldns_rdf *
179 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
180 {
181  ldns_rdf *rd;
182  rd = LDNS_MALLOC(ldns_rdf);
183  if (!rd) {
184  return NULL;
185  }
186  ldns_rdf_set_size(rd, size);
187  ldns_rdf_set_type(rd, type);
188  ldns_rdf_set_data(rd, data);
189  return rd;
190 }
191 
192 ldns_rdf *
193 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
194 {
195  ldns_rdf *rdf;
196 
197  /* if the size is too big, fail */
198  if (size > LDNS_MAX_RDFLEN) {
199  return NULL;
200  }
201 
202  /* allocate space */
203  rdf = LDNS_MALLOC(ldns_rdf);
204  if (!rdf) {
205  return NULL;
206  }
207  rdf->_data = LDNS_XMALLOC(uint8_t, size);
208  if (!rdf->_data) {
209  LDNS_FREE(rdf);
210  return NULL;
211  }
212 
213  /* set the values */
214  ldns_rdf_set_type(rdf, type);
215  ldns_rdf_set_size(rdf, size);
216  memcpy(rdf->_data, data, size);
217 
218  return rdf;
219 }
220 
221 ldns_rdf *
223 {
224  assert(rd != NULL);
226  ldns_rdf_size(rd), ldns_rdf_data(rd)));
227 }
228 
229 void
231 {
232  if (rd) {
233  if (rd->_data) {
234  LDNS_FREE(rd->_data);
235  }
236  LDNS_FREE(rd);
237  }
238 }
239 
240 void
242 {
243  if (rd) {
244  LDNS_FREE(rd);
245  }
246 }
247 
248 ldns_rdf *
249 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
250 {
251  ldns_rdf *rdf = NULL;
252  ldns_status status;
253 
254  switch (type) {
255  case LDNS_RDF_TYPE_DNAME:
256  status = ldns_str2rdf_dname(&rdf, str);
257  break;
258  case LDNS_RDF_TYPE_INT8:
259  status = ldns_str2rdf_int8(&rdf, str);
260  break;
261  case LDNS_RDF_TYPE_INT16:
262  status = ldns_str2rdf_int16(&rdf, str);
263  break;
264  case LDNS_RDF_TYPE_INT32:
265  status = ldns_str2rdf_int32(&rdf, str);
266  break;
267  case LDNS_RDF_TYPE_A:
268  status = ldns_str2rdf_a(&rdf, str);
269  break;
270  case LDNS_RDF_TYPE_AAAA:
271  status = ldns_str2rdf_aaaa(&rdf, str);
272  break;
273  case LDNS_RDF_TYPE_STR:
274  status = ldns_str2rdf_str(&rdf, str);
275  break;
276  case LDNS_RDF_TYPE_APL:
277  status = ldns_str2rdf_apl(&rdf, str);
278  break;
279  case LDNS_RDF_TYPE_B64:
280  status = ldns_str2rdf_b64(&rdf, str);
281  break;
283  status = ldns_str2rdf_b32_ext(&rdf, str);
284  break;
285  case LDNS_RDF_TYPE_HEX:
286  status = ldns_str2rdf_hex(&rdf, str);
287  break;
288  case LDNS_RDF_TYPE_NSEC:
289  status = ldns_str2rdf_nsec(&rdf, str);
290  break;
291  case LDNS_RDF_TYPE_TYPE:
292  status = ldns_str2rdf_type(&rdf, str);
293  break;
294  case LDNS_RDF_TYPE_CLASS:
295  status = ldns_str2rdf_class(&rdf, str);
296  break;
298  status = ldns_str2rdf_cert_alg(&rdf, str);
299  break;
300  case LDNS_RDF_TYPE_ALG:
301  status = ldns_str2rdf_alg(&rdf, str);
302  break;
304  status = ldns_str2rdf_unknown(&rdf, str);
305  break;
306  case LDNS_RDF_TYPE_TIME:
307  status = ldns_str2rdf_time(&rdf, str);
308  break;
310  status = ldns_str2rdf_period(&rdf, str);
311  break;
312  case LDNS_RDF_TYPE_TSIG:
313  status = ldns_str2rdf_tsig(&rdf, str);
314  break;
316  status = ldns_str2rdf_service(&rdf, str);
317  break;
318  case LDNS_RDF_TYPE_LOC:
319  status = ldns_str2rdf_loc(&rdf, str);
320  break;
321  case LDNS_RDF_TYPE_WKS:
322  status = ldns_str2rdf_wks(&rdf, str);
323  break;
324  case LDNS_RDF_TYPE_NSAP:
325  status = ldns_str2rdf_nsap(&rdf, str);
326  break;
327  case LDNS_RDF_TYPE_ATMA:
328  status = ldns_str2rdf_atma(&rdf, str);
329  break;
331  status = ldns_str2rdf_ipseckey(&rdf, str);
332  break;
334  status = ldns_str2rdf_nsec3_salt(&rdf, str);
335  break;
337  status = ldns_str2rdf_b32_ext(&rdf, str);
338  break;
339  case LDNS_RDF_TYPE_NONE:
340  default:
341  /* default default ??? */
342  status = LDNS_STATUS_ERR;
343  break;
344  }
345  if (LDNS_STATUS_OK == status) {
346  ldns_rdf_set_type(rdf, type);
347  return rdf;
348  }
349  if (rdf) {
350  LDNS_FREE(rdf);
351  }
352  return NULL;
353 }
354 
357 {
358  return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
359 }
360 
362 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
363 {
364  char *line;
365  ldns_rdf *r;
366  ssize_t t;
367 
368  line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
369  if (!line) {
370  return LDNS_STATUS_MEM_ERR;
371  }
372 
373  /* read an entire line in from the file */
374  if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
375  LDNS_FREE(line);
377  }
378  r = ldns_rdf_new_frm_str(type, (const char*) line);
379  LDNS_FREE(line);
380  if (rdf) {
381  *rdf = r;
382  return LDNS_STATUS_OK;
383  } else {
384  return LDNS_STATUS_NULL;
385  }
386 }
387 
388 ldns_rdf *
390 {
391  uint8_t buf_4[LDNS_IP4ADDRLEN];
392  uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
393  ldns_rdf *rev;
394  ldns_rdf *in_addr;
395  ldns_rdf *ret_dname;
396  uint8_t octet;
397  uint8_t nnibble;
398  uint8_t nibble;
399  uint8_t i, j;
400 
401  char *char_dname;
402  int nbit;
403 
404  if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
406  return NULL;
407  }
408 
409  in_addr = NULL;
410  ret_dname = NULL;
411 
412  switch(ldns_rdf_get_type(rd)) {
413  case LDNS_RDF_TYPE_A:
414  /* the length of the buffer is 4 */
415  buf_4[3] = ldns_rdf_data(rd)[0];
416  buf_4[2] = ldns_rdf_data(rd)[1];
417  buf_4[1] = ldns_rdf_data(rd)[2];
418  buf_4[0] = ldns_rdf_data(rd)[3];
419  in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
420  if (!in_addr) {
421  return NULL;
422  }
423  /* make a new rdf and convert that back */
425  LDNS_IP4ADDRLEN, (void*)&buf_4);
426  if (!rev) {
427  LDNS_FREE(in_addr);
428  return NULL;
429  }
430 
431  /* convert rev to a string */
432  char_dname = ldns_rdf2str(rev);
433  if (!char_dname) {
434  LDNS_FREE(in_addr);
435  ldns_rdf_deep_free(rev);
436  return NULL;
437  }
438  /* transform back to rdf with type dname */
439  ret_dname = ldns_dname_new_frm_str(char_dname);
440  if (!ret_dname) {
441  LDNS_FREE(in_addr);
442  ldns_rdf_deep_free(rev);
443  LDNS_FREE(char_dname);
444  return NULL;
445  }
446  /* not needed anymore */
447  ldns_rdf_deep_free(rev);
448  LDNS_FREE(char_dname);
449  break;
450  case LDNS_RDF_TYPE_AAAA:
451  /* some foo magic to reverse the nibbles ... */
452 
453  for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
454  /* calculate octett (8 bit) */
455  octet = ( ((unsigned int) nbit) & 0x78) >> 3;
456  /* calculate nibble */
457  nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
458  /* extract nibble */
459  nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
460  nnibble)) ) ) >> ( 4 * (1 -
461  nnibble));
462 
463  buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
464  (octet * 2 + nnibble)] =
465  (uint8_t)ldns_int_to_hexdigit((int)nibble);
466  }
467 
468  char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
469  if (!char_dname) {
470  return NULL;
471  }
472  char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
473 
474  /* walk the string and add . 's */
475  for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
476  char_dname[j] = (char)buf_6[i];
477  if (i != LDNS_IP6ADDRLEN * 2 - 1) {
478  char_dname[j + 1] = '.';
479  }
480  }
481  in_addr = ldns_dname_new_frm_str("ip6.arpa.");
482  if (!in_addr) {
483  LDNS_FREE(char_dname);
484  return NULL;
485  }
486 
487  /* convert rev to a string */
488  ret_dname = ldns_dname_new_frm_str(char_dname);
489  LDNS_FREE(char_dname);
490  if (!ret_dname) {
491  ldns_rdf_deep_free(in_addr);
492  return NULL;
493  }
494  break;
495  default:
496  break;
497  }
498  /* add the suffix */
499  rev = ldns_dname_cat_clone(ret_dname, in_addr);
500 
501  ldns_rdf_deep_free(ret_dname);
502  ldns_rdf_deep_free(in_addr);
503  return rev;
504 }
505 
507 ldns_octet(char *word, size_t *length)
508 {
509  char *s;
510  char *p;
511  *length = 0;
512 
513  for (s = p = word; *s != '\0'; s++,p++) {
514  switch (*s) {
515  case '.':
516  if (s[1] == '.') {
518  }
519  *p = *s;
520  (*length)++;
521  break;
522  case '\\':
523  if ('0' <= s[1] && s[1] <= '9' &&
524  '0' <= s[2] && s[2] <= '9' &&
525  '0' <= s[3] && s[3] <= '9') {
526  /* \DDD seen */
527  int val = ((s[1] - '0') * 100 +
528  (s[2] - '0') * 10 + (s[3] - '0'));
529 
530  if (0 <= val && val <= 255) {
531  /* this also handles \0 */
532  s += 3;
533  *p = val;
534  (*length)++;
535  } else {
537  }
538  } else {
539  /* an espaced character, like <space> ?
540  * remove the '\' keep the rest */
541  *p = *++s;
542  (*length)++;
543  }
544  break;
545  case '\"':
546  /* non quoted " Is either first or the last character in
547  * the string */
548 
549  *p = *++s; /* skip it */
550  (*length)++;
551  /* I'm not sure if this is needed in libdns... MG */
552  if ( *s == '\0' ) {
553  /* ok, it was the last one */
554  *p = '\0';
555  return LDNS_STATUS_OK;
556  }
557  break;
558  default:
559  *p = *s;
560  (*length)++;
561  break;
562  }
563  }
564  *p = '\0';
565  return LDNS_STATUS_OK;
566 }
567 
568 int
569 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
570 {
571  uint16_t i1, i2, i;
572  uint8_t *d1, *d2;
573 
574  /* only when both are not NULL we can say anything about them */
575  if (!rd1 && !rd2) {
576  return 0;
577  }
578  if (!rd1 || !rd2) {
579  return -1;
580  }
581  i1 = ldns_rdf_size(rd1);
582  i2 = ldns_rdf_size(rd2);
583 
584  if (i1 < i2) {
585  return -1;
586  } else if (i1 > i2) {
587  return +1;
588  } else {
589  d1 = (uint8_t*)ldns_rdf_data(rd1);
590  d2 = (uint8_t*)ldns_rdf_data(rd2);
591  for(i = 0; i < i1; i++) {
592  if (d1[i] < d2[i]) {
593  return -1;
594  } else if (d1[i] > d2[i]) {
595  return +1;
596  }
597  }
598  }
599  return 0;
600 }
601 
602 uint32_t
603 ldns_str2period(const char *nptr, const char **endptr)
604 {
605  int sign = 0;
606  uint32_t i = 0;
607  uint32_t seconds = 0;
608 
609  for(*endptr = nptr; **endptr; (*endptr)++) {
610  switch (**endptr) {
611  case ' ':
612  case '\t':
613  break;
614  case '-':
615  if(sign == 0) {
616  sign = -1;
617  } else {
618  return seconds;
619  }
620  break;
621  case '+':
622  if(sign == 0) {
623  sign = 1;
624  } else {
625  return seconds;
626  }
627  break;
628  case 's':
629  case 'S':
630  seconds += i;
631  i = 0;
632  break;
633  case 'm':
634  case 'M':
635  seconds += i * 60;
636  i = 0;
637  break;
638  case 'h':
639  case 'H':
640  seconds += i * 60 * 60;
641  i = 0;
642  break;
643  case 'd':
644  case 'D':
645  seconds += i * 60 * 60 * 24;
646  i = 0;
647  break;
648  case 'w':
649  case 'W':
650  seconds += i * 60 * 60 * 24 * 7;
651  i = 0;
652  break;
653  case '0':
654  case '1':
655  case '2':
656  case '3':
657  case '4':
658  case '5':
659  case '6':
660  case '7':
661  case '8':
662  case '9':
663  i *= 10;
664  i += (**endptr - '0');
665  break;
666  default:
667  seconds += i;
668  /* disregard signedness */
669  return seconds;
670  }
671  }
672  seconds += i;
673  /* disregard signedness */
674  return seconds;
675 }