rdata.c revision 269257
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 */
23size_t
24ldns_rdf_size(const ldns_rdf *rd)
25{
26	assert(rd != NULL);
27	return rd->_size;
28}
29
30ldns_rdf_type
31ldns_rdf_get_type(const ldns_rdf *rd)
32{
33	assert(rd != NULL);
34	return rd->_type;
35}
36
37uint8_t *
38ldns_rdf_data(const ldns_rdf *rd)
39{
40	assert(rd != NULL);
41	return rd->_data;
42}
43
44/* write */
45void
46ldns_rdf_set_size(ldns_rdf *rd, size_t size)
47{
48	assert(rd != NULL);
49	rd->_size = size;
50}
51
52void
53ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
54{
55	assert(rd != NULL);
56	rd->_type = type;
57}
58
59void
60ldns_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 */
69uint8_t
70ldns_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
83uint16_t
84ldns_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
97uint32_t
98ldns_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
111time_t
112ldns_rdf2native_time_t(const ldns_rdf *rd)
113{
114	uint32_t data;
115
116	/* only allow 32 bit rdfs */
117	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD ||
118			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) {
119		return 0;
120	}
121	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
122	return (time_t)ntohl(data);
123}
124
125ldns_rdf *
126ldns_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
131ldns_rdf *
132ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
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
146ldns_rdf *
147ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
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
161ldns_rdf *
162ldns_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 */
178ldns_rdf *
179ldns_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
192ldns_rdf *
193ldns_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
221ldns_rdf *
222ldns_rdf_clone(const ldns_rdf *rd)
223{
224	assert(rd != NULL);
225	return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
226		ldns_rdf_size(rd), ldns_rdf_data(rd)));
227}
228
229void
230ldns_rdf_deep_free(ldns_rdf *rd)
231{
232	if (rd) {
233		if (rd->_data) {
234			LDNS_FREE(rd->_data);
235		}
236		LDNS_FREE(rd);
237	}
238}
239
240void
241ldns_rdf_free(ldns_rdf *rd)
242{
243	if (rd) {
244		LDNS_FREE(rd);
245	}
246}
247
248ldns_rdf *
249ldns_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;
282	case LDNS_RDF_TYPE_B32_EXT:
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;
297	case LDNS_RDF_TYPE_CERT_ALG:
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;
303	case LDNS_RDF_TYPE_UNKNOWN:
304		status = ldns_str2rdf_unknown(&rdf, str);
305		break;
306	case LDNS_RDF_TYPE_TIME:
307		status = ldns_str2rdf_time(&rdf, str);
308		break;
309	case LDNS_RDF_TYPE_PERIOD:
310		status = ldns_str2rdf_period(&rdf, str);
311		break;
312	case LDNS_RDF_TYPE_HIP:
313		status = ldns_str2rdf_hip(&rdf, str);
314		break;
315	case LDNS_RDF_TYPE_SERVICE:
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;
330	case LDNS_RDF_TYPE_IPSECKEY:
331		status = ldns_str2rdf_ipseckey(&rdf, str);
332		break;
333	case LDNS_RDF_TYPE_NSEC3_SALT:
334		status = ldns_str2rdf_nsec3_salt(&rdf, str);
335		break;
336	case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
337		status = ldns_str2rdf_b32_ext(&rdf, str);
338		break;
339	case LDNS_RDF_TYPE_ILNP64:
340		status = ldns_str2rdf_ilnp64(&rdf, str);
341		break;
342	case LDNS_RDF_TYPE_EUI48:
343		status = ldns_str2rdf_eui48(&rdf, str);
344		break;
345	case LDNS_RDF_TYPE_EUI64:
346		status = ldns_str2rdf_eui64(&rdf, str);
347		break;
348	case LDNS_RDF_TYPE_TAG:
349		status = ldns_str2rdf_tag(&rdf, str);
350		break;
351	case LDNS_RDF_TYPE_LONG_STR:
352		status = ldns_str2rdf_long_str(&rdf, str);
353		break;
354	case LDNS_RDF_TYPE_NONE:
355	default:
356		/* default default ??? */
357		status = LDNS_STATUS_ERR;
358		break;
359	}
360	if (LDNS_STATUS_OK == status) {
361		ldns_rdf_set_type(rdf, type);
362		return rdf;
363	}
364	if (rdf) {
365		LDNS_FREE(rdf);
366	}
367	return NULL;
368}
369
370ldns_status
371ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
372{
373	return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
374}
375
376ldns_status
377ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
378{
379	char *line;
380	ldns_rdf *r;
381	ssize_t t;
382
383	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
384	if (!line) {
385		return LDNS_STATUS_MEM_ERR;
386	}
387
388	/* read an entire line in from the file */
389	if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
390		LDNS_FREE(line);
391		return LDNS_STATUS_SYNTAX_RDATA_ERR;
392	}
393	r =  ldns_rdf_new_frm_str(type, (const char*) line);
394	LDNS_FREE(line);
395	if (rdf) {
396		*rdf = r;
397		return LDNS_STATUS_OK;
398	} else {
399		return LDNS_STATUS_NULL;
400	}
401}
402
403ldns_rdf *
404ldns_rdf_address_reverse(ldns_rdf *rd)
405{
406	uint8_t buf_4[LDNS_IP4ADDRLEN];
407	uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
408	ldns_rdf *rev;
409	ldns_rdf *in_addr;
410	ldns_rdf *ret_dname;
411	uint8_t octet;
412	uint8_t nnibble;
413	uint8_t nibble;
414	uint8_t i, j;
415
416	char *char_dname;
417	int nbit;
418
419	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
420			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
421		return NULL;
422	}
423
424	in_addr = NULL;
425	ret_dname = NULL;
426
427	switch(ldns_rdf_get_type(rd)) {
428		case LDNS_RDF_TYPE_A:
429			/* the length of the buffer is 4 */
430			buf_4[3] = ldns_rdf_data(rd)[0];
431			buf_4[2] = ldns_rdf_data(rd)[1];
432			buf_4[1] = ldns_rdf_data(rd)[2];
433			buf_4[0] = ldns_rdf_data(rd)[3];
434			in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
435			if (!in_addr) {
436				return NULL;
437			}
438			/* make a new rdf and convert that back  */
439			rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
440				LDNS_IP4ADDRLEN, (void*)&buf_4);
441			if (!rev) {
442				LDNS_FREE(in_addr);
443				return NULL;
444			}
445
446			/* convert rev to a string */
447			char_dname = ldns_rdf2str(rev);
448			if (!char_dname) {
449				LDNS_FREE(in_addr);
450				ldns_rdf_deep_free(rev);
451				return NULL;
452			}
453			/* transform back to rdf with type dname */
454			ret_dname = ldns_dname_new_frm_str(char_dname);
455			if (!ret_dname) {
456				LDNS_FREE(in_addr);
457				ldns_rdf_deep_free(rev);
458				LDNS_FREE(char_dname);
459				return NULL;
460			}
461			/* not needed anymore */
462			ldns_rdf_deep_free(rev);
463			LDNS_FREE(char_dname);
464			break;
465		case LDNS_RDF_TYPE_AAAA:
466			/* some foo magic to reverse the nibbles ... */
467
468			for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
469				/* calculate octett (8 bit) */
470				octet = ( ((unsigned int) nbit) & 0x78) >> 3;
471				/* calculate nibble */
472				nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
473				/* extract nibble */
474				nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
475						 nnibble)) ) ) >> ( 4 * (1 -
476						nnibble));
477
478				buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
479					(octet * 2 + nnibble)] =
480						(uint8_t)ldns_int_to_hexdigit((int)nibble);
481			}
482
483			char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
484			if (!char_dname) {
485				return NULL;
486			}
487			char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
488
489			/* walk the string and add . 's */
490			for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
491				char_dname[j] = (char)buf_6[i];
492				if (i != LDNS_IP6ADDRLEN * 2 - 1) {
493					char_dname[j + 1] = '.';
494				}
495			}
496			in_addr = ldns_dname_new_frm_str("ip6.arpa.");
497			if (!in_addr) {
498				LDNS_FREE(char_dname);
499				return NULL;
500			}
501
502			/* convert rev to a string */
503			ret_dname = ldns_dname_new_frm_str(char_dname);
504			LDNS_FREE(char_dname);
505			if (!ret_dname) {
506				ldns_rdf_deep_free(in_addr);
507				return NULL;
508			}
509			break;
510		default:
511			break;
512	}
513	/* add the suffix */
514	rev = ldns_dname_cat_clone(ret_dname, in_addr);
515
516	ldns_rdf_deep_free(ret_dname);
517	ldns_rdf_deep_free(in_addr);
518	return rev;
519}
520
521ldns_status
522ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
523                            uint8_t *hit_size, uint8_t** hit,
524                            uint16_t *pk_size, uint8_t** pk)
525{
526	uint8_t *data;
527	size_t rdf_size;
528
529	if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
530		return LDNS_STATUS_INVALID_POINTER;
531	} else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
532		return LDNS_STATUS_INVALID_RDF_TYPE;
533	} else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
534		return LDNS_STATUS_WIRE_RDATA_ERR;
535	}
536	data = ldns_rdf_data(rdf);
537	*hit_size = data[0];
538	*alg      = data[1];
539	*pk_size  = ldns_read_uint16(data + 2);
540	*hit      = data + 4;
541	*pk       = data + 4 + *hit_size;
542	if (*hit_size == 0 || *pk_size == 0 ||
543			rdf_size < (size_t) *hit_size + *pk_size + 4) {
544		return LDNS_STATUS_WIRE_RDATA_ERR;
545	}
546	return LDNS_STATUS_OK;
547}
548
549ldns_status
550ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
551                                uint8_t hit_size, uint8_t *hit,
552				uint16_t pk_size, uint8_t *pk)
553{
554	uint8_t *data;
555
556	if (! rdf) {
557		return LDNS_STATUS_INVALID_POINTER;
558	}
559	if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
560		return LDNS_STATUS_RDATA_OVERFLOW;
561	}
562	data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
563	if (data == NULL) {
564		return LDNS_STATUS_MEM_ERR;
565	}
566	data[0] = hit_size;
567	data[1] = alg;
568	ldns_write_uint16(data + 2, pk_size);
569	memcpy(data + 4, hit, hit_size);
570	memcpy(data + 4 + hit_size, pk, pk_size);
571	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
572	if (! *rdf) {
573		LDNS_FREE(data);
574		return LDNS_STATUS_MEM_ERR;
575	}
576	return LDNS_STATUS_OK;
577}
578
579ldns_status
580ldns_octet(char *word, size_t *length)
581{
582    char *s;
583    char *p;
584    *length = 0;
585
586    for (s = p = word; *s != '\0'; s++,p++) {
587        switch (*s) {
588            case '.':
589                if (s[1] == '.') {
590		    return LDNS_STATUS_EMPTY_LABEL;
591                }
592                *p = *s;
593                (*length)++;
594                break;
595            case '\\':
596                if ('0' <= s[1] && s[1] <= '9' &&
597                    '0' <= s[2] && s[2] <= '9' &&
598                    '0' <= s[3] && s[3] <= '9') {
599                    /* \DDD seen */
600                    int val = ((s[1] - '0') * 100 +
601                           (s[2] - '0') * 10 + (s[3] - '0'));
602
603                    if (0 <= val && val <= 255) {
604                        /* this also handles \0 */
605                        s += 3;
606                        *p = val;
607                        (*length)++;
608                    } else {
609                        return LDNS_STATUS_DDD_OVERFLOW;
610                    }
611                } else {
612                    /* an espaced character, like \<space> ?
613                    * remove the '\' keep the rest */
614                    *p = *++s;
615                    (*length)++;
616                }
617                break;
618            case '\"':
619                /* non quoted " Is either first or the last character in
620                 * the string */
621
622                *p = *++s; /* skip it */
623                (*length)++;
624		/* I'm not sure if this is needed in libdns... MG */
625                if ( *s == '\0' ) {
626                    /* ok, it was the last one */
627                    *p  = '\0';
628		    return LDNS_STATUS_OK;
629                }
630                break;
631            default:
632                *p = *s;
633                (*length)++;
634                break;
635        }
636    }
637    *p = '\0';
638    return LDNS_STATUS_OK;
639}
640
641int
642ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
643{
644	uint16_t i1, i2, i;
645	uint8_t *d1, *d2;
646
647	/* only when both are not NULL we can say anything about them */
648	if (!rd1 && !rd2) {
649		return 0;
650	}
651	if (!rd1 || !rd2) {
652		return -1;
653	}
654	i1 = ldns_rdf_size(rd1);
655	i2 = ldns_rdf_size(rd2);
656
657	if (i1 < i2) {
658		return -1;
659	} else if (i1 > i2) {
660		return +1;
661	} else {
662		d1 = (uint8_t*)ldns_rdf_data(rd1);
663		d2 = (uint8_t*)ldns_rdf_data(rd2);
664		for(i = 0; i < i1; i++) {
665			if (d1[i] < d2[i]) {
666				return -1;
667			} else if (d1[i] > d2[i]) {
668				return +1;
669			}
670		}
671	}
672	return 0;
673}
674
675uint32_t
676ldns_str2period(const char *nptr, const char **endptr)
677{
678	int sign = 0;
679	uint32_t i = 0;
680	uint32_t seconds = 0;
681
682	for(*endptr = nptr; **endptr; (*endptr)++) {
683		switch (**endptr) {
684			case ' ':
685			case '\t':
686				break;
687			case '-':
688				if(sign == 0) {
689					sign = -1;
690				} else {
691					return seconds;
692				}
693				break;
694			case '+':
695				if(sign == 0) {
696					sign = 1;
697				} else {
698					return seconds;
699				}
700				break;
701			case 's':
702			case 'S':
703				seconds += i;
704				i = 0;
705				break;
706			case 'm':
707			case 'M':
708				seconds += i * 60;
709				i = 0;
710				break;
711			case 'h':
712			case 'H':
713				seconds += i * 60 * 60;
714				i = 0;
715				break;
716			case 'd':
717			case 'D':
718				seconds += i * 60 * 60 * 24;
719				i = 0;
720				break;
721			case 'w':
722			case 'W':
723				seconds += i * 60 * 60 * 24 * 7;
724				i = 0;
725				break;
726			case '0':
727			case '1':
728			case '2':
729			case '3':
730			case '4':
731			case '5':
732			case '6':
733			case '7':
734			case '8':
735			case '9':
736				i *= 10;
737				i += (**endptr - '0');
738				break;
739			default:
740				seconds += i;
741				/* disregard signedness */
742				return seconds;
743		}
744	}
745	seconds += i;
746	/* disregard signedness */
747	return seconds;
748}
749