From 010e6f63edc4be4e127c18fc6c2c2a138efc93d2 Mon Sep 17 00:00:00 2001 Message-Id: <010e6f63edc4be4e127c18fc6c2c2a138efc93d2.1715097639.git.mdw@distorted.org.uk> From: Mark Wooding Date: Tue, 18 Mar 2008 20:21:11 +0000 Subject: [PATCH] server: Add a peer without sending key-exchange packets. Organization: Straylight/Edgeware From: Mark Wooding When contacting a passive peer, the initial pre-challenge will cause the peer to complain about an unsolicited packet. The -cork option to ADD makes the new peer silent until contacted by the (presumably awoken) passive peer. --- doc/tripe-admin.5.in | 4 ++++ server/admin.c | 2 ++ server/keyexch.c | 22 +++++++++++++++------- server/peer.c | 6 ++++-- server/tripe.h | 6 +++++- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/doc/tripe-admin.5.in b/doc/tripe-admin.5.in index 968400e7..caaf2557 100644 --- a/doc/tripe-admin.5.in +++ b/doc/tripe-admin.5.in @@ -287,6 +287,10 @@ be contacted. The following options are recognised. Run the command in the background, using the given .IR tag . .TP +.B "\-cork" +Don't send an immediate challenge to the peer; instead, wait until it +sends us something before responding. +.TP .BI "\-keepalive " time Send a no-op packet if we've not sent a packet to the peer in the last .I time diff --git a/server/admin.c b/server/admin.c index 135a589c..73c71070 100644 --- a/server/admin.c +++ b/server/admin.c @@ -1210,6 +1210,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) add->peer.name = 0; add->peer.t_ka = 0; add->peer.tops = tun_default; + add->peer.kxf = 0; /* --- Parse options --- */ @@ -1229,6 +1230,7 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) } }) OPTTIME("-keepalive", t, { add->peer.t_ka = t; }) + OPT("-cork", { add->peer.kxf |= KXF_CORK; }) }); /* --- Make sure someone's not got there already --- */ diff --git a/server/keyexch.c b/server/keyexch.c index df70774d..e7052729 100644 --- a/server/keyexch.c +++ b/server/keyexch.c @@ -1065,7 +1065,7 @@ static void start(keyexch *kx, time_t now) assert(kx->f & KXF_DEAD); - kx->f &= ~KXF_DEAD; + kx->f &= ~(KXF_DEAD | KXF_CORK); kx->nr = 0; kx->alpha = mprand_range(MP_NEW, gg->r, &rand_global, 0); kx->c = G_CREATE(gg); G_EXP(gg, kx->c, gg->g, kx->alpha); @@ -1161,6 +1161,12 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) size_t sz = BSZ(b); int rc; + if (kx->f & KXF_CORK) { + start(kx, now); + settimer(kx, now + T_RETRY); + a_notify("KXSTART", A_END); + } + if (checkpub(kx)) return; @@ -1168,7 +1174,6 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) stop(kx); start(kx, now); } - T( trace(T_KEYEXCH, "keyexch: processing %s packet from `%s'", msg < KX_NMSG ? pkname[msg] : "unknown", p_name(kx->p)); ) @@ -1248,6 +1253,7 @@ void kx_newkeys(keyexch *kx) * Arguments: @keyexch *kx@ = pointer to key exchange context * @peer *p@ = pointer to peer context * @keyset **ks@ = pointer to keyset list + * @unsigned f@ = various useful flags * * Returns: Zero if OK, nonzero if it failed. * @@ -1256,7 +1262,7 @@ void kx_newkeys(keyexch *kx) * exchange. */ -int kx_init(keyexch *kx, peer *p, keyset **ks) +int kx_init(keyexch *kx, peer *p, keyset **ks, unsigned f) { kx->ks = ks; kx->p = p; @@ -1265,10 +1271,12 @@ int kx_init(keyexch *kx, peer *p, keyset **ks) G_DESTROY(gg, kx->kpub); return (-1); } - kx->f = KXF_DEAD | KXF_PUBKEY; - start(kx, time(0)); - resend(kx); - /* Don't notify here: the ADD message hasn't gone out yet. */ + kx->f = KXF_DEAD | KXF_PUBKEY | f; + if (!(kx->f & KXF_CORK)) { + start(kx, time(0)); + resend(kx); + /* Don't notify here: the ADD message hasn't gone out yet. */ + } return (0); } diff --git a/server/peer.c b/server/peer.c index 99d4447d..675ceff8 100644 --- a/server/peer.c +++ b/server/peer.c @@ -706,7 +706,7 @@ peer *p_create(peerspec *spec) if ((p->t = spec->tops->create(p, &p->ifname)) == 0) goto tidy_0; p_setkatimer(p); - if (kx_init(&p->kx, p, &p->ks)) + if (kx_init(&p->kx, p, &p->ks, p->spec.kxf)) goto tidy_1; p->next = peers; if (peers) @@ -717,8 +717,10 @@ peer *p_create(peerspec *spec) "%s", p->ifname, "?ADDR", &p->spec.sa, A_END); - a_notify("KXSTART", "?PEER", p, A_END); + if (!(p->spec.kxf & KXF_CORK)) { + a_notify("KXSTART", "?PEER", p, A_END); /* Couldn't tell anyone before */ + } return (p); tidy_1: diff --git a/server/tripe.h b/server/tripe.h index 44b4e045..9c9653e0 100644 --- a/server/tripe.h +++ b/server/tripe.h @@ -249,6 +249,7 @@ typedef struct keyexch { #define KXF_TIMER 1u /* Waiting for a timer to go off */ #define KXF_DEAD 2u /* The key-exchanger isn't up */ #define KXF_PUBKEY 4u /* Key exchanger has a public key */ +#define KXF_CORK 8u /* Don't send anything yet */ enum { KXS_DEAD, /* Uninitialized state (magical) */ @@ -310,6 +311,7 @@ typedef struct peerspec { unsigned long t_ka; /* Keep alive interval */ addr sa; /* Socket address to speak to */ size_t sasz; /* Socket address size */ + unsigned kxf; /* Key exchange flags to set */ } peerspec; typedef struct peer { @@ -576,6 +578,7 @@ extern void kx_newkeys(keyexch */*kx*/); * Arguments: @keyexch *kx@ = pointer to key exchange context * @peer *p@ = pointer to peer context * @keyset **ks@ = pointer to keyset list + * @unsigned f@ = various useful flags * * Returns: Zero if OK, nonzero if it failed. * @@ -584,7 +587,8 @@ extern void kx_newkeys(keyexch */*kx*/); * exchange. */ -extern int kx_init(keyexch */*kx*/, peer */*p*/, keyset **/*ks*/); +extern int kx_init(keyexch */*kx*/, peer */*p*/, + keyset **/*ks*/, unsigned /*f*/); /*----- Keysets and symmetric cryptography --------------------------------*/ -- [mdw]