General spring-cleaning. Most of the code is pretty nice now.
[yaid] / yaid.h
diff --git a/yaid.h b/yaid.h
index 80aa98b..126c201 100644 (file)
--- a/yaid.h
+++ b/yaid.h
 #include <mLib/sel.h>
 #include <mLib/selbuf.h>
 
-/*----- System specifics --------------------------------------------------*/
+/*----- Address family handling -------------------------------------------*/
 
-#define SYS_UNDEF 0
-#define SYS_LINUX 1
-
-#if SYS == SYS_LINUX
-#  include <linux/netlink.h>
-#  include <linux/rtnetlink.h>
-#else
-#  error "Unsupported operating system: sorry.  Patches welcome!"
-#endif
+/* The maximum length of an address formatted as a text string, including the
+ * terminating null byte.
+ */
+#define ADDRLEN 64
 
-/*----- Data structures ---------------------------------------------------*/
+/* A list of address types. */
+#define ADDRTYPES(_)                                                   \
+  _(ipv4, IPV4)                                                                \
+  _(ipv6, IPV6)
 
-#define ADDRLEN 64
+/* Address types for the various families, in the form acceptable to
+ * inet_ntop(3) and inet_pton(3). */
+#define TYPE_IPV4 struct in_addr
+#define TYPE_IPV6 struct in6_addr
 
+/* A union of address types. */
 union addr {
-  struct in_addr ipv4;
-  struct in6_addr ipv6;
+#define UMEMB(ty, TY) TYPE_##TY ty;
+  ADDRTYPES(UMEMB)
+#undef UMEMB
 };
 
+/* A socket holds an address and a port number. */
 struct socket {
-  union addr addr;
-  unsigned port;
+  union addr addr;                     /* The address */
+  unsigned port;                       /* The port, in /host/ byte order */
 };
 
+/* An address pattern consists of an address and a prefix length: the
+ * pattern matches an address if they agree in the first LEN bits.
+ */
 struct addrpat {
-  unsigned len;
-  union addr addr;
+  union addr addr;                     /* The base address */
+  unsigned len;                                /* The prefix length */
 };
 
+/* A port pattern matches a port if the port is within the stated (inclusive)
+ * bounds.
+ */
 struct portpat {
   unsigned lo, hi;
 };
 
+/* A socket pattern consists simply of an address pattern and a port pattern:
+ * it matches a socket componentwise.
+ */
 struct sockpat {
   struct addrpat addr;
   struct portpat port;
 };
 
-#define ADDRTYPES(_)                                                   \
-  _(ipv4, IPV4)                                                                \
-  _(ipv6, IPV6)
-
+/* The table of address-type operations.  Each address family has one of
+ * these, so that most of the program doesn't need to worry about these
+ * details.
+ */
 struct addrops {
-  int af;
-  const char *name;
-  unsigned len;
-  const union addr *any;
-  const struct addrops_sys *sys;
+  int af;                              /* The AF_* constant */
+  const char *name;                    /* Name of the protocol, for logs */
+  unsigned len;                                /* Length of an address, in bits */
+  const union addr *any;               /* A wildcard address */
+  const struct addrops_sys *sys;       /* Pointer to system-specific ops */
+
   int (*addreq)(const union addr *, const union addr *);
+       /* Return nonzero if the two addresses are equal. */
+
   int (*match_addrpat)(const struct addrpat *, const union addr *);
+       /* Return nonzero if the pattern matches the address. */
+
   void (*socket_to_sockaddr)(const struct socket *s, void *, size_t *);
+       /* Convert a socket structure to a `struct sockaddr', and return the
+        * size of the latter.
+        */
+
   void (*sockaddr_to_addr)(const void *, union addr *);
+       /* Extract the address from a `struct sockaddr'. */
+
   int (*init_listen_socket)(int);
+       /* Perform any necessary extra operations on a socket which is going
+        * to be used to listen for incoming connections.
+        */
 };
 
+/* A handy constant for each address family.  These are more useful than the
+ * AF_* constants in that they form a dense sequence.
+ */
 enum {
 #define DEFADDR(ty, TY) ADDR_##TY,
   ADDRTYPES(DEFADDR)
@@ -131,25 +161,53 @@ enum {
   ADDR_LIMIT
 };
 
+/* The table of address operations, indexed by the ADDR_* constants defined
+ * just above.
+ */
 extern const struct addrops addroptab[];
-#define OPS_SYS(ty, TY)                                        \
+
+/* System-specific operations, provided by the system-specific code for its
+ * own purposes.
+ */
+#define OPS_SYS(ty, TY)                                                        \
   extern const struct addrops_sys addrops_sys_##ty;
 ADDRTYPES(OPS_SYS)
 #undef OPS_SYS
 
+/* Answer whether the sockets SA and SB are equal. */
+extern int sockeq(const struct addrops */*ao*/,
+                 const struct socket */*sa*/, const struct socket */*sb*/);
+
+/* Write a textual description of S to the string D. */
+extern void dputsock(dstr */*d*/, const struct addrops */*ao*/,
+                    const struct socket */*s*/);
+
+/*----- Queries and responses ---------------------------------------------*/
+
+/* Constants for describing the `L'ocal and `R'emote ends of a connection. */
 enum { L, R, NDIR };
 
+/* Response types, and the data needed to represent any associated data.  A
+ * U(MEMB, TYPE) constructs a union member; an N means no associated data.
+ */
 #define RESPONSE(_)                                                    \
   _(ERROR, U(error, unsigned))                                         \
   _(UID, U(uid, uid_t))                                                        \
   _(NAT, U(nat, struct socket))
 
+enum {
+#define DEFENUM(what, branch) R_##what,
+  RESPONSE(DEFENUM)
+#undef DEFENUM
+  R_LIMIT
+};
+
+/* Protocol error tokens. */
 #define ERROR(_)                                                       \
   _(INVPORT, "INVALID-PORT")                                           \
   _(NOUSER, "NO-USER")                                                 \
   _(HIDDEN, "HIDDEN-USER")                                             \
   _(UNKNOWN, "UNKNOWN-ERROR")
-extern const char *const errtok[];
 
 enum {
 #define DEFENUM(err, tok) E_##err,
@@ -158,18 +216,16 @@ enum {
   E_LIMIT
 };
 
-enum {
-#define DEFENUM(what, branch) R_##what,
-  RESPONSE(DEFENUM)
-#undef DEFENUM
-  R_LIMIT
-};
+extern const char *const errtok[];
 
+/* The query structure keeps together the parameters to the client's query
+ * and our response to it.
+ */
 struct query {
-  const struct addrops *ao;
-  struct socket s[NDIR];
-  unsigned resp;
-  union {
+  const struct addrops *ao;            /* Address family operations */
+  struct socket s[NDIR];               /* The local and remote ends */
+  unsigned resp;                       /* Our response type */
+  union {                              /* A union of response data */
 #define DEFBRANCH(WHAT, branch) branch
 #define U(memb, ty) ty memb;
 #define N
@@ -180,13 +236,28 @@ struct query {
   } u;
 } query;
 
-enum {
-  T_OK,
-  T_EOL,
-  T_EOF,
-  T_ERROR
-};
+/*----- Common utility functions ------------------------------------------*/
+
+/* Format and log MSG somewhere sensible, at the syslog(3) priority PRIO.
+ * Prefix it with a description of the query Q, if non-null.
+ */
+extern void logmsg(const struct query */*q*/,
+                  int /*prio*/, const char */*msg*/, ...);
 
+/*----- System-specific connection identification code --------------------*/
+
+/* Find out who is responsible for the connection described in the query Q.
+ * Write the answer to Q.  Errors are logged and reported via the query
+ * structure.
+ */
+extern void identify(struct query */*q*/);
+
+/* Initialize the system-specific code. */
+extern void init_sys(void);
+
+/*----- Policy management -------------------------------------------------*/
+
+/* The possible policy actions and their names. */
 #define ACTIONS(_)                                                     \
   _(USER, "user")                                                      \
   _(TOKEN, "token")                                                    \
@@ -202,54 +273,85 @@ enum {
   A_LIMIT
 };
 
+/* A policy action. */
 struct action {
   unsigned act;
   union {
-    unsigned user;
-    char *lie;
+    unsigned user;                     /* Bitmask of permitted actions */
+    char *lie;                         /* The user name to impersonate */
   } u;
 };
 
+/* A policy rule: if the query matches the pattern, then perform the
+ * action.
+ */
 struct policy {
   const struct addrops *ao;
   struct sockpat sp[NDIR];
   struct action act;
 };
-#define POLICY_INIT(a) { 0, { { { 0 } } }, { a } }
+#define POLICY_INIT(a) { .act.act = a }
+DA_DECL(policy_v, struct policy);
 
-struct policy_file {
-  FILE *fp;
-  const struct query *q;
-  const char *name;
-  const char *what;
-  int err;
-  int lno;
-  struct policy p;
-};
+/* Initialize a policy structure.  In this state, it doesn't actually have
+ * any resources allocated (so can be simply discarded) but it's safe to free
+ * (using `free_policy').
+ */
+extern void init_policy(struct policy */*p*/);
 
-DA_DECL(policy_v, struct policy);
+/* Free a policy structure, resetting it to its freshly-initialized state.
+ * This function is idempotent.
+ */
+extern void free_policy(struct policy */*p*/);
+
+/* Print a policy rule to standard output. */
+extern void print_policy(const struct policy */*p*/);
+
+/* Return true if the query matches the patterns in the policy rule. */
+extern int match_policy(const struct policy */*p*/,
+                       const struct query */*q*/);
+
+/*----- Parsing policy files ----------------------------------------------*/
 
-/*----- Functions provided ------------------------------------------------*/
+/* Possible results from a parse. */
+enum {
+  T_OK,                                        /* Successful: results returned */
+  T_EOL,                               /* End-of-line found immediately */
+  T_EOF,                               /* End-of-file found immediately */
+  T_ERROR                              /* Some kind of error occurred */
+};
 
-int sockeq(const struct addrops *ao,
-          const struct socket *sa, const struct socket *sb);
-void dputsock(dstr *d, const struct addrops *ao, const struct socket *s);
+/* A context for parsing a policy file. */
+struct policy_file {
+  FILE *fp;                            /* The file to read from */
+  const struct query *q;               /* A query to use for logging */
+  const char *name;                    /* The name of the file */
+  const char *what;                    /* A description of the file */
+  int err;                             /* Have there been any errors? */
+  int lno;                             /* The current line number */
+  struct policy p;                     /* Parsed policy rule goes here */
+};
 
-void logmsg(const struct query *q, int prio, const char *msg, ...);
+/* Open a policy file by NAME.  The description WHAT and query Q are used for
+ * formatting error messages for the log.
+ */
+extern int open_policy_file(struct policy_file */*pf*/, const char */*name*/,
+                           const char */*what*/, const struct query */*q*/);
 
-void identify(struct query *q);
-void init_sys(void);
+/* Read a policy rule from the file, storing it in PF->p.  Return one of the
+ * T_* codes.
+ */
+extern int read_policy_file(struct policy_file */*pf*/);
+
+/* Close a policy file.  It doesn't matter whether the file was completely
+ * read.
+ */
+extern void close_policy_file(struct policy_file */*pf*/);
 
-void init_policy(struct policy *p);
-void free_policy(struct policy *p);
-void print_policy(const struct policy *p);
-int match_policy(const struct policy *p, const struct query *q);
-int parse_policy(FILE *fp, struct policy *p);
-int open_policy_file(struct policy_file *pf, const char *name,
-                    const char *what, const struct query *q);
-int read_policy_file(struct policy_file *pf);
-void close_policy_file(struct policy_file *pf);
-int load_policy_file(const char *file, policy_v *pv);
+/* Load a policy file, writing a vector of records into PV.  If the policy
+ * file has errors, then leave PV unchanged and return nonzero.
+ */
+extern int load_policy_file(const char */*file*/, policy_v */*pv*/);
 
 /*----- That's all, folks -------------------------------------------------*/