Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/ldns/rdata.c
39475 views
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
/* 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
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
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 *
147
ldns_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
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 *
222
ldns_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
229
void
230
ldns_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
240
void
241
ldns_rdf_free(ldns_rdf *rd)
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;
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_CERTIFICATE_USAGE:
355
status = ldns_str2rdf_certificate_usage(&rdf, str);
356
break;
357
case LDNS_RDF_TYPE_SELECTOR:
358
status = ldns_str2rdf_selector(&rdf, str);
359
break;
360
case LDNS_RDF_TYPE_MATCHING_TYPE:
361
status = ldns_str2rdf_matching_type(&rdf, str);
362
break;
363
case LDNS_RDF_TYPE_AMTRELAY:
364
status = ldns_str2rdf_amtrelay(&rdf, str);
365
break;
366
case LDNS_RDF_TYPE_SVCPARAMS:
367
status = ldns_str2rdf_svcparams(&rdf, str);
368
break;
369
case LDNS_RDF_TYPE_NONE:
370
default:
371
/* default default ??? */
372
status = LDNS_STATUS_ERR;
373
break;
374
}
375
if (LDNS_STATUS_OK == status) {
376
ldns_rdf_set_type(rdf, type);
377
return rdf;
378
}
379
if (rdf) {
380
LDNS_FREE(rdf);
381
}
382
return NULL;
383
}
384
385
ldns_status
386
ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
387
{
388
return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
389
}
390
391
ldns_status
392
ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
393
{
394
char *line;
395
ldns_rdf *r;
396
ssize_t t;
397
398
line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
399
if (!line) {
400
return LDNS_STATUS_MEM_ERR;
401
}
402
403
/* read an entire line in from the file */
404
if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
405
LDNS_FREE(line);
406
return LDNS_STATUS_SYNTAX_RDATA_ERR;
407
}
408
r = ldns_rdf_new_frm_str(type, (const char*) line);
409
LDNS_FREE(line);
410
if (rdf) {
411
*rdf = r;
412
return LDNS_STATUS_OK;
413
} else {
414
return LDNS_STATUS_NULL;
415
}
416
}
417
418
ldns_rdf *
419
ldns_rdf_address_reverse(const ldns_rdf *rd)
420
{
421
uint8_t buf_4[LDNS_IP4ADDRLEN];
422
uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
423
ldns_rdf *rev;
424
ldns_rdf *in_addr;
425
ldns_rdf *ret_dname;
426
uint8_t octet;
427
uint8_t nnibble;
428
uint8_t nibble;
429
uint8_t i, j;
430
431
char *char_dname;
432
int nbit;
433
434
if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
435
ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
436
return NULL;
437
}
438
439
in_addr = NULL;
440
ret_dname = NULL;
441
442
switch(ldns_rdf_get_type(rd)) {
443
case LDNS_RDF_TYPE_A:
444
/* the length of the buffer is 4 */
445
buf_4[3] = ldns_rdf_data(rd)[0];
446
buf_4[2] = ldns_rdf_data(rd)[1];
447
buf_4[1] = ldns_rdf_data(rd)[2];
448
buf_4[0] = ldns_rdf_data(rd)[3];
449
in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
450
if (!in_addr) {
451
return NULL;
452
}
453
/* make a new rdf and convert that back */
454
rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
455
LDNS_IP4ADDRLEN, (void*)&buf_4);
456
if (!rev) {
457
LDNS_FREE(in_addr);
458
return NULL;
459
}
460
461
/* convert rev to a string */
462
char_dname = ldns_rdf2str(rev);
463
if (!char_dname) {
464
LDNS_FREE(in_addr);
465
ldns_rdf_deep_free(rev);
466
return NULL;
467
}
468
/* transform back to rdf with type dname */
469
ret_dname = ldns_dname_new_frm_str(char_dname);
470
if (!ret_dname) {
471
LDNS_FREE(in_addr);
472
ldns_rdf_deep_free(rev);
473
LDNS_FREE(char_dname);
474
return NULL;
475
}
476
/* not needed anymore */
477
ldns_rdf_deep_free(rev);
478
LDNS_FREE(char_dname);
479
break;
480
case LDNS_RDF_TYPE_AAAA:
481
/* some foo magic to reverse the nibbles ... */
482
483
for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
484
/* calculate octet (8 bit) */
485
octet = ( ((unsigned int) nbit) & 0x78) >> 3;
486
/* calculate nibble */
487
nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
488
/* extract nibble */
489
nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
490
nnibble)) ) ) >> ( 4 * (1 -
491
nnibble));
492
493
buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
494
(octet * 2 + nnibble)] =
495
(uint8_t)ldns_int_to_hexdigit((int)nibble);
496
}
497
498
char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
499
if (!char_dname) {
500
return NULL;
501
}
502
char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
503
504
/* walk the string and add . 's */
505
for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
506
char_dname[j] = (char)buf_6[i];
507
if (i != LDNS_IP6ADDRLEN * 2 - 1) {
508
char_dname[j + 1] = '.';
509
}
510
}
511
in_addr = ldns_dname_new_frm_str("ip6.arpa.");
512
if (!in_addr) {
513
LDNS_FREE(char_dname);
514
return NULL;
515
}
516
517
/* convert rev to a string */
518
ret_dname = ldns_dname_new_frm_str(char_dname);
519
LDNS_FREE(char_dname);
520
if (!ret_dname) {
521
ldns_rdf_deep_free(in_addr);
522
return NULL;
523
}
524
break;
525
default:
526
break;
527
}
528
/* add the suffix */
529
rev = ldns_dname_cat_clone(ret_dname, in_addr);
530
531
ldns_rdf_deep_free(ret_dname);
532
ldns_rdf_deep_free(in_addr);
533
return rev;
534
}
535
536
ldns_status
537
ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
538
uint8_t *hit_size, uint8_t** hit,
539
uint16_t *pk_size, uint8_t** pk)
540
{
541
uint8_t *data;
542
size_t rdf_size;
543
544
if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
545
return LDNS_STATUS_INVALID_POINTER;
546
} else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
547
return LDNS_STATUS_INVALID_RDF_TYPE;
548
} else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
549
return LDNS_STATUS_WIRE_RDATA_ERR;
550
}
551
data = ldns_rdf_data(rdf);
552
*hit_size = data[0];
553
*alg = data[1];
554
*pk_size = ldns_read_uint16(data + 2);
555
*hit = data + 4;
556
*pk = data + 4 + *hit_size;
557
if (*hit_size == 0 || *pk_size == 0 ||
558
rdf_size < (size_t) *hit_size + *pk_size + 4) {
559
return LDNS_STATUS_WIRE_RDATA_ERR;
560
}
561
return LDNS_STATUS_OK;
562
}
563
564
ldns_status
565
ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
566
uint8_t hit_size, uint8_t *hit,
567
uint16_t pk_size, uint8_t *pk)
568
{
569
uint8_t *data;
570
571
if (! rdf) {
572
return LDNS_STATUS_INVALID_POINTER;
573
}
574
if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
575
return LDNS_STATUS_RDATA_OVERFLOW;
576
}
577
data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
578
if (data == NULL) {
579
return LDNS_STATUS_MEM_ERR;
580
}
581
data[0] = hit_size;
582
data[1] = alg;
583
ldns_write_uint16(data + 2, pk_size);
584
memcpy(data + 4, hit, hit_size);
585
memcpy(data + 4 + hit_size, pk, pk_size);
586
*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
587
if (! *rdf) {
588
LDNS_FREE(data);
589
return LDNS_STATUS_MEM_ERR;
590
}
591
return LDNS_STATUS_OK;
592
}
593
594
ldns_status
595
ldns_octet(char *word, size_t *length)
596
{
597
char *s;
598
char *p;
599
*length = 0;
600
601
for (s = p = word; *s != '\0'; s++,p++) {
602
switch (*s) {
603
case '.':
604
if (s[1] == '.') {
605
return LDNS_STATUS_EMPTY_LABEL;
606
}
607
*p = *s;
608
(*length)++;
609
break;
610
case '\\':
611
if ('0' <= s[1] && s[1] <= '9' &&
612
'0' <= s[2] && s[2] <= '9' &&
613
'0' <= s[3] && s[3] <= '9') {
614
/* \DDD seen */
615
int val = ((s[1] - '0') * 100 +
616
(s[2] - '0') * 10 + (s[3] - '0'));
617
618
if (0 <= val && val <= 255) {
619
/* this also handles \0 */
620
s += 3;
621
*p = val;
622
(*length)++;
623
} else {
624
return LDNS_STATUS_DDD_OVERFLOW;
625
}
626
} else {
627
/* an escaped character, like \<space> ?
628
* remove the '\' keep the rest */
629
*p = *++s;
630
(*length)++;
631
}
632
break;
633
case '\"':
634
/* non quoted " Is either first or the last character in
635
* the string */
636
637
*p = *++s; /* skip it */
638
(*length)++;
639
/* I'm not sure if this is needed in libdns... MG */
640
if ( *s == '\0' ) {
641
/* ok, it was the last one */
642
*p = '\0';
643
return LDNS_STATUS_OK;
644
}
645
break;
646
default:
647
*p = *s;
648
(*length)++;
649
break;
650
}
651
}
652
*p = '\0';
653
return LDNS_STATUS_OK;
654
}
655
656
int
657
ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
658
{
659
uint16_t i1, i2, i;
660
uint8_t *d1, *d2;
661
662
/* only when both are not NULL we can say anything about them */
663
if (!rd1 && !rd2) {
664
return 0;
665
}
666
if (!rd1 || !rd2) {
667
return -1;
668
}
669
i1 = ldns_rdf_size(rd1);
670
i2 = ldns_rdf_size(rd2);
671
672
if (i1 < i2) {
673
return -1;
674
} else if (i1 > i2) {
675
return +1;
676
} else {
677
d1 = (uint8_t*)ldns_rdf_data(rd1);
678
d2 = (uint8_t*)ldns_rdf_data(rd2);
679
for(i = 0; i < i1; i++) {
680
if (d1[i] < d2[i]) {
681
return -1;
682
} else if (d1[i] > d2[i]) {
683
return +1;
684
}
685
}
686
}
687
return 0;
688
}
689
690
uint32_t
691
ldns_str2period(const char *nptr, const char **endptr)
692
{
693
int sign = 0;
694
uint32_t i = 0;
695
uint32_t seconds = 0;
696
697
for(*endptr = nptr; **endptr; (*endptr)++) {
698
switch (**endptr) {
699
case ' ':
700
case '\t':
701
break;
702
case '-':
703
if(sign == 0) {
704
sign = -1;
705
} else {
706
return seconds;
707
}
708
break;
709
case '+':
710
if(sign == 0) {
711
sign = 1;
712
} else {
713
return seconds;
714
}
715
break;
716
case 's':
717
case 'S':
718
seconds += i;
719
i = 0;
720
break;
721
case 'm':
722
case 'M':
723
seconds += i * 60;
724
i = 0;
725
break;
726
case 'h':
727
case 'H':
728
seconds += i * 60 * 60;
729
i = 0;
730
break;
731
case 'd':
732
case 'D':
733
seconds += i * 60 * 60 * 24;
734
i = 0;
735
break;
736
case 'w':
737
case 'W':
738
seconds += i * 60 * 60 * 24 * 7;
739
i = 0;
740
break;
741
case '0':
742
case '1':
743
case '2':
744
case '3':
745
case '4':
746
case '5':
747
case '6':
748
case '7':
749
case '8':
750
case '9':
751
i *= 10;
752
i += (**endptr - '0');
753
break;
754
default:
755
seconds += i;
756
/* disregard signedness */
757
return seconds;
758
}
759
}
760
seconds += i;
761
/* disregard signedness */
762
return seconds;
763
}
764
765