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