00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <ldns/config.h>
00014
00015 #include <ldns/ldns.h>
00016
00017
00018
00019
00020
00021
00022
00023 size_t
00024 ldns_rdf_size(const ldns_rdf *rd)
00025 {
00026 assert(rd != NULL);
00027 return rd->_size;
00028 }
00029
00030 ldns_rdf_type
00031 ldns_rdf_get_type(const ldns_rdf *rd)
00032 {
00033 assert(rd != NULL);
00034 return rd->_type;
00035 }
00036
00037 uint8_t *
00038 ldns_rdf_data(const ldns_rdf *rd)
00039 {
00040 assert(rd != NULL);
00041 return rd->_data;
00042 }
00043
00044
00045 void
00046 ldns_rdf_set_size(ldns_rdf *rd, size_t size)
00047 {
00048 assert(rd != NULL);
00049 rd->_size = size;
00050 }
00051
00052 void
00053 ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
00054 {
00055 assert(rd != NULL);
00056 rd->_type = type;
00057 }
00058
00059 void
00060 ldns_rdf_set_data(ldns_rdf *rd, void *data)
00061 {
00062
00063 assert(rd != NULL);
00064 rd->_data = data;
00065 }
00066
00067
00068
00069 uint8_t
00070 ldns_rdf2native_int8(const ldns_rdf *rd)
00071 {
00072 uint8_t data;
00073
00074
00075 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
00076 return 0;
00077 }
00078
00079 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00080 return data;
00081 }
00082
00083 uint16_t
00084 ldns_rdf2native_int16(const ldns_rdf *rd)
00085 {
00086 uint16_t data;
00087
00088
00089 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
00090 return 0;
00091 }
00092
00093 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00094 return ntohs(data);
00095 }
00096
00097 uint32_t
00098 ldns_rdf2native_int32(const ldns_rdf *rd)
00099 {
00100 uint32_t data;
00101
00102
00103 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
00104 return 0;
00105 }
00106
00107 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00108 return ntohl(data);
00109 }
00110
00111 time_t
00112 ldns_rdf2native_time_t(const ldns_rdf *rd)
00113 {
00114 uint32_t data;
00115
00116
00117 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD ||
00118 ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) {
00119 return 0;
00120 }
00121 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
00122 return (time_t)ntohl(data);
00123 }
00124
00125 ldns_rdf *
00126 ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
00127 {
00128 return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
00129 }
00130
00131 ldns_rdf *
00132 ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
00133 {
00134 uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
00135 ldns_rdf* rdf;
00136 if (!rdf_data) {
00137 return NULL;
00138 }
00139 ldns_write_uint16(rdf_data, value);
00140 rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
00141 if(!rdf)
00142 LDNS_FREE(rdf_data);
00143 return rdf;
00144 }
00145
00146 ldns_rdf *
00147 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
00148 {
00149 uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
00150 ldns_rdf* rdf;
00151 if (!rdf_data) {
00152 return NULL;
00153 }
00154 ldns_write_uint32(rdf_data, value);
00155 rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
00156 if(!rdf)
00157 LDNS_FREE(rdf_data);
00158 return rdf;
00159 }
00160
00161 ldns_rdf *
00162 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
00163 {
00164 uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
00165 ldns_rdf* rdf;
00166 if (!rdf_data) {
00167 return NULL;
00168 }
00169 ldns_write_uint16(rdf_data, size);
00170 memcpy(rdf_data + 2, data, size);
00171 rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
00172 if(!rdf)
00173 LDNS_FREE(rdf_data);
00174 return rdf;
00175 }
00176
00177
00178 ldns_rdf *
00179 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
00180 {
00181 ldns_rdf *rd;
00182 rd = LDNS_MALLOC(ldns_rdf);
00183 if (!rd) {
00184 return NULL;
00185 }
00186 ldns_rdf_set_size(rd, size);
00187 ldns_rdf_set_type(rd, type);
00188 ldns_rdf_set_data(rd, data);
00189 return rd;
00190 }
00191
00192 ldns_rdf *
00193 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
00194 {
00195 ldns_rdf *rdf;
00196
00197
00198 if (size > LDNS_MAX_RDFLEN) {
00199 return NULL;
00200 }
00201
00202
00203 rdf = LDNS_MALLOC(ldns_rdf);
00204 if (!rdf) {
00205 return NULL;
00206 }
00207 rdf->_data = LDNS_XMALLOC(uint8_t, size);
00208 if (!rdf->_data) {
00209 LDNS_FREE(rdf);
00210 return NULL;
00211 }
00212
00213
00214 ldns_rdf_set_type(rdf, type);
00215 ldns_rdf_set_size(rdf, size);
00216 memcpy(rdf->_data, data, size);
00217
00218 return rdf;
00219 }
00220
00221 ldns_rdf *
00222 ldns_rdf_clone(const ldns_rdf *rd)
00223 {
00224 assert(rd != NULL);
00225 return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
00226 ldns_rdf_size(rd), ldns_rdf_data(rd)));
00227 }
00228
00229 void
00230 ldns_rdf_deep_free(ldns_rdf *rd)
00231 {
00232 if (rd) {
00233 if (rd->_data) {
00234 LDNS_FREE(rd->_data);
00235 }
00236 LDNS_FREE(rd);
00237 }
00238 }
00239
00240 void
00241 ldns_rdf_free(ldns_rdf *rd)
00242 {
00243 if (rd) {
00244 LDNS_FREE(rd);
00245 }
00246 }
00247
00248 ldns_rdf *
00249 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
00250 {
00251 ldns_rdf *rdf = NULL;
00252 ldns_status status;
00253
00254 switch (type) {
00255 case LDNS_RDF_TYPE_DNAME:
00256 status = ldns_str2rdf_dname(&rdf, str);
00257 break;
00258 case LDNS_RDF_TYPE_INT8:
00259 status = ldns_str2rdf_int8(&rdf, str);
00260 break;
00261 case LDNS_RDF_TYPE_INT16:
00262 status = ldns_str2rdf_int16(&rdf, str);
00263 break;
00264 case LDNS_RDF_TYPE_INT32:
00265 status = ldns_str2rdf_int32(&rdf, str);
00266 break;
00267 case LDNS_RDF_TYPE_A:
00268 status = ldns_str2rdf_a(&rdf, str);
00269 break;
00270 case LDNS_RDF_TYPE_AAAA:
00271 status = ldns_str2rdf_aaaa(&rdf, str);
00272 break;
00273 case LDNS_RDF_TYPE_STR:
00274 status = ldns_str2rdf_str(&rdf, str);
00275 break;
00276 case LDNS_RDF_TYPE_APL:
00277 status = ldns_str2rdf_apl(&rdf, str);
00278 break;
00279 case LDNS_RDF_TYPE_B64:
00280 status = ldns_str2rdf_b64(&rdf, str);
00281 break;
00282 case LDNS_RDF_TYPE_B32_EXT:
00283 status = ldns_str2rdf_b32_ext(&rdf, str);
00284 break;
00285 case LDNS_RDF_TYPE_HEX:
00286 status = ldns_str2rdf_hex(&rdf, str);
00287 break;
00288 case LDNS_RDF_TYPE_NSEC:
00289 status = ldns_str2rdf_nsec(&rdf, str);
00290 break;
00291 case LDNS_RDF_TYPE_TYPE:
00292 status = ldns_str2rdf_type(&rdf, str);
00293 break;
00294 case LDNS_RDF_TYPE_CLASS:
00295 status = ldns_str2rdf_class(&rdf, str);
00296 break;
00297 case LDNS_RDF_TYPE_CERT_ALG:
00298 status = ldns_str2rdf_cert_alg(&rdf, str);
00299 break;
00300 case LDNS_RDF_TYPE_ALG:
00301 status = ldns_str2rdf_alg(&rdf, str);
00302 break;
00303 case LDNS_RDF_TYPE_UNKNOWN:
00304 status = ldns_str2rdf_unknown(&rdf, str);
00305 break;
00306 case LDNS_RDF_TYPE_TIME:
00307 status = ldns_str2rdf_time(&rdf, str);
00308 break;
00309 case LDNS_RDF_TYPE_PERIOD:
00310 status = ldns_str2rdf_period(&rdf, str);
00311 break;
00312 case LDNS_RDF_TYPE_HIP:
00313 status = ldns_str2rdf_hip(&rdf, str);
00314 break;
00315 case LDNS_RDF_TYPE_SERVICE:
00316 status = ldns_str2rdf_service(&rdf, str);
00317 break;
00318 case LDNS_RDF_TYPE_LOC:
00319 status = ldns_str2rdf_loc(&rdf, str);
00320 break;
00321 case LDNS_RDF_TYPE_WKS:
00322 status = ldns_str2rdf_wks(&rdf, str);
00323 break;
00324 case LDNS_RDF_TYPE_NSAP:
00325 status = ldns_str2rdf_nsap(&rdf, str);
00326 break;
00327 case LDNS_RDF_TYPE_ATMA:
00328 status = ldns_str2rdf_atma(&rdf, str);
00329 break;
00330 case LDNS_RDF_TYPE_IPSECKEY:
00331 status = ldns_str2rdf_ipseckey(&rdf, str);
00332 break;
00333 case LDNS_RDF_TYPE_NSEC3_SALT:
00334 status = ldns_str2rdf_nsec3_salt(&rdf, str);
00335 break;
00336 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
00337 status = ldns_str2rdf_b32_ext(&rdf, str);
00338 break;
00339 case LDNS_RDF_TYPE_ILNP64:
00340 status = ldns_str2rdf_ilnp64(&rdf, str);
00341 break;
00342 case LDNS_RDF_TYPE_EUI48:
00343 status = ldns_str2rdf_eui48(&rdf, str);
00344 break;
00345 case LDNS_RDF_TYPE_EUI64:
00346 status = ldns_str2rdf_eui64(&rdf, str);
00347 break;
00348 case LDNS_RDF_TYPE_TAG:
00349 status = ldns_str2rdf_tag(&rdf, str);
00350 break;
00351 case LDNS_RDF_TYPE_LONG_STR:
00352 status = ldns_str2rdf_long_str(&rdf, str);
00353 break;
00354 case LDNS_RDF_TYPE_NONE:
00355 default:
00356
00357 status = LDNS_STATUS_ERR;
00358 break;
00359 }
00360 if (LDNS_STATUS_OK == status) {
00361 ldns_rdf_set_type(rdf, type);
00362 return rdf;
00363 }
00364 if (rdf) {
00365 LDNS_FREE(rdf);
00366 }
00367 return NULL;
00368 }
00369
00370 ldns_status
00371 ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
00372 {
00373 return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
00374 }
00375
00376 ldns_status
00377 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
00378 {
00379 char *line;
00380 ldns_rdf *r;
00381 ssize_t t;
00382
00383 line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00384 if (!line) {
00385 return LDNS_STATUS_MEM_ERR;
00386 }
00387
00388
00389 if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
00390 LDNS_FREE(line);
00391 return LDNS_STATUS_SYNTAX_RDATA_ERR;
00392 }
00393 r = ldns_rdf_new_frm_str(type, (const char*) line);
00394 LDNS_FREE(line);
00395 if (rdf) {
00396 *rdf = r;
00397 return LDNS_STATUS_OK;
00398 } else {
00399 return LDNS_STATUS_NULL;
00400 }
00401 }
00402
00403 ldns_rdf *
00404 ldns_rdf_address_reverse(ldns_rdf *rd)
00405 {
00406 uint8_t buf_4[LDNS_IP4ADDRLEN];
00407 uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
00408 ldns_rdf *rev;
00409 ldns_rdf *in_addr;
00410 ldns_rdf *ret_dname;
00411 uint8_t octet;
00412 uint8_t nnibble;
00413 uint8_t nibble;
00414 uint8_t i, j;
00415
00416 char *char_dname;
00417 int nbit;
00418
00419 if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
00420 ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
00421 return NULL;
00422 }
00423
00424 in_addr = NULL;
00425 ret_dname = NULL;
00426
00427 switch(ldns_rdf_get_type(rd)) {
00428 case LDNS_RDF_TYPE_A:
00429
00430 buf_4[3] = ldns_rdf_data(rd)[0];
00431 buf_4[2] = ldns_rdf_data(rd)[1];
00432 buf_4[1] = ldns_rdf_data(rd)[2];
00433 buf_4[0] = ldns_rdf_data(rd)[3];
00434 in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
00435 if (!in_addr) {
00436 return NULL;
00437 }
00438
00439 rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
00440 LDNS_IP4ADDRLEN, (void*)&buf_4);
00441 if (!rev) {
00442 LDNS_FREE(in_addr);
00443 return NULL;
00444 }
00445
00446
00447 char_dname = ldns_rdf2str(rev);
00448 if (!char_dname) {
00449 LDNS_FREE(in_addr);
00450 ldns_rdf_deep_free(rev);
00451 return NULL;
00452 }
00453
00454 ret_dname = ldns_dname_new_frm_str(char_dname);
00455 if (!ret_dname) {
00456 LDNS_FREE(in_addr);
00457 ldns_rdf_deep_free(rev);
00458 LDNS_FREE(char_dname);
00459 return NULL;
00460 }
00461
00462 ldns_rdf_deep_free(rev);
00463 LDNS_FREE(char_dname);
00464 break;
00465 case LDNS_RDF_TYPE_AAAA:
00466
00467
00468 for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
00469
00470 octet = ( ((unsigned int) nbit) & 0x78) >> 3;
00471
00472 nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
00473
00474 nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
00475 nnibble)) ) ) >> ( 4 * (1 -
00476 nnibble));
00477
00478 buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
00479 (octet * 2 + nnibble)] =
00480 (uint8_t)ldns_int_to_hexdigit((int)nibble);
00481 }
00482
00483 char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
00484 if (!char_dname) {
00485 return NULL;
00486 }
00487 char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0';
00488
00489
00490 for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
00491 char_dname[j] = (char)buf_6[i];
00492 if (i != LDNS_IP6ADDRLEN * 2 - 1) {
00493 char_dname[j + 1] = '.';
00494 }
00495 }
00496 in_addr = ldns_dname_new_frm_str("ip6.arpa.");
00497 if (!in_addr) {
00498 LDNS_FREE(char_dname);
00499 return NULL;
00500 }
00501
00502
00503 ret_dname = ldns_dname_new_frm_str(char_dname);
00504 LDNS_FREE(char_dname);
00505 if (!ret_dname) {
00506 ldns_rdf_deep_free(in_addr);
00507 return NULL;
00508 }
00509 break;
00510 default:
00511 break;
00512 }
00513
00514 rev = ldns_dname_cat_clone(ret_dname, in_addr);
00515
00516 ldns_rdf_deep_free(ret_dname);
00517 ldns_rdf_deep_free(in_addr);
00518 return rev;
00519 }
00520
00521 ldns_status
00522 ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
00523 uint8_t *hit_size, uint8_t** hit,
00524 uint16_t *pk_size, uint8_t** pk)
00525 {
00526 uint8_t *data;
00527 size_t rdf_size;
00528
00529 if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
00530 return LDNS_STATUS_INVALID_POINTER;
00531 } else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
00532 return LDNS_STATUS_INVALID_RDF_TYPE;
00533 } else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
00534 return LDNS_STATUS_WIRE_RDATA_ERR;
00535 }
00536 data = ldns_rdf_data(rdf);
00537 *hit_size = data[0];
00538 *alg = data[1];
00539 *pk_size = ldns_read_uint16(data + 2);
00540 *hit = data + 4;
00541 *pk = data + 4 + *hit_size;
00542 if (*hit_size == 0 || *pk_size == 0 ||
00543 rdf_size < (size_t) *hit_size + *pk_size + 4) {
00544 return LDNS_STATUS_WIRE_RDATA_ERR;
00545 }
00546 return LDNS_STATUS_OK;
00547 }
00548
00549 ldns_status
00550 ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
00551 uint8_t hit_size, uint8_t *hit,
00552 uint16_t pk_size, uint8_t *pk)
00553 {
00554 uint8_t *data;
00555
00556 if (! rdf) {
00557 return LDNS_STATUS_INVALID_POINTER;
00558 }
00559 if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
00560 return LDNS_STATUS_RDATA_OVERFLOW;
00561 }
00562 data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
00563 if (data == NULL) {
00564 return LDNS_STATUS_MEM_ERR;
00565 }
00566 data[0] = hit_size;
00567 data[1] = alg;
00568 ldns_write_uint16(data + 2, pk_size);
00569 memcpy(data + 4, hit, hit_size);
00570 memcpy(data + 4 + hit_size, pk, pk_size);
00571 *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
00572 if (! *rdf) {
00573 LDNS_FREE(data);
00574 return LDNS_STATUS_MEM_ERR;
00575 }
00576 return LDNS_STATUS_OK;
00577 }
00578
00579 ldns_status
00580 ldns_octet(char *word, size_t *length)
00581 {
00582 char *s;
00583 char *p;
00584 *length = 0;
00585
00586 for (s = p = word; *s != '\0'; s++,p++) {
00587 switch (*s) {
00588 case '.':
00589 if (s[1] == '.') {
00590 return LDNS_STATUS_EMPTY_LABEL;
00591 }
00592 *p = *s;
00593 (*length)++;
00594 break;
00595 case '\\':
00596 if ('0' <= s[1] && s[1] <= '9' &&
00597 '0' <= s[2] && s[2] <= '9' &&
00598 '0' <= s[3] && s[3] <= '9') {
00599
00600 int val = ((s[1] - '0') * 100 +
00601 (s[2] - '0') * 10 + (s[3] - '0'));
00602
00603 if (0 <= val && val <= 255) {
00604
00605 s += 3;
00606 *p = val;
00607 (*length)++;
00608 } else {
00609 return LDNS_STATUS_DDD_OVERFLOW;
00610 }
00611 } else {
00612
00613
00614 *p = *++s;
00615 (*length)++;
00616 }
00617 break;
00618 case '\"':
00619
00620
00621
00622 *p = *++s;
00623 (*length)++;
00624
00625 if ( *s == '\0' ) {
00626
00627 *p = '\0';
00628 return LDNS_STATUS_OK;
00629 }
00630 break;
00631 default:
00632 *p = *s;
00633 (*length)++;
00634 break;
00635 }
00636 }
00637 *p = '\0';
00638 return LDNS_STATUS_OK;
00639 }
00640
00641 int
00642 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
00643 {
00644 uint16_t i1, i2, i;
00645 uint8_t *d1, *d2;
00646
00647
00648 if (!rd1 && !rd2) {
00649 return 0;
00650 }
00651 if (!rd1 || !rd2) {
00652 return -1;
00653 }
00654 i1 = ldns_rdf_size(rd1);
00655 i2 = ldns_rdf_size(rd2);
00656
00657 if (i1 < i2) {
00658 return -1;
00659 } else if (i1 > i2) {
00660 return +1;
00661 } else {
00662 d1 = (uint8_t*)ldns_rdf_data(rd1);
00663 d2 = (uint8_t*)ldns_rdf_data(rd2);
00664 for(i = 0; i < i1; i++) {
00665 if (d1[i] < d2[i]) {
00666 return -1;
00667 } else if (d1[i] > d2[i]) {
00668 return +1;
00669 }
00670 }
00671 }
00672 return 0;
00673 }
00674
00675 uint32_t
00676 ldns_str2period(const char *nptr, const char **endptr)
00677 {
00678 int sign = 0;
00679 uint32_t i = 0;
00680 uint32_t seconds = 0;
00681
00682 for(*endptr = nptr; **endptr; (*endptr)++) {
00683 switch (**endptr) {
00684 case ' ':
00685 case '\t':
00686 break;
00687 case '-':
00688 if(sign == 0) {
00689 sign = -1;
00690 } else {
00691 return seconds;
00692 }
00693 break;
00694 case '+':
00695 if(sign == 0) {
00696 sign = 1;
00697 } else {
00698 return seconds;
00699 }
00700 break;
00701 case 's':
00702 case 'S':
00703 seconds += i;
00704 i = 0;
00705 break;
00706 case 'm':
00707 case 'M':
00708 seconds += i * 60;
00709 i = 0;
00710 break;
00711 case 'h':
00712 case 'H':
00713 seconds += i * 60 * 60;
00714 i = 0;
00715 break;
00716 case 'd':
00717 case 'D':
00718 seconds += i * 60 * 60 * 24;
00719 i = 0;
00720 break;
00721 case 'w':
00722 case 'W':
00723 seconds += i * 60 * 60 * 24 * 7;
00724 i = 0;
00725 break;
00726 case '0':
00727 case '1':
00728 case '2':
00729 case '3':
00730 case '4':
00731 case '5':
00732 case '6':
00733 case '7':
00734 case '8':
00735 case '9':
00736 i *= 10;
00737 i += (**endptr - '0');
00738 break;
00739 default:
00740 seconds += i;
00741
00742 return seconds;
00743 }
00744 }
00745 seconds += i;
00746
00747 return seconds;
00748 }