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