xref: /openbsd/usr.sbin/nsd/util.h (revision 55cc5ba3)
1 /*
2  * util.h -- set of various support routines.
3  *
4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #ifndef _UTIL_H_
11 #define _UTIL_H_
12 
13 #include <sys/time.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <time.h>
17 struct rr;
18 struct buffer;
19 struct region;
20 
21 #ifdef HAVE_SYSLOG_H
22 #  include <syslog.h>
23 #else
24 #  define LOG_ERR 3
25 #  define LOG_WARNING 4
26 #  define LOG_NOTICE 5
27 #  define LOG_INFO 6
28 
29 /* Unused, but passed to log_open. */
30 #  define LOG_PID 0x01
31 #  define LOG_DAEMON (3<<3)
32 #endif
33 
34 #define ALIGN_UP(n, alignment)  \
35 	(((n) + (alignment) - 1) & (~((alignment) - 1)))
36 #define PADDING(n, alignment)   \
37 	(ALIGN_UP((n), (alignment)) - (n))
38 
39 /*
40  * Initialize the logging system.  All messages are logged to stderr
41  * until log_open and log_set_log_function are called.
42  */
43 void log_init(const char *ident);
44 
45 /*
46  * Open the system log.  If FILENAME is not NULL, a log file is opened
47  * as well.
48  */
49 void log_open(int option, int facility, const char *filename);
50 
51 /*
52  * Reopen the logfile.
53  */
54 void log_reopen(const char *filename, uint8_t verbose);
55 
56 /*
57  * Finalize the logging system.
58  */
59 void log_finalize(void);
60 
61 /*
62  * Type of function to use for the actual logging.
63  */
64 typedef void log_function_type(int priority, const char *message);
65 
66 /*
67  * The function used to log to the log file.
68  */
69 log_function_type log_file;
70 
71 /*
72  * The function used to log to syslog.  The messages are also logged
73  * using log_file.
74  */
75 log_function_type log_syslog;
76 
77 /*
78  * The function used to log to syslog only.
79  */
80 log_function_type log_only_syslog;
81 
82 /*
83  * Set the logging function to use (log_file or log_syslog).
84  */
85 void log_set_log_function(log_function_type *log_function);
86 
87 /*
88  * Log a message using the current log function.
89  */
90 void log_msg(int priority, const char *format, ...)
91 	ATTR_FORMAT(printf, 2, 3);
92 
93 /*
94  * Log a message using the current log function.
95  */
96 void log_vmsg(int priority, const char *format, va_list args);
97 
98 /*
99  * Verbose output switch
100  */
101 extern int verbosity;
102 #define VERBOSITY(level, args)					\
103 	do {							\
104 		if ((level) <= verbosity) {			\
105 			log_msg args ;				\
106 		}						\
107 	} while (0)
108 
109 /*
110  * Set the INDEXth bit of BITS to 1.
111  */
112 void set_bit(uint8_t bits[], size_t index);
113 
114 /*
115  * Set the INDEXth bit of BITS to 0.
116  */
117 void clear_bit(uint8_t bits[], size_t index);
118 
119 /*
120  * Return the value of the INDEXth bit of BITS.
121  */
122 int get_bit(uint8_t bits[], size_t index);
123 
124 /* A general purpose lookup table */
125 typedef struct lookup_table lookup_table_type;
126 struct lookup_table {
127 	int id;
128 	const char *name;
129 };
130 
131 /*
132  * Looks up the table entry by name, returns NULL if not found.
133  */
134 lookup_table_type *lookup_by_name(lookup_table_type table[], const char *name);
135 
136 /*
137  * Looks up the table entry by id, returns NULL if not found.
138  */
139 lookup_table_type *lookup_by_id(lookup_table_type table[], int id);
140 
141 /*
142  * (Re-)allocate SIZE bytes of memory.  Report an error if the memory
143  * could not be allocated and exit the program.  These functions never
144  * return NULL.
145  */
146 void *xalloc(size_t size);
147 void *xmallocarray(size_t num, size_t size);
148 void *xalloc_zero(size_t size);
149 void *xalloc_array_zero(size_t num, size_t size);
150 void *xrealloc(void *ptr, size_t size);
151 char *xstrdup(const char *src);
152 
153 /*
154  * Mmap allocator routines.
155  *
156  */
157 #ifdef USE_MMAP_ALLOC
158 void *mmap_alloc(size_t size);
159 void mmap_free(void *ptr);
160 #endif /* USE_MMAP_ALLOC */
161 
162 /*
163  * Write SIZE bytes of DATA to FILE.  Report an error on failure.
164  *
165  * Returns 0 on failure, 1 on success.
166  */
167 int write_data(FILE *file, const void *data, size_t size);
168 
169 /*
170  * like write_data, but keeps track of crc
171  */
172 int write_data_crc(FILE *file, const void *data, size_t size, uint32_t* crc);
173 
174 /*
175  * Write the complete buffer to the socket, irrespective of short
176  * writes or interrupts. This function blocks to write the data.
177  * Returns 0 on error, 1 on success.
178  */
179 int write_socket(int s, const void *data, size_t size);
180 
181 /*
182  * Copy data allowing for unaligned accesses in network byte order
183  * (big endian).
184  */
185 static inline void
186 write_uint16(void *dst, uint16_t data)
187 {
188 #ifdef ALLOW_UNALIGNED_ACCESSES
189 	* (uint16_t *) dst = htons(data);
190 #else
191 	uint8_t *p = (uint8_t *) dst;
192 	p[0] = (uint8_t) ((data >> 8) & 0xff);
193 	p[1] = (uint8_t) (data & 0xff);
194 #endif
195 }
196 
197 static inline void
198 write_uint32(void *dst, uint32_t data)
199 {
200 #ifdef ALLOW_UNALIGNED_ACCESSES
201 	* (uint32_t *) dst = htonl(data);
202 #else
203 	uint8_t *p = (uint8_t *) dst;
204 	p[0] = (uint8_t) ((data >> 24) & 0xff);
205 	p[1] = (uint8_t) ((data >> 16) & 0xff);
206 	p[2] = (uint8_t) ((data >> 8) & 0xff);
207 	p[3] = (uint8_t) (data & 0xff);
208 #endif
209 }
210 
211 static inline void
212 write_uint64(void *dst, uint64_t data)
213 {
214 	uint8_t *p = (uint8_t *) dst;
215 	p[0] = (uint8_t) ((data >> 56) & 0xff);
216 	p[1] = (uint8_t) ((data >> 48) & 0xff);
217 	p[2] = (uint8_t) ((data >> 40) & 0xff);
218 	p[3] = (uint8_t) ((data >> 32) & 0xff);
219 	p[4] = (uint8_t) ((data >> 24) & 0xff);
220 	p[5] = (uint8_t) ((data >> 16) & 0xff);
221 	p[6] = (uint8_t) ((data >> 8) & 0xff);
222 	p[7] = (uint8_t) (data & 0xff);
223 }
224 
225 /*
226  * Copy data allowing for unaligned accesses in network byte order
227  * (big endian).
228  */
229 static inline uint16_t
230 read_uint16(const void *src)
231 {
232 #ifdef ALLOW_UNALIGNED_ACCESSES
233 	return ntohs(* (const uint16_t *) src);
234 #else
235 	const uint8_t *p = (const uint8_t *) src;
236 	return (p[0] << 8) | p[1];
237 #endif
238 }
239 
240 static inline uint32_t
241 read_uint32(const void *src)
242 {
243 #ifdef ALLOW_UNALIGNED_ACCESSES
244 	return ntohl(* (const uint32_t *) src);
245 #else
246 	const uint8_t *p = (const uint8_t *) src;
247 	return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
248 #endif
249 }
250 
251 static inline uint64_t
252 read_uint64(const void *src)
253 {
254 	const uint8_t *p = (const uint8_t *) src;
255 	return
256 	    ((uint64_t)p[0] << 56) |
257 	    ((uint64_t)p[1] << 48) |
258 	    ((uint64_t)p[2] << 40) |
259 	    ((uint64_t)p[3] << 32) |
260 	    ((uint64_t)p[4] << 24) |
261 	    ((uint64_t)p[5] << 16) |
262 	    ((uint64_t)p[6] <<  8) |
263 	    (uint64_t)p[7];
264 }
265 
266 /*
267  * Print debugging information using log_msg,
268  * set the logfile as /dev/stdout or /dev/stderr if you like.
269  * nsd -F 0xFFFF enables all debug facilities.
270  */
271 #define DEBUG_PARSER           0x0001U
272 #define DEBUG_ZONEC            0x0002U
273 #define DEBUG_QUERY            0x0004U
274 #define DEBUG_DBACCESS         0x0008U
275 #define DEBUG_NAME_COMPRESSION 0x0010U
276 #define DEBUG_XFRD             0x0020U
277 #define DEBUG_IPC              0x0040U
278 
279 extern unsigned nsd_debug_facilities;
280 extern int nsd_debug_level;
281 #ifdef NDEBUG
282 #define DEBUG(facility, level, args)  /* empty */
283 #else
284 #define DEBUG(facility, level, args)				\
285 	do {							\
286 		if ((facility) & nsd_debug_facilities &&	\
287 		    (level) <= nsd_debug_level) {		\
288 			log_msg args ;				\
289 		}						\
290 	} while (0)
291 #endif
292 
293 /* set to true to log time prettyprinted, or false to print epoch */
294 extern int log_time_asc;
295 
296 /*
297  * Timespec functions.
298  */
299 int timespec_compare(const struct timespec *left, const struct timespec *right);
300 void timespec_add(struct timespec *left, const struct timespec *right);
301 void timespec_subtract(struct timespec *left, const struct timespec *right);
302 
303 static inline void
304 timeval_to_timespec(struct timespec *left,
305 		    const struct timeval *right)
306 {
307 	left->tv_sec = right->tv_sec;
308 	left->tv_nsec = 1000 * right->tv_usec;
309 }
310 
311 /* get the time */
312 void get_time(struct timespec* t);
313 
314 /*
315  * Converts a string representation of a period of time into
316  * a long integer of seconds or serial value.
317  *
318  * Set the endptr to the first illegal character.
319  *
320  * Interface is similar as strtol(3)
321  *
322  * Returns:
323  *	LONG_MIN if underflow occurs
324  *	LONG_MAX if overflow occurs.
325  *	otherwise number of seconds
326  *
327  * XXX These functions do not check the range.
328  *
329  */
330 uint32_t strtoserial(const char *nptr, const char **endptr);
331 uint32_t strtottl(const char *nptr, const char **endptr);
332 
333 /*
334  * Convert binary data to a string of hexadecimal characters.
335  */
336 ssize_t hex_ntop(uint8_t const *src, size_t srclength, char *target,
337 		 size_t targsize);
338 ssize_t hex_pton(const char* src, uint8_t* target, size_t targsize);
339 
340 /*
341  * convert base32 data from and to string. Returns length.
342  * -1 on error. Use (byte count*8)%5==0.
343  */
344 int b32_pton(char const *src, uint8_t *target, size_t targsize);
345 int b32_ntop(uint8_t const *src, size_t srclength, char *target,
346 	size_t targsize);
347 
348 /*
349  * Strip trailing and leading whitespace from str.
350  */
351 void strip_string(char *str);
352 
353 /*
354  * Convert a single (hexadecimal) digit to its integer value.
355  */
356 int hexdigit_to_int(char ch);
357 
358 /*
359  * Convert TM to seconds since epoch (midnight, January 1st, 1970).
360  * Like timegm(3), which is not always available.
361  */
362 time_t mktime_from_utc(const struct tm *tm);
363 
364 /*
365  * Add bytes to given crc. Returns new CRC sum.
366  * Start crc val with 0xffffffff on first call. XOR crc with
367  * 0xffffffff at the end again to get final POSIX 1003.2 checksum.
368  */
369 uint32_t compute_crc(uint32_t crc, uint8_t* data, size_t len);
370 
371 /*
372  * Compares two 32-bit serial numbers as defined in RFC1982.  Returns
373  * <0 if a < b, 0 if a == b, and >0 if a > b.  The result is undefined
374  * if a != b but neither is greater or smaller (see RFC1982 section
375  * 3.2.).
376  */
377 int compare_serial(uint32_t a, uint32_t b);
378 
379 /*
380  * Generate a random query ID.
381  */
382 uint16_t qid_generate(void);
383 /* value between 0 .. (max-1) inclusive */
384 int random_generate(int max);
385 
386 /*
387  * call region_destroy on (region*)data, useful for region_add_cleanup().
388  */
389 void cleanup_region(void *data);
390 
391 /*
392  * Region used to store owner and origin of previous RR (used
393  * for pretty printing of zone data).
394  * Keep the same between calls to print_rr.
395  */
396 struct state_pretty_rr {
397 	struct region *previous_owner_region;
398 	const struct dname *previous_owner;
399 	const struct dname *previous_owner_origin;
400 };
401 struct state_pretty_rr* create_pretty_rr(struct region* region);
402 /* print rr to file, returns 0 on failure(nothing is written) */
403 int print_rr(FILE *out, struct state_pretty_rr* state, struct rr *record,
404 	struct region* tmp_region, struct buffer* tmp_buffer);
405 
406 /*
407  * Convert a numeric rcode value to a human readable string
408  */
409 const char* rcode2str(int rc);
410 
411 void addr2str(
412 #ifdef INET6
413 	struct sockaddr_storage *addr
414 #else
415 	struct sockaddr_in *addr
416 #endif
417 	, char* str, size_t len);
418 
419 /* print addr@port */
420 void addrport2str(
421 #ifdef INET6
422 	struct sockaddr_storage *addr
423 #else
424 	struct sockaddr_in *addr
425 #endif
426 	, char* str, size_t len);
427 
428 /** copy dirname string and append slash.  Previous dirname is leaked,
429  * but it is to be used once, at startup, for chroot */
430 void append_trailing_slash(const char** dirname, struct region* region);
431 
432 /** true if filename starts with chroot or is not absolute */
433 int file_inside_chroot(const char* fname, const char* chr);
434 
435 /** Something went wrong, give error messages and exit. */
436 void error(const char *format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
437 
438 #if HAVE_CPUSET_T
439 int number_of_cpus(void);
440 int set_cpu_affinity(cpuset_t *set);
441 #endif
442 
443 #endif /* _UTIL_H_ */
444