xref: /dflybsd-src/contrib/ldns/rdata.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * rdata.c
3825eb42bSJan Lentfer  *
4825eb42bSJan Lentfer  * rdata implementation
5825eb42bSJan Lentfer  *
6825eb42bSJan Lentfer  * a Net::DNS like library for C
7825eb42bSJan Lentfer  *
8825eb42bSJan Lentfer  * (c) NLnet Labs, 2004-2006
9825eb42bSJan Lentfer  *
10825eb42bSJan Lentfer  * See the file LICENSE for the license
11825eb42bSJan Lentfer  */
12825eb42bSJan Lentfer 
13825eb42bSJan Lentfer #include <ldns/config.h>
14825eb42bSJan Lentfer 
15825eb42bSJan Lentfer #include <ldns/ldns.h>
16825eb42bSJan Lentfer 
17825eb42bSJan Lentfer /*
18825eb42bSJan Lentfer  * Access functions
19825eb42bSJan Lentfer  * do this as functions to get type checking
20825eb42bSJan Lentfer  */
21825eb42bSJan Lentfer 
22825eb42bSJan Lentfer /* read */
23825eb42bSJan Lentfer size_t
ldns_rdf_size(const ldns_rdf * rd)24825eb42bSJan Lentfer ldns_rdf_size(const ldns_rdf *rd)
25825eb42bSJan Lentfer {
26825eb42bSJan Lentfer 	assert(rd != NULL);
27825eb42bSJan Lentfer 	return rd->_size;
28825eb42bSJan Lentfer }
29825eb42bSJan Lentfer 
30825eb42bSJan Lentfer ldns_rdf_type
ldns_rdf_get_type(const ldns_rdf * rd)31825eb42bSJan Lentfer ldns_rdf_get_type(const ldns_rdf *rd)
32825eb42bSJan Lentfer {
33825eb42bSJan Lentfer 	assert(rd != NULL);
34825eb42bSJan Lentfer 	return rd->_type;
35825eb42bSJan Lentfer }
36825eb42bSJan Lentfer 
37825eb42bSJan Lentfer uint8_t *
ldns_rdf_data(const ldns_rdf * rd)38825eb42bSJan Lentfer ldns_rdf_data(const ldns_rdf *rd)
39825eb42bSJan Lentfer {
40825eb42bSJan Lentfer 	assert(rd != NULL);
41825eb42bSJan Lentfer 	return rd->_data;
42825eb42bSJan Lentfer }
43825eb42bSJan Lentfer 
44825eb42bSJan Lentfer /* write */
45825eb42bSJan Lentfer void
ldns_rdf_set_size(ldns_rdf * rd,size_t size)46825eb42bSJan Lentfer ldns_rdf_set_size(ldns_rdf *rd, size_t size)
47825eb42bSJan Lentfer {
48825eb42bSJan Lentfer 	assert(rd != NULL);
49825eb42bSJan Lentfer 	rd->_size = size;
50825eb42bSJan Lentfer }
51825eb42bSJan Lentfer 
52825eb42bSJan Lentfer void
ldns_rdf_set_type(ldns_rdf * rd,ldns_rdf_type type)53825eb42bSJan Lentfer ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
54825eb42bSJan Lentfer {
55825eb42bSJan Lentfer 	assert(rd != NULL);
56825eb42bSJan Lentfer 	rd->_type = type;
57825eb42bSJan Lentfer }
58825eb42bSJan Lentfer 
59825eb42bSJan Lentfer void
ldns_rdf_set_data(ldns_rdf * rd,void * data)60825eb42bSJan Lentfer ldns_rdf_set_data(ldns_rdf *rd, void *data)
61825eb42bSJan Lentfer {
62825eb42bSJan Lentfer 	/* only copy the pointer */
63825eb42bSJan Lentfer 	assert(rd != NULL);
64825eb42bSJan Lentfer 	rd->_data = data;
65825eb42bSJan Lentfer }
66825eb42bSJan Lentfer 
67825eb42bSJan Lentfer /* for types that allow it, return
68825eb42bSJan Lentfer  * the native/host order type */
69825eb42bSJan Lentfer uint8_t
ldns_rdf2native_int8(const ldns_rdf * rd)70825eb42bSJan Lentfer ldns_rdf2native_int8(const ldns_rdf *rd)
71825eb42bSJan Lentfer {
72825eb42bSJan Lentfer 	uint8_t data;
73825eb42bSJan Lentfer 
74825eb42bSJan Lentfer 	/* only allow 8 bit rdfs */
75825eb42bSJan Lentfer 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
76825eb42bSJan Lentfer 		return 0;
77825eb42bSJan Lentfer 	}
78825eb42bSJan Lentfer 
79825eb42bSJan Lentfer 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
80825eb42bSJan Lentfer 	return data;
81825eb42bSJan Lentfer }
82825eb42bSJan Lentfer 
83825eb42bSJan Lentfer uint16_t
ldns_rdf2native_int16(const ldns_rdf * rd)84825eb42bSJan Lentfer ldns_rdf2native_int16(const ldns_rdf *rd)
85825eb42bSJan Lentfer {
86825eb42bSJan Lentfer 	uint16_t data;
87825eb42bSJan Lentfer 
88825eb42bSJan Lentfer 	/* only allow 16 bit rdfs */
89825eb42bSJan Lentfer 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
90825eb42bSJan Lentfer 		return 0;
91825eb42bSJan Lentfer 	}
92825eb42bSJan Lentfer 
93825eb42bSJan Lentfer 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
94825eb42bSJan Lentfer 	return ntohs(data);
95825eb42bSJan Lentfer }
96825eb42bSJan Lentfer 
97825eb42bSJan Lentfer uint32_t
ldns_rdf2native_int32(const ldns_rdf * rd)98825eb42bSJan Lentfer ldns_rdf2native_int32(const ldns_rdf *rd)
99825eb42bSJan Lentfer {
100825eb42bSJan Lentfer 	uint32_t data;
101825eb42bSJan Lentfer 
102825eb42bSJan Lentfer 	/* only allow 32 bit rdfs */
103825eb42bSJan Lentfer 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
104825eb42bSJan Lentfer 		return 0;
105825eb42bSJan Lentfer 	}
106825eb42bSJan Lentfer 
107825eb42bSJan Lentfer 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
108825eb42bSJan Lentfer 	return ntohl(data);
109825eb42bSJan Lentfer }
110825eb42bSJan Lentfer 
111825eb42bSJan Lentfer time_t
ldns_rdf2native_time_t(const ldns_rdf * rd)112825eb42bSJan Lentfer ldns_rdf2native_time_t(const ldns_rdf *rd)
113825eb42bSJan Lentfer {
114825eb42bSJan Lentfer 	uint32_t data;
115825eb42bSJan Lentfer 
1165340022aSzrj 	/* only allow 32 bit rdfs */
1175340022aSzrj 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD ||
1185340022aSzrj 			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) {
119825eb42bSJan Lentfer 		return 0;
120825eb42bSJan Lentfer 	}
1215340022aSzrj 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
1225340022aSzrj 	return (time_t)ntohl(data);
123825eb42bSJan Lentfer }
124825eb42bSJan Lentfer 
125825eb42bSJan Lentfer ldns_rdf *
ldns_native2rdf_int8(ldns_rdf_type type,uint8_t value)126825eb42bSJan Lentfer ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
127825eb42bSJan Lentfer {
128825eb42bSJan Lentfer 	return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
129825eb42bSJan Lentfer }
130825eb42bSJan Lentfer 
131825eb42bSJan Lentfer ldns_rdf *
ldns_native2rdf_int16(ldns_rdf_type type,uint16_t value)132825eb42bSJan Lentfer ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
133825eb42bSJan Lentfer {
134825eb42bSJan Lentfer 	uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
135ac996e71SJan Lentfer         ldns_rdf* rdf;
136825eb42bSJan Lentfer 	if (!rdf_data) {
137825eb42bSJan Lentfer 		return NULL;
138825eb42bSJan Lentfer 	}
139825eb42bSJan Lentfer 	ldns_write_uint16(rdf_data, value);
140ac996e71SJan Lentfer 	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
141ac996e71SJan Lentfer         if(!rdf)
142ac996e71SJan Lentfer                 LDNS_FREE(rdf_data);
143ac996e71SJan Lentfer         return rdf;
144825eb42bSJan Lentfer }
145825eb42bSJan Lentfer 
146825eb42bSJan Lentfer ldns_rdf *
ldns_native2rdf_int32(ldns_rdf_type type,uint32_t value)147825eb42bSJan Lentfer ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
148825eb42bSJan Lentfer {
149825eb42bSJan Lentfer 	uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
150ac996e71SJan Lentfer         ldns_rdf* rdf;
151825eb42bSJan Lentfer 	if (!rdf_data) {
152825eb42bSJan Lentfer 		return NULL;
153825eb42bSJan Lentfer 	}
154825eb42bSJan Lentfer 	ldns_write_uint32(rdf_data, value);
155ac996e71SJan Lentfer 	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
156ac996e71SJan Lentfer         if(!rdf)
157ac996e71SJan Lentfer                 LDNS_FREE(rdf_data);
158ac996e71SJan Lentfer         return rdf;
159825eb42bSJan Lentfer }
160825eb42bSJan Lentfer 
161825eb42bSJan Lentfer ldns_rdf *
ldns_native2rdf_int16_data(size_t size,uint8_t * data)162825eb42bSJan Lentfer ldns_native2rdf_int16_data(size_t size, uint8_t *data)
163825eb42bSJan Lentfer {
164825eb42bSJan Lentfer 	uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
165ac996e71SJan Lentfer         ldns_rdf* rdf;
166825eb42bSJan Lentfer 	if (!rdf_data) {
167825eb42bSJan Lentfer 		return NULL;
168825eb42bSJan Lentfer 	}
169825eb42bSJan Lentfer 	ldns_write_uint16(rdf_data, size);
170825eb42bSJan Lentfer 	memcpy(rdf_data + 2, data, size);
171ac996e71SJan Lentfer 	rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
172ac996e71SJan Lentfer         if(!rdf)
173ac996e71SJan Lentfer                 LDNS_FREE(rdf_data);
174ac996e71SJan Lentfer         return rdf;
175825eb42bSJan Lentfer }
176825eb42bSJan Lentfer 
177825eb42bSJan Lentfer /* note: data must be allocated memory */
178825eb42bSJan Lentfer ldns_rdf *
ldns_rdf_new(ldns_rdf_type type,size_t size,void * data)179825eb42bSJan Lentfer ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
180825eb42bSJan Lentfer {
181825eb42bSJan Lentfer 	ldns_rdf *rd;
182825eb42bSJan Lentfer 	rd = LDNS_MALLOC(ldns_rdf);
183825eb42bSJan Lentfer 	if (!rd) {
184825eb42bSJan Lentfer 		return NULL;
185825eb42bSJan Lentfer 	}
186825eb42bSJan Lentfer 	ldns_rdf_set_size(rd, size);
187825eb42bSJan Lentfer 	ldns_rdf_set_type(rd, type);
188825eb42bSJan Lentfer 	ldns_rdf_set_data(rd, data);
189825eb42bSJan Lentfer 	return rd;
190825eb42bSJan Lentfer }
191825eb42bSJan Lentfer 
192825eb42bSJan Lentfer ldns_rdf *
ldns_rdf_new_frm_data(ldns_rdf_type type,size_t size,const void * data)193825eb42bSJan Lentfer ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
194825eb42bSJan Lentfer {
195825eb42bSJan Lentfer 	ldns_rdf *rdf;
196825eb42bSJan Lentfer 
197825eb42bSJan Lentfer 	/* if the size is too big, fail */
198825eb42bSJan Lentfer 	if (size > LDNS_MAX_RDFLEN) {
199825eb42bSJan Lentfer 		return NULL;
200825eb42bSJan Lentfer 	}
201825eb42bSJan Lentfer 
202825eb42bSJan Lentfer 	/* allocate space */
203825eb42bSJan Lentfer 	rdf = LDNS_MALLOC(ldns_rdf);
204825eb42bSJan Lentfer 	if (!rdf) {
205825eb42bSJan Lentfer 		return NULL;
206825eb42bSJan Lentfer 	}
207825eb42bSJan Lentfer 	rdf->_data = LDNS_XMALLOC(uint8_t, size);
208825eb42bSJan Lentfer 	if (!rdf->_data) {
209825eb42bSJan Lentfer 		LDNS_FREE(rdf);
210825eb42bSJan Lentfer 		return NULL;
211825eb42bSJan Lentfer 	}
212825eb42bSJan Lentfer 
213825eb42bSJan Lentfer 	/* set the values */
214825eb42bSJan Lentfer 	ldns_rdf_set_type(rdf, type);
215825eb42bSJan Lentfer 	ldns_rdf_set_size(rdf, size);
216825eb42bSJan Lentfer 	memcpy(rdf->_data, data, size);
217825eb42bSJan Lentfer 
218825eb42bSJan Lentfer 	return rdf;
219825eb42bSJan Lentfer }
220825eb42bSJan Lentfer 
221825eb42bSJan Lentfer ldns_rdf *
ldns_rdf_clone(const ldns_rdf * rd)222825eb42bSJan Lentfer ldns_rdf_clone(const ldns_rdf *rd)
223825eb42bSJan Lentfer {
224825eb42bSJan Lentfer 	assert(rd != NULL);
225825eb42bSJan Lentfer 	return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
226825eb42bSJan Lentfer 		ldns_rdf_size(rd), ldns_rdf_data(rd)));
227825eb42bSJan Lentfer }
228825eb42bSJan Lentfer 
229825eb42bSJan Lentfer void
ldns_rdf_deep_free(ldns_rdf * rd)230825eb42bSJan Lentfer ldns_rdf_deep_free(ldns_rdf *rd)
231825eb42bSJan Lentfer {
232825eb42bSJan Lentfer 	if (rd) {
233825eb42bSJan Lentfer 		if (rd->_data) {
234825eb42bSJan Lentfer 			LDNS_FREE(rd->_data);
235825eb42bSJan Lentfer 		}
236825eb42bSJan Lentfer 		LDNS_FREE(rd);
237825eb42bSJan Lentfer 	}
238825eb42bSJan Lentfer }
239825eb42bSJan Lentfer 
240825eb42bSJan Lentfer void
ldns_rdf_free(ldns_rdf * rd)241825eb42bSJan Lentfer ldns_rdf_free(ldns_rdf *rd)
242825eb42bSJan Lentfer {
243825eb42bSJan Lentfer 	if (rd) {
244825eb42bSJan Lentfer 		LDNS_FREE(rd);
245825eb42bSJan Lentfer 	}
246825eb42bSJan Lentfer }
247825eb42bSJan Lentfer 
248825eb42bSJan Lentfer ldns_rdf *
ldns_rdf_new_frm_str(ldns_rdf_type type,const char * str)249825eb42bSJan Lentfer ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
250825eb42bSJan Lentfer {
251825eb42bSJan Lentfer 	ldns_rdf *rdf = NULL;
252825eb42bSJan Lentfer 	ldns_status status;
253825eb42bSJan Lentfer 
254825eb42bSJan Lentfer 	switch (type) {
255825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_DNAME:
256825eb42bSJan Lentfer 		status = ldns_str2rdf_dname(&rdf, str);
257825eb42bSJan Lentfer 		break;
258825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_INT8:
259825eb42bSJan Lentfer 		status = ldns_str2rdf_int8(&rdf, str);
260825eb42bSJan Lentfer 		break;
261825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_INT16:
262825eb42bSJan Lentfer 		status = ldns_str2rdf_int16(&rdf, str);
263825eb42bSJan Lentfer 		break;
264825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_INT32:
265825eb42bSJan Lentfer 		status = ldns_str2rdf_int32(&rdf, str);
266825eb42bSJan Lentfer 		break;
267825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_A:
268825eb42bSJan Lentfer 		status = ldns_str2rdf_a(&rdf, str);
269825eb42bSJan Lentfer 		break;
270825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_AAAA:
271825eb42bSJan Lentfer 		status = ldns_str2rdf_aaaa(&rdf, str);
272825eb42bSJan Lentfer 		break;
273825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_STR:
274825eb42bSJan Lentfer 		status = ldns_str2rdf_str(&rdf, str);
275825eb42bSJan Lentfer 		break;
276825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_APL:
277825eb42bSJan Lentfer 		status = ldns_str2rdf_apl(&rdf, str);
278825eb42bSJan Lentfer 		break;
279825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_B64:
280825eb42bSJan Lentfer 		status = ldns_str2rdf_b64(&rdf, str);
281825eb42bSJan Lentfer 		break;
282825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_B32_EXT:
283825eb42bSJan Lentfer 		status = ldns_str2rdf_b32_ext(&rdf, str);
284825eb42bSJan Lentfer 		break;
285825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_HEX:
286825eb42bSJan Lentfer 		status = ldns_str2rdf_hex(&rdf, str);
287825eb42bSJan Lentfer 		break;
288825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_NSEC:
289825eb42bSJan Lentfer 		status = ldns_str2rdf_nsec(&rdf, str);
290825eb42bSJan Lentfer 		break;
291825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_TYPE:
292825eb42bSJan Lentfer 		status = ldns_str2rdf_type(&rdf, str);
293825eb42bSJan Lentfer 		break;
294825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_CLASS:
295825eb42bSJan Lentfer 		status = ldns_str2rdf_class(&rdf, str);
296825eb42bSJan Lentfer 		break;
297825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_CERT_ALG:
298825eb42bSJan Lentfer 		status = ldns_str2rdf_cert_alg(&rdf, str);
299825eb42bSJan Lentfer 		break;
300825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_ALG:
301825eb42bSJan Lentfer 		status = ldns_str2rdf_alg(&rdf, str);
302825eb42bSJan Lentfer 		break;
303825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_UNKNOWN:
304825eb42bSJan Lentfer 		status = ldns_str2rdf_unknown(&rdf, str);
305825eb42bSJan Lentfer 		break;
306825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_TIME:
307825eb42bSJan Lentfer 		status = ldns_str2rdf_time(&rdf, str);
308825eb42bSJan Lentfer 		break;
309825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_PERIOD:
310825eb42bSJan Lentfer 		status = ldns_str2rdf_period(&rdf, str);
311825eb42bSJan Lentfer 		break;
3125340022aSzrj 	case LDNS_RDF_TYPE_HIP:
3135340022aSzrj 		status = ldns_str2rdf_hip(&rdf, str);
314825eb42bSJan Lentfer 		break;
315825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_SERVICE:
316825eb42bSJan Lentfer 		status = ldns_str2rdf_service(&rdf, str);
317825eb42bSJan Lentfer 		break;
318825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_LOC:
319825eb42bSJan Lentfer 		status = ldns_str2rdf_loc(&rdf, str);
320825eb42bSJan Lentfer 		break;
321825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_WKS:
322825eb42bSJan Lentfer 		status = ldns_str2rdf_wks(&rdf, str);
323825eb42bSJan Lentfer 		break;
324825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_NSAP:
325825eb42bSJan Lentfer 		status = ldns_str2rdf_nsap(&rdf, str);
326825eb42bSJan Lentfer 		break;
327825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_ATMA:
328825eb42bSJan Lentfer 		status = ldns_str2rdf_atma(&rdf, str);
329825eb42bSJan Lentfer 		break;
330825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_IPSECKEY:
331825eb42bSJan Lentfer 		status = ldns_str2rdf_ipseckey(&rdf, str);
332825eb42bSJan Lentfer 		break;
333825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_NSEC3_SALT:
334825eb42bSJan Lentfer 		status = ldns_str2rdf_nsec3_salt(&rdf, str);
335825eb42bSJan Lentfer 		break;
336825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
337825eb42bSJan Lentfer 		status = ldns_str2rdf_b32_ext(&rdf, str);
338825eb42bSJan Lentfer 		break;
3395340022aSzrj 	case LDNS_RDF_TYPE_ILNP64:
3405340022aSzrj 		status = ldns_str2rdf_ilnp64(&rdf, str);
3415340022aSzrj 		break;
3425340022aSzrj 	case LDNS_RDF_TYPE_EUI48:
3435340022aSzrj 		status = ldns_str2rdf_eui48(&rdf, str);
3445340022aSzrj 		break;
3455340022aSzrj 	case LDNS_RDF_TYPE_EUI64:
3465340022aSzrj 		status = ldns_str2rdf_eui64(&rdf, str);
3475340022aSzrj 		break;
3485340022aSzrj 	case LDNS_RDF_TYPE_TAG:
3495340022aSzrj 		status = ldns_str2rdf_tag(&rdf, str);
3505340022aSzrj 		break;
3515340022aSzrj 	case LDNS_RDF_TYPE_LONG_STR:
3525340022aSzrj 		status = ldns_str2rdf_long_str(&rdf, str);
3535340022aSzrj 		break;
3545340022aSzrj 	case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
3555340022aSzrj 		status = ldns_str2rdf_certificate_usage(&rdf, str);
3565340022aSzrj 		break;
3575340022aSzrj 	case LDNS_RDF_TYPE_SELECTOR:
3585340022aSzrj 		status = ldns_str2rdf_selector(&rdf, str);
3595340022aSzrj 		break;
3605340022aSzrj 	case LDNS_RDF_TYPE_MATCHING_TYPE:
3615340022aSzrj 		status = ldns_str2rdf_matching_type(&rdf, str);
3625340022aSzrj 		break;
363819dec71SDaniel Fojt 	case LDNS_RDF_TYPE_AMTRELAY:
364819dec71SDaniel Fojt 		status = ldns_str2rdf_amtrelay(&rdf, str);
365819dec71SDaniel Fojt 		break;
366*ee791febSAntonio Huete Jimenez 	case LDNS_RDF_TYPE_SVCPARAMS:
367*ee791febSAntonio Huete Jimenez 		status = ldns_str2rdf_svcparams(&rdf, str);
368*ee791febSAntonio Huete Jimenez 		break;
369825eb42bSJan Lentfer 	case LDNS_RDF_TYPE_NONE:
370825eb42bSJan Lentfer 	default:
371825eb42bSJan Lentfer 		/* default default ??? */
372825eb42bSJan Lentfer 		status = LDNS_STATUS_ERR;
373825eb42bSJan Lentfer 		break;
374825eb42bSJan Lentfer 	}
375825eb42bSJan Lentfer 	if (LDNS_STATUS_OK == status) {
376825eb42bSJan Lentfer 		ldns_rdf_set_type(rdf, type);
377825eb42bSJan Lentfer 		return rdf;
378825eb42bSJan Lentfer 	}
379825eb42bSJan Lentfer 	if (rdf) {
380825eb42bSJan Lentfer 		LDNS_FREE(rdf);
381825eb42bSJan Lentfer 	}
382825eb42bSJan Lentfer 	return NULL;
383825eb42bSJan Lentfer }
384825eb42bSJan Lentfer 
385825eb42bSJan Lentfer ldns_status
ldns_rdf_new_frm_fp(ldns_rdf ** rdf,ldns_rdf_type type,FILE * fp)386825eb42bSJan Lentfer ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
387825eb42bSJan Lentfer {
388825eb42bSJan Lentfer 	return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
389825eb42bSJan Lentfer }
390825eb42bSJan Lentfer 
391825eb42bSJan Lentfer ldns_status
ldns_rdf_new_frm_fp_l(ldns_rdf ** rdf,ldns_rdf_type type,FILE * fp,int * line_nr)392825eb42bSJan Lentfer ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
393825eb42bSJan Lentfer {
394825eb42bSJan Lentfer 	char *line;
395825eb42bSJan Lentfer 	ldns_rdf *r;
396825eb42bSJan Lentfer 	ssize_t t;
397825eb42bSJan Lentfer 
398825eb42bSJan Lentfer 	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
399825eb42bSJan Lentfer 	if (!line) {
400825eb42bSJan Lentfer 		return LDNS_STATUS_MEM_ERR;
401825eb42bSJan Lentfer 	}
402825eb42bSJan Lentfer 
403825eb42bSJan Lentfer 	/* read an entire line in from the file */
404ac996e71SJan Lentfer 	if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
405825eb42bSJan Lentfer 		LDNS_FREE(line);
406825eb42bSJan Lentfer 		return LDNS_STATUS_SYNTAX_RDATA_ERR;
407825eb42bSJan Lentfer 	}
408825eb42bSJan Lentfer 	r =  ldns_rdf_new_frm_str(type, (const char*) line);
409825eb42bSJan Lentfer 	LDNS_FREE(line);
410825eb42bSJan Lentfer 	if (rdf) {
411825eb42bSJan Lentfer 		*rdf = r;
412825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
413825eb42bSJan Lentfer 	} else {
414825eb42bSJan Lentfer 		return LDNS_STATUS_NULL;
415825eb42bSJan Lentfer 	}
416825eb42bSJan Lentfer }
417825eb42bSJan Lentfer 
418825eb42bSJan Lentfer ldns_rdf *
ldns_rdf_address_reverse(const ldns_rdf * rd)4195340022aSzrj ldns_rdf_address_reverse(const ldns_rdf *rd)
420825eb42bSJan Lentfer {
421825eb42bSJan Lentfer 	uint8_t buf_4[LDNS_IP4ADDRLEN];
422825eb42bSJan Lentfer 	uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
423825eb42bSJan Lentfer 	ldns_rdf *rev;
424825eb42bSJan Lentfer 	ldns_rdf *in_addr;
425825eb42bSJan Lentfer 	ldns_rdf *ret_dname;
426825eb42bSJan Lentfer 	uint8_t octet;
427825eb42bSJan Lentfer 	uint8_t nnibble;
428825eb42bSJan Lentfer 	uint8_t nibble;
429825eb42bSJan Lentfer 	uint8_t i, j;
430825eb42bSJan Lentfer 
431825eb42bSJan Lentfer 	char *char_dname;
432825eb42bSJan Lentfer 	int nbit;
433825eb42bSJan Lentfer 
434825eb42bSJan Lentfer 	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
435825eb42bSJan Lentfer 			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
436825eb42bSJan Lentfer 		return NULL;
437825eb42bSJan Lentfer 	}
438825eb42bSJan Lentfer 
439825eb42bSJan Lentfer 	in_addr = NULL;
440825eb42bSJan Lentfer 	ret_dname = NULL;
441825eb42bSJan Lentfer 
442825eb42bSJan Lentfer 	switch(ldns_rdf_get_type(rd)) {
443825eb42bSJan Lentfer 		case LDNS_RDF_TYPE_A:
444825eb42bSJan Lentfer 			/* the length of the buffer is 4 */
445825eb42bSJan Lentfer 			buf_4[3] = ldns_rdf_data(rd)[0];
446825eb42bSJan Lentfer 			buf_4[2] = ldns_rdf_data(rd)[1];
447825eb42bSJan Lentfer 			buf_4[1] = ldns_rdf_data(rd)[2];
448825eb42bSJan Lentfer 			buf_4[0] = ldns_rdf_data(rd)[3];
449825eb42bSJan Lentfer 			in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
450825eb42bSJan Lentfer 			if (!in_addr) {
451825eb42bSJan Lentfer 				return NULL;
452825eb42bSJan Lentfer 			}
453825eb42bSJan Lentfer 			/* make a new rdf and convert that back  */
454825eb42bSJan Lentfer 			rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
455825eb42bSJan Lentfer 				LDNS_IP4ADDRLEN, (void*)&buf_4);
456825eb42bSJan Lentfer 			if (!rev) {
457825eb42bSJan Lentfer 				LDNS_FREE(in_addr);
458825eb42bSJan Lentfer 				return NULL;
459825eb42bSJan Lentfer 			}
460825eb42bSJan Lentfer 
461825eb42bSJan Lentfer 			/* convert rev to a string */
462825eb42bSJan Lentfer 			char_dname = ldns_rdf2str(rev);
463825eb42bSJan Lentfer 			if (!char_dname) {
464825eb42bSJan Lentfer 				LDNS_FREE(in_addr);
465825eb42bSJan Lentfer 				ldns_rdf_deep_free(rev);
466825eb42bSJan Lentfer 				return NULL;
467825eb42bSJan Lentfer 			}
468825eb42bSJan Lentfer 			/* transform back to rdf with type dname */
469825eb42bSJan Lentfer 			ret_dname = ldns_dname_new_frm_str(char_dname);
470825eb42bSJan Lentfer 			if (!ret_dname) {
471825eb42bSJan Lentfer 				LDNS_FREE(in_addr);
472825eb42bSJan Lentfer 				ldns_rdf_deep_free(rev);
473825eb42bSJan Lentfer 				LDNS_FREE(char_dname);
474825eb42bSJan Lentfer 				return NULL;
475825eb42bSJan Lentfer 			}
476825eb42bSJan Lentfer 			/* not needed anymore */
477825eb42bSJan Lentfer 			ldns_rdf_deep_free(rev);
478825eb42bSJan Lentfer 			LDNS_FREE(char_dname);
479825eb42bSJan Lentfer 			break;
480825eb42bSJan Lentfer 		case LDNS_RDF_TYPE_AAAA:
481825eb42bSJan Lentfer 			/* some foo magic to reverse the nibbles ... */
482825eb42bSJan Lentfer 
483825eb42bSJan Lentfer 			for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
4845340022aSzrj 				/* calculate octet (8 bit) */
485825eb42bSJan Lentfer 				octet = ( ((unsigned int) nbit) & 0x78) >> 3;
486825eb42bSJan Lentfer 				/* calculate nibble */
487825eb42bSJan Lentfer 				nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
488825eb42bSJan Lentfer 				/* extract nibble */
489825eb42bSJan Lentfer 				nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
490825eb42bSJan Lentfer 						 nnibble)) ) ) >> ( 4 * (1 -
491825eb42bSJan Lentfer 						nnibble));
492825eb42bSJan Lentfer 
493825eb42bSJan Lentfer 				buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
494825eb42bSJan Lentfer 					(octet * 2 + nnibble)] =
495825eb42bSJan Lentfer 						(uint8_t)ldns_int_to_hexdigit((int)nibble);
496825eb42bSJan Lentfer 			}
497825eb42bSJan Lentfer 
498825eb42bSJan Lentfer 			char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
499825eb42bSJan Lentfer 			if (!char_dname) {
500825eb42bSJan Lentfer 				return NULL;
501825eb42bSJan Lentfer 			}
502825eb42bSJan Lentfer 			char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
503825eb42bSJan Lentfer 
504825eb42bSJan Lentfer 			/* walk the string and add . 's */
505825eb42bSJan Lentfer 			for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
506825eb42bSJan Lentfer 				char_dname[j] = (char)buf_6[i];
507825eb42bSJan Lentfer 				if (i != LDNS_IP6ADDRLEN * 2 - 1) {
508825eb42bSJan Lentfer 					char_dname[j + 1] = '.';
509825eb42bSJan Lentfer 				}
510825eb42bSJan Lentfer 			}
511825eb42bSJan Lentfer 			in_addr = ldns_dname_new_frm_str("ip6.arpa.");
512825eb42bSJan Lentfer 			if (!in_addr) {
513825eb42bSJan Lentfer 				LDNS_FREE(char_dname);
514825eb42bSJan Lentfer 				return NULL;
515825eb42bSJan Lentfer 			}
516825eb42bSJan Lentfer 
517825eb42bSJan Lentfer 			/* convert rev to a string */
518825eb42bSJan Lentfer 			ret_dname = ldns_dname_new_frm_str(char_dname);
519825eb42bSJan Lentfer 			LDNS_FREE(char_dname);
520825eb42bSJan Lentfer 			if (!ret_dname) {
521825eb42bSJan Lentfer 				ldns_rdf_deep_free(in_addr);
522825eb42bSJan Lentfer 				return NULL;
523825eb42bSJan Lentfer 			}
524825eb42bSJan Lentfer 			break;
525825eb42bSJan Lentfer 		default:
526825eb42bSJan Lentfer 			break;
527825eb42bSJan Lentfer 	}
528825eb42bSJan Lentfer 	/* add the suffix */
529825eb42bSJan Lentfer 	rev = ldns_dname_cat_clone(ret_dname, in_addr);
530825eb42bSJan Lentfer 
531825eb42bSJan Lentfer 	ldns_rdf_deep_free(ret_dname);
532825eb42bSJan Lentfer 	ldns_rdf_deep_free(in_addr);
533825eb42bSJan Lentfer 	return rev;
534825eb42bSJan Lentfer }
535825eb42bSJan Lentfer 
536825eb42bSJan Lentfer ldns_status
ldns_rdf_hip_get_alg_hit_pk(ldns_rdf * rdf,uint8_t * alg,uint8_t * hit_size,uint8_t ** hit,uint16_t * pk_size,uint8_t ** pk)5375340022aSzrj ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
5385340022aSzrj                             uint8_t *hit_size, uint8_t** hit,
5395340022aSzrj                             uint16_t *pk_size, uint8_t** pk)
5405340022aSzrj {
5415340022aSzrj 	uint8_t *data;
5425340022aSzrj 	size_t rdf_size;
5435340022aSzrj 
5445340022aSzrj 	if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
5455340022aSzrj 		return LDNS_STATUS_INVALID_POINTER;
5465340022aSzrj 	} else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
5475340022aSzrj 		return LDNS_STATUS_INVALID_RDF_TYPE;
5485340022aSzrj 	} else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
5495340022aSzrj 		return LDNS_STATUS_WIRE_RDATA_ERR;
5505340022aSzrj 	}
5515340022aSzrj 	data = ldns_rdf_data(rdf);
5525340022aSzrj 	*hit_size = data[0];
5535340022aSzrj 	*alg      = data[1];
5545340022aSzrj 	*pk_size  = ldns_read_uint16(data + 2);
5555340022aSzrj 	*hit      = data + 4;
5565340022aSzrj 	*pk       = data + 4 + *hit_size;
5575340022aSzrj 	if (*hit_size == 0 || *pk_size == 0 ||
5585340022aSzrj 			rdf_size < (size_t) *hit_size + *pk_size + 4) {
5595340022aSzrj 		return LDNS_STATUS_WIRE_RDATA_ERR;
5605340022aSzrj 	}
5615340022aSzrj 	return LDNS_STATUS_OK;
5625340022aSzrj }
5635340022aSzrj 
5645340022aSzrj ldns_status
ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf ** rdf,uint8_t alg,uint8_t hit_size,uint8_t * hit,uint16_t pk_size,uint8_t * pk)5655340022aSzrj ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
5665340022aSzrj                                 uint8_t hit_size, uint8_t *hit,
5675340022aSzrj 				uint16_t pk_size, uint8_t *pk)
5685340022aSzrj {
5695340022aSzrj 	uint8_t *data;
5705340022aSzrj 
5715340022aSzrj 	if (! rdf) {
5725340022aSzrj 		return LDNS_STATUS_INVALID_POINTER;
5735340022aSzrj 	}
5745340022aSzrj 	if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
5755340022aSzrj 		return LDNS_STATUS_RDATA_OVERFLOW;
5765340022aSzrj 	}
5775340022aSzrj 	data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
5785340022aSzrj 	if (data == NULL) {
5795340022aSzrj 		return LDNS_STATUS_MEM_ERR;
5805340022aSzrj 	}
5815340022aSzrj 	data[0] = hit_size;
5825340022aSzrj 	data[1] = alg;
5835340022aSzrj 	ldns_write_uint16(data + 2, pk_size);
5845340022aSzrj 	memcpy(data + 4, hit, hit_size);
5855340022aSzrj 	memcpy(data + 4 + hit_size, pk, pk_size);
5865340022aSzrj 	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
5875340022aSzrj 	if (! *rdf) {
5885340022aSzrj 		LDNS_FREE(data);
5895340022aSzrj 		return LDNS_STATUS_MEM_ERR;
5905340022aSzrj 	}
5915340022aSzrj 	return LDNS_STATUS_OK;
5925340022aSzrj }
5935340022aSzrj 
5945340022aSzrj ldns_status
ldns_octet(char * word,size_t * length)595825eb42bSJan Lentfer ldns_octet(char *word, size_t *length)
596825eb42bSJan Lentfer {
597825eb42bSJan Lentfer     char *s;
598825eb42bSJan Lentfer     char *p;
599825eb42bSJan Lentfer     *length = 0;
600825eb42bSJan Lentfer 
601825eb42bSJan Lentfer     for (s = p = word; *s != '\0'; s++,p++) {
602825eb42bSJan Lentfer         switch (*s) {
603825eb42bSJan Lentfer             case '.':
604825eb42bSJan Lentfer                 if (s[1] == '.') {
605825eb42bSJan Lentfer 		    return LDNS_STATUS_EMPTY_LABEL;
606825eb42bSJan Lentfer                 }
607825eb42bSJan Lentfer                 *p = *s;
608825eb42bSJan Lentfer                 (*length)++;
609825eb42bSJan Lentfer                 break;
610825eb42bSJan Lentfer             case '\\':
611825eb42bSJan Lentfer                 if ('0' <= s[1] && s[1] <= '9' &&
612825eb42bSJan Lentfer                     '0' <= s[2] && s[2] <= '9' &&
613825eb42bSJan Lentfer                     '0' <= s[3] && s[3] <= '9') {
614825eb42bSJan Lentfer                     /* \DDD seen */
615825eb42bSJan Lentfer                     int val = ((s[1] - '0') * 100 +
616825eb42bSJan Lentfer                            (s[2] - '0') * 10 + (s[3] - '0'));
617825eb42bSJan Lentfer 
618825eb42bSJan Lentfer                     if (0 <= val && val <= 255) {
619825eb42bSJan Lentfer                         /* this also handles \0 */
620825eb42bSJan Lentfer                         s += 3;
621825eb42bSJan Lentfer                         *p = val;
622825eb42bSJan Lentfer                         (*length)++;
623825eb42bSJan Lentfer                     } else {
624825eb42bSJan Lentfer                         return LDNS_STATUS_DDD_OVERFLOW;
625825eb42bSJan Lentfer                     }
626825eb42bSJan Lentfer                 } else {
627*ee791febSAntonio Huete Jimenez                     /* an escaped character, like \<space> ?
628825eb42bSJan Lentfer                     * remove the '\' keep the rest */
629825eb42bSJan Lentfer                     *p = *++s;
630825eb42bSJan Lentfer                     (*length)++;
631825eb42bSJan Lentfer                 }
632825eb42bSJan Lentfer                 break;
633825eb42bSJan Lentfer             case '\"':
634825eb42bSJan Lentfer                 /* non quoted " Is either first or the last character in
635825eb42bSJan Lentfer                  * the string */
636825eb42bSJan Lentfer 
637825eb42bSJan Lentfer                 *p = *++s; /* skip it */
638825eb42bSJan Lentfer                 (*length)++;
639825eb42bSJan Lentfer 		/* I'm not sure if this is needed in libdns... MG */
640825eb42bSJan Lentfer                 if ( *s == '\0' ) {
641825eb42bSJan Lentfer                     /* ok, it was the last one */
642825eb42bSJan Lentfer                     *p  = '\0';
643825eb42bSJan Lentfer 		    return LDNS_STATUS_OK;
644825eb42bSJan Lentfer                 }
645825eb42bSJan Lentfer                 break;
646825eb42bSJan Lentfer             default:
647825eb42bSJan Lentfer                 *p = *s;
648825eb42bSJan Lentfer                 (*length)++;
649825eb42bSJan Lentfer                 break;
650825eb42bSJan Lentfer         }
651825eb42bSJan Lentfer     }
652825eb42bSJan Lentfer     *p = '\0';
653825eb42bSJan Lentfer     return LDNS_STATUS_OK;
654825eb42bSJan Lentfer }
655825eb42bSJan Lentfer 
656825eb42bSJan Lentfer int
ldns_rdf_compare(const ldns_rdf * rd1,const ldns_rdf * rd2)657825eb42bSJan Lentfer ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
658825eb42bSJan Lentfer {
659825eb42bSJan Lentfer 	uint16_t i1, i2, i;
660825eb42bSJan Lentfer 	uint8_t *d1, *d2;
661825eb42bSJan Lentfer 
662825eb42bSJan Lentfer 	/* only when both are not NULL we can say anything about them */
663825eb42bSJan Lentfer 	if (!rd1 && !rd2) {
664825eb42bSJan Lentfer 		return 0;
665825eb42bSJan Lentfer 	}
666825eb42bSJan Lentfer 	if (!rd1 || !rd2) {
667825eb42bSJan Lentfer 		return -1;
668825eb42bSJan Lentfer 	}
669825eb42bSJan Lentfer 	i1 = ldns_rdf_size(rd1);
670825eb42bSJan Lentfer 	i2 = ldns_rdf_size(rd2);
671825eb42bSJan Lentfer 
672825eb42bSJan Lentfer 	if (i1 < i2) {
673825eb42bSJan Lentfer 		return -1;
674825eb42bSJan Lentfer 	} else if (i1 > i2) {
675825eb42bSJan Lentfer 		return +1;
676825eb42bSJan Lentfer 	} else {
677825eb42bSJan Lentfer 		d1 = (uint8_t*)ldns_rdf_data(rd1);
678825eb42bSJan Lentfer 		d2 = (uint8_t*)ldns_rdf_data(rd2);
679825eb42bSJan Lentfer 		for(i = 0; i < i1; i++) {
680825eb42bSJan Lentfer 			if (d1[i] < d2[i]) {
681825eb42bSJan Lentfer 				return -1;
682825eb42bSJan Lentfer 			} else if (d1[i] > d2[i]) {
683825eb42bSJan Lentfer 				return +1;
684825eb42bSJan Lentfer 			}
685825eb42bSJan Lentfer 		}
686825eb42bSJan Lentfer 	}
687825eb42bSJan Lentfer 	return 0;
688825eb42bSJan Lentfer }
689825eb42bSJan Lentfer 
690825eb42bSJan Lentfer uint32_t
ldns_str2period(const char * nptr,const char ** endptr)691825eb42bSJan Lentfer ldns_str2period(const char *nptr, const char **endptr)
692825eb42bSJan Lentfer {
693825eb42bSJan Lentfer 	int sign = 0;
694825eb42bSJan Lentfer 	uint32_t i = 0;
695825eb42bSJan Lentfer 	uint32_t seconds = 0;
696825eb42bSJan Lentfer 
697825eb42bSJan Lentfer 	for(*endptr = nptr; **endptr; (*endptr)++) {
698825eb42bSJan Lentfer 		switch (**endptr) {
699825eb42bSJan Lentfer 			case ' ':
700825eb42bSJan Lentfer 			case '\t':
701825eb42bSJan Lentfer 				break;
702825eb42bSJan Lentfer 			case '-':
703825eb42bSJan Lentfer 				if(sign == 0) {
704825eb42bSJan Lentfer 					sign = -1;
705825eb42bSJan Lentfer 				} else {
706825eb42bSJan Lentfer 					return seconds;
707825eb42bSJan Lentfer 				}
708825eb42bSJan Lentfer 				break;
709825eb42bSJan Lentfer 			case '+':
710825eb42bSJan Lentfer 				if(sign == 0) {
711825eb42bSJan Lentfer 					sign = 1;
712825eb42bSJan Lentfer 				} else {
713825eb42bSJan Lentfer 					return seconds;
714825eb42bSJan Lentfer 				}
715825eb42bSJan Lentfer 				break;
716825eb42bSJan Lentfer 			case 's':
717825eb42bSJan Lentfer 			case 'S':
718825eb42bSJan Lentfer 				seconds += i;
719825eb42bSJan Lentfer 				i = 0;
720825eb42bSJan Lentfer 				break;
721825eb42bSJan Lentfer 			case 'm':
722825eb42bSJan Lentfer 			case 'M':
723825eb42bSJan Lentfer 				seconds += i * 60;
724825eb42bSJan Lentfer 				i = 0;
725825eb42bSJan Lentfer 				break;
726825eb42bSJan Lentfer 			case 'h':
727825eb42bSJan Lentfer 			case 'H':
728825eb42bSJan Lentfer 				seconds += i * 60 * 60;
729825eb42bSJan Lentfer 				i = 0;
730825eb42bSJan Lentfer 				break;
731825eb42bSJan Lentfer 			case 'd':
732825eb42bSJan Lentfer 			case 'D':
733825eb42bSJan Lentfer 				seconds += i * 60 * 60 * 24;
734825eb42bSJan Lentfer 				i = 0;
735825eb42bSJan Lentfer 				break;
736825eb42bSJan Lentfer 			case 'w':
737825eb42bSJan Lentfer 			case 'W':
738825eb42bSJan Lentfer 				seconds += i * 60 * 60 * 24 * 7;
739825eb42bSJan Lentfer 				i = 0;
740825eb42bSJan Lentfer 				break;
741825eb42bSJan Lentfer 			case '0':
742825eb42bSJan Lentfer 			case '1':
743825eb42bSJan Lentfer 			case '2':
744825eb42bSJan Lentfer 			case '3':
745825eb42bSJan Lentfer 			case '4':
746825eb42bSJan Lentfer 			case '5':
747825eb42bSJan Lentfer 			case '6':
748825eb42bSJan Lentfer 			case '7':
749825eb42bSJan Lentfer 			case '8':
750825eb42bSJan Lentfer 			case '9':
751825eb42bSJan Lentfer 				i *= 10;
752825eb42bSJan Lentfer 				i += (**endptr - '0');
753825eb42bSJan Lentfer 				break;
754825eb42bSJan Lentfer 			default:
755825eb42bSJan Lentfer 				seconds += i;
756825eb42bSJan Lentfer 				/* disregard signedness */
757825eb42bSJan Lentfer 				return seconds;
758825eb42bSJan Lentfer 		}
759825eb42bSJan Lentfer 	}
760825eb42bSJan Lentfer 	seconds += i;
761825eb42bSJan Lentfer 	/* disregard signedness */
762825eb42bSJan Lentfer 	return seconds;
763825eb42bSJan Lentfer }
764