#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define MAX_PEER_ADDRS 5
+/* send at most this many copies; honour at most that many addresses */
+
+struct comm_if;
+struct comm_addr;
typedef char *string_t;
typedef const char *cstring_t;
-typedef enum {False,True} bool_t;
+
+#define False (_Bool)0
+#define True (_Bool)1
+typedef _Bool bool_t;
+
+union iaddr {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef CONFIG_IPV6
+ struct sockaddr_in6 sin6;
+#endif
+};
#define ASSERT(x) do { if (!(x)) { fatal("assertion failed line %d file " \
__FILE__,__LINE__); } } while(0)
/* List-manipulation functions */
extern list_t *list_new(void);
-extern int32_t list_length(list_t *a);
+extern int32_t list_length(const list_t *a);
extern list_t *list_append(list_t *a, item_t *i);
extern list_t *list_append_list(list_t *a, list_t *b);
/* Returns an item from the list (index starts at 0), or NULL */
extern void *safe_malloc(size_t size, const char *message);
extern void *safe_malloc_ary(size_t size, size_t count, const char *message);
+void setcloexec(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, ...);
extern uint64_t now_global;
/***** END of utility functions *****/
+/***** START of max_start_pad handling *****/
+
+extern int32_t site_max_start_pad, transform_max_start_pad,
+ comm_max_start_pad;
+
+void update_max_start_pad(int32_t *our_module_global, int32_t our_instance);
+int32_t calculate_max_start_pad(void);
+
+/***** END of max_start_pad handling *****/
+
/***** SCHEDULING support */
/* If nfds_io is insufficient for your needs, set it to the required
type. 'address' will be NULL if there was a problem with the query. It
will be freed once resolve_answer_fn returns. It is in network byte
order. */
-/* XXX extend to be able to provide multiple answers */
-typedef void resolve_answer_fn(void *st, struct in_addr *addr);
+typedef void resolve_answer_fn(void *st, const struct comm_addr *addrs,
+ int naddrs);
typedef bool_t resolve_request_fn(void *st, cstring_t name,
+ int remoteport, struct comm_if *comm,
resolve_answer_fn *cb, void *cst);
struct resolver_if {
void *st;
must start by memsetting it with FILLZERO, or some
equivalent. */
struct comm_if *comm;
- struct sockaddr_in sin;
+ union iaddr ia;
};
/* Return True if the packet was processed, and shouldn't be passed to
comm_notify_fn *fn);
typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf,
const struct comm_addr *dest);
+ /* Only returns false if (we know that) the local network
+ * environment is such that this address cannot work; transient
+ * or unknown/unexpected failures return true. */
typedef const char *comm_addr_to_string_fn(void *commst,
const struct comm_addr *ca);
/* Returned string is in a static buffer. */
struct comm_if {
void *st;
- int32_t min_start_pad;
comm_request_notify_fn *request_notify;
comm_release_notify_fn *release_notify;
comm_sendmsg_fn *sendmsg;
comm_addr_to_string_fn *addr_to_string;
};
+static inline const char *comm_addr_to_string(const struct comm_addr *ca)
+{
+ return ca->comm->addr_to_string(ca->comm->st, ca);
+}
+
/* LOG interface */
+#define LOG_MESSAGE_BUFLEN 1023
+
typedef void log_msg_fn(void *st, int class, const char *message, ...);
typedef void log_vmsg_fn(void *st, int class, const char *message,
va_list args);
struct log_if {
void *st;
- log_msg_fn *log;
- log_vmsg_fn *vlog;
+ log_vmsg_fn *vlogfn; /* printf format checking. Use [v]slilog instead */
+ char buff[LOG_MESSAGE_BUFLEN+1];
};
/* (convenience functions, defined in util.c) */
extern void slilog(struct log_if *lf, int class, const char *message, ...)
extern void vslilog(struct log_if *lf, int class, const char *message, va_list)
FORMAT(printf,3,0);
+/* Versions which take (parts of) (multiple) messages, using \n to
+ * distinguish one message from another. */
+extern void slilog_part(struct log_if *lf, int class, const char *message, ...)
+FORMAT(printf,3,4);
+extern void vslilog_part(struct log_if *lf, int class, const char *message,
+ va_list) FORMAT(printf,3,0);
+
/* SITE interface */
/* Pretty much a placeholder; allows starting and stopping of processing,
/* TRANSFORM interface */
/* A reversable transformation. Transforms buffer in-place; may add
- data to start or end. Maximum amount of data to be added before
- the packet specified in max_start_pad. (Reverse transformations decrease
+ data to start or end. (Reverse transformations decrease
length, of course.) Transformations may be key-dependent, in which
case key material is passed in at initialisation time. They may
also depend on internal factors (eg. time) and keep internal
struct transform_if {
void *st;
- int32_t max_start_pad; /* these two are both <<< INT_MAX */
- int32_t keylen; /* 0 means give the transform exactly as much as there is */
+ int capab_transformnum;
+ int32_t keylen; /* <<< INT_MAX */
transform_createinstance_fn *create;
};
#define MAXIMUM_LINK_QUALITY 3
typedef void netlink_link_quality_fn(void *st, uint32_t quality);
typedef void netlink_register_fn(void *st, netlink_deliver_fn *deliver,
- void *dst, int32_t max_start_pad);
+ void *dst, uint32_t *localmtu_r /* NULL ok */);
typedef void netlink_output_config_fn(void *st, struct buffer_if *buf);
typedef bool_t netlink_check_config_fn(void *st, struct buffer_if *buf);
typedef void netlink_set_mtu_fn(void *st, int32_t new_mtu);
uint8_t *base;
uint8_t *start;
int32_t size; /* Size of buffer contents */
- int32_t len; /* Total length allocated at base */
+ int32_t alloclen; /* Total length allocated at base */
};
/***** LOG functions *****/
#define M_FATAL 0x100
/* The fatal() family of functions require messages that do not end in '\n' */
-extern NORETURN(fatal(const char *message, ...));
-extern NORETURN(fatal_perror(const char *message, ...));
-extern NORETURN(fatal_status(int status, const char *message, ...));
-extern NORETURN(fatal_perror_status(int status, const char *message, ...));
+extern NORETURN(fatal(const char *message, ...)) FORMAT(printf,1,2);
+extern NORETURN(fatal_perror(const char *message, ...)) FORMAT(printf,1,2);
+extern NORETURN(fatal_status(int status, const char *message, ...))
+ FORMAT(printf,2,3);
+extern NORETURN(fatal_perror_status(int status, const char *message, ...))
+ FORMAT(printf,2,3);
/* The cfgfatal() family of functions require messages that end in '\n' */
extern NORETURN(cfgfatal(struct cloc loc, cstring_t facility,
- const char *message, ...));
+ const char *message, ...)) FORMAT(printf,3,4);
extern void cfgfile_postreadcheck(struct cloc loc, FILE *f);
extern NORETURN(vcfgfatal_maybefile(FILE *maybe_f, struct cloc loc,
cstring_t facility, const char *message,
- va_list));
+ va_list))
+ FORMAT(printf,4,0);
extern NORETURN(cfgfatal_maybefile(FILE *maybe_f, struct cloc loc,
cstring_t facility,
- const char *message, ...));
+ const char *message, ...))
+ FORMAT(printf,4,5);
extern void Message(uint32_t class, const char *message, ...)
FORMAT(printf,2,3);
#define FILLZERO(obj) (memset(&(obj),0,sizeof((obj))))
+/*
+ * void COPY_OBJ( OBJECT& dst, const OBJECT& src);
+ * void COPY_ARRAY(OBJECT *dst, const OBJECT *src, INTEGER count);
+ * // Typesafe: we check that the type OBJECT is the same in both cases.
+ * // It is OK to use COPY_OBJ on an array object, proviced it's
+ * // _actually_ the whole array object and not decayed into a
+ * // pointer (e.g. a formal parameter).
+ */
+#define COPY_OBJ(dst,src) \
+ (&(dst)==&(src), memcpy(&(dst),&(src),sizeof((dst))))
+#define COPY_ARRAY(dst,src,count) \
+ (&(dst)[0]==&(src)[0], memcpy((dst),(src),sizeof((dst)[0])*(count)))
+
#endif /* secnet_h */