1238104Sdes/* 2238104Sdes * util.h 3238104Sdes * 4238104Sdes * helper function header file 5238104Sdes * 6238104Sdes * a Net::DNS like library for C 7238104Sdes * 8238104Sdes * (c) NLnet Labs, 2004 9238104Sdes * 10238104Sdes * See the file LICENSE for the license 11238104Sdes */ 12238104Sdes 13238104Sdes#ifndef _UTIL_H 14238104Sdes#define _UTIL_H 15238104Sdes 16238104Sdes@include_inttypes_h@ 17238104Sdes@include_systypes_h@ 18238104Sdes@include_unistd_h@ 19238104Sdes#include <ldns/common.h> 20238104Sdes#include <time.h> 21238104Sdes#include <stdio.h> 22238104Sdes 23238104Sdes#ifdef __cplusplus 24238104Sdesextern "C" { 25238104Sdes#endif 26238104Sdes 27238104Sdes#define dprintf(X,Y) fprintf(stderr, (X), (Y)) 28238104Sdes/* #define dprintf(X, Y) */ 29238104Sdes 30238104Sdes#define LDNS_VERSION "@PACKAGE_VERSION@" 31238104Sdes#define LDNS_REVISION ((@LDNS_VERSION_MAJOR@<<16)|(@LDNS_VERSION_MINOR@<<8)|(@LDNS_VERSION_MICRO@)) 32238104Sdes 33238104Sdes/** 34238104Sdes * splint static inline workaround 35238104Sdes */ 36238104Sdes#ifdef S_SPLINT_S 37238104Sdes# define INLINE 38238104Sdes#else 39238104Sdes# ifdef SWIG 40238104Sdes# define INLINE static 41238104Sdes# else 42238104Sdes# define INLINE static inline 43238104Sdes# endif 44238104Sdes#endif 45238104Sdes 46238104Sdes/** 47238104Sdes * Memory management macros 48238104Sdes */ 49238104Sdes#define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) 50238104Sdes 51238104Sdes#define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) 52238104Sdes 53238104Sdes#define LDNS_CALLOC(type, count) ((type *) calloc((count), sizeof(type))) 54238104Sdes 55238104Sdes#define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) 56238104Sdes 57238104Sdes#define LDNS_XREALLOC(ptr, type, count) \ 58238104Sdes ((type *) realloc((ptr), (count) * sizeof(type))) 59238104Sdes 60238104Sdes#define LDNS_FREE(ptr) \ 61238104Sdes do { free((ptr)); (ptr) = NULL; } while (0) 62238104Sdes 63238104Sdes#define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); 64238104Sdes 65238104Sdes/* 66238104Sdes * Copy data allowing for unaligned accesses in network byte order 67238104Sdes * (big endian). 68238104Sdes */ 69238104SdesINLINE uint16_t 70238104Sdesldns_read_uint16(const void *src) 71238104Sdes{ 72238104Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 73266238Sdes return ntohs(*(const uint16_t *) src); 74238104Sdes#else 75266238Sdes const uint8_t *p = (const uint8_t *) src; 76238104Sdes return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; 77238104Sdes#endif 78238104Sdes} 79238104Sdes 80238104SdesINLINE uint32_t 81238104Sdesldns_read_uint32(const void *src) 82238104Sdes{ 83238104Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 84266238Sdes return ntohl(*(const uint32_t *) src); 85238104Sdes#else 86266238Sdes const uint8_t *p = (const uint8_t *) src; 87238104Sdes return ( ((uint32_t) p[0] << 24) 88238104Sdes | ((uint32_t) p[1] << 16) 89238104Sdes | ((uint32_t) p[2] << 8) 90238104Sdes | (uint32_t) p[3]); 91238104Sdes#endif 92238104Sdes} 93238104Sdes 94238104Sdes/* 95238104Sdes * Copy data allowing for unaligned accesses in network byte order 96238104Sdes * (big endian). 97238104Sdes */ 98238104SdesINLINE void 99238104Sdesldns_write_uint16(void *dst, uint16_t data) 100238104Sdes{ 101238104Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 102238104Sdes * (uint16_t *) dst = htons(data); 103238104Sdes#else 104238104Sdes uint8_t *p = (uint8_t *) dst; 105238104Sdes p[0] = (uint8_t) ((data >> 8) & 0xff); 106238104Sdes p[1] = (uint8_t) (data & 0xff); 107238104Sdes#endif 108238104Sdes} 109238104Sdes 110238104SdesINLINE void 111238104Sdesldns_write_uint32(void *dst, uint32_t data) 112238104Sdes{ 113238104Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 114238104Sdes * (uint32_t *) dst = htonl(data); 115238104Sdes#else 116238104Sdes uint8_t *p = (uint8_t *) dst; 117238104Sdes p[0] = (uint8_t) ((data >> 24) & 0xff); 118238104Sdes p[1] = (uint8_t) ((data >> 16) & 0xff); 119238104Sdes p[2] = (uint8_t) ((data >> 8) & 0xff); 120238104Sdes p[3] = (uint8_t) (data & 0xff); 121238104Sdes#endif 122238104Sdes} 123238104Sdes 124238104Sdes/* warning. */ 125238104SdesINLINE void 126238104Sdesldns_write_uint64_as_uint48(void *dst, uint64_t data) 127238104Sdes{ 128238104Sdes uint8_t *p = (uint8_t *) dst; 129238104Sdes p[0] = (uint8_t) ((data >> 40) & 0xff); 130238104Sdes p[1] = (uint8_t) ((data >> 32) & 0xff); 131238104Sdes p[2] = (uint8_t) ((data >> 24) & 0xff); 132238104Sdes p[3] = (uint8_t) ((data >> 16) & 0xff); 133238104Sdes p[4] = (uint8_t) ((data >> 8) & 0xff); 134238104Sdes p[5] = (uint8_t) (data & 0xff); 135238104Sdes} 136238104Sdes 137238104Sdes 138238104Sdes/** 139238104Sdes * Structure to do a Schwartzian-like transformation, for instance when 140238104Sdes * sorting. If you need a transformation on the objects that are sorted, 141238104Sdes * you can sue this to store the transformed values, so you do not 142238104Sdes * need to do the transformation again for each comparison 143238104Sdes */ 144238104Sdesstruct ldns_schwartzian_compare_struct { 145238104Sdes void *original_object; 146238104Sdes void *transformed_object; 147238104Sdes}; 148238104Sdes 149238104Sdes/** A general purpose lookup table 150238104Sdes * 151238104Sdes * Lookup tables are arrays of (id, name) pairs, 152238104Sdes * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", 153238104Sdes * and vice versa. The lookup tables themselves are defined wherever needed, 154238104Sdes * for instance in \ref host2str.c 155238104Sdes */ 156238104Sdesstruct ldns_struct_lookup_table { 157238104Sdes int id; 158238104Sdes const char *name; 159238104Sdes}; 160238104Sdestypedef struct ldns_struct_lookup_table ldns_lookup_table; 161238104Sdes 162238104Sdes/** 163238104Sdes * Looks up the table entry by name, returns NULL if not found. 164238104Sdes * \param[in] table the lookup table to search in 165238104Sdes * \param[in] name what to search for 166238104Sdes * \return the item found 167238104Sdes */ 168238104Sdesldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], 169238104Sdes const char *name); 170238104Sdes 171238104Sdes/** 172238104Sdes * Looks up the table entry by id, returns NULL if not found. 173238104Sdes * \param[in] table the lookup table to search in 174238104Sdes * \param[in] id what to search for 175238104Sdes * \return the item found 176238104Sdes */ 177238104Sdesldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); 178238104Sdes 179238104Sdes/** 180238104Sdes * Returns the value of the specified bit 181238104Sdes * The bits are counted from left to right, so bit #0 is the 182238104Sdes * left most bit. 183238104Sdes * \param[in] bits array holding the bits 184238104Sdes * \param[in] index to the wanted bit 185238104Sdes * \return 186238104Sdes */ 187238104Sdesint ldns_get_bit(uint8_t bits[], size_t index); 188238104Sdes 189238104Sdes 190238104Sdes/** 191238104Sdes * Returns the value of the specified bit 192238104Sdes * The bits are counted from right to left, so bit #0 is the 193238104Sdes * right most bit. 194238104Sdes * \param[in] bits array holding the bits 195238104Sdes * \param[in] index to the wanted bit 196238104Sdes * \return 1 or 0 depending no the bit state 197238104Sdes */ 198238104Sdesint ldns_get_bit_r(uint8_t bits[], size_t index); 199238104Sdes 200238104Sdes/** 201238104Sdes * sets the specified bit in the specified byte to 202238104Sdes * 1 if value is true, 0 if false 203238104Sdes * The bits are counted from right to left, so bit #0 is the 204238104Sdes * right most bit. 205238104Sdes * \param[in] byte the bit to set the bit in 206238104Sdes * \param[in] bit_nr the bit to set (0 <= n <= 7) 207238104Sdes * \param[in] value whether to set the bit to 1 or 0 208238104Sdes * \return 1 or 0 depending no the bit state 209238104Sdes */ 210238104Sdesvoid ldns_set_bit(uint8_t *byte, int bit_nr, bool value); 211238104Sdes 212238104Sdes/** 213238104Sdes * Returns the value of a to the power of b 214238104Sdes * (or 1 of b < 1) 215238104Sdes */ 216238104Sdes/*@unused@*/ 217238104SdesINLINE long 218238104Sdesldns_power(long a, long b) { 219238104Sdes long result = 1; 220238104Sdes while (b > 0) { 221238104Sdes if (b & 1) { 222238104Sdes result *= a; 223238104Sdes if (b == 1) { 224238104Sdes return result; 225238104Sdes } 226238104Sdes } 227238104Sdes a *= a; 228238104Sdes b /= 2; 229238104Sdes } 230238104Sdes return result; 231238104Sdes} 232238104Sdes 233238104Sdes/** 234238104Sdes * Returns the int value of the given (hex) digit 235238104Sdes * \param[in] ch the hex char to convert 236238104Sdes * \return the converted decimal value 237238104Sdes */ 238238104Sdesint ldns_hexdigit_to_int(char ch); 239238104Sdes 240238104Sdes/** 241238104Sdes * Returns the char (hex) representation of the given int 242238104Sdes * \param[in] ch the int to convert 243238104Sdes * \return the converted hex char 244238104Sdes */ 245238104Sdeschar ldns_int_to_hexdigit(int ch); 246238104Sdes 247238104Sdes/** 248238104Sdes * Converts a hex string to binary data 249238104Sdes * 250238104Sdes * \param[out] data The binary result is placed here. 251238104Sdes * At least strlen(str)/2 bytes should be allocated 252238104Sdes * \param[in] str The hex string to convert. 253238104Sdes * This string should not contain spaces 254238104Sdes * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number 255238104Sdes */ 256238104Sdesint 257238104Sdesldns_hexstring_to_data(uint8_t *data, const char *str); 258238104Sdes 259238104Sdes/** 260238104Sdes * Show the internal library version 261238104Sdes * \return a string with the version in it 262238104Sdes */ 263238104Sdesconst char * ldns_version(void); 264238104Sdes 265238104Sdes/** 266238104Sdes * Convert TM to seconds since epoch (midnight, January 1st, 1970). 267238104Sdes * Like timegm(3), which is not always available. 268238104Sdes * \param[in] tm a struct tm* with the date 269238104Sdes * \return the seconds since epoch 270238104Sdes */ 271246854Sdestime_t ldns_mktime_from_utc(const struct tm *tm); 272246854Sdes 273238104Sdestime_t mktime_from_utc(const struct tm *tm); 274238104Sdes 275238104Sdes/** 276238104Sdes * The function interprets time as the number of seconds since epoch 277238104Sdes * with respect to now using serial arithmitics (rfc1982). 278238104Sdes * That number of seconds is then converted to broken-out time information. 279238104Sdes * This is especially usefull when converting the inception and expiration 280238104Sdes * fields of RRSIG records. 281238104Sdes * 282238104Sdes * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) 283238104Sdes * to be intepreted as a serial arithmitics number relative to now. 284238104Sdes * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) 285238104Sdes * to which the time value is compared to determine the final value. 286238104Sdes * \param[out] result the struct with the broken-out time information 287238104Sdes * \return result on success or NULL on error 288238104Sdes */ 289238104Sdesstruct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); 290238104Sdes 291238104Sdes/** 292238104Sdes * Seed the random function. 293238104Sdes * If the file descriptor is specified, the random generator is seeded with 294238104Sdes * data from that file. If not, /dev/urandom is used. 295238104Sdes * 296238104Sdes * applications should call this if they need entropy data within ldns 297238104Sdes * If openSSL is available, it is automatically seeded from /dev/urandom 298238104Sdes * or /dev/random. 299238104Sdes * 300238104Sdes * If you need more entropy, or have no openssl available, this function 301238104Sdes * MUST be called at the start of the program 302238104Sdes * 303238104Sdes * If openssl *is* available, this function just adds more entropy 304238104Sdes * 305238104Sdes * \param[in] fd a file providing entropy data for the seed 306238104Sdes * \param[in] size the number of bytes to use as entropy data. If this is 0, 307238104Sdes * only the minimal amount is taken (usually 4 bytes) 308238104Sdes * \return 0 if seeding succeeds, 1 if it fails 309238104Sdes */ 310238104Sdesint ldns_init_random(FILE *fd, unsigned int size); 311238104Sdes 312238104Sdes/** 313238104Sdes * Get random number. 314238104Sdes * \return random number. 315238104Sdes * 316238104Sdes */ 317238104Sdesuint16_t ldns_get_random(void); 318238104Sdes 319238104Sdes/** 320238104Sdes * Encode data as BubbleBabble 321238104Sdes * 322238104Sdes * \param[in] data a pointer to data to be encoded 323238104Sdes * \param[in] len size the number of bytes of data 324238104Sdes * \return a string of BubbleBabble 325238104Sdes */ 326238104Sdeschar *ldns_bubblebabble(uint8_t *data, size_t len); 327238104Sdes 328266114Sdes 329266114SdesINLINE time_t ldns_time(time_t *t) { return time(t); } 330266114Sdes 331266114Sdes 332238104Sdes/** 333238104Sdes * calculates the size needed to store the result of b32_ntop 334238104Sdes */ 335238104Sdes/*@unused@*/ 336266114SdesINLINE size_t ldns_b32_ntop_calculate_size(size_t src_data_length) 337238104Sdes{ 338266114Sdes return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8; 339238104Sdes} 340266114Sdes 341266114SdesINLINE size_t ldns_b32_ntop_calculate_size_no_padding(size_t src_data_length) 342266114Sdes{ 343266114Sdes return ((src_data_length + 3) * 8 / 5) - 4; 344266114Sdes} 345266114Sdes 346266114Sdesint ldns_b32_ntop(const uint8_t* src_data, size_t src_data_length, 347266114Sdes char* target_text_buffer, size_t target_text_buffer_size); 348266114Sdes 349266114Sdesint ldns_b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length, 350266114Sdes char* target_text_buffer, size_t target_text_buffer_size); 351266114Sdes 352266114Sdes#if ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP 353266114Sdes 354266114Sdesint b32_ntop(const uint8_t* src_data, size_t src_data_length, 355266114Sdes char* target_text_buffer, size_t target_text_buffer_size); 356266114Sdes 357266114Sdesint b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length, 358266114Sdes char* target_text_buffer, size_t target_text_buffer_size); 359266114Sdes 360266114Sdes#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP */ 361266114Sdes 362266114Sdes 363238104Sdes/** 364238104Sdes * calculates the size needed to store the result of b32_pton 365238104Sdes */ 366238104Sdes/*@unused@*/ 367266114SdesINLINE size_t ldns_b32_pton_calculate_size(size_t src_text_length) 368238104Sdes{ 369266114Sdes return src_text_length * 5 / 8; 370238104Sdes} 371238104Sdes 372266114Sdesint ldns_b32_pton(const char* src_text, size_t src_text_length, 373266114Sdes uint8_t* target_data_buffer, size_t target_data_buffer_size); 374238104Sdes 375266114Sdesint ldns_b32_pton_extended_hex(const char* src_text, size_t src_text_length, 376266114Sdes uint8_t* target_data_buffer, size_t target_data_buffer_size); 377266114Sdes 378266114Sdes#if ! LDNS_BUILD_CONFIG_HAVE_B32_PTON 379266114Sdes 380266114Sdesint b32_pton(const char* src_text, size_t src_text_length, 381266114Sdes uint8_t* target_data_buffer, size_t target_data_buffer_size); 382266114Sdes 383266114Sdesint b32_pton_extended_hex(const char* src_text, size_t src_text_length, 384266114Sdes uint8_t* target_data_buffer, size_t target_data_buffer_size); 385266114Sdes 386266114Sdes#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_PTON */ 387266114Sdes 388266114Sdes 389238104Sdes#ifdef __cplusplus 390238104Sdes} 391238104Sdes#endif 392238104Sdes 393238104Sdes#endif /* !_UTIL_H */ 394