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