chiark / gitweb /
Merge branches 'mdw/knock' and 'mdw/ipv6' into bleeding
[tripe] / server / peer.c
index 94629213ca4e37ea85e30bfc33fd00fba9265fff..a8099e41adb7776a026f283b10bf625d810eb65c 100644 (file)
@@ -366,7 +366,7 @@ static void p_read(int fd, unsigned mode, void *v)
     })
     buf_init(&b, buf_i, n);
     buf_getbyte(&b);
-    if (c_check(&b) || BLEFT(&b)) {
+    if (c_check(0, 0, &b) || BLEFT(&b)) {
       a_warn("PEER", "-", "invalid-greeting", A_END);
       return;
     }
@@ -427,9 +427,8 @@ static void p_read(int fd, unsigned mode, void *v)
       }
       break;
     case MSG_KEYEXCH:
-      if (!p) goto unexp;
-      p_rxupdstats(p, n);
-      kx_message(&p->kx, ch & MSG_TYPEMASK, &b);
+      if (p) p_rxupdstats(p, n);
+      if (kx_message(p ? &p->kx : 0, &a, ch & MSG_TYPEMASK, &b)) goto unexp;
       break;
     case MSG_MISC:
       switch (ch & MSG_TYPEMASK) {
@@ -469,6 +468,16 @@ static void p_read(int fd, unsigned mode, void *v)
            p_ponged(p, MISC_EPONG, &bb);
          }
          break;
+       case MISC_BYE:
+         buf_init(&bb, buf_t, sizeof(buf_t));
+         if (p_decrypt(&p, &a, n, ch, &b, &bb)) return;
+         if (!(p->spec.f&PSF_EPHEM)) return;
+         if (BOK(&bb)) {
+           buf_flip(&bb);
+           if (BSZ(&bb)) return;
+           p_destroy(p, 0);
+         }
+         break;
       }
       break;
     default:
@@ -503,6 +512,30 @@ buf *p_txstart(peer *p, unsigned msg)
   return (&p->b);
 }
 
+/* --- @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.
+ */
+
+int p_txaddr(const addr *a, const void *p, size_t sz)
+{
+  socklen_t sasz = addrsz(a);
+
+  IF_TRACING(T_PEER, trace_block(T_PACKET, "peer: sending packet", p, sz); )
+  if (sendto(sock.fd, p, sz, 0, &a->sa, sasz) < 0) {
+    a_warn("PEER", "?ADDR", a, "socket-write-error", "?ERRNO", A_END);
+    return (-1);
+  }
+  return (0);
+}
+
 /* --- @p_txend@ --- *
  *
  * Arguments:  @peer *p@ = pointer to peer block
@@ -931,6 +964,7 @@ peer *p_create(peerspec *spec)
   p->spec.name = (/*unconst*/ char *)SYM_NAME(p->byname);
   if (spec->tag) p->spec.tag = xstrdup(spec->tag);
   if (spec->privtag) p->spec.privtag = xstrdup(spec->privtag);
+  if (spec->knock) p->spec.knock = xstrdup(spec->knock);
   p->ks = 0;
   p->pings = 0;
   p->ifname = 0;
@@ -946,7 +980,7 @@ peer *p_create(peerspec *spec)
   T( trace(T_TUNNEL, "peer: attached interface %s to peer `%s'",
           p->ifname, p_name(p)); )
   p_setkatimer(p);
-  if (kx_init(&p->kx, p, &p->ks, p->spec.f & PSF_KXMASK))
+  if (kx_setup(&p->kx, p, &p->ks, p->spec.f & PSF_KXMASK))
     goto tidy_4;
   a_notify("ADD",
           "?PEER", p,
@@ -1057,17 +1091,28 @@ peer *p_find(const char *name)
 /* --- @p_destroy@ --- *
  *
  * Arguments:  @peer *p@ = pointer to a peer
+ *             @int bye@ = say goodbye to the peer?
  *
  * Returns:    ---
  *
  * Use:                Destroys a peer.
  */
 
-void p_destroy(peer *p)
+void p_destroy(peer *p, int bye)
 {
   ping *pg, *ppg;
+  buf *b, bb;
 
   T( trace(T_PEER, "peer: destroying peer `%s'", p->spec.name); )
+
+  if (bye && (p->spec.f&PSF_EPHEM)) {
+    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);
+  }
+
   a_notify("KILL", "%s", p->spec.name, A_END);
   ksl_free(&p->ks);
   kx_free(&p->kx);
@@ -1075,6 +1120,7 @@ void p_destroy(peer *p)
   if (p->ifname) xfree(p->ifname);
   if (p->spec.tag) xfree(p->spec.tag);
   if (p->spec.privtag) xfree(p->spec.privtag);
+  if (p->spec.knock) xfree(p->spec.knock);
   p->t->ops->destroy(p->t);
   if (p->spec.t_ka) sel_rmtimer(&p->tka);
   for (pg = p->pings; pg; pg = ppg) {