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