*['EPING'] +
_kwopts(kw, ['timeout']) +
[peer]))
- def forcekx(me, peer):
- return _simple(me.command('FORCEKX', peer))
+ def forcekx(me, peer, **kw):
+ return _simple(me.command(*['FORCEKX'] +
+ _kwopts(kw, ["quiet"]) +
+ [peer]))
def getchal(me):
return _oneline(me.command('GETCHAL', filter = _tokenjoin))
def greet(me, peer, chal):
return list(me.command('HELP', filter = _tokenjoin))
def ifname(me, peer):
return _oneline(me.command('IFNAME', peer, filter = _tokenjoin))
- def kill(me, peer):
- return _simple(me.command('KILL', peer))
+ def kill(me, peer, **kw):
+ return _simple(me.command(*['KILL'] +
+ _kwopts(kw, ["quiet"]) +
+ [peer]))
def list(me):
return list(me.command('LIST', filter = _tokenjoin))
def notify(me, *msg):
static void acmd_kill(admin *a, unsigned ac, char *av[])
{
peer *p;
+ int bye = 1;
+ OPTIONS(ac, av, {
+ OPT("-quiet", { bye = 0; })
+ });
+ if (!*av || av[1]) goto bad_syntax;
if ((p = a_findpeer(a, av[0])) != 0) {
- p_destroy(p, 1);
+ p_destroy(p, bye);
a_ok(a);
}
+ return;
+
+bad_syntax:
+ a_fail(a, "bad-syntax", "kill", "[OPTIONS] PEER", A_END);
}
static void acmd_forcekx(admin *a, unsigned ac, char *av[])
{
peer *p;
+ int quiet = 0;
+ OPTIONS(ac, av, {
+ OPT("-quiet", { quiet = 1; })
+ });
+ if (!*av || av[1]) goto bad_syntax;
if ((p = a_findpeer(a, av[0])) != 0) {
- kx_start(&p->kx, 1);
+ if (!quiet) kx_start(&p->kx, 1);
+ else { p->kx.t_valid = time(0) - T_VALID - 1; }
a_ok(a);
}
+ return;
+
+bad_syntax:
+ a_fail(a, "bad-syntax", "forcekx", "[OPTIONS] PEER", A_END);
}
static void acmd_reload(admin *a, unsigned ac, char *av[])
{ "checkchal", "CHAL", 1, 1, acmd_checkchal },
{ "daemon", 0, 0, 0, acmd_daemon },
{ "eping", "[OPTIONS] PEER", 1, 0xffff, acmd_eping },
- { "forcekx", "PEER", 1, 1, acmd_forcekx },
+ { "forcekx", "[OPTIONS] PEER", 1, 0xffff, acmd_forcekx },
{ "getchal", 0, 0, 0, acmd_getchal },
{ "greet", "PEER CHAL", 2, 2, acmd_greet },
{ "help", 0, 0, 0, acmd_help },
{ "ifname", "PEER", 1, 1, acmd_ifname },
{ "jobs", 0, 0, 0, acmd_jobs },
- { "kill", "PEER", 1, 1, acmd_kill },
+ { "kill", "[OPTIONS] PEER", 1, 0xffff, acmd_kill },
{ "list", 0, 0, 0, acmd_list },
{ "notify", "MESSAGE ...", 1, 0xffff, acmd_notify },
{ "peerinfo", "PEER", 1, 1, acmd_peerinfo },
.B PING
command.
.SP
-.BI "FORCEKX " peer
+.BI "FORCEKX \fR[" options "\fR] " peer
Requests the server to begin a new key exchange with
.I peer
-immediately.
+immediately. The following options are recognized.
+.RS
+.\"+opts
+.TP
+.B "\-quiet"
+Don't actually start a new key exchange; just quietly mark any previous
+key exchange as stale so that a fresh attempt from the peer will
+succeed. This is was introduced for use during testing, but it's also
+useful when a remote peer has forgotten about us: it would be
+annoying if, once it's learns about us and tries to reinitiate a key
+exchange, we ignore it because we think we've already done one recently;
+on the other hand, forcing a key exchange before the remote peer has
+been reinformed about us is a waste of packets.
+.\"-opts
+.RE
.SP
.B "GETCHAL"
Requests a challenge. The challenge is returned in an
.B "\-ephemeral"
\(en see the
.B "ADD"
-command.
+command. The following options are
+recognized.
+.RS
+.\"+opts
+.TP
+.B "\-quiet"
+Suppress any
+.B bye
+message to an ephemeral peer: just quietly forget about it. This is
+used during testing, and is not expected to be generally useful.
+.\"-opts
+.RE
.SP
.B "LIST"
For each currently-known peer, an