1246853Sdes/* 2246853Sdes * util.h 3246853Sdes * 4246853Sdes * helper function header file 5246853Sdes * 6246853Sdes * a Net::DNS like library for C 7246853Sdes * 8246853Sdes * (c) NLnet Labs, 2004 9246853Sdes * 10246853Sdes * See the file LICENSE for the license 11246853Sdes */ 12246853Sdes 13246853Sdes#ifndef _UTIL_H 14246853Sdes#define _UTIL_H 15246853Sdes 16246853Sdes#include <inttypes.h> 17246853Sdes#include <sys/types.h> 18246853Sdes#include <unistd.h> 19246853Sdes#include <ldns/common.h> 20246853Sdes#include <time.h> 21246853Sdes#include <stdio.h> 22246853Sdes 23246853Sdes#ifdef __cplusplus 24246853Sdesextern "C" { 25246853Sdes#endif 26246853Sdes 27246853Sdes#define dprintf(X,Y) fprintf(stderr, (X), (Y)) 28246853Sdes/* #define dprintf(X, Y) */ 29246853Sdes 30266114Sdes#define LDNS_VERSION "1.6.17" 31266114Sdes#define LDNS_REVISION ((1<<16)|(6<<8)|(17)) 32246853Sdes 33246853Sdes/** 34246853Sdes * splint static inline workaround 35246853Sdes */ 36246853Sdes#ifdef S_SPLINT_S 37246853Sdes# define INLINE 38246853Sdes#else 39246853Sdes# ifdef SWIG 40246853Sdes# define INLINE static 41246853Sdes# else 42246853Sdes# define INLINE static inline 43246853Sdes# endif 44246853Sdes#endif 45246853Sdes 46246853Sdes/** 47246853Sdes * Memory management macros 48246853Sdes */ 49246853Sdes#define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) 50246853Sdes 51246853Sdes#define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) 52246853Sdes 53246853Sdes#define LDNS_CALLOC(type, count) ((type *) calloc((count), sizeof(type))) 54246853Sdes 55246853Sdes#define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) 56246853Sdes 57246853Sdes#define LDNS_XREALLOC(ptr, type, count) \ 58246853Sdes ((type *) realloc((ptr), (count) * sizeof(type))) 59246853Sdes 60246853Sdes#define LDNS_FREE(ptr) \ 61246853Sdes do { free((ptr)); (ptr) = NULL; } while (0) 62246853Sdes 63246853Sdes#define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); 64246853Sdes 65246853Sdes/* 66246853Sdes * Copy data allowing for unaligned accesses in network byte order 67246853Sdes * (big endian). 68246853Sdes */ 69246853SdesINLINE uint16_t 70246853Sdesldns_read_uint16(const void *src) 71246853Sdes{ 72246853Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 73266238Sdes return ntohs(*(const uint16_t *) src); 74246853Sdes#else 75266238Sdes const uint8_t *p = (const uint8_t *) src; 76246853Sdes return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; 77246853Sdes#endif 78246853Sdes} 79246853Sdes 80246853SdesINLINE uint32_t 81246853Sdesldns_read_uint32(const void *src) 82246853Sdes{ 83246853Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 84266238Sdes return ntohl(*(const uint32_t *) src); 85246853Sdes#else 86266238Sdes const uint8_t *p = (const uint8_t *) src; 87246853Sdes return ( ((uint32_t) p[0] << 24) 88246853Sdes | ((uint32_t) p[1] << 16) 89246853Sdes | ((uint32_t) p[2] << 8) 90246853Sdes | (uint32_t) p[3]); 91246853Sdes#endif 92246853Sdes} 93246853Sdes 94246853Sdes/* 95246853Sdes * Copy data allowing for unaligned accesses in network byte order 96246853Sdes * (big endian). 97246853Sdes */ 98246853SdesINLINE void 99246853Sdesldns_write_uint16(void *dst, uint16_t data) 100246853Sdes{ 101246853Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 102246853Sdes * (uint16_t *) dst = htons(data); 103246853Sdes#else 104246853Sdes uint8_t *p = (uint8_t *) dst; 105246853Sdes p[0] = (uint8_t) ((data >> 8) & 0xff); 106246853Sdes p[1] = (uint8_t) (data & 0xff); 107246853Sdes#endif 108246853Sdes} 109246853Sdes 110246853SdesINLINE void 111246853Sdesldns_write_uint32(void *dst, uint32_t data) 112246853Sdes{ 113246853Sdes#ifdef ALLOW_UNALIGNED_ACCESSES 114246853Sdes * (uint32_t *) dst = htonl(data); 115246853Sdes#else 116246853Sdes uint8_t *p = (uint8_t *) dst; 117246853Sdes p[0] = (uint8_t) ((data >> 24) & 0xff); 118246853Sdes p[1] = (uint8_t) ((data >> 16) & 0xff); 119246853Sdes p[2] = (uint8_t) ((data >> 8) & 0xff); 120246853Sdes p[3] = (uint8_t) (data & 0xff); 121246853Sdes#endif 122246853Sdes} 123246853Sdes 124246853Sdes/* warning. */ 125246853SdesINLINE void 126246853Sdesldns_write_uint64_as_uint48(void *dst, uint64_t data) 127246853Sdes{ 128246853Sdes uint8_t *p = (uint8_t *) dst; 129246853Sdes p[0] = (uint8_t) ((data >> 40) & 0xff); 130246853Sdes p[1] = (uint8_t) ((data >> 32) & 0xff); 131246853Sdes p[2] = (uint8_t) ((data >> 24) & 0xff); 132246853Sdes p[3] = (uint8_t) ((data >> 16) & 0xff); 133246853Sdes p[4] = (uint8_t) ((data >> 8) & 0xff); 134246853Sdes p[5] = (uint8_t) (data & 0xff); 135246853Sdes} 136246853Sdes 137246853Sdes 138246853Sdes/** 139246853Sdes * Structure to do a Schwartzian-like transformation, for instance when 140246853Sdes * sorting. If you need a transformation on the objects that are sorted, 141246853Sdes * you can sue this to store the transformed values, so you do not 142246853Sdes * need to do the transformation again for each comparison 143246853Sdes */ 144246853Sdesstruct ldns_schwartzian_compare_struct { 145246853Sdes void *original_object; 146246853Sdes void *transformed_object; 147246853Sdes}; 148246853Sdes 149246853Sdes/** A general purpose lookup table 150246853Sdes * 151246853Sdes * Lookup tables are arrays of (id, name) pairs, 152246853Sdes * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", 153246853Sdes * and vice versa. The lookup tables themselves are defined wherever needed, 154246853Sdes * for instance in \ref host2str.c 155246853Sdes */ 156246853Sdesstruct ldns_struct_lookup_table { 157246853Sdes int id; 158246853Sdes const char *name; 159246853Sdes}; 160246853Sdestypedef struct ldns_struct_lookup_table ldns_lookup_table; 161246853Sdes 162246853Sdes/** 163246853Sdes * Looks up the table entry by name, returns NULL if not found. 164246853Sdes * \param[in] table the lookup table to search in 165246853Sdes * \param[in] name what to search for 166246853Sdes * \return the item found 167246853Sdes */ 168246853Sdesldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], 169246853Sdes const char *name); 170246853Sdes 171246853Sdes/** 172246853Sdes * Looks up the table entry by id, returns NULL if not found. 173246853Sdes * \param[in] table the lookup table to search in 174246853Sdes * \param[in] id what to search for 175246853Sdes * \return the item found 176246853Sdes */ 177246853Sdesldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); 178246853Sdes 179246853Sdes/** 180246853Sdes * Returns the value of the specified bit 181246853Sdes * The bits are counted from left to right, so bit #0 is the 182246853Sdes * left most bit. 183246853Sdes * \param[in] bits array holding the bits 184246853Sdes * \param[in] index to the wanted bit 185246853Sdes * \return 186246853Sdes */ 187246853Sdesint ldns_get_bit(uint8_t bits[], size_t index); 188246853Sdes 189246853Sdes 190246853Sdes/** 191246853Sdes * Returns the value of the specified bit 192246853Sdes * The bits are counted from right to left, so bit #0 is the 193246853Sdes * right most bit. 194246853Sdes * \param[in] bits array holding the bits 195246853Sdes * \param[in] index to the wanted bit 196246853Sdes * \return 1 or 0 depending no the bit state 197246853Sdes */ 198246853Sdesint ldns_get_bit_r(uint8_t bits[], size_t index); 199246853Sdes 200246853Sdes/** 201246853Sdes * sets the specified bit in the specified byte to 202246853Sdes * 1 if value is true, 0 if false 203246853Sdes * The bits are counted from right to left, so bit #0 is the 204246853Sdes * right most bit. 205246853Sdes * \param[in] byte the bit to set the bit in 206246853Sdes * \param[in] bit_nr the bit to set (0 <= n <= 7) 207246853Sdes * \param[in] value whether to set the bit to 1 or 0 208246853Sdes * \return 1 or 0 depending no the bit state 209246853Sdes */ 210246853Sdesvoid ldns_set_bit(uint8_t *byte, int bit_nr, bool value); 211246853Sdes 212246853Sdes/** 213246853Sdes * Returns the value of a to the power of b 214246853Sdes * (or 1 of b < 1) 215246853Sdes */ 216246853Sdes/*@unused@*/ 217246853SdesINLINE long 218246853Sdesldns_power(long a, long b) { 219246853Sdes long result = 1; 220246853Sdes while (b > 0) { 221246853Sdes if (b & 1) { 222246853Sdes result *= a; 223246853Sdes if (b == 1) { 224246853Sdes return result; 225246853Sdes } 226246853Sdes } 227246853Sdes a *= a; 228246853Sdes b /= 2; 229246853Sdes } 230246853Sdes return result; 231246853Sdes} 232246853Sdes 233246853Sdes/** 234246853Sdes * Returns the int value of the given (hex) digit 235246853Sdes * \param[in] ch the hex char to convert 236246853Sdes * \return the converted decimal value 237246853Sdes */ 238246853Sdesint ldns_hexdigit_to_int(char ch); 239246853Sdes 240246853Sdes/** 241246853Sdes * Returns the char (hex) representation of the given int 242246853Sdes * \param[in] ch the int to convert 243246853Sdes * \return the converted hex char 244246853Sdes */ 245246853Sdeschar ldns_int_to_hexdigit(int ch); 246246853Sdes 247246853Sdes/** 248246853Sdes * Converts a hex string to binary data 249246853Sdes * 250246853Sdes * \param[out] data The binary result is placed here. 251246853Sdes * At least strlen(str)/2 bytes should be allocated 252246853Sdes * \param[in] str The hex string to convert. 253246853Sdes * This string should not contain spaces 254246853Sdes * \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 255246853Sdes */ 256246853Sdesint 257246853Sdesldns_hexstring_to_data(uint8_t *data, const char *str); 258246853Sdes 259246853Sdes/** 260246853Sdes * Show the internal library version 261246853Sdes * \return a string with the version in it 262246853Sdes */ 263246853Sdesconst char * ldns_version(void); 264246853Sdes 265246853Sdes/** 266246853Sdes * Convert TM to seconds since epoch (midnight, January 1st, 1970). 267246853Sdes * Like timegm(3), which is not always available. 268246853Sdes * \param[in] tm a struct tm* with the date 269246853Sdes * \return the seconds since epoch 270246853Sdes */ 271246854Sdestime_t ldns_mktime_from_utc(const struct tm *tm); 272246854Sdes 273246853Sdestime_t mktime_from_utc(const struct tm *tm); 274246853Sdes 275246853Sdes/** 276246853Sdes * The function interprets time as the number of seconds since epoch 277246853Sdes * with respect to now using serial arithmitics (rfc1982). 278246853Sdes * That number of seconds is then converted to broken-out time information. 279246853Sdes * This is especially usefull when converting the inception and expiration 280246853Sdes * fields of RRSIG records. 281246853Sdes * 282246853Sdes * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) 283246853Sdes * to be intepreted as a serial arithmitics number relative to now. 284246853Sdes * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) 285246853Sdes * to which the time value is compared to determine the final value. 286246853Sdes * \param[out] result the struct with the broken-out time information 287246853Sdes * \return result on success or NULL on error 288246853Sdes */ 289246853Sdesstruct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); 290246853Sdes 291246853Sdes/** 292246853Sdes * Seed the random function. 293246853Sdes * If the file descriptor is specified, the random generator is seeded with 294246853Sdes * data from that file. If not, /dev/urandom is used. 295246853Sdes * 296246853Sdes * applications should call this if they need entropy data within ldns 297246853Sdes * If openSSL is available, it is automatically seeded from /dev/urandom 298246853Sdes * or /dev/random. 299246853Sdes * 300246853Sdes * If you need more entropy, or have no openssl available, this function 301246853Sdes * MUST be called at the start of the program 302246853Sdes * 303246853Sdes * If openssl *is* available, this function just adds more entropy 304246853Sdes * 305246853Sdes * \param[in] fd a file providing entropy data for the seed 306246853Sdes * \param[in] size the number of bytes to use as entropy data. If this is 0, 307246853Sdes * only the minimal amount is taken (usually 4 bytes) 308246853Sdes * \return 0 if seeding succeeds, 1 if it fails 309246853Sdes */ 310246853Sdesint ldns_init_random(FILE *fd, unsigned int size); 311246853Sdes 312246853Sdes/** 313246853Sdes * Get random number. 314246853Sdes * \return random number. 315246853Sdes * 316246853Sdes */ 317246853Sdesuint16_t ldns_get_random(void); 318246853Sdes 319246853Sdes/** 320246853Sdes * Encode data as BubbleBabble 321246853Sdes * 322246853Sdes * \param[in] data a pointer to data to be encoded 323246853Sdes * \param[in] len size the number of bytes of data 324246853Sdes * \return a string of BubbleBabble 325246853Sdes */ 326246853Sdeschar *ldns_bubblebabble(uint8_t *data, size_t len); 327246853Sdes 328266114Sdes 329266114SdesINLINE time_t ldns_time(time_t *t) { return time(t); } 330266114Sdes 331266114Sdes 332246853Sdes/** 333246853Sdes * calculates the size needed to store the result of b32_ntop 334246853Sdes */ 335246853Sdes/*@unused@*/ 336266114SdesINLINE size_t ldns_b32_ntop_calculate_size(size_t src_data_length) 337246853Sdes{ 338266114Sdes return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8; 339246853Sdes} 340266114Sdes 341266114SdesINLINE size_t ldns_b32_ntop_calculate_size_no_padding(size_t src_data_length) 342246853Sdes{ 343266114Sdes return ((src_data_length + 3) * 8 / 5) - 4; 344246853Sdes} 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 363249453Sdes/** 364266114Sdes * calculates the size needed to store the result of b32_pton 365249453Sdes */ 366249453Sdes/*@unused@*/ 367266114SdesINLINE size_t ldns_b32_pton_calculate_size(size_t src_text_length) 368249453Sdes{ 369266114Sdes return src_text_length * 5 / 8; 370249453Sdes} 371246853Sdes 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); 374246853Sdes 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 389246853Sdes#ifdef __cplusplus 390246853Sdes} 391246853Sdes#endif 392246853Sdes 393246853Sdes#endif /* !_UTIL_H */ 394