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.
Run the command in the background, using the given
.IR tag .
.TP
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
.BI "\-keepalive " time
Send a no-op packet if we've not sent a packet to the peer in the last
.I time
add->peer.name = 0;
add->peer.t_ka = 0;
add->peer.tops = tun_default;
add->peer.name = 0;
add->peer.t_ka = 0;
add->peer.tops = tun_default;
/* --- Parse options --- */
/* --- Parse options --- */
}
})
OPTTIME("-keepalive", t, { add->peer.t_ka = t; })
}
})
OPTTIME("-keepalive", t, { add->peer.t_ka = t; })
+ OPT("-cork", { add->peer.kxf |= KXF_CORK; })
});
/* --- Make sure someone's not got there already --- */
});
/* --- Make sure someone's not got there already --- */
assert(kx->f & KXF_DEAD);
assert(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);
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);
size_t sz = BSZ(b);
int rc;
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;
if (checkpub(kx))
return;
stop(kx);
start(kx, now);
}
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)); )
T( trace(T_KEYEXCH, "keyexch: processing %s packet from `%s'",
msg < KX_NMSG ? pkname[msg] : "unknown", p_name(kx->p)); )
* Arguments: @keyexch *kx@ = pointer to key exchange context
* @peer *p@ = pointer to peer context
* @keyset **ks@ = pointer to keyset list
* 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.
*
*
* Returns: Zero if OK, nonzero if it failed.
*
-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;
{
kx->ks = ks;
kx->p = p;
G_DESTROY(gg, kx->kpub);
return (-1);
}
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. */
+ }
if ((p->t = spec->tops->create(p, &p->ifname)) == 0)
goto tidy_0;
p_setkatimer(p);
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)
goto tidy_1;
p->next = peers;
if (peers)
"%s", p->ifname,
"?ADDR", &p->spec.sa,
A_END);
"%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 */
/* Couldn't tell anyone before */
#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_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) */
enum {
KXS_DEAD, /* Uninitialized state (magical) */
unsigned long t_ka; /* Keep alive interval */
addr sa; /* Socket address to speak to */
size_t sasz; /* Socket address size */
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 {
} peerspec;
typedef struct peer {
* Arguments: @keyexch *kx@ = pointer to key exchange context
* @peer *p@ = pointer to peer context
* @keyset **ks@ = pointer to keyset list
* 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.
*
*
* Returns: Zero if OK, nonzero if it failed.
*
-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 --------------------------------*/
/*----- Keysets and symmetric cryptography --------------------------------*/