chiark / gitweb /
General overhaul of tunnelling: allow multiple tunnel drivers in one daemon,
[tripe] / admin.c
diff --git a/admin.c b/admin.c
index 57d9ccfacca6a895cff93939462117884c3fc7bf..24d86c64ac40dcf7a33e61c84d6ccb2eac48ae6a 100644 (file)
--- a/admin.c
+++ b/admin.c
@@ -78,23 +78,6 @@ static void a_unlock(admin */*a*/);
 
 /*----- Output functions --------------------------------------------------*/
 
-/* --- @mystrieq@ --- *
- *
- * Arguments:  @const char *x, *y@ = two strings
- *
- * Returns:    True if @x@ and @y are equal, up to case.
- */
-
-static int mystrieq(const char *x, const char *y)
-{
-  for (;;) {
-    if (!*x && !*y) return (1);
-    if (tolower((unsigned char)*x) != tolower((unsigned char)*y))
-      return (0);
-    x++; y++;
-  }
-}
-
 /* --- @trywrite@ --- *
  *
  * Arguments:  @admin *a@ = pointer to an admin block
@@ -433,6 +416,10 @@ void a_notify(const char *fmt, ...)
 
 void a_quit(void)
 {
+  peer *p;
+
+  while ((p = p_first()) != 0)
+    p_destroy(p);
   close(sock.fd);
   unlink(sockname);
   exit(0);
@@ -506,7 +493,7 @@ static void a_resolve(struct hostent *h, void *v)
     a_fail(a, "peer-exists %s", a->pname);
   else {
     memcpy(&a->peer.sin.sin_addr, h->h_addr, sizeof(struct in_addr));
-    if (!p_create(a->pname, &a->peer.sa, a->sasz))
+    if (!p_create(a->pname, a->tops, &a->peer.sa, a->sasz))
       a_fail(a, "peer-create-fail %s", a->pname);
     else
       a_ok(a);
@@ -558,7 +545,8 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
 {
   unsigned long pt;
   struct timeval tv;
-  unsigned i;
+  unsigned i, j;
+  const tunnel_ops *tops = tun_default;
   char *p;
 
   /* --- Make sure someone's not got there already --- */
@@ -568,13 +556,40 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
     return;
   }
 
+  /* --- Parse options --- */
+
+  i = 1;
+  for (;;) {
+    if (!av[i])
+      goto bad_syntax;
+    if (mystrieq(av[i], "-tunnel")) {
+      i++;
+      if (!av[i])
+       goto bad_syntax;
+      for (j = 0;; j++) {
+       if (!tunnels[j]) {
+         a_fail(a, "unknown-tunnel %s", av[i]);
+         return;
+       }
+       if (mystrieq(av[i], tunnels[j]->name)) {
+         tops = tunnels[j];
+         break;
+       }
+      }
+      i++;
+    } else if (mystrieq(av[i], "--")) {
+      i++;
+      break;
+    } else
+      break;
+  }
+
   /* --- Fill in the easy bits of address --- */
 
   BURN(a->peer);
-  i = 1;
   if (mystrieq(av[i], "inet")) i++;
   if (ac - i != 2) {
-    a_fail(a, "bad-syntax -- add PEER [inet] ADDRESS PORT");
+    a_fail(a, "bad-syntax -- add PEER [-tunnel TUN] [inet] ADDRESS PORT");
     return;
   }
   a->peer.sin.sin_family = AF_INET;
@@ -597,7 +612,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
   /* --- If the name is numeric, do it the easy way --- */
   
   if (inet_aton(av[i], &a->peer.sin.sin_addr)) {
-    if (!p_create(av[0], &a->peer.sa, a->sasz))
+    if (!p_create(av[0], tops, &a->peer.sa, a->sasz))
       a_fail(a, "peer-create-fail %s", a->pname);
     else
       a_ok(a);
@@ -613,6 +628,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
 
   a->pname = xstrdup(av[0]);
   a->paddr = xstrdup(av[i]);
+  a->tops = tops;
   selbuf_disable(&a->b);
   gettimeofday(&tv, 0);
   tv.tv_sec += T_RESOLVE;
@@ -620,6 +636,11 @@ static void acmd_add(admin *a, unsigned ac, char *av[])
   bres_byname(&a->r, a->paddr, a_resolve, a);
   T( trace(T_ADMIN, "admin: %u resolving hostname `%s'",
           a->seq, a->paddr); )
+  return;
+
+bad_syntax:
+  a_fail(a, "bad-syntax -- add PEER [-tunnel TUN] ADDR ...");
+  return;
 }
 
 /*----- Administration commands -------------------------------------------*/
@@ -848,6 +869,14 @@ static void acmd_version(admin *a, unsigned ac, char *av[])
   a_ok(a);
 }
 
+static void acmd_tunnels(admin *a, unsigned ac, char *av[])
+{
+  int i;
+  for (i = 0; tunnels[i]; i++)
+    a_info(a, "%s", tunnels[i]->name);
+  a_ok(a);
+}
+
 /* --- The command table and help --- */
 
 typedef struct acmd {
@@ -875,7 +904,9 @@ static const acmd acmdtab[] = {
   { "addr",    "addr PEER",            1,      1,      acmd_addr },
   { "stats",   "stats PEER",           1,      1,      acmd_stats },
   { "kill",    "kill PEER",            1,      1,      acmd_kill },
-  { "add",     "add PEER ADDR ...",    2,      0xffff, acmd_add },
+  { "add",     "add PEER [-tunnel TUN] ADDR ...",
+                                       2,      0xffff, acmd_add },
+  { "tunnels", "tunnels",              0,      0,      acmd_tunnels },
   { "quit",    "quit",                 0,      0,      acmd_quit },
   { 0,         0,                      0,      0,      0 }
 };