1 /* 2 * util.h 3 * 4 * helper function header file 5 * 6 * a Net::DNS like library for C 7 * 8 * (c) NLnet Labs, 2004 9 * 10 * See the file LICENSE for the license 11 */ 12 13 #ifndef _UTIL_H 14 #define _UTIL_H 15 16 #include <inttypes.h> 17 #include <ldns/common.h> 18 #include <time.h> 19 #include <stdio.h> 20 21 #define dprintf(X,Y) fprintf(stderr, (X), (Y)) 22 /* #define dprintf(X, Y) */ 23 24 #define LDNS_VERSION "1.6.4" 25 #define LDNS_REVISION 0x010604 26 27 /** 28 * splint static inline workaround 29 */ 30 #ifdef S_SPLINT_S 31 # define INLINE 32 #else 33 # ifdef SWIG 34 # define INLINE static 35 # else 36 # define INLINE static inline 37 # endif 38 #endif 39 40 /** 41 * Memory management macros 42 */ 43 #define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) 44 45 #define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) 46 47 #define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) 48 49 #define LDNS_XREALLOC(ptr, type, count) \ 50 ((type *) realloc((ptr), (count) * sizeof(type))) 51 52 #define LDNS_FREE(ptr) \ 53 do { free((ptr)); (ptr) = NULL; } while (0) 54 55 #define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); 56 57 /* 58 * Copy data allowing for unaligned accesses in network byte order 59 * (big endian). 60 */ 61 INLINE uint16_t 62 ldns_read_uint16(const void *src) 63 { 64 #ifdef ALLOW_UNALIGNED_ACCESSES 65 return ntohs(*(uint16_t *) src); 66 #else 67 uint8_t *p = (uint8_t *) src; 68 return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; 69 #endif 70 } 71 72 INLINE uint32_t 73 ldns_read_uint32(const void *src) 74 { 75 #ifdef ALLOW_UNALIGNED_ACCESSES 76 return ntohl(*(uint32_t *) src); 77 #else 78 uint8_t *p = (uint8_t *) src; 79 return ( ((uint32_t) p[0] << 24) 80 | ((uint32_t) p[1] << 16) 81 | ((uint32_t) p[2] << 8) 82 | (uint32_t) p[3]); 83 #endif 84 } 85 86 /* 87 * Copy data allowing for unaligned accesses in network byte order 88 * (big endian). 89 */ 90 INLINE void 91 ldns_write_uint16(void *dst, uint16_t data) 92 { 93 #ifdef ALLOW_UNALIGNED_ACCESSES 94 * (uint16_t *) dst = htons(data); 95 #else 96 uint8_t *p = (uint8_t *) dst; 97 p[0] = (uint8_t) ((data >> 8) & 0xff); 98 p[1] = (uint8_t) (data & 0xff); 99 #endif 100 } 101 102 INLINE void 103 ldns_write_uint32(void *dst, uint32_t data) 104 { 105 #ifdef ALLOW_UNALIGNED_ACCESSES 106 * (uint32_t *) dst = htonl(data); 107 #else 108 uint8_t *p = (uint8_t *) dst; 109 p[0] = (uint8_t) ((data >> 24) & 0xff); 110 p[1] = (uint8_t) ((data >> 16) & 0xff); 111 p[2] = (uint8_t) ((data >> 8) & 0xff); 112 p[3] = (uint8_t) (data & 0xff); 113 #endif 114 } 115 116 /* warning. */ 117 INLINE void 118 ldns_write_uint64_as_uint48(void *dst, uint64_t data) 119 { 120 uint8_t *p = (uint8_t *) dst; 121 p[0] = (uint8_t) ((data >> 40) & 0xff); 122 p[1] = (uint8_t) ((data >> 32) & 0xff); 123 p[2] = (uint8_t) ((data >> 24) & 0xff); 124 p[3] = (uint8_t) ((data >> 16) & 0xff); 125 p[4] = (uint8_t) ((data >> 8) & 0xff); 126 p[5] = (uint8_t) (data & 0xff); 127 } 128 129 130 /** 131 * Structure to do a Schwartzian-like transformation, for instance when 132 * sorting. If you need a transformation on the objects that are sorted, 133 * you can sue this to store the transformed values, so you do not 134 * need to do the transformation again for each comparison 135 */ 136 struct ldns_schwartzian_compare_struct { 137 void *original_object; 138 void *transformed_object; 139 }; 140 141 /** A general purpose lookup table 142 * 143 * Lookup tables are arrays of (id, name) pairs, 144 * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", 145 * and vice versa. The lookup tables themselves are defined wherever needed, 146 * for instance in \ref host2str.c 147 */ 148 struct ldns_struct_lookup_table { 149 int id; 150 const char *name; 151 }; 152 typedef struct ldns_struct_lookup_table ldns_lookup_table; 153 154 /** 155 * Looks up the table entry by name, returns NULL if not found. 156 * \param[in] table the lookup table to search in 157 * \param[in] name what to search for 158 * \return the item found 159 */ 160 ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], 161 const char *name); 162 163 /** 164 * Looks up the table entry by id, returns NULL if not found. 165 * \param[in] table the lookup table to search in 166 * \param[in] id what to search for 167 * \return the item found 168 */ 169 ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); 170 171 /** 172 * Returns the value of the specified bit 173 * The bits are counted from left to right, so bit #0 is the 174 * left most bit. 175 * \param[in] bits array holding the bits 176 * \param[in] index to the wanted bit 177 * \return 178 */ 179 int ldns_get_bit(uint8_t bits[], size_t index); 180 181 182 /** 183 * Returns the value of the specified bit 184 * The bits are counted from right to left, so bit #0 is the 185 * right most bit. 186 * \param[in] bits array holding the bits 187 * \param[in] index to the wanted bit 188 * \return 1 or 0 depending no the bit state 189 */ 190 int ldns_get_bit_r(uint8_t bits[], size_t index); 191 192 /** 193 * sets the specified bit in the specified byte to 194 * 1 if value is true, 0 if false 195 * The bits are counted from right to left, so bit #0 is the 196 * right most bit. 197 * \param[in] byte the bit to set the bit in 198 * \param[in] bit_nr the bit to set (0 <= n <= 7) 199 * \param[in] value whether to set the bit to 1 or 0 200 * \return 1 or 0 depending no the bit state 201 */ 202 void ldns_set_bit(uint8_t *byte, int bit_nr, bool value); 203 204 /** 205 * Returns the value of a to the power of b 206 * (or 1 of b < 1) 207 */ 208 /*@unused@*/ 209 INLINE long 210 ldns_power(long a, long b) { 211 long result = 1; 212 while (b > 0) { 213 if (b & 1) { 214 result *= a; 215 if (b == 1) { 216 return result; 217 } 218 } 219 a *= a; 220 b /= 2; 221 } 222 return result; 223 } 224 225 /** 226 * Returns the int value of the given (hex) digit 227 * \param[in] ch the hex char to convert 228 * \return the converted decimal value 229 */ 230 int ldns_hexdigit_to_int(char ch); 231 232 /** 233 * Returns the char (hex) representation of the given int 234 * \param[in] ch the int to convert 235 * \return the converted hex char 236 */ 237 char ldns_int_to_hexdigit(int ch); 238 239 /** 240 * Converts a hex string to binary data 241 * 242 * \param[out] data The binary result is placed here. 243 * At least strlen(str)/2 bytes should be allocated 244 * \param[in] str The hex string to convert. 245 * This string should not contain spaces 246 * \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 247 */ 248 int 249 ldns_hexstring_to_data(uint8_t *data, const char *str); 250 251 /** 252 * Show the internal library version 253 * \return a string with the version in it 254 */ 255 const char * ldns_version(void); 256 257 /** 258 * Convert TM to seconds since epoch (midnight, January 1st, 1970). 259 * Like timegm(3), which is not always available. 260 * \param[in] tm a struct tm* with the date 261 * \return the seconds since epoch 262 */ 263 time_t mktime_from_utc(const struct tm *tm); 264 265 /** 266 * Seed the random function. 267 * If the file descriptor is specified, the random generator is seeded with 268 * data from that file. If not, /dev/urandom is used. 269 * 270 * applications should call this if they need entropy data within ldns 271 * If openSSL is available, it is automatically seeded from /dev/urandom 272 * or /dev/random. 273 * 274 * If you need more entropy, or have no openssl available, this function 275 * MUST be called at the start of the program 276 * 277 * If openssl *is* available, this function just adds more entropy 278 * 279 * \param[in] fd a file providing entropy data for the seed 280 * \param[in] size the number of bytes to use as entropy data. If this is 0, 281 * only the minimal amount is taken (usually 4 bytes) 282 * \return 0 if seeding succeeds, 1 if it fails 283 */ 284 int ldns_init_random(FILE *fd, unsigned int size); 285 286 287 /** 288 * Encode data as BubbleBabble 289 * 290 * \param[in] data a pointer to data to be encoded 291 * \param[in] len size the number of bytes of data 292 * \return a string of BubbleBabble 293 */ 294 char *ldns_bubblebabble(uint8_t *data, size_t len); 295 296 #ifndef B32_NTOP 297 int ldns_b32_ntop(uint8_t const *src, size_t srclength, 298 char *target, size_t targsize); 299 int b32_ntop(uint8_t const *src, size_t srclength, 300 char *target, size_t targsize); 301 int ldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, 302 char *target, size_t targsize); 303 int b32_ntop_extended_hex(uint8_t const *src, size_t srclength, 304 char *target, size_t targsize); 305 /** 306 * calculates the size needed to store the result of b32_ntop 307 */ 308 /*@unused@*/ 309 INLINE size_t ldns_b32_ntop_calculate_size(size_t srcsize) 310 { 311 size_t result = ((((srcsize / 5) * 8) - 2) + 2); 312 return result; 313 } 314 #endif /* !B32_NTOP */ 315 #ifndef B32_PTON 316 int ldns_b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); 317 int b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); 318 int ldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); 319 int b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); 320 /** 321 * calculates the size needed to store the result of b32_pton 322 */ 323 /*@unused@*/ 324 INLINE size_t ldns_b32_pton_calculate_size(size_t srcsize) 325 { 326 size_t result = ((((srcsize) / 8) * 5)); 327 return result; 328 } 329 #endif /* !B32_PTON */ 330 331 #endif /* !_UTIL_H */ 332