#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
+#include <fnmatch.h>
#include <sys/poll.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* from process.c */
extern void start_signal_handling(void);
+void afterfork(void);
+/* Must be called before exec in every child made after
+ start_signal_handling. Safe to call in earlier children too. */
+
+void childpersist_closefd_hook(void *fd_p, uint32_t newphase);
+/* Convenience hook function for use with add_hook PHASE_CHILDPERSIST.
+ With `int fd' in your state struct, pass fd_p=&fd. The hook checks
+ whether fd>=0, so you can use it for an fd which is only sometimes
+ open. This function will set fd to -1, so it is idempotent. */
+
/***** CONFIGURATION support *****/
extern bool_t just_check_config; /* If True then we're going to exit after
extern void *safe_realloc_ary(void *p, size_t size, size_t count,
const char *message);
+#define NEW(p) \
+ ((p)=safe_malloc(sizeof(*(p)), \
+ __FILE__ ":" #p))
+#define NEW_ARY(p,count) \
+ ((p)=safe_malloc_ary(sizeof(*(p)),(count), \
+ __FILE__ ":" #p "[" #count "]"))
+#define REALLOC_ARY(p,count) \
+ ((p)=safe_realloc_ary((p),sizeof(*(p)),(count), \
+ __FILE__ ":" #p "[" #count "]"))
+
void setcloexec(int fd); /* cannot fail */
+void setnonblock(int fd); /* cannot fail */
void pipe_cloexec(int fd[2]); /* pipe(), setcloexec() twice; cannot fail */
extern int sys_cmd(const char *file, const char *argc, ...);
/* If nfds_io is insufficient for your needs, set it to the required
number and return ERANGE. timeout is in milliseconds; if it is too
- high then lower it. It starts at -1 (==infinite) */
+ high then lower it. It starts at -1 (==infinite). */
+/* Note that beforepoll_fn may NOT do anything which might change the
+ fds or timeouts wanted by other registered poll loop loopers.
+ Callers should make sure of this by not making any calls into other
+ modules from the beforepoll_fn; the easiest way to ensure this is
+ for beforepoll_fn to only retreive information and not take any
+ action.
+ */
typedef int beforepoll_fn(void *st, struct pollfd *fds, int *nfds_io,
int *timeout_io);
typedef void afterpoll_fn(void *st, struct pollfd *fds, int nfds);
+ /* If beforepoll_fn returned ERANGE, afterpoll_fn gets nfds==0.
+ afterpoll_fn never gets !!(fds[].revents & POLLNVAL) - such
+ a report is detected as a fatal error by the event loop. */
/* void BEFOREPOLL_WANT_FDS(int want);
* Expects: int *nfds_io;
/* Register interest in the main loop of the program. Before a call
to poll() your supplied beforepoll function will be called. After
- the call to poll() the supplied afterpoll function will be called.
- max_nfds is a _hint_ about the maximum number of struct pollfd
- structures you may require - you can always ask for more in
- *nfds_io. */
-extern void register_for_poll(void *st, beforepoll_fn *before,
- afterpoll_fn *after, int32_t max_nfds,
- cstring_t desc);
+ the call to poll() the supplied afterpoll function will be called. */
+struct poll_interest *register_for_poll(void *st, beforepoll_fn *before,
+ afterpoll_fn *after, cstring_t desc);
+void deregister_for_poll(struct poll_interest *i);
/***** END of scheduling support */
PHASE_DROPPRIV, /* Last chance for privileged operations */
PHASE_RUN,
PHASE_SHUTDOWN, /* About to die; delete key material, etc. */
+ PHASE_CHILDPERSIST, /* Forked long-term child: close fds, etc. */
/* Keep this last: */
NR_PHASES,
};
+/* Each module should, in its CHILDPERSIST hooks, close all fds which
+ constitute ownership of important operating system resources, or
+ which are used for IPC with other processes who want to get the
+ usual disconnection effects if the main secnet process dies.
+ CHILDPERSIST hooks are not run if the child is going to exec;
+ so fds such as described above should be CLOEXEC too. */
+
typedef void hook_fn(void *self, uint32_t newphase);
bool_t add_hook(uint32_t phase, hook_fn *f, void *state);
bool_t remove_hook(uint32_t phase, hook_fn *f, void *state);
extern uint32_t current_phase;
extern void enter_phase(uint32_t new_phase);
+void phase_hooks_init(void); /* for main() only */
+void clear_phase_hooks(uint32_t phase); /* for afterfork() */
+
/* Some features (like netlink 'soft' routes) require that secnet
retain root privileges. They should indicate that here when
appropriate. */
extern bool_t require_root_privileges;
extern cstring_t require_root_privileges_explanation;
+/* Some modules may want to know whether secnet is going to drop
+ privilege, so that they know whether to do privsep. Call only
+ in phases SETUP and later. */
+bool_t will_droppriv(void);
+
/***** END of program lifetime support *****/
/***** MODULE support *****/
extern init_module resolver_module;
extern init_module random_module;
extern init_module udp_module;
+extern init_module polypath_module;
extern init_module util_module;
extern init_module site_module;
extern init_module transform_eax_module;
};
/* Return True if the packet was processed, and shouldn't be passed to
- any other potential receivers. */
+ any other potential receivers. (buf is freed iff True returned.) */
typedef bool_t comm_notify_fn(void *state, struct buffer_if *buf,
const struct comm_addr *source);
typedef void comm_request_notify_fn(void *commst, void *nst,
comm_addr_to_string_fn *addr_to_string;
};
-bool_t iaddr_equal(const union iaddr *ia, const union iaddr *ib);
+bool_t iaddr_equal(const union iaddr *ia, const union iaddr *ib,
+ bool_t ignoreport);
static inline const char *comm_addr_to_string(const struct comm_addr *ca)
{
static inline bool_t comm_addr_equal(const struct comm_addr *a,
const struct comm_addr *b)
{
- return a->comm==b->comm && iaddr_equal(&a->ia,&b->ia);
+ return a->comm==b->comm && iaddr_equal(&a->ia,&b->ia,False);
}
/* LOG interface */
extern NORETURN(fatal_perror_status(int status, const char *message, ...))
FORMAT(printf,2,3);
+/* Convenient nonfatal logging. Requires message that does not end in '\n'.
+ * If class contains M_FATAL, exits (after entering PHASE_SHUTDOWN).
+ * lg, errnoval and loc may sensibly be 0. desc must NOT be 0.
+ * lg_[v]perror save and restore errno. */
+void lg_vperror(struct log_if *lg, const char *desc, struct cloc *loc,
+ int class, int errnoval, const char *fmt, va_list al)
+ FORMAT(printf,6,0);
+void lg_perror(struct log_if *lg, const char *desc, struct cloc *loc,
+ int class, int errnoval, const char *fmt, ...)
+ FORMAT(printf,6,7);
+void lg_exitstatus(struct log_if *lg, const char *desc, struct cloc *loc,
+ int class, int status, const char *progname);
+
/* The cfgfatal() family of functions require messages that end in '\n' */
extern NORETURN(cfgfatal(struct cloc loc, cstring_t facility,
const char *message, ...)) FORMAT(printf,3,4);