#include <pwd.h>
#include <grp.h>
+#ifdef HAVE_LIBADNS
+# define ADNS_FEATURE_MANYAF
+# include <adns.h>
+#endif
+
#include <mLib/alloc.h>
#include <mLib/arena.h>
#include <mLib/base64.h>
-#include <mLib/bres.h>
+#ifndef HAVE_LIBADNS
+# include <mLib/bres.h>
+#endif
#include <mLib/codec.h>
#include <mLib/daemonize.h>
#include <mLib/dstr.h>
#include <catacomb/ct.h>
#include <catacomb/chacha.h>
+#include <catacomb/gaead.h>
#include <catacomb/gcipher.h>
#include <catacomb/gmac.h>
#include <catacomb/grand.h>
+#include <catacomb/latinpoly.h>
#include <catacomb/key.h>
#include <catacomb/paranoia.h>
#include <catacomb/poly1305.h>
DHFMT_VAR /* Variable-width-format, mostly a bad idea */
};
+typedef struct deriveargs {
+ const char *what; /* Operation name (hashed) */
+ unsigned f; /* Flags */
+#define DF_IN 1u /* Make incoming key */
+#define DF_OUT 2u /* Make outgoing key */
+ const gchash *hc; /* Hash class */
+ const octet *k; /* Pointer to contributions */
+ size_t x, y, z; /* Markers in contributions */
+} deriveargs;
+
typedef struct bulkalgs {
const struct bulkops *ops;
} bulkalgs;
size_t tagsz;
} bulkchal;
-struct rawkey;
-
typedef struct dhops {
const char *name;
* after which the keys must no longer be used.
*/
- bulkctx *(*genkeys)(const bulkalgs */*a*/, const struct rawkey */*rk*/);
+ bulkctx *(*genkeys)(const bulkalgs */*a*/, const deriveargs */*a*/);
/* Generate session keys and construct and return an appropriate
- * context for using them, by calling @ks_derive@.
+ * context for using them. The offsets @a->x@, @a->y@ and @a->z@
+ * separate the key material into three parts. Between @a->k@ and
+ * @a->k + a->x@ is `my' contribution to the key material; between
+ * @a->k + a->x@ and @a->k + a->y@ is `your' contribution; and
+ * between @a->k + a->y@ and @a->k + a->z@ is a shared value we made
+ * together. These are used to construct (up to) two collections of
+ * symmetric keys: one for outgoing messages, the other for incoming
+ * messages. If @a->x == 0@ (or @a->y == a->x@) then my (or your)
+ * contribution is omitted.
*/
bulkchal *(*genchal)(const bulkalgs */*a*/);
/* Release a bulk encryption context and the resources it holds. */
int (*chaltag)(bulkchal */*bc*/, const void */*m*/, size_t /*msz*/,
- void */*t*/);
- /* Calculate a tag for the challenge in @m@, @msz@, and write it to
- * @t@. Return @-1@ on error, zero on success.
+ uint32 /*seq*/, void */*t*/);
+ /* Calculate a tag for the challenge in @m@, @msz@, with the sequence
+ * number @seq@, and write it to @t@. Return @-1@ on error, zero on
+ * success.
*/
int (*chalvrf)(bulkchal */*bc*/, const void */*m*/, size_t /*msz*/,
- const void */*t*/);
- /* Check the tag @t@ on @m@, @msz@: return zero if the tag is OK,
- * nonzero if it's bad.
+ uint32 /*seq*/, const void */*t*/);
+ /* Check the tag @t@ on @m@, @msz@ and @seq@: return zero if the tag
+ * is OK, nonzero if it's bad.
*/
void (*freechal)(bulkchal */*bc*/);
struct kdata {
unsigned ref; /* Reference counter */
struct knode *kn; /* Pointer to cache entry */
+ uint32 id; /* The underlying key's id */
char *tag; /* Full tag name of the key */
dhgrp *grp; /* The group we work in */
dhsc *k; /* The private key (or null) */
/*----- Data structures ---------------------------------------------------*/
+/* --- The address-family table --- */
+
+#define ADDRFAM(_) \
+ _(INET, want_ipv4) \
+ _(INET6, want_ipv6)
+
+enum {
+#define ENUM(af, qf) AFIX_##af,
+ ADDRFAM(ENUM)
+#undef ENUM
+ NADDRFAM
+};
+
+extern const struct addrfam {
+ int af;
+ const char *name;
+#ifdef HAVE_LIBADNS
+ adns_queryflags qf;
+#endif
+} aftab[NADDRFAM];
+
/* --- Socket addresses --- *
*
* A magic union of supported socket addresses.
typedef union addr {
struct sockaddr sa;
struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
} addr;
/* --- Mapping keyed on addresses --- */
const char *name; /* Name of this tunnel driver */
unsigned flags; /* Various interesting flags */
#define TUNF_PRIVOPEN 1u /* Need helper to open file */
- void (*init)(void); /* Initializes the system */
+ int (*init)(void); /* Initializes the system */
tunnel *(*create)(struct peer */*p*/, int /*fd*/, char **/*ifn*/);
/* Initializes a new tunnel */
void (*setifname)(tunnel */*t*/, const char */*ifn*/);
struct tunnel { const tunnel_ops *ops; };
#endif
+typedef struct tun_iter {
+ const struct tunnel_node *next;
+} tun_iter;
+
/* --- Peer statistics --- *
*
* Contains various interesting and not-so-interesting statistics about a
char *name; /* Peer's name */
char *privtag; /* Private key tag */
char *tag; /* Public key tag */
+ char *knock; /* Knock string, or null */
const tunnel_ops *tops; /* Tunnel operations */
unsigned long t_ka; /* Keep alive interval */
addr sa; /* Socket address to speak to */
unsigned f; /* Flags for the peer */
#define PSF_KXMASK 255u /* Key-exchange flags to set */
#define PSF_MOBILE 256u /* Address may change rapidly */
+#define PSF_EPHEM 512u /* Association is ephemeral */
} peerspec;
typedef struct peer_byname {
peer_byaddr *byaddr; /* Lookup-by-address block */
struct ping *pings; /* Pings we're waiting for */
peerspec spec; /* Specifications for this peer */
+ int afix; /* Index of address family */
tunnel *t; /* Tunnel for local packets */
char *ifname; /* Interface name for tunnel */
keyset *ks; /* List head for keysets */
typedef struct peer_iter { sym_iter i; } peer_iter;
+typedef struct udpsocket {
+ sel_file sf; /* Selector for the socket */
+ unsigned port; /* Chosen port number */
+} udpsocket;
+
typedef struct ping {
struct ping *next, *prev; /* Links to next and previous */
peer *p; /* Peer so we can free it */
typedef struct admin_resop {
admin_bgop bg; /* Background operation header */
char *addr; /* Hostname to be resolved */
+#ifdef HAVE_LIBADNS
+ adns_query q;
+#else
bres_client r; /* Background resolver task */
+#endif
sel_timer t; /* Timer for resolver */
addr sa; /* Socket address */
+ unsigned port; /* Port number chosen */
size_t sasz; /* Socket address size */
void (*func)(struct admin_resop *, int); /* Handler */
} admin_resop;
extern sel_state sel; /* Global I/O event state */
extern octet buf_i[PKBUFSZ], buf_o[PKBUFSZ], buf_t[PKBUFSZ], buf_u[PKBUFSZ];
-extern const tunnel_ops *tunnels[]; /* Table of tunnels (0-term) */
-extern const tunnel_ops *tun_default; /* Default tunnel to use */
+extern udpsocket udpsock[NADDRFAM]; /* The master UDP sockets */
extern kdata *master; /* Default private key */
-extern const char *tag_priv; /* Default private key tag */
+extern char *tag_priv; /* Default private key tag */
#ifndef NTRACE
extern const trace_opt tr_opts[]; /* Trace options array */
* @const char *pubkr@ = public keyring file
* @const char *ptag@ = default private-key tag
*
- * Returns: ---
+ * Returns: Zero on success, @-1@ on failure.
*
* Use: Initializes the key-management machinery, loading the
* keyrings and so on.
*/
-extern void km_init(const char */*privkr*/, const char */*pubkr*/,
- const char */*ptag*/);
+extern int km_init(const char */*privkr*/, const char */*pubkr*/,
+ const char */*ptag*/);
/* --- @km_reload@ --- *
*
extern int km_reload(void);
+/* --- @km_clear@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Forget the currently loaded keyrings. The @master@ key will
+ * be cleared, but other keys already loaded will continue to
+ * exist until their reference count drops to zero. Call
+ * @km_init@ to make everything work again.
+ */
+
+extern void km_clear(void);
+
/* --- @km_findpub@, @km_findpriv@ --- *
*
* Arguments: @const char *tag@ = key tag to load
extern kdata *km_findpub(const char */*tag*/);
extern kdata *km_findpriv(const char */*tag*/);
+/* --- @km_findpubbyid@, @km_findprivbyid@ --- *
+ *
+ * Arguments: @uint32 id@ = key id to load
+ *
+ * Returns: Pointer to the kdata object if successful, or null on error.
+ *
+ * Use: Fetches a public or private key from the keyring given its
+ * numeric id.
+ */
+
+extern kdata *km_findpubbyid(uint32 /*id*/);
+extern kdata *km_findprivbyid(uint32 /*id*/);
+
/* --- @km_samealgsp@ --- *
*
* Arguments: @const kdata *kdx, *kdy@ = two key data objects
/* --- @kx_message@ --- *
*
* Arguments: @keyexch *kx@ = pointer to key exchange context
+ * @const addr *a@ = sender's IP address and port
* @unsigned msg@ = the message code
* @buf *b@ = pointer to buffer containing the packet
*
- * Returns: ---
+ * Returns: Nonzero if the sender's address was unknown.
*
* Use: Reads a packet containing key exchange messages and handles
* it.
*/
-extern void kx_message(keyexch */*kx*/, unsigned /*msg*/, buf */*b*/);
+extern int kx_message(keyexch */*kx*/, const addr */*a*/,
+ unsigned /*msg*/, buf */*b*/);
/* --- @kx_free@ --- *
*
extern void kx_newkeys(keyexch */*kx*/);
-/* --- @kx_init@ --- *
+/* --- @kx_setup@ --- *
*
* Arguments: @keyexch *kx@ = pointer to key exchange context
* @peer *p@ = pointer to peer context
* exchange.
*/
-extern int kx_init(keyexch */*kx*/, peer */*p*/,
- keyset **/*ks*/, unsigned /*f*/);
+extern int kx_setup(keyexch */*kx*/, peer */*p*/,
+ keyset **/*ks*/, unsigned /*f*/);
-/*----- Keysets and symmetric cryptography --------------------------------*/
-
-/* --- @ks_drop@ --- *
+/* --- @kx_init@ --- *
*
- * Arguments: @keyset *ks@ = pointer to a keyset
+ * Arguments: ---
*
* Returns: ---
*
- * Use: Decrements a keyset's reference counter. If the counter hits
- * zero, the keyset is freed.
+ * Use: Initializes the key-exchange logic.
*/
-extern void ks_drop(keyset */*ks*/);
+extern void kx_init(void);
+
+/*----- Keysets and symmetric cryptography --------------------------------*/
-/* --- @ks_derivekey@ --- *
+/* --- @ks_drop@ --- *
*
- * Arguments: @octet *k@ = pointer to an output buffer of at least
- * @MAXHASHSZ@ bytes
- * @size_t ksz@ = actual size wanted (for tracing)
- * @const struct rawkey *rk@ = a raw key, as passed into
- * @genkeys@
- * @int dir@ = direction for the key (@DIR_IN@ or @DIR_OUT@)
- * @const char *what@ = label for the key (input to derivation)
+ * Arguments: @keyset *ks@ = pointer to a keyset
*
* Returns: ---
*
- * Use: Derives a session key, for use on incoming or outgoing data.
- * This function is part of a private protocol between @ks_gen@
- * and the bulk crypto transform @genkeys@ operation.
+ * Use: Decrements a keyset's reference counter. If the counter hits
+ * zero, the keyset is freed.
*/
-extern void ks_derivekey(octet */*k*/, size_t /*ksz*/,
- const struct rawkey */*rk*/,
- int /*dir*/, const char */*what*/);
+extern void ks_drop(keyset */*ks*/);
/* --- @ks_gen@ --- *
*
- * Arguments: @const void *k@ = pointer to key material
- * @size_t x, y, z@ = offsets into key material (see below)
+ * Arguments: @deriveargs *a@ = key derivation parameters (modified)
* @peer *p@ = pointer to peer information
*
* Returns: A pointer to the new keyset.
*
- * Use: Derives a new keyset from the given key material. The
- * offsets @x@, @y@ and @z@ separate the key material into three
- * parts. Between the @k@ and @k + x@ is `my' contribution to
- * the key material; between @k + x@ and @k + y@ is `your'
- * contribution; and between @k + y@ and @k + z@ is a shared
- * value we made together. These are used to construct two
- * collections of symmetric keys: one for outgoing messages, the
- * other for incoming messages.
+ * Use: Derives a new keyset from the given key material. This will
+ * set the @what@, @f@, and @hc@ members in @*a@; other members
+ * must be filled in by the caller.
*
* The new key is marked so that it won't be selected for output
* by @ksl_encrypt@. You can still encrypt data with it by
* calling @ks_encrypt@ directly.
*/
-extern keyset *ks_gen(const void */*k*/,
- size_t /*x*/, size_t /*y*/, size_t /*z*/,
- peer */*p*/);
+extern keyset *ks_gen(deriveargs */*a*/, peer */*p*/);
/* --- @ks_activate@ --- *
*
/* --- @c_new@ --- *
*
- * Arguments: @buf *b@ = where to put the challenge
+ * Arguments: @const void *m@ = pointer to associated message, or null
+ * @size_t msz@ = length of associated message
+ * @buf *b@ = where to put the challenge
*
* Returns: Zero if OK, nonzero on error.
*
* Use: Issues a new challenge.
*/
-extern int c_new(buf */*b*/);
+extern int c_new(const void */*m*/, size_t /*msz*/, buf */*b*/);
/* --- @c_check@ --- *
*
- * Arguments: @buf *b@ = where to find the challenge
+ * Arguments: @const void *m@ = pointer to associated message, or null
+ * @size_t msz@ = length of associated message
+ * @buf *b@ = where to find the challenge
*
* Returns: Zero if OK, nonzero if it didn't work.
*
* Use: Checks a challenge. On failure, the buffer is broken.
*/
-extern int c_check(buf */*b*/);
+extern int c_check(const void */*m*/, size_t /*msz*/, buf */*b*/);
/*----- Administration interface ------------------------------------------*/
*
* * "?PEER" PEER -- peer's name
*
- * * "?ERRNO" ERRNO -- system error code
+ * * "?ERR" CODE -- system error code
+ *
+ * * "?ERRNO" -- system error code from @errno@
*
* * "[!]..." ... -- @dstr_putf@-like string as single token
*/
*
* Returns: ---
*
- * Use: Creates a new admin connection.
+ * Use: Creates a new admin connection. It's safe to call this
+ * before @a_init@ -- and, indeed, this makes sense if you also
+ * call @a_switcherr@ to report initialization errors through
+ * the administration machinery.
*/
extern void a_create(int /*fd_in*/, int /*fd_out*/, unsigned /*f*/);
-/* --- @a_quit@ --- *
- *
- * Arguments: ---
- *
- * Returns: ---
- *
- * Use: Shuts things down nicely.
- */
-
-extern void a_quit(void);
-
/* --- @a_preselect@ --- *
*
* Arguments: ---
extern void a_daemon(void);
+/* --- @a_listen@ --- *
+ *
+ * Arguments: @const char *name@ = socket name to create
+ * @uid_t u@ = user to own the socket
+ * @gid_t g@ = group to own the socket
+ * @mode_t m@ = permissions to set on the socket
+ *
+ * Returns: Zero on success, @-1@ on failure.
+ *
+ * Use: Creates the admin listening socket.
+ */
+
+extern int a_listen(const char */*sock*/,
+ uid_t /*u*/, gid_t /*g*/, mode_t /*m*/);
+
+/* --- @a_unlisten@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Stops listening to the administration socket and removes it.
+ */
+
+extern void a_unlisten(void);
+
+/* --- @a_switcherr@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Arrange to report warnings, trace messages, etc. to
+ * administration clients rather than the standard-error stream.
+ *
+ * Obviously this makes no sense unless there is at least one
+ * client established. Calling @a_listen@ won't help with this,
+ * because the earliest a new client can connect is during the
+ * first select-loop iteration, which is too late: some initial
+ * client must have been added manually using @a_create@.
+ */
+
+extern void a_switcherr(void);
+
+/* --- @a_signals@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Establishes handlers for the obvious signals.
+ */
+
+extern void a_signals(void);
+
/* --- @a_init@ --- *
*
* Arguments: @const char *sock@ = socket name to create
* @gid_t g@ = group to own the socket
* @mode_t m@ = permissions to set on the socket
*
- * Returns: ---
+ * Returns: Zero on success, @-1@ on failure.
*
* Use: Creates the admin listening socket.
*/
-extern void a_init(const char */*sock*/,
- uid_t /*u*/, gid_t /*g*/, mode_t /*m*/);
+extern int a_init(void);
/*----- Mapping with addresses as keys ------------------------------------*/
*
* Arguments: @int detachp@ = whether to detach the child from its terminal
*
- * Returns: ---
+ * Returns: Zero on success, @-1@ on failure.
*
* Use: Separates off the privileged tunnel-opening service from the
* rest of the server.
*/
-extern void ps_split(int /*detachp*/);
+extern int ps_split(int /*detachp*/);
/* --- @ps_quit@ --- *
*
extern buf *p_txstart(peer */*p*/, unsigned /*msg*/);
+/* --- @p_txaddr@ --- *
+ *
+ * Arguments: @const addr *a@ = recipient address
+ * @const void *p@ = pointer to packet to send
+ * @size_t sz@ = length of packet
+ *
+ * Returns: Zero if successful, nonzero on error.
+ *
+ * Use: Sends a packet to an address which (possibly) isn't a current
+ * peer.
+ */
+
+extern int p_txaddr(const addr */*a*/, const void */*p*/, size_t /*sz*/);
+
/* --- @p_txend@ --- *
*
* Arguments: @peer *p@ = pointer to peer block
extern const addr *p_addr(peer */*p*/);
+/* --- @p_bind@ --- *
+ *
+ * Arguments: @struct addrinfo *ailist@ = addresses to bind to
+ *
+ * Returns: Zero on success, @-1@ on failure.
+ *
+ * Use: Binds to the main UDP sockets.
+ */
+
+extern int p_bind(struct addrinfo */*ailist*/);
+
+/* --- @p_unbind@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Unbinds the UDP sockets. There must not be any active peers,
+ * and none can be created until the sockets are rebound.
+ */
+
+extern void p_unbind(void);
+
/* --- @p_init@ --- *
*
- * Arguments: @struct in_addr addr@ = address to bind to
- * @unsigned port@ = port number to listen to
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Initializes the peer system.
+ */
+
+extern void p_init(void);
+
+/* --- @p_addtun@ --- *
+ *
+ * Arguments: @const tunnel_ops *tops@ = tunnel ops to add
+ *
+ * Returns: Zero on success, @-1@ on failure.
+ *
+ * Use: Adds a tunnel class to the list of known classes, if it
+ * initializes properly. If there is no current default tunnel,
+ * then this one is made the default.
+ *
+ * Does nothing if the tunnel class is already known. So adding
+ * a bunch of tunnels takes quadratic time, but there will be
+ * too few to care about.
+ */
+
+extern int p_addtun(const tunnel_ops */*tops*/);
+
+/* --- @p_setdflttun@ --- *
+ *
+ * Arguments: @const tunnel_ops *tops@ = tunnel ops to set
*
* Returns: ---
*
- * Use: Initializes the peer system; creates the socket.
+ * Use: Sets the default tunnel. It must already be registered. The
+ * old default is forgotten.
*/
-extern void p_init(struct in_addr /*addr*/, unsigned /*port*/);
+extern void p_setdflttun(const tunnel_ops */*tops*/);
-/* --- @p_port@ --- *
+/* --- @p_dflttun@ --- *
*
* Arguments: ---
*
- * Returns: Port number used for socket.
+ * Returns: A pointer to the current default tunnel operations, or null
+ * if no tunnels are defined.
+ */
+
+extern const tunnel_ops *p_dflttun(void);
+
+/* --- @p_findtun@ --- *
+ *
+ * Arguments: @const char *name@ = tunnel name
+ *
+ * Returns: Pointer to the tunnel operations, or null.
+ *
+ * Use: Finds the operations for a named tunnel class.
+ */
+
+extern const tunnel_ops *p_findtun(const char */*name*/);
+
+/* --- @p_mktuniter@ --- *
+ *
+ * Arguments: @tuniter *i@ = pointer to iterator to initialize
+ *
+ * Returns: ---
+ *
+ * Use: Initializes a tunnel iterator.
+ */
+
+extern void p_mktuniter(tun_iter */*i*/);
+
+/* --- @p_nexttun@ --- *
+ *
+ * Arguments: @tuniter *i@ = pointer to iterator
+ *
+ * Returns: Pointer to the next tunnel's operations, or null.
+ */
+
+extern const tunnel_ops *p_nexttun(tun_iter */*i*/);
+
+/* --- @FOREACH_TUN@ --- *
+ *
+ * Arguments: @tops@ = name to bind to each tunnel
+ * @stuff@ = thing to do for each item
+ *
+ * Use: Does something for each known tunnel class.
*/
-unsigned p_port(void);
+#define FOREACH_TUN(tops, stuff) do { \
+ tun_iter i_; \
+ const tunnel_ops *tops; \
+ for (p_mktuniter(&i_); (tops = p_nexttun(&i_)) != 0; ) stuff; \
+} while (0)
/* --- @p_create@ --- *
*
/* --- @p_destroy@ --- *
*
* Arguments: @peer *p@ = pointer to a peer
+ * @int bye@ = say goodbye to the peer?
*
* Returns: ---
*
* Use: Destroys a peer.
*/
-extern void p_destroy(peer */*p*/);
+extern void p_destroy(peer */*p*/, int /*bye*/);
+
+/* --- @p_destroyall@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Destroys all of the peers, saying goodbye.
+ */
+
+extern void p_destroyall(void);
/* --- @FOREACH_PEER@ --- *
*
extern peer *p_next(peer_iter */*i*/);
+/*----- The interval timer ------------------------------------------------*/
+
+/* --- @iv_addreason@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Adds an `interval timer reason'; if there are no others, the
+ * interval timer is engaged.
+ */
+
+extern void iv_addreason(void);
+
+/* --- @iv_rmreason@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Removes an interval timer reason; if there are none left, the
+ * interval timer is disengaged.
+ */
+
+extern void iv_rmreason(void);
+
+/*----- The main loop -----------------------------------------------------*/
+
+/* --- @lp_init@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Initializes the main loop. Most importantly, this sets up
+ * the select multiplexor that everything else hooks onto.
+ */
+
+extern void lp_init(void);
+
+/* --- @lp_end@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Requests an exit from the main loop.
+ */
+
+extern void lp_end(void);
+
+/* --- @lp_run@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: Zero on successful termination; @-1@ if things went wrong.
+ *
+ * Use: Cranks the main loop until it should be cranked no more.
+ */
+
+extern int lp_run(void);
+
/*----- Tunnel drivers ----------------------------------------------------*/
#ifdef TUN_LINUX
extern int mystrieq(const char */*x*/, const char */*y*/);
+/* --- @afix@ --- *
+ *
+ * Arguments: @int af@ = an address family code
+ *
+ * Returns: The index of the address family's record in @aftab@, or @-1@.
+ */
+
+extern int afix(int af);
+
/* --- @addrsz@ --- *
*
* Arguments: @const addr *a@ = a network address
extern socklen_t addrsz(const addr */*a*/);
+/* --- @getport@, @setport@ --- *
+ *
+ * Arguments: @addr *a@ = a network address
+ * @unsigned port@ = port number to set
+ *
+ * Returns: ---
+ *
+ * Use: Retrieves or sets the port number in an address structure.
+ */
+
+extern unsigned getport(addr */*a*/);
+extern void setport(addr */*a*/, unsigned /*port*/);
+
/* --- @seq_reset@ --- *
*
* Arguments: @seqwin *s@ = sequence-checking window
extern int seq_check(seqwin */*s*/, uint32 /*q*/, const char */*service*/);
+typedef struct ratelim {
+ unsigned n, max, persec;
+ struct timeval when;
+} ratelim;
+
+/* --- @ratelim_init@ --- *
+ *
+ * Arguments: @ratelim *r@ = rate-limiting state to fill in
+ * @unsigned persec@ = credit to accumulate per second
+ * @unsigned max@ = maximum credit to retain
+ *
+ * Returns: ---
+ *
+ * Use: Initialize a rate-limiting state.
+ */
+
+extern void ratelim_init(ratelim */*r*/,
+ unsigned /*persec*/, unsigned /*max*/);
+
+/* --- @ratelim_withdraw@ --- *
+ *
+ * Arguments: @ratelim *r@ = rate-limiting state
+ * @unsigned n@ = credit to withdraw
+ *
+ * Returns: Zero if successful; @-1@ if there is unsufficient credit
+ *
+ * Use: Updates the state with any accumulated credit. Then, if
+ * there there are more than @n@ credits available, withdraw @n@
+ * and return successfully; otherwise, report failure.
+ */
+
+extern int ratelim_withdraw(ratelim */*r*/, unsigned /*n*/);
+
+/* --- @ies_encrypt@ --- *
+ *
+ * Arguments: @kdata *kpub@ = recipient's public key
+ * @unsigned ty@ = message type octet
+ * @buf *b@ = input message buffer
+ * @buf *bb@ = output buffer for the ciphertext
+ *
+ * Returns: On error, returns a @KSERR_...@ code or breaks the buffer;
+ * on success, returns zero and the buffer is good.
+ *
+ * Use: Encrypts a message for a recipient, given their public key.
+ * This does not (by itself) provide forward secrecy or sender
+ * authenticity. The ciphertext is self-delimiting (unlike
+ * @ks_encrypt@).
+ */
+
+extern int ies_encrypt(kdata */*kpub*/, unsigned /*ty*/,
+ buf */*b*/, buf */*bb*/);
+
+/* --- @ies_decrypt@ --- *
+ *
+ * Arguments: @kdata *kpub@ = private key key
+ * @unsigned ty@ = message type octet
+ * @buf *b@ = input ciphertext buffer
+ * @buf *bb@ = output buffer for the message
+ *
+ * Returns: On error, returns a @KSERR_...@ code; on success, returns
+ * zero and the buffer is good.
+ *
+ * Use: Decrypts a message encrypted using @ies_encrypt@, given our
+ * private key.
+ */
+
+extern int ies_decrypt(kdata */*kpriv*/, unsigned /*ty*/,
+ buf */*b*/, buf */*bb*/);
+
/*----- That's all, folks -------------------------------------------------*/
#ifdef __cplusplus