1238104Sdes/* 2238104Sdes * rdata.c 3238104Sdes * 4238104Sdes * rdata implementation 5238104Sdes * 6238104Sdes * a Net::DNS like library for C 7238104Sdes * 8238104Sdes * (c) NLnet Labs, 2004-2006 9238104Sdes * 10238104Sdes * See the file LICENSE for the license 11238104Sdes */ 12238104Sdes 13238104Sdes#include <ldns/config.h> 14238104Sdes 15238104Sdes#include <ldns/ldns.h> 16238104Sdes 17238104Sdes/* 18238104Sdes * Access functions 19238104Sdes * do this as functions to get type checking 20238104Sdes */ 21238104Sdes 22238104Sdes/* read */ 23238104Sdessize_t 24238104Sdesldns_rdf_size(const ldns_rdf *rd) 25238104Sdes{ 26238104Sdes assert(rd != NULL); 27238104Sdes return rd->_size; 28238104Sdes} 29238104Sdes 30238104Sdesldns_rdf_type 31238104Sdesldns_rdf_get_type(const ldns_rdf *rd) 32238104Sdes{ 33238104Sdes assert(rd != NULL); 34238104Sdes return rd->_type; 35238104Sdes} 36238104Sdes 37238104Sdesuint8_t * 38238104Sdesldns_rdf_data(const ldns_rdf *rd) 39238104Sdes{ 40238104Sdes assert(rd != NULL); 41238104Sdes return rd->_data; 42238104Sdes} 43238104Sdes 44238104Sdes/* write */ 45238104Sdesvoid 46238104Sdesldns_rdf_set_size(ldns_rdf *rd, size_t size) 47238104Sdes{ 48238104Sdes assert(rd != NULL); 49238104Sdes rd->_size = size; 50238104Sdes} 51238104Sdes 52238104Sdesvoid 53238104Sdesldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type) 54238104Sdes{ 55238104Sdes assert(rd != NULL); 56238104Sdes rd->_type = type; 57238104Sdes} 58238104Sdes 59238104Sdesvoid 60238104Sdesldns_rdf_set_data(ldns_rdf *rd, void *data) 61238104Sdes{ 62238104Sdes /* only copy the pointer */ 63238104Sdes assert(rd != NULL); 64238104Sdes rd->_data = data; 65238104Sdes} 66238104Sdes 67238104Sdes/* for types that allow it, return 68238104Sdes * the native/host order type */ 69238104Sdesuint8_t 70238104Sdesldns_rdf2native_int8(const ldns_rdf *rd) 71238104Sdes{ 72238104Sdes uint8_t data; 73238104Sdes 74238104Sdes /* only allow 8 bit rdfs */ 75238104Sdes if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) { 76238104Sdes return 0; 77238104Sdes } 78238104Sdes 79238104Sdes memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 80238104Sdes return data; 81238104Sdes} 82238104Sdes 83238104Sdesuint16_t 84238104Sdesldns_rdf2native_int16(const ldns_rdf *rd) 85238104Sdes{ 86238104Sdes uint16_t data; 87238104Sdes 88238104Sdes /* only allow 16 bit rdfs */ 89238104Sdes if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) { 90238104Sdes return 0; 91238104Sdes } 92238104Sdes 93238104Sdes memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 94238104Sdes return ntohs(data); 95238104Sdes} 96238104Sdes 97238104Sdesuint32_t 98238104Sdesldns_rdf2native_int32(const ldns_rdf *rd) 99238104Sdes{ 100238104Sdes uint32_t data; 101238104Sdes 102238104Sdes /* only allow 32 bit rdfs */ 103238104Sdes if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) { 104238104Sdes return 0; 105238104Sdes } 106238104Sdes 107238104Sdes memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 108238104Sdes return ntohl(data); 109238104Sdes} 110238104Sdes 111238104Sdestime_t 112238104Sdesldns_rdf2native_time_t(const ldns_rdf *rd) 113238104Sdes{ 114238104Sdes uint32_t data; 115269257Sdes 116269257Sdes /* only allow 32 bit rdfs */ 117269257Sdes if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD || 118269257Sdes ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) { 119269257Sdes return 0; 120238104Sdes } 121269257Sdes memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 122269257Sdes return (time_t)ntohl(data); 123238104Sdes} 124238104Sdes 125238104Sdesldns_rdf * 126238104Sdesldns_native2rdf_int8(ldns_rdf_type type, uint8_t value) 127238104Sdes{ 128238104Sdes return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value); 129238104Sdes} 130238104Sdes 131238104Sdesldns_rdf * 132238104Sdesldns_native2rdf_int16(ldns_rdf_type type, uint16_t value) 133238104Sdes{ 134238104Sdes uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1); 135238104Sdes ldns_rdf* rdf; 136238104Sdes if (!rdf_data) { 137238104Sdes return NULL; 138238104Sdes } 139238104Sdes ldns_write_uint16(rdf_data, value); 140238104Sdes rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data); 141238104Sdes if(!rdf) 142238104Sdes LDNS_FREE(rdf_data); 143238104Sdes return rdf; 144238104Sdes} 145238104Sdes 146238104Sdesldns_rdf * 147238104Sdesldns_native2rdf_int32(ldns_rdf_type type, uint32_t value) 148238104Sdes{ 149238104Sdes uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1); 150238104Sdes ldns_rdf* rdf; 151238104Sdes if (!rdf_data) { 152238104Sdes return NULL; 153238104Sdes } 154238104Sdes ldns_write_uint32(rdf_data, value); 155238104Sdes rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data); 156238104Sdes if(!rdf) 157238104Sdes LDNS_FREE(rdf_data); 158238104Sdes return rdf; 159238104Sdes} 160238104Sdes 161238104Sdesldns_rdf * 162238104Sdesldns_native2rdf_int16_data(size_t size, uint8_t *data) 163238104Sdes{ 164238104Sdes uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2); 165238104Sdes ldns_rdf* rdf; 166238104Sdes if (!rdf_data) { 167238104Sdes return NULL; 168238104Sdes } 169238104Sdes ldns_write_uint16(rdf_data, size); 170238104Sdes memcpy(rdf_data + 2, data, size); 171238104Sdes rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data); 172238104Sdes if(!rdf) 173238104Sdes LDNS_FREE(rdf_data); 174238104Sdes return rdf; 175238104Sdes} 176238104Sdes 177238104Sdes/* note: data must be allocated memory */ 178238104Sdesldns_rdf * 179238104Sdesldns_rdf_new(ldns_rdf_type type, size_t size, void *data) 180238104Sdes{ 181238104Sdes ldns_rdf *rd; 182238104Sdes rd = LDNS_MALLOC(ldns_rdf); 183238104Sdes if (!rd) { 184238104Sdes return NULL; 185238104Sdes } 186238104Sdes ldns_rdf_set_size(rd, size); 187238104Sdes ldns_rdf_set_type(rd, type); 188238104Sdes ldns_rdf_set_data(rd, data); 189238104Sdes return rd; 190238104Sdes} 191238104Sdes 192238104Sdesldns_rdf * 193238104Sdesldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data) 194238104Sdes{ 195238104Sdes ldns_rdf *rdf; 196238104Sdes 197238104Sdes /* if the size is too big, fail */ 198238104Sdes if (size > LDNS_MAX_RDFLEN) { 199238104Sdes return NULL; 200238104Sdes } 201238104Sdes 202238104Sdes /* allocate space */ 203238104Sdes rdf = LDNS_MALLOC(ldns_rdf); 204238104Sdes if (!rdf) { 205238104Sdes return NULL; 206238104Sdes } 207238104Sdes rdf->_data = LDNS_XMALLOC(uint8_t, size); 208238104Sdes if (!rdf->_data) { 209238104Sdes LDNS_FREE(rdf); 210238104Sdes return NULL; 211238104Sdes } 212238104Sdes 213238104Sdes /* set the values */ 214238104Sdes ldns_rdf_set_type(rdf, type); 215238104Sdes ldns_rdf_set_size(rdf, size); 216238104Sdes memcpy(rdf->_data, data, size); 217238104Sdes 218238104Sdes return rdf; 219238104Sdes} 220238104Sdes 221238104Sdesldns_rdf * 222238104Sdesldns_rdf_clone(const ldns_rdf *rd) 223238104Sdes{ 224238104Sdes assert(rd != NULL); 225238104Sdes return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd), 226238104Sdes ldns_rdf_size(rd), ldns_rdf_data(rd))); 227238104Sdes} 228238104Sdes 229238104Sdesvoid 230238104Sdesldns_rdf_deep_free(ldns_rdf *rd) 231238104Sdes{ 232238104Sdes if (rd) { 233238104Sdes if (rd->_data) { 234238104Sdes LDNS_FREE(rd->_data); 235238104Sdes } 236238104Sdes LDNS_FREE(rd); 237238104Sdes } 238238104Sdes} 239238104Sdes 240238104Sdesvoid 241238104Sdesldns_rdf_free(ldns_rdf *rd) 242238104Sdes{ 243238104Sdes if (rd) { 244238104Sdes LDNS_FREE(rd); 245238104Sdes } 246238104Sdes} 247238104Sdes 248238104Sdesldns_rdf * 249238104Sdesldns_rdf_new_frm_str(ldns_rdf_type type, const char *str) 250238104Sdes{ 251238104Sdes ldns_rdf *rdf = NULL; 252238104Sdes ldns_status status; 253238104Sdes 254238104Sdes switch (type) { 255238104Sdes case LDNS_RDF_TYPE_DNAME: 256238104Sdes status = ldns_str2rdf_dname(&rdf, str); 257238104Sdes break; 258238104Sdes case LDNS_RDF_TYPE_INT8: 259238104Sdes status = ldns_str2rdf_int8(&rdf, str); 260238104Sdes break; 261238104Sdes case LDNS_RDF_TYPE_INT16: 262238104Sdes status = ldns_str2rdf_int16(&rdf, str); 263238104Sdes break; 264238104Sdes case LDNS_RDF_TYPE_INT32: 265238104Sdes status = ldns_str2rdf_int32(&rdf, str); 266238104Sdes break; 267238104Sdes case LDNS_RDF_TYPE_A: 268238104Sdes status = ldns_str2rdf_a(&rdf, str); 269238104Sdes break; 270238104Sdes case LDNS_RDF_TYPE_AAAA: 271238104Sdes status = ldns_str2rdf_aaaa(&rdf, str); 272238104Sdes break; 273238104Sdes case LDNS_RDF_TYPE_STR: 274238104Sdes status = ldns_str2rdf_str(&rdf, str); 275238104Sdes break; 276238104Sdes case LDNS_RDF_TYPE_APL: 277238104Sdes status = ldns_str2rdf_apl(&rdf, str); 278238104Sdes break; 279238104Sdes case LDNS_RDF_TYPE_B64: 280238104Sdes status = ldns_str2rdf_b64(&rdf, str); 281238104Sdes break; 282238104Sdes case LDNS_RDF_TYPE_B32_EXT: 283238104Sdes status = ldns_str2rdf_b32_ext(&rdf, str); 284238104Sdes break; 285238104Sdes case LDNS_RDF_TYPE_HEX: 286238104Sdes status = ldns_str2rdf_hex(&rdf, str); 287238104Sdes break; 288238104Sdes case LDNS_RDF_TYPE_NSEC: 289238104Sdes status = ldns_str2rdf_nsec(&rdf, str); 290238104Sdes break; 291238104Sdes case LDNS_RDF_TYPE_TYPE: 292238104Sdes status = ldns_str2rdf_type(&rdf, str); 293238104Sdes break; 294238104Sdes case LDNS_RDF_TYPE_CLASS: 295238104Sdes status = ldns_str2rdf_class(&rdf, str); 296238104Sdes break; 297238104Sdes case LDNS_RDF_TYPE_CERT_ALG: 298238104Sdes status = ldns_str2rdf_cert_alg(&rdf, str); 299238104Sdes break; 300238104Sdes case LDNS_RDF_TYPE_ALG: 301238104Sdes status = ldns_str2rdf_alg(&rdf, str); 302238104Sdes break; 303238104Sdes case LDNS_RDF_TYPE_UNKNOWN: 304238104Sdes status = ldns_str2rdf_unknown(&rdf, str); 305238104Sdes break; 306238104Sdes case LDNS_RDF_TYPE_TIME: 307238104Sdes status = ldns_str2rdf_time(&rdf, str); 308238104Sdes break; 309238104Sdes case LDNS_RDF_TYPE_PERIOD: 310238104Sdes status = ldns_str2rdf_period(&rdf, str); 311238104Sdes break; 312269257Sdes case LDNS_RDF_TYPE_HIP: 313269257Sdes status = ldns_str2rdf_hip(&rdf, str); 314238104Sdes break; 315238104Sdes case LDNS_RDF_TYPE_SERVICE: 316238104Sdes status = ldns_str2rdf_service(&rdf, str); 317238104Sdes break; 318238104Sdes case LDNS_RDF_TYPE_LOC: 319238104Sdes status = ldns_str2rdf_loc(&rdf, str); 320238104Sdes break; 321238104Sdes case LDNS_RDF_TYPE_WKS: 322238104Sdes status = ldns_str2rdf_wks(&rdf, str); 323238104Sdes break; 324238104Sdes case LDNS_RDF_TYPE_NSAP: 325238104Sdes status = ldns_str2rdf_nsap(&rdf, str); 326238104Sdes break; 327238104Sdes case LDNS_RDF_TYPE_ATMA: 328238104Sdes status = ldns_str2rdf_atma(&rdf, str); 329238104Sdes break; 330238104Sdes case LDNS_RDF_TYPE_IPSECKEY: 331238104Sdes status = ldns_str2rdf_ipseckey(&rdf, str); 332238104Sdes break; 333238104Sdes case LDNS_RDF_TYPE_NSEC3_SALT: 334238104Sdes status = ldns_str2rdf_nsec3_salt(&rdf, str); 335238104Sdes break; 336238104Sdes case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 337238104Sdes status = ldns_str2rdf_b32_ext(&rdf, str); 338238104Sdes break; 339269257Sdes case LDNS_RDF_TYPE_ILNP64: 340269257Sdes status = ldns_str2rdf_ilnp64(&rdf, str); 341269257Sdes break; 342269257Sdes case LDNS_RDF_TYPE_EUI48: 343269257Sdes status = ldns_str2rdf_eui48(&rdf, str); 344269257Sdes break; 345269257Sdes case LDNS_RDF_TYPE_EUI64: 346269257Sdes status = ldns_str2rdf_eui64(&rdf, str); 347269257Sdes break; 348269257Sdes case LDNS_RDF_TYPE_TAG: 349269257Sdes status = ldns_str2rdf_tag(&rdf, str); 350269257Sdes break; 351269257Sdes case LDNS_RDF_TYPE_LONG_STR: 352269257Sdes status = ldns_str2rdf_long_str(&rdf, str); 353269257Sdes break; 354238104Sdes case LDNS_RDF_TYPE_NONE: 355238104Sdes default: 356238104Sdes /* default default ??? */ 357238104Sdes status = LDNS_STATUS_ERR; 358238104Sdes break; 359238104Sdes } 360238104Sdes if (LDNS_STATUS_OK == status) { 361238104Sdes ldns_rdf_set_type(rdf, type); 362238104Sdes return rdf; 363238104Sdes } 364238104Sdes if (rdf) { 365238104Sdes LDNS_FREE(rdf); 366238104Sdes } 367238104Sdes return NULL; 368238104Sdes} 369238104Sdes 370238104Sdesldns_status 371238104Sdesldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp) 372238104Sdes{ 373238104Sdes return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL); 374238104Sdes} 375238104Sdes 376238104Sdesldns_status 377238104Sdesldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr) 378238104Sdes{ 379238104Sdes char *line; 380238104Sdes ldns_rdf *r; 381238104Sdes ssize_t t; 382238104Sdes 383238104Sdes line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 384238104Sdes if (!line) { 385238104Sdes return LDNS_STATUS_MEM_ERR; 386238104Sdes } 387238104Sdes 388238104Sdes /* read an entire line in from the file */ 389238104Sdes if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) { 390238104Sdes LDNS_FREE(line); 391238104Sdes return LDNS_STATUS_SYNTAX_RDATA_ERR; 392238104Sdes } 393238104Sdes r = ldns_rdf_new_frm_str(type, (const char*) line); 394238104Sdes LDNS_FREE(line); 395238104Sdes if (rdf) { 396238104Sdes *rdf = r; 397238104Sdes return LDNS_STATUS_OK; 398238104Sdes } else { 399238104Sdes return LDNS_STATUS_NULL; 400238104Sdes } 401238104Sdes} 402238104Sdes 403238104Sdesldns_rdf * 404238104Sdesldns_rdf_address_reverse(ldns_rdf *rd) 405238104Sdes{ 406238104Sdes uint8_t buf_4[LDNS_IP4ADDRLEN]; 407238104Sdes uint8_t buf_6[LDNS_IP6ADDRLEN * 2]; 408238104Sdes ldns_rdf *rev; 409238104Sdes ldns_rdf *in_addr; 410238104Sdes ldns_rdf *ret_dname; 411238104Sdes uint8_t octet; 412238104Sdes uint8_t nnibble; 413238104Sdes uint8_t nibble; 414238104Sdes uint8_t i, j; 415238104Sdes 416238104Sdes char *char_dname; 417238104Sdes int nbit; 418238104Sdes 419238104Sdes if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A && 420238104Sdes ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) { 421238104Sdes return NULL; 422238104Sdes } 423238104Sdes 424238104Sdes in_addr = NULL; 425238104Sdes ret_dname = NULL; 426238104Sdes 427238104Sdes switch(ldns_rdf_get_type(rd)) { 428238104Sdes case LDNS_RDF_TYPE_A: 429238104Sdes /* the length of the buffer is 4 */ 430238104Sdes buf_4[3] = ldns_rdf_data(rd)[0]; 431238104Sdes buf_4[2] = ldns_rdf_data(rd)[1]; 432238104Sdes buf_4[1] = ldns_rdf_data(rd)[2]; 433238104Sdes buf_4[0] = ldns_rdf_data(rd)[3]; 434238104Sdes in_addr = ldns_dname_new_frm_str("in-addr.arpa."); 435238104Sdes if (!in_addr) { 436238104Sdes return NULL; 437238104Sdes } 438238104Sdes /* make a new rdf and convert that back */ 439238104Sdes rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A, 440238104Sdes LDNS_IP4ADDRLEN, (void*)&buf_4); 441238104Sdes if (!rev) { 442238104Sdes LDNS_FREE(in_addr); 443238104Sdes return NULL; 444238104Sdes } 445238104Sdes 446238104Sdes /* convert rev to a string */ 447238104Sdes char_dname = ldns_rdf2str(rev); 448238104Sdes if (!char_dname) { 449238104Sdes LDNS_FREE(in_addr); 450238104Sdes ldns_rdf_deep_free(rev); 451238104Sdes return NULL; 452238104Sdes } 453238104Sdes /* transform back to rdf with type dname */ 454238104Sdes ret_dname = ldns_dname_new_frm_str(char_dname); 455238104Sdes if (!ret_dname) { 456238104Sdes LDNS_FREE(in_addr); 457238104Sdes ldns_rdf_deep_free(rev); 458238104Sdes LDNS_FREE(char_dname); 459238104Sdes return NULL; 460238104Sdes } 461238104Sdes /* not needed anymore */ 462238104Sdes ldns_rdf_deep_free(rev); 463238104Sdes LDNS_FREE(char_dname); 464238104Sdes break; 465238104Sdes case LDNS_RDF_TYPE_AAAA: 466238104Sdes /* some foo magic to reverse the nibbles ... */ 467238104Sdes 468238104Sdes for (nbit = 127; nbit >= 0; nbit = nbit - 4) { 469238104Sdes /* calculate octett (8 bit) */ 470238104Sdes octet = ( ((unsigned int) nbit) & 0x78) >> 3; 471238104Sdes /* calculate nibble */ 472238104Sdes nnibble = ( ((unsigned int) nbit) & 0x04) >> 2; 473238104Sdes /* extract nibble */ 474238104Sdes nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 - 475238104Sdes nnibble)) ) ) >> ( 4 * (1 - 476238104Sdes nnibble)); 477238104Sdes 478238104Sdes buf_6[(LDNS_IP6ADDRLEN * 2 - 1) - 479238104Sdes (octet * 2 + nnibble)] = 480238104Sdes (uint8_t)ldns_int_to_hexdigit((int)nibble); 481238104Sdes } 482238104Sdes 483238104Sdes char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4)); 484238104Sdes if (!char_dname) { 485238104Sdes return NULL; 486238104Sdes } 487238104Sdes char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */ 488238104Sdes 489238104Sdes /* walk the string and add . 's */ 490238104Sdes for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) { 491238104Sdes char_dname[j] = (char)buf_6[i]; 492238104Sdes if (i != LDNS_IP6ADDRLEN * 2 - 1) { 493238104Sdes char_dname[j + 1] = '.'; 494238104Sdes } 495238104Sdes } 496238104Sdes in_addr = ldns_dname_new_frm_str("ip6.arpa."); 497238104Sdes if (!in_addr) { 498238104Sdes LDNS_FREE(char_dname); 499238104Sdes return NULL; 500238104Sdes } 501238104Sdes 502238104Sdes /* convert rev to a string */ 503238104Sdes ret_dname = ldns_dname_new_frm_str(char_dname); 504238104Sdes LDNS_FREE(char_dname); 505238104Sdes if (!ret_dname) { 506238104Sdes ldns_rdf_deep_free(in_addr); 507238104Sdes return NULL; 508238104Sdes } 509238104Sdes break; 510238104Sdes default: 511238104Sdes break; 512238104Sdes } 513238104Sdes /* add the suffix */ 514238104Sdes rev = ldns_dname_cat_clone(ret_dname, in_addr); 515238104Sdes 516238104Sdes ldns_rdf_deep_free(ret_dname); 517238104Sdes ldns_rdf_deep_free(in_addr); 518238104Sdes return rev; 519238104Sdes} 520238104Sdes 521238104Sdesldns_status 522269257Sdesldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg, 523269257Sdes uint8_t *hit_size, uint8_t** hit, 524269257Sdes uint16_t *pk_size, uint8_t** pk) 525269257Sdes{ 526269257Sdes uint8_t *data; 527269257Sdes size_t rdf_size; 528269257Sdes 529269257Sdes if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) { 530269257Sdes return LDNS_STATUS_INVALID_POINTER; 531269257Sdes } else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) { 532269257Sdes return LDNS_STATUS_INVALID_RDF_TYPE; 533269257Sdes } else if ((rdf_size = ldns_rdf_size(rdf)) < 6) { 534269257Sdes return LDNS_STATUS_WIRE_RDATA_ERR; 535269257Sdes } 536269257Sdes data = ldns_rdf_data(rdf); 537269257Sdes *hit_size = data[0]; 538269257Sdes *alg = data[1]; 539269257Sdes *pk_size = ldns_read_uint16(data + 2); 540269257Sdes *hit = data + 4; 541269257Sdes *pk = data + 4 + *hit_size; 542269257Sdes if (*hit_size == 0 || *pk_size == 0 || 543269257Sdes rdf_size < (size_t) *hit_size + *pk_size + 4) { 544269257Sdes return LDNS_STATUS_WIRE_RDATA_ERR; 545269257Sdes } 546269257Sdes return LDNS_STATUS_OK; 547269257Sdes} 548269257Sdes 549269257Sdesldns_status 550269257Sdesldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg, 551269257Sdes uint8_t hit_size, uint8_t *hit, 552269257Sdes uint16_t pk_size, uint8_t *pk) 553269257Sdes{ 554269257Sdes uint8_t *data; 555269257Sdes 556269257Sdes if (! rdf) { 557269257Sdes return LDNS_STATUS_INVALID_POINTER; 558269257Sdes } 559269257Sdes if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) { 560269257Sdes return LDNS_STATUS_RDATA_OVERFLOW; 561269257Sdes } 562269257Sdes data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size); 563269257Sdes if (data == NULL) { 564269257Sdes return LDNS_STATUS_MEM_ERR; 565269257Sdes } 566269257Sdes data[0] = hit_size; 567269257Sdes data[1] = alg; 568269257Sdes ldns_write_uint16(data + 2, pk_size); 569269257Sdes memcpy(data + 4, hit, hit_size); 570269257Sdes memcpy(data + 4 + hit_size, pk, pk_size); 571269257Sdes *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data); 572269257Sdes if (! *rdf) { 573269257Sdes LDNS_FREE(data); 574269257Sdes return LDNS_STATUS_MEM_ERR; 575269257Sdes } 576269257Sdes return LDNS_STATUS_OK; 577269257Sdes} 578269257Sdes 579269257Sdesldns_status 580238104Sdesldns_octet(char *word, size_t *length) 581238104Sdes{ 582238104Sdes char *s; 583238104Sdes char *p; 584238104Sdes *length = 0; 585238104Sdes 586238104Sdes for (s = p = word; *s != '\0'; s++,p++) { 587238104Sdes switch (*s) { 588238104Sdes case '.': 589238104Sdes if (s[1] == '.') { 590238104Sdes return LDNS_STATUS_EMPTY_LABEL; 591238104Sdes } 592238104Sdes *p = *s; 593238104Sdes (*length)++; 594238104Sdes break; 595238104Sdes case '\\': 596238104Sdes if ('0' <= s[1] && s[1] <= '9' && 597238104Sdes '0' <= s[2] && s[2] <= '9' && 598238104Sdes '0' <= s[3] && s[3] <= '9') { 599238104Sdes /* \DDD seen */ 600238104Sdes int val = ((s[1] - '0') * 100 + 601238104Sdes (s[2] - '0') * 10 + (s[3] - '0')); 602238104Sdes 603238104Sdes if (0 <= val && val <= 255) { 604238104Sdes /* this also handles \0 */ 605238104Sdes s += 3; 606238104Sdes *p = val; 607238104Sdes (*length)++; 608238104Sdes } else { 609238104Sdes return LDNS_STATUS_DDD_OVERFLOW; 610238104Sdes } 611238104Sdes } else { 612238104Sdes /* an espaced character, like \<space> ? 613238104Sdes * remove the '\' keep the rest */ 614238104Sdes *p = *++s; 615238104Sdes (*length)++; 616238104Sdes } 617238104Sdes break; 618238104Sdes case '\"': 619238104Sdes /* non quoted " Is either first or the last character in 620238104Sdes * the string */ 621238104Sdes 622238104Sdes *p = *++s; /* skip it */ 623238104Sdes (*length)++; 624238104Sdes /* I'm not sure if this is needed in libdns... MG */ 625238104Sdes if ( *s == '\0' ) { 626238104Sdes /* ok, it was the last one */ 627238104Sdes *p = '\0'; 628238104Sdes return LDNS_STATUS_OK; 629238104Sdes } 630238104Sdes break; 631238104Sdes default: 632238104Sdes *p = *s; 633238104Sdes (*length)++; 634238104Sdes break; 635238104Sdes } 636238104Sdes } 637238104Sdes *p = '\0'; 638238104Sdes return LDNS_STATUS_OK; 639238104Sdes} 640238104Sdes 641238104Sdesint 642238104Sdesldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2) 643238104Sdes{ 644238104Sdes uint16_t i1, i2, i; 645238104Sdes uint8_t *d1, *d2; 646238104Sdes 647238104Sdes /* only when both are not NULL we can say anything about them */ 648238104Sdes if (!rd1 && !rd2) { 649238104Sdes return 0; 650238104Sdes } 651238104Sdes if (!rd1 || !rd2) { 652238104Sdes return -1; 653238104Sdes } 654238104Sdes i1 = ldns_rdf_size(rd1); 655238104Sdes i2 = ldns_rdf_size(rd2); 656238104Sdes 657238104Sdes if (i1 < i2) { 658238104Sdes return -1; 659238104Sdes } else if (i1 > i2) { 660238104Sdes return +1; 661238104Sdes } else { 662238104Sdes d1 = (uint8_t*)ldns_rdf_data(rd1); 663238104Sdes d2 = (uint8_t*)ldns_rdf_data(rd2); 664238104Sdes for(i = 0; i < i1; i++) { 665238104Sdes if (d1[i] < d2[i]) { 666238104Sdes return -1; 667238104Sdes } else if (d1[i] > d2[i]) { 668238104Sdes return +1; 669238104Sdes } 670238104Sdes } 671238104Sdes } 672238104Sdes return 0; 673238104Sdes} 674238104Sdes 675238104Sdesuint32_t 676238104Sdesldns_str2period(const char *nptr, const char **endptr) 677238104Sdes{ 678238104Sdes int sign = 0; 679238104Sdes uint32_t i = 0; 680238104Sdes uint32_t seconds = 0; 681238104Sdes 682238104Sdes for(*endptr = nptr; **endptr; (*endptr)++) { 683238104Sdes switch (**endptr) { 684238104Sdes case ' ': 685238104Sdes case '\t': 686238104Sdes break; 687238104Sdes case '-': 688238104Sdes if(sign == 0) { 689238104Sdes sign = -1; 690238104Sdes } else { 691238104Sdes return seconds; 692238104Sdes } 693238104Sdes break; 694238104Sdes case '+': 695238104Sdes if(sign == 0) { 696238104Sdes sign = 1; 697238104Sdes } else { 698238104Sdes return seconds; 699238104Sdes } 700238104Sdes break; 701238104Sdes case 's': 702238104Sdes case 'S': 703238104Sdes seconds += i; 704238104Sdes i = 0; 705238104Sdes break; 706238104Sdes case 'm': 707238104Sdes case 'M': 708238104Sdes seconds += i * 60; 709238104Sdes i = 0; 710238104Sdes break; 711238104Sdes case 'h': 712238104Sdes case 'H': 713238104Sdes seconds += i * 60 * 60; 714238104Sdes i = 0; 715238104Sdes break; 716238104Sdes case 'd': 717238104Sdes case 'D': 718238104Sdes seconds += i * 60 * 60 * 24; 719238104Sdes i = 0; 720238104Sdes break; 721238104Sdes case 'w': 722238104Sdes case 'W': 723238104Sdes seconds += i * 60 * 60 * 24 * 7; 724238104Sdes i = 0; 725238104Sdes break; 726238104Sdes case '0': 727238104Sdes case '1': 728238104Sdes case '2': 729238104Sdes case '3': 730238104Sdes case '4': 731238104Sdes case '5': 732238104Sdes case '6': 733238104Sdes case '7': 734238104Sdes case '8': 735238104Sdes case '9': 736238104Sdes i *= 10; 737238104Sdes i += (**endptr - '0'); 738238104Sdes break; 739238104Sdes default: 740238104Sdes seconds += i; 741238104Sdes /* disregard signedness */ 742238104Sdes return seconds; 743238104Sdes } 744238104Sdes } 745238104Sdes seconds += i; 746238104Sdes /* disregard signedness */ 747238104Sdes return seconds; 748238104Sdes} 749