struct tunnel_node *next;
const tunnel_ops *tops;
} *tunnels, **tunnels_tail = &tunnels;
+static ratelim wgt_limit;
const tunnel_ops *dflttun;
/*----- Main code ---------------------------------------------------------*/
{
peer *p, *q;
int err = KSERR_DECRYPT;
+ buf b;
/* --- If we have a match on the source address then try that first --- */
searched:
if (!p) {
- if (!q)
+ if (!q) {
a_warn("PEER", "-", "unexpected-source", "?ADDR", a, A_END);
- else {
+ if (!ratelim_withdraw(&wgt_limit, 1)) {
+ buf_init(&b, buf_t, sizeof(buf_t));
+ buf_putbyte(&b, MSG_MISC | MISC_WGT);
+ if (n > WGTLEN) n = WGTLEN;
+ buf_put(&b, buf_i, n);
+ T( trace(T_PEER, "peer: sending who-goes-there message"); )
+ assert(BOK(&b)); p_txaddr(a, BBASE(&b), BLEN(&b));
+ }
+ } else {
a_warn("PEER", "?PEER", p, "decrypt-failed",
"error-code", "%d", err, A_END);
p_rxupdstats(q, n);
ssize_t n;
int ch;
buf b, bb;
+ const octet *q;
+ unsigned i;
+ time_t now;
#ifndef NTRACE
int ix = -1;
char name[NI_MAXHOST], svc[NI_MAXSERV];
buf_flip(&bb);
p_encrypt(p, MSG_MISC | MISC_EPONG, &bb,
p_txstart(p, MSG_MISC | MISC_EPONG));
- p_txend(p, 0);
+ p_txend(p, TXF_WGT);
}
break;
case MISC_EPONG:
p_destroy(p, 0);
}
break;
+ case MISC_WGT:
+ if (!p) goto unexp;
+ if (!(p->spec.f&PSF_EPHEM))
+ { a_warn("PEER", "?PEER", p, "unexpected-wgt", A_END); break; }
+ n = BLEFT(&b); if (n > WGTLEN) n = WGTLEN;
+ now = time(0);
+ q = buf_get(&b, n); assert(q);
+ for (i = 0; i < NWGT; i++) {
+ if (p->wgt[i].when != (time_t)-1 &&
+ now - p->wgt[i].when <= T_WGT &&
+ p->wgt[i].sz == n &&
+ MEMCMP(p->wgt[i].msg, ==, q, n))
+ goto found_wgt;
+ }
+ a_warn("PEER", "?PEER", p, "unrecognized-wgt", A_END);
+ break;
+ found_wgt:
+ if (p->spec.knock) {
+ T( trace(T_PEER, "peer: who-goes-there from peer: knocking"); )
+ kx_start(&p->kx, 0);
+ } else {
+ T( trace(T_PEER, "peer: who-goes-there from peer: notifying"); )
+ a_notify("WGT", "?PEER", p, A_END);
+ }
+ break;
}
break;
default:
void p_txend(peer *p, unsigned f)
{
+ size_t n;
+
if (p_dotxend(p)) {
+ if ((f&TXF_WGT) && (p->spec.f&PSF_EPHEM)) {
+ n = BLEN(&p->b); if (n > WGTLEN) n = WGTLEN;
+ memcpy(p->wgt[p->wgtix].msg, BBASE(&p->b), n);
+ p->wgt[p->wgtix].sz = n;
+ p->wgt[p->wgtix].when = time(0);
+ p->wgtix++; if (p->wgtix >= NWGT) p->wgtix = 0;
+ }
if (p->spec.t_ka) {
sel_rmtimer(&p->tka);
p_setkatimer(p);
p_encrypt(p, MSG_MISC | MISC_EPING, &bb, b);
if (!BOK(b))
return (-1);
- p_txend(p, 0);
+ p_txend(p, TXF_WGT);
break;
default:
abort();
if (BOK(bb) && BLEN(bb)) {
p->st.n_ipout++;
p->st.sz_ipout += BLEN(bb);
- p_txend(p, 0);
+ p_txend(p, TXF_WGT);
}
}
{
sym_create(&byname);
am_create(&byaddr);
+ ratelim_init(&wgt_limit, 5, 100);
}
/* --- @p_addtun@ --- *
peer *p = CREATE(peer);
const tunnel_ops *tops = spec->tops;
int fd;
- unsigned f;
+ unsigned f, i;
p->byname = sym_find(&byname, spec->name, -1, sizeof(peer_byname), &f);
if (f) goto tidy_0;
/* Couldn't tell anyone before */
}
if (p->spec.f & PSF_MOBILE) nmobile++;
+ for (i = 0; i < NWGT; i++) {
+ p->wgt[i].sz = 0;
+ p->wgt[i].when = (time_t)-1;
+ }
+ p->wgtix = 0;
return (p);
tidy_4: