Dispatch to methods handling address-family specifics.
[yaid] / linux.c
diff --git a/linux.c b/linux.c
index 91c03aa..252b69c 100644 (file)
--- a/linux.c
+++ b/linux.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * Discover the owner of a connection
+ * Discover the owner of a connection (Linux version)
  *
  * (c) 2012 Straylight/Edgeware
  */
 
 /*----- Static variables --------------------------------------------------*/
 
-const char *const errtok[] = {
-#define DEFTOK(err, tok) tok,
-  ERROR(DEFTOK)
-#undef DEFTOK
+struct addrops_sys {
+  const char *procfile;
+  int (*parseaddr)(char **, union addr *);
 };
 
-static int parseaddr4(char **pp, union addr *a)
+static int parseaddr_ipv4(char **pp, union addr *a)
   { a->ipv4.s_addr = strtoul(*pp, pp, 16); return (0); }
 
-static int addreq4(const union addr *a, const union addr *aa)
-  { return a->ipv4.s_addr == aa->ipv4.s_addr; }
+const struct addrops_sys addrops_sys_ipv4 = {
+  "/proc/net/tcp", parseaddr_ipv4
+};
 
-static int parseaddr6(char **pp, union addr *a)
+static int parseaddr_ipv6(char **pp, union addr *a)
 {
   int i, j;
   unsigned long y;
@@ -65,27 +65,13 @@ static int parseaddr6(char **pp, union addr *a)
   return (0);
 }
 
-static int addreq6(const union addr *a, const union addr *b)
-  { return !memcmp(a->ipv6.s6_addr, b->ipv6.s6_addr, 16); }
-
-static const struct addrfamily {
-  int af;
-  const char *procfile;
-  int (*parseaddr)(char **pp, union addr *a);
-  int (*addreq)(const union addr *a, const union addr *aa);
-} addrfamilytab[] = {
-  { AF_INET, "/proc/net/tcp", parseaddr4, addreq4 },
-  { AF_INET6, "/proc/net/tcp6", parseaddr6, addreq6 },
-  { -1 }
+const struct addrops_sys addrops_sys_ipv6 = {
+  "/proc/net/tcp6", parseaddr_ipv6
 };
 
 /*----- Main code ---------------------------------------------------------*/
 
-static int sockeq(const struct addrfamily *af,
-                 const struct socket *sa, const struct socket *sb)
-  { return (af->addreq(&sa->addr, &sb->addr) && sa->port == sb->port); }
-
-static int get_default_gw(int af, union addr *a)
+int get_default_gw(int af, union addr *a)
 {
   int fd;
   char buf[32768];
@@ -152,7 +138,6 @@ done:
 
 void identify(struct query *q)
 {
-  const struct addrfamily *af;
   FILE *fp = 0;
   dstr d = DSTR_INIT;
   char *p, *pp;
@@ -170,19 +155,13 @@ void identify(struct query *q)
   enum { LOC, REM, ST, UID, NFIELD };
   int f, ff[NFIELD];
 
-  for (af = addrfamilytab; af->af >= 0; af++)
-    if (af->af == q->af) goto found_af;
-  logmsg(q, LOG_ERR, "unexpected address family `%d'", q->af);
-  goto err_unk;
-found_af:;
-
-  if (get_default_gw(q->af, &s[0].addr) &&
-      af->addreq(&s[0].addr, &q->s[R].addr))
+  if (get_default_gw(q->ao->af, &s[0].addr) &&
+      q->ao->addreq(&s[0].addr, &q->s[R].addr))
     gwp = 1;
 
-  if ((fp = fopen(af->procfile, "r")) == 0) {
+  if ((fp = fopen(q->ao->sys->procfile, "r")) == 0) {
     logmsg(q, LOG_ERR, "failed to open `%s' for reading: %s",
-          af->procfile, strerror(errno));
+          q->ao->sys->procfile, strerror(errno));
     goto err_unk;
   }
 
@@ -194,7 +173,8 @@ found_af:;
 
   if (dstr_putline(&d, fp) == EOF) {
     logmsg(q, LOG_ERR, "failed to read header line from `%s': %s",
-          af->procfile, ferror(fp) ? strerror(errno) : "unexpected EOF");
+          q->ao->sys->procfile,
+          ferror(fp) ? strerror(errno) : "unexpected EOF");
     goto err_unk;
   }
 
@@ -218,7 +198,7 @@ found_af:;
   for (i = 0; i < NFIELD; i++) {
     if (ff[i] < 0) {
       logmsg(q, LOG_ERR, "failed to find required fields in `%s'",
-            af->procfile);
+            q->ao->sys->procfile);
       goto err_unk;
     }
   }
@@ -239,10 +219,10 @@ found_af:;
       continue;
 
     compare:
-      if (af->parseaddr(&p, &s[0].addr)) goto next_row;
+      if (q->ao->sys->parseaddr(&p, &s[0].addr)) goto next_row;
       if (*p != ':') break; p++;
       s[0].port = strtoul(p, 0, 16);
-      if (!sockeq(af, &q->s[i], &s[0]) &&
+      if (!sockeq(q->ao, &q->s[i], &s[0]) &&
          (i != R || !gwp || q->s[R].port != s[0].port))
        goto next_row;
     }
@@ -260,7 +240,7 @@ found_af:;
     goto err_unk;
   }
 
-  if (q->af == AF_INET) {
+  if (q->ao->af == AF_INET) {
     fclose(fp);
     if ((fp = fopen("/proc/net/ip_conntrack", "r")) == 0) {
       if (errno == ENOENT)
@@ -309,13 +289,13 @@ found_af:;
       {
        dstr dd = DSTR_INIT;
        dstr_putf(&dd, "%sestab ", (fl & F_ESTAB) ? " " : "!");
-       dputsock(&dd, af->af, &s[0]);
+       dputsock(&dd, q->ao, &s[0]);
        dstr_puts(&dd, "<->");
-       dputsock(&dd, af->af, &s[1]);
+       dputsock(&dd, q->ao, &s[1]);
        dstr_puts(&dd, " | ");
-       dputsock(&dd, af->af, &s[2]);
+       dputsock(&dd, q->ao, &s[2]);
        dstr_puts(&dd, "<->");
-       dputsock(&dd, af->af, &s[3]);
+       dputsock(&dd, q->ao, &s[3]);
        printf("parsed: %s\n", dd.buf);
        dstr_destroy(&dd);
       }
@@ -324,12 +304,12 @@ found_af:;
       if (!(fl & F_ESTAB)) continue;
 
       for (i = 0; i < 4; i++)
-       if (sockeq(af, &s[i], &q->s[L])) goto found_local;
+       if (sockeq(q->ao, &s[i], &q->s[L])) goto found_local;
       continue;
       putchar('.');
     found_local:
-      if (!sockeq(af, &s[i^1], &s[i^2]) ||
-         !sockeq(af, &s[i^1], &q->s[R]))
+      if (!sockeq(q->ao, &s[i^1], &s[i^2]) ||
+         !sockeq(q->ao, &s[i^1], &q->s[R]))
        continue;
       q->resp = R_NAT;
       q->u.nat = s[i^3];