server/tests.at: Abstract out the wait-for-knock machinery.
[tripe] / server / peer.c
index 278a6b2..0b5a6c2 100644 (file)
@@ -430,7 +430,7 @@ static void p_read(int fd, unsigned mode, void *v)
          if (!p) goto unexp;
          p_rxupdstats(p, n);
          buf_put(p_txstart(p, MSG_MISC | MISC_PONG), BCUR(&b), BLEFT(&b));
-         p_txend(p);
+         p_txend(p, 0);
          break;
        case MISC_PONG:
          if (!p) goto unexp;
@@ -445,7 +445,7 @@ static void p_read(int fd, unsigned mode, void *v)
            buf_flip(&bb);
            p_encrypt(p, MSG_MISC | MISC_EPONG, &bb,
                      p_txstart(p, MSG_MISC | MISC_EPONG));
-           p_txend(p);
+           p_txend(p, 0);
          }
          break;
        case MISC_EPONG:
@@ -533,6 +533,7 @@ int p_txaddr(const addr *a, const void *p, size_t sz)
 /* --- @p_txend@ --- *
  *
  * Arguments:  @peer *p@ = pointer to peer block
+ *             @unsigned f@ = flags
  *
  * Returns:    ---
  *
@@ -562,11 +563,13 @@ static int p_dotxend(peer *p)
   }
 }
 
-void p_txend(peer *p)
+void p_txend(peer *p, unsigned f)
 {
-  if (p_dotxend(p) && p->spec.t_ka) {
-    sel_rmtimer(&p->tka);
-    p_setkatimer(p);
+  if (p_dotxend(p)) {
+    if (p->spec.t_ka) {
+      sel_rmtimer(&p->tka);
+      p_setkatimer(p);
+    }
   }
 }
 
@@ -656,7 +659,7 @@ int p_pingsend(peer *p, ping *pg, unsigned type,
       pg->msg = MISC_PONG;
       b = p_txstart(p, MSG_MISC | MISC_PING);
       p_pingwrite(pg, b);
-      p_txend(p);
+      p_txend(p, 0);
       break;
     case MISC_EPING:
       pg->msg = MISC_EPONG;
@@ -667,7 +670,7 @@ int p_pingsend(peer *p, ping *pg, unsigned type,
       p_encrypt(p, MSG_MISC | MISC_EPING, &bb, b);
       if (!BOK(b))
        return (-1);
-      p_txend(p);
+      p_txend(p, 0);
       break;
     default:
       abort();
@@ -704,7 +707,7 @@ void p_greet(peer *p, const void *c, size_t sz)
 {
   buf *b = p_txstart(p, MSG_MISC | MISC_GREET);
   buf_put(b, c, sz);
-  p_txend(p);
+  p_txend(p, 0);
 }
 
 /* --- @p_tun@ --- *
@@ -726,7 +729,7 @@ void p_tun(peer *p, buf *b)
   if (BOK(bb) && BLEN(bb)) {
     p->st.n_ipout++;
     p->st.sz_ipout += BLEN(bb);
-    p_txend(p);
+    p_txend(p, 0);
   }
 }
 
@@ -809,14 +812,14 @@ const addr *p_addr(peer *p) { return (&p->spec.sa); }
  *
  * Arguments:  @struct addrinfo *ailist@ = addresses to bind to
  *
- * Returns:    ---
+ * Returns:    Zero on success, @-1@ on failure.
  *
- * Use:                Initializes the peer system; creates the socket.
+ * Use:                Binds to the main UDP sockets.
  */
 
-void p_bind(struct addrinfo *ailist)
+int p_bind(struct addrinfo *ailist)
 {
-  int fd;
+  int fd = -1;
   int len = PKBUFSZ;
   int yes = 1;
   int i;
@@ -842,13 +845,13 @@ void p_bind(struct addrinfo *ailist)
     if ((fd = socket(ai->ai_family, SOCK_DGRAM, 0)) < 0) {
       a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
             "create-failed", "?ERRNO", A_END);
-      exit(EXIT_FAILURE);
+      goto fail;
     }
     if (i == AFIX_INET6 &&
        setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes))) {
       a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
             "set-v6only-failed", "?ERRNO", A_END);
-      exit(EXIT_FAILURE);
+      goto fail;
     }
     assert(ai->ai_addrlen <= sizeof(a));
     memcpy(&a, ai->ai_addr, ai->ai_addrlen);
@@ -856,13 +859,13 @@ void p_bind(struct addrinfo *ailist)
     if (bind(fd, &a.sa, addrsz(&a))) {
       a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
             "bind-failed", "?ERRNO", A_END);
-      exit(EXIT_FAILURE);
+      goto fail;
     }
     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) ||
        setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len))) {
       a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
             "set-buffers-failed", "?ERRNO", A_END);
-      exit(EXIT_FAILURE);
+      goto fail;
     }
     fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
     if (port)
@@ -872,15 +875,22 @@ void p_bind(struct addrinfo *ailist)
       if (getsockname(fd, &a.sa, &sz)) {
        a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
               "read-local-address-failed", "?ERRNO", A_END);
-       exit(EXIT_FAILURE);
+       goto fail;
       }
       udpsock[i].port = lastport = getport(&a);
     }
     T( trace(T_PEER, "peer: created %s socket", aftab[i].name); )
     sel_initfile(&sel, &udpsock[i].sf, fd, SEL_READ, p_read, 0);
     sel_addfile(&udpsock[i].sf);
+    fd = -1;
   }
 
+  return (0);
+
+fail:
+  if (fd != -1) close(fd);
+  p_unbind();
+  return (-1);
 }
 
 /* --- @p_unbind@ --- *
@@ -928,28 +938,29 @@ void p_init(void)
  *
  * Arguments:  @const tunnel_ops *tops@ = tunnel ops to add
  *
- * Returns:    ---
+ * Returns:    Zero on success, @-1@ on failure.
  *
- * Use:                Adds a tunnel class to the list of known classes.  If there
- *             is no current default tunnel, then this one is made the
- *             default.
+ * 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.
  */
 
-void p_addtun(const tunnel_ops *tops)
+int p_addtun(const tunnel_ops *tops)
 {
   struct tunnel_node *tn;
 
   for (tn = tunnels; tn; tn = tn->next)
-    if (tn->tops == tops) return;
-  tops->init();
+    if (tn->tops == tops) return (0);
+  if (tops->init()) return (-1);
   tn = CREATE(struct tunnel_node);
   tn->next = 0; tn->tops = tops;
   *tunnels_tail = tn; tunnels_tail = &tn->next;
   if (!dflttun) dflttun = tops;
+  return (0);
 }
 
 /* --- @p_setdflttun@ --- *
@@ -1229,12 +1240,12 @@ void p_destroy(peer *p, int bye)
 
   T( trace(T_PEER, "peer: destroying peer `%s'", p->spec.name); )
 
-  if (bye && (p->spec.f&PSF_EPHEM)) {
+  if (bye) {
     b = p_txstart(p, MSG_MISC | MISC_BYE);
     buf_init(&bb, buf_t, sizeof(buf_t));
     assert(BOK(&bb)); buf_flip(&bb);
     p_encrypt(p, MSG_MISC | MISC_BYE, &bb, b);
-    p_txend(p);
+    p_txend(p, 0);
   }
 
   a_notify("KILL", "%s", p->spec.name, A_END);