| 1 | /* Core interface of secnet, to be used by all modules */ |
| 2 | |
| 3 | #ifndef secnet_h |
| 4 | #define secnet_h |
| 5 | |
| 6 | #include "config.h" |
| 7 | #include <stdlib.h> |
| 8 | #include <stdarg.h> |
| 9 | #include <stdio.h> |
| 10 | #include <string.h> |
| 11 | #include <assert.h> |
| 12 | #include <fcntl.h> |
| 13 | #include <unistd.h> |
| 14 | #include <sys/poll.h> |
| 15 | #include <sys/types.h> |
| 16 | #include <sys/time.h> |
| 17 | #include <netinet/in.h> |
| 18 | |
| 19 | typedef char *string_t; |
| 20 | typedef const char *cstring_t; |
| 21 | |
| 22 | #define False (_Bool)0 |
| 23 | #define True (_Bool)1 |
| 24 | typedef _Bool bool_t; |
| 25 | |
| 26 | #define ASSERT(x) do { if (!(x)) { fatal("assertion failed line %d file " \ |
| 27 | __FILE__,__LINE__); } } while(0) |
| 28 | |
| 29 | /* from version.c */ |
| 30 | |
| 31 | extern char version[]; |
| 32 | |
| 33 | /* from logmsg.c */ |
| 34 | extern uint32_t message_level; |
| 35 | extern bool_t secnet_is_daemon; |
| 36 | extern struct log_if *system_log; |
| 37 | |
| 38 | /* from process.c */ |
| 39 | extern void start_signal_handling(void); |
| 40 | |
| 41 | /***** CONFIGURATION support *****/ |
| 42 | |
| 43 | extern bool_t just_check_config; /* If True then we're going to exit after |
| 44 | reading the configuration file */ |
| 45 | extern bool_t background; /* If True then we'll eventually run as a daemon */ |
| 46 | |
| 47 | typedef struct dict dict_t; /* Configuration dictionary */ |
| 48 | typedef struct closure closure_t; |
| 49 | typedef struct item item_t; |
| 50 | typedef struct list list_t; /* A list of items */ |
| 51 | |
| 52 | /* Configuration file location, for error-reporting */ |
| 53 | struct cloc { |
| 54 | cstring_t file; |
| 55 | int line; |
| 56 | }; |
| 57 | |
| 58 | /* Modules export closures, which can be invoked from the configuration file. |
| 59 | "Invoking" a closure usually returns another closure (of a different |
| 60 | type), but can actually return any configuration object. */ |
| 61 | typedef list_t *(apply_fn)(closure_t *self, struct cloc loc, |
| 62 | dict_t *context, list_t *data); |
| 63 | struct closure { |
| 64 | cstring_t description; /* For debugging */ |
| 65 | uint32_t type; /* Central registry... */ |
| 66 | apply_fn *apply; |
| 67 | void *interface; /* Interface for use inside secnet; depends on type */ |
| 68 | }; |
| 69 | |
| 70 | enum types { t_null, t_bool, t_string, t_number, t_dict, t_closure }; |
| 71 | struct item { |
| 72 | enum types type; |
| 73 | union { |
| 74 | bool_t bool; |
| 75 | string_t string; |
| 76 | uint32_t number; |
| 77 | dict_t *dict; |
| 78 | closure_t *closure; |
| 79 | } data; |
| 80 | struct cloc loc; |
| 81 | }; |
| 82 | |
| 83 | /* Note that it is unwise to use this structure directly; use the list |
| 84 | manipulation functions instead. */ |
| 85 | struct list { |
| 86 | item_t *item; |
| 87 | struct list *next; |
| 88 | }; |
| 89 | |
| 90 | /* In the following two lookup functions, NULL means 'not found' */ |
| 91 | /* Lookup a value in the specified dictionary, or its parents */ |
| 92 | extern list_t *dict_lookup(dict_t *dict, cstring_t key); |
| 93 | /* Lookup a value in just the specified dictionary */ |
| 94 | extern list_t *dict_lookup_primitive(dict_t *dict, cstring_t key); |
| 95 | /* Add a value to the specified dictionary */ |
| 96 | extern void dict_add(dict_t *dict, cstring_t key, list_t *val); |
| 97 | /* Obtain an array of keys in the dictionary. malloced; caller frees */ |
| 98 | extern cstring_t *dict_keys(dict_t *dict); |
| 99 | |
| 100 | /* List-manipulation functions */ |
| 101 | extern list_t *list_new(void); |
| 102 | extern int32_t list_length(list_t *a); |
| 103 | extern list_t *list_append(list_t *a, item_t *i); |
| 104 | extern list_t *list_append_list(list_t *a, list_t *b); |
| 105 | /* Returns an item from the list (index starts at 0), or NULL */ |
| 106 | extern item_t *list_elem(list_t *l, int32_t index); |
| 107 | |
| 108 | /* Convenience functions */ |
| 109 | extern list_t *new_closure(closure_t *cl); |
| 110 | extern void add_closure(dict_t *dict, cstring_t name, apply_fn apply); |
| 111 | extern void *find_cl_if(dict_t *dict, cstring_t name, uint32_t type, |
| 112 | bool_t fail_if_invalid, cstring_t desc, |
| 113 | struct cloc loc); |
| 114 | extern item_t *dict_find_item(dict_t *dict, cstring_t key, bool_t required, |
| 115 | cstring_t desc, struct cloc loc); |
| 116 | extern string_t dict_read_string(dict_t *dict, cstring_t key, bool_t required, |
| 117 | cstring_t desc, struct cloc loc); |
| 118 | extern uint32_t dict_read_number(dict_t *dict, cstring_t key, bool_t required, |
| 119 | cstring_t desc, struct cloc loc, |
| 120 | uint32_t def); |
| 121 | /* return value can safely be assigned to int32_t */ |
| 122 | extern bool_t dict_read_bool(dict_t *dict, cstring_t key, bool_t required, |
| 123 | cstring_t desc, struct cloc loc, bool_t def); |
| 124 | struct flagstr { |
| 125 | cstring_t name; |
| 126 | uint32_t value; |
| 127 | }; |
| 128 | extern uint32_t string_to_word(cstring_t s, struct cloc loc, |
| 129 | struct flagstr *f, cstring_t desc); |
| 130 | extern uint32_t string_list_to_word(list_t *l, struct flagstr *f, |
| 131 | cstring_t desc); |
| 132 | |
| 133 | /***** END of configuration support *****/ |
| 134 | |
| 135 | /***** UTILITY functions *****/ |
| 136 | |
| 137 | extern char *safe_strdup(const char *string, const char *message); |
| 138 | extern void *safe_malloc(size_t size, const char *message); |
| 139 | extern void *safe_malloc_ary(size_t size, size_t count, const char *message); |
| 140 | |
| 141 | void setcloexec(int fd); /* cannot fail */ |
| 142 | void pipe_cloexec(int fd[2]); /* pipe(), setcloexec() twice; cannot fail */ |
| 143 | |
| 144 | extern int sys_cmd(const char *file, const char *argc, ...); |
| 145 | |
| 146 | extern uint64_t now_global; |
| 147 | extern struct timeval tv_now_global; |
| 148 | |
| 149 | static const uint64_t *const now = &now_global; |
| 150 | static const struct timeval *const tv_now = &tv_now_global; |
| 151 | |
| 152 | /* "now" is current program time, in milliseconds. It is derived |
| 153 | from tv_now. Both are provided by the event loop. */ |
| 154 | |
| 155 | /***** END of utility functions *****/ |
| 156 | |
| 157 | /***** START of max_start_pad handling *****/ |
| 158 | |
| 159 | extern int32_t site_max_start_pad, transform_max_start_pad, |
| 160 | comm_max_start_pad; |
| 161 | |
| 162 | void update_max_start_pad(int32_t *our_module_global, int32_t our_instance); |
| 163 | int32_t calculate_max_start_pad(void); |
| 164 | |
| 165 | /***** END of max_start_pad handling *****/ |
| 166 | |
| 167 | /***** SCHEDULING support */ |
| 168 | |
| 169 | /* If nfds_io is insufficient for your needs, set it to the required |
| 170 | number and return ERANGE. timeout is in milliseconds; if it is too |
| 171 | high then lower it. It starts at -1 (==infinite) */ |
| 172 | typedef int beforepoll_fn(void *st, struct pollfd *fds, int *nfds_io, |
| 173 | int *timeout_io); |
| 174 | typedef void afterpoll_fn(void *st, struct pollfd *fds, int nfds); |
| 175 | |
| 176 | /* Register interest in the main loop of the program. Before a call |
| 177 | to poll() your supplied beforepoll function will be called. After |
| 178 | the call to poll() the supplied afterpoll function will be called. |
| 179 | max_nfds is a _hint_ about the maximum number of struct pollfd |
| 180 | structures you may require - you can always ask for more in |
| 181 | *nfds_io. */ |
| 182 | extern void register_for_poll(void *st, beforepoll_fn *before, |
| 183 | afterpoll_fn *after, int32_t max_nfds, |
| 184 | cstring_t desc); |
| 185 | |
| 186 | /***** END of scheduling support */ |
| 187 | |
| 188 | /***** PROGRAM LIFETIME support */ |
| 189 | |
| 190 | /* The secnet program goes through a number of phases in its lifetime. |
| 191 | Module code may arrange to be called just as various phases are |
| 192 | entered. |
| 193 | |
| 194 | Remember to update the table in util.c if changing the set of |
| 195 | phases. */ |
| 196 | |
| 197 | enum phase { |
| 198 | PHASE_INIT, |
| 199 | PHASE_GETOPTS, /* Process command-line arguments */ |
| 200 | PHASE_READCONFIG, /* Parse and process configuration file */ |
| 201 | PHASE_SETUP, /* Process information in configuration */ |
| 202 | PHASE_DAEMONIZE, /* Become a daemon (if necessary) */ |
| 203 | PHASE_GETRESOURCES, /* Obtain all external resources */ |
| 204 | PHASE_DROPPRIV, /* Last chance for privileged operations */ |
| 205 | PHASE_RUN, |
| 206 | PHASE_SHUTDOWN, /* About to die; delete key material, etc. */ |
| 207 | /* Keep this last: */ |
| 208 | NR_PHASES, |
| 209 | }; |
| 210 | |
| 211 | typedef void hook_fn(void *self, uint32_t newphase); |
| 212 | bool_t add_hook(uint32_t phase, hook_fn *f, void *state); |
| 213 | bool_t remove_hook(uint32_t phase, hook_fn *f, void *state); |
| 214 | |
| 215 | extern uint32_t current_phase; |
| 216 | extern void enter_phase(uint32_t new_phase); |
| 217 | |
| 218 | /* Some features (like netlink 'soft' routes) require that secnet |
| 219 | retain root privileges. They should indicate that here when |
| 220 | appropriate. */ |
| 221 | extern bool_t require_root_privileges; |
| 222 | extern cstring_t require_root_privileges_explanation; |
| 223 | |
| 224 | /***** END of program lifetime support *****/ |
| 225 | |
| 226 | /***** MODULE support *****/ |
| 227 | |
| 228 | /* Module initialisation function type - modules export one function of |
| 229 | this type which is called to initialise them. For dynamically loaded |
| 230 | modules it's called "secnet_module". */ |
| 231 | typedef void init_module(dict_t *dict); |
| 232 | |
| 233 | extern void init_builtin_modules(dict_t *dict); |
| 234 | |
| 235 | extern init_module resolver_module; |
| 236 | extern init_module random_module; |
| 237 | extern init_module udp_module; |
| 238 | extern init_module util_module; |
| 239 | extern init_module site_module; |
| 240 | extern init_module transform_eax_module; |
| 241 | extern init_module transform_cbcmac_module; |
| 242 | extern init_module netlink_module; |
| 243 | extern init_module rsa_module; |
| 244 | extern init_module dh_module; |
| 245 | extern init_module md5_module; |
| 246 | extern init_module slip_module; |
| 247 | extern init_module tun_module; |
| 248 | extern init_module sha1_module; |
| 249 | extern init_module log_module; |
| 250 | |
| 251 | /***** END of module support *****/ |
| 252 | |
| 253 | /***** CLOSURE TYPES and interface definitions *****/ |
| 254 | |
| 255 | #define CL_PURE 0 |
| 256 | #define CL_RESOLVER 1 |
| 257 | #define CL_RANDOMSRC 2 |
| 258 | #define CL_RSAPUBKEY 3 |
| 259 | #define CL_RSAPRIVKEY 4 |
| 260 | #define CL_COMM 5 |
| 261 | #define CL_IPIF 6 |
| 262 | #define CL_LOG 7 |
| 263 | #define CL_SITE 8 |
| 264 | #define CL_TRANSFORM 9 |
| 265 | #define CL_DH 11 |
| 266 | #define CL_HASH 12 |
| 267 | #define CL_BUFFER 13 |
| 268 | #define CL_NETLINK 14 |
| 269 | |
| 270 | struct buffer_if; |
| 271 | |
| 272 | /* PURE closure requires no interface */ |
| 273 | |
| 274 | /* RESOLVER interface */ |
| 275 | |
| 276 | /* Answers to queries are delivered to a function of this |
| 277 | type. 'address' will be NULL if there was a problem with the query. It |
| 278 | will be freed once resolve_answer_fn returns. It is in network byte |
| 279 | order. */ |
| 280 | /* XXX extend to be able to provide multiple answers */ |
| 281 | typedef void resolve_answer_fn(void *st, struct in_addr *addr); |
| 282 | typedef bool_t resolve_request_fn(void *st, cstring_t name, |
| 283 | resolve_answer_fn *cb, void *cst); |
| 284 | struct resolver_if { |
| 285 | void *st; |
| 286 | resolve_request_fn *request; |
| 287 | }; |
| 288 | |
| 289 | /* RANDOMSRC interface */ |
| 290 | |
| 291 | /* Return some random data. Returns TRUE for success. */ |
| 292 | typedef bool_t random_fn(void *st, int32_t bytes, uint8_t *buff); |
| 293 | |
| 294 | struct random_if { |
| 295 | void *st; |
| 296 | bool_t blocking; |
| 297 | random_fn *generate; |
| 298 | }; |
| 299 | |
| 300 | /* RSAPUBKEY interface */ |
| 301 | |
| 302 | typedef bool_t rsa_checksig_fn(void *st, uint8_t *data, int32_t datalen, |
| 303 | cstring_t signature); |
| 304 | struct rsapubkey_if { |
| 305 | void *st; |
| 306 | rsa_checksig_fn *check; |
| 307 | }; |
| 308 | |
| 309 | /* RSAPRIVKEY interface */ |
| 310 | |
| 311 | typedef string_t rsa_makesig_fn(void *st, uint8_t *data, int32_t datalen); |
| 312 | struct rsaprivkey_if { |
| 313 | void *st; |
| 314 | rsa_makesig_fn *sign; |
| 315 | }; |
| 316 | |
| 317 | /* COMM interface */ |
| 318 | |
| 319 | struct comm_addr { |
| 320 | /* This struct is pure data; in particular comm's clients may |
| 321 | freely copy it. */ |
| 322 | /* Everyone is also guaranteed that all padding is set to zero, ie |
| 323 | that comm_addrs referring to semantically identical peers will |
| 324 | compare equal with memcmp. Anyone who constructs a comm_addr |
| 325 | must start by memsetting it with FILLZERO, or some |
| 326 | equivalent. */ |
| 327 | struct comm_if *comm; |
| 328 | struct sockaddr_in sin; |
| 329 | }; |
| 330 | |
| 331 | /* Return True if the packet was processed, and shouldn't be passed to |
| 332 | any other potential receivers. */ |
| 333 | typedef bool_t comm_notify_fn(void *state, struct buffer_if *buf, |
| 334 | const struct comm_addr *source); |
| 335 | typedef void comm_request_notify_fn(void *commst, void *nst, |
| 336 | comm_notify_fn *fn); |
| 337 | typedef void comm_release_notify_fn(void *commst, void *nst, |
| 338 | comm_notify_fn *fn); |
| 339 | typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf, |
| 340 | const struct comm_addr *dest); |
| 341 | typedef const char *comm_addr_to_string_fn(void *commst, |
| 342 | const struct comm_addr *ca); |
| 343 | /* Returned string is in a static buffer. */ |
| 344 | struct comm_if { |
| 345 | void *st; |
| 346 | comm_request_notify_fn *request_notify; |
| 347 | comm_release_notify_fn *release_notify; |
| 348 | comm_sendmsg_fn *sendmsg; |
| 349 | comm_addr_to_string_fn *addr_to_string; |
| 350 | }; |
| 351 | |
| 352 | static inline const char *comm_addr_to_string(const struct comm_addr *ca) |
| 353 | { |
| 354 | return ca->comm->addr_to_string(ca->comm->st, ca); |
| 355 | } |
| 356 | |
| 357 | /* LOG interface */ |
| 358 | |
| 359 | #define LOG_MESSAGE_BUFLEN 1023 |
| 360 | |
| 361 | typedef void log_msg_fn(void *st, int class, const char *message, ...); |
| 362 | typedef void log_vmsg_fn(void *st, int class, const char *message, |
| 363 | va_list args); |
| 364 | struct log_if { |
| 365 | void *st; |
| 366 | log_vmsg_fn *vlogfn; /* printf format checking. Use [v]slilog instead */ |
| 367 | char buff[LOG_MESSAGE_BUFLEN+1]; |
| 368 | }; |
| 369 | /* (convenience functions, defined in util.c) */ |
| 370 | extern void slilog(struct log_if *lf, int class, const char *message, ...) |
| 371 | FORMAT(printf,3,4); |
| 372 | extern void vslilog(struct log_if *lf, int class, const char *message, va_list) |
| 373 | FORMAT(printf,3,0); |
| 374 | |
| 375 | /* Versions which take (parts of) (multiple) messages, using \n to |
| 376 | * distinguish one message from another. */ |
| 377 | extern void slilog_part(struct log_if *lf, int class, const char *message, ...) |
| 378 | FORMAT(printf,3,4); |
| 379 | extern void vslilog_part(struct log_if *lf, int class, const char *message, |
| 380 | va_list) FORMAT(printf,3,0); |
| 381 | |
| 382 | /* SITE interface */ |
| 383 | |
| 384 | /* Pretty much a placeholder; allows starting and stopping of processing, |
| 385 | key expiry, etc. */ |
| 386 | typedef void site_control_fn(void *st, bool_t run); |
| 387 | typedef uint32_t site_status_fn(void *st); |
| 388 | struct site_if { |
| 389 | void *st; |
| 390 | site_control_fn *control; |
| 391 | site_status_fn *status; |
| 392 | }; |
| 393 | |
| 394 | /* TRANSFORM interface */ |
| 395 | |
| 396 | /* A reversable transformation. Transforms buffer in-place; may add |
| 397 | data to start or end. (Reverse transformations decrease |
| 398 | length, of course.) Transformations may be key-dependent, in which |
| 399 | case key material is passed in at initialisation time. They may |
| 400 | also depend on internal factors (eg. time) and keep internal |
| 401 | state. A struct transform_if only represents a particular type of |
| 402 | transformation; instances of the transformation (eg. with |
| 403 | particular key material) have a different C type. The same |
| 404 | secret key will be used in opposite directions between a pair of |
| 405 | secnets; one of these pairs will get direction==False, the other True. */ |
| 406 | |
| 407 | typedef struct transform_inst_if *transform_createinstance_fn(void *st); |
| 408 | typedef bool_t transform_setkey_fn(void *st, uint8_t *key, int32_t keylen, |
| 409 | bool_t direction); |
| 410 | typedef bool_t transform_valid_fn(void *st); /* 0: no key; 1: ok */ |
| 411 | typedef void transform_delkey_fn(void *st); |
| 412 | typedef void transform_destroyinstance_fn(void *st); |
| 413 | /* Returns: |
| 414 | * 0: all is well |
| 415 | * 1: for any other problem |
| 416 | * 2: message decrypted but sequence number was out of range |
| 417 | */ |
| 418 | typedef uint32_t transform_apply_fn(void *st, struct buffer_if *buf, |
| 419 | const char **errmsg); |
| 420 | |
| 421 | struct transform_inst_if { |
| 422 | void *st; |
| 423 | transform_setkey_fn *setkey; |
| 424 | transform_valid_fn *valid; |
| 425 | transform_delkey_fn *delkey; |
| 426 | transform_apply_fn *forwards; |
| 427 | transform_apply_fn *reverse; |
| 428 | transform_destroyinstance_fn *destroy; |
| 429 | }; |
| 430 | |
| 431 | struct transform_if { |
| 432 | void *st; |
| 433 | int capab_transformnum; |
| 434 | int32_t keylen; /* <<< INT_MAX */ |
| 435 | transform_createinstance_fn *create; |
| 436 | }; |
| 437 | |
| 438 | /* NETLINK interface */ |
| 439 | |
| 440 | /* Used by netlink to deliver to site, and by site to deliver to |
| 441 | netlink. cid is the client identifier returned by |
| 442 | netlink_regnets_fn. If buf has size 0 then the function is just |
| 443 | being called for its site-effects (eg. making the site code attempt |
| 444 | to bring up a network link) */ |
| 445 | typedef void netlink_deliver_fn(void *st, struct buffer_if *buf); |
| 446 | /* site code can tell netlink when outgoing packets will be dropped, |
| 447 | so netlink can generate appropriate ICMP and make routing decisions */ |
| 448 | #define LINK_QUALITY_UNUSED 0 /* This link is unused, do not make this netlink */ |
| 449 | #define LINK_QUALITY_DOWN 1 /* No chance of a packet being delivered right away*/ |
| 450 | #define LINK_QUALITY_DOWN_STALE_ADDRESS 2 /* Link down, old address information */ |
| 451 | #define LINK_QUALITY_DOWN_CURRENT_ADDRESS 3 /* Link down, current address information */ |
| 452 | #define LINK_QUALITY_UP 4 /* Link active */ |
| 453 | #define MAXIMUM_LINK_QUALITY 3 |
| 454 | typedef void netlink_link_quality_fn(void *st, uint32_t quality); |
| 455 | typedef void netlink_register_fn(void *st, netlink_deliver_fn *deliver, |
| 456 | void *dst, uint32_t *localmtu_r /* NULL ok */); |
| 457 | typedef void netlink_output_config_fn(void *st, struct buffer_if *buf); |
| 458 | typedef bool_t netlink_check_config_fn(void *st, struct buffer_if *buf); |
| 459 | typedef void netlink_set_mtu_fn(void *st, int32_t new_mtu); |
| 460 | struct netlink_if { |
| 461 | void *st; |
| 462 | netlink_register_fn *reg; |
| 463 | netlink_deliver_fn *deliver; |
| 464 | netlink_link_quality_fn *set_quality; |
| 465 | netlink_set_mtu_fn *set_mtu; |
| 466 | }; |
| 467 | |
| 468 | /* DH interface */ |
| 469 | |
| 470 | /* Returns public key as a malloced hex string */ |
| 471 | typedef string_t dh_makepublic_fn(void *st, uint8_t *secret, |
| 472 | int32_t secretlen); |
| 473 | /* Fills buffer (up to buflen) with shared secret */ |
| 474 | typedef void dh_makeshared_fn(void *st, uint8_t *secret, |
| 475 | int32_t secretlen, cstring_t rempublic, |
| 476 | uint8_t *sharedsecret, int32_t buflen); |
| 477 | struct dh_if { |
| 478 | void *st; |
| 479 | int32_t len; /* Approximate size of modulus in bytes */ |
| 480 | int32_t ceil_len; /* Number of bytes just sufficient to contain modulus */ |
| 481 | dh_makepublic_fn *makepublic; |
| 482 | dh_makeshared_fn *makeshared; |
| 483 | }; |
| 484 | |
| 485 | /* HASH interface */ |
| 486 | |
| 487 | typedef void *hash_init_fn(void); |
| 488 | typedef void hash_update_fn(void *st, const void *buf, int32_t len); |
| 489 | typedef void hash_final_fn(void *st, uint8_t *digest); |
| 490 | struct hash_if { |
| 491 | int32_t len; /* Hash output length in bytes */ |
| 492 | hash_init_fn *init; |
| 493 | hash_update_fn *update; |
| 494 | hash_final_fn *final; |
| 495 | }; |
| 496 | |
| 497 | /* BUFFER interface */ |
| 498 | |
| 499 | struct buffer_if { |
| 500 | bool_t free; |
| 501 | cstring_t owner; /* Set to constant string */ |
| 502 | uint32_t flags; /* How paranoid should we be? */ |
| 503 | struct cloc loc; /* Where we were defined */ |
| 504 | uint8_t *base; |
| 505 | uint8_t *start; |
| 506 | int32_t size; /* Size of buffer contents */ |
| 507 | int32_t alloclen; /* Total length allocated at base */ |
| 508 | }; |
| 509 | |
| 510 | /***** LOG functions *****/ |
| 511 | |
| 512 | #define M_DEBUG_CONFIG 0x001 |
| 513 | #define M_DEBUG_PHASE 0x002 |
| 514 | #define M_DEBUG 0x004 |
| 515 | #define M_INFO 0x008 |
| 516 | #define M_NOTICE 0x010 |
| 517 | #define M_WARNING 0x020 |
| 518 | #define M_ERR 0x040 |
| 519 | #define M_SECURITY 0x080 |
| 520 | #define M_FATAL 0x100 |
| 521 | |
| 522 | /* The fatal() family of functions require messages that do not end in '\n' */ |
| 523 | extern NORETURN(fatal(const char *message, ...)) FORMAT(printf,1,2); |
| 524 | extern NORETURN(fatal_perror(const char *message, ...)) FORMAT(printf,1,2); |
| 525 | extern NORETURN(fatal_status(int status, const char *message, ...)) |
| 526 | FORMAT(printf,2,3); |
| 527 | extern NORETURN(fatal_perror_status(int status, const char *message, ...)) |
| 528 | FORMAT(printf,2,3); |
| 529 | |
| 530 | /* The cfgfatal() family of functions require messages that end in '\n' */ |
| 531 | extern NORETURN(cfgfatal(struct cloc loc, cstring_t facility, |
| 532 | const char *message, ...)) FORMAT(printf,3,4); |
| 533 | extern void cfgfile_postreadcheck(struct cloc loc, FILE *f); |
| 534 | extern NORETURN(vcfgfatal_maybefile(FILE *maybe_f, struct cloc loc, |
| 535 | cstring_t facility, const char *message, |
| 536 | va_list)) |
| 537 | FORMAT(printf,4,0); |
| 538 | extern NORETURN(cfgfatal_maybefile(FILE *maybe_f, struct cloc loc, |
| 539 | cstring_t facility, |
| 540 | const char *message, ...)) |
| 541 | FORMAT(printf,4,5); |
| 542 | |
| 543 | extern void Message(uint32_t class, const char *message, ...) |
| 544 | FORMAT(printf,2,3); |
| 545 | extern void log_from_fd(int fd, cstring_t prefix, struct log_if *log); |
| 546 | |
| 547 | /***** END of log functions *****/ |
| 548 | |
| 549 | #define STRING2(x) #x |
| 550 | #define STRING(x) STRING2(x) |
| 551 | |
| 552 | #define FILLZERO(obj) (memset(&(obj),0,sizeof((obj)))) |
| 553 | |
| 554 | /* |
| 555 | * void COPY_OBJ( OBJECT& dst, const OBJECT& src); |
| 556 | * void COPY_ARRAY(OBJECT *dst, const OBJECT *src, INTEGER count); |
| 557 | * // Typesafe: we check that the type OBJECT is the same in both cases. |
| 558 | * // It is OK to use COPY_OBJ on an array object, provided it's |
| 559 | * // _actually_ the whole array object and not decayed into a |
| 560 | * // pointer (e.g. a formal parameter). |
| 561 | */ |
| 562 | #define COPY_OBJ(dst,src) \ |
| 563 | (&(dst)==&(src), memcpy(&(dst),&(src),sizeof((dst)))) |
| 564 | #define COPY_ARRAY(dst,src,count) \ |
| 565 | (&(dst)[0]==&(src)[0], memcpy((dst),(src),sizeof((dst)[0])*(count))) |
| 566 | |
| 567 | #endif /* secnet_h */ |