X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/18969e42a11e11ef8a3ea81eaf0038e8e74e004d..refs/heads/mdw/wgt:/server/peer.c diff --git a/server/peer.c b/server/peer.c index 0b5a6c22..b20f2fd3 100644 --- a/server/peer.c +++ b/server/peer.c @@ -40,6 +40,7 @@ static struct tunnel_node { struct tunnel_node *next; const tunnel_ops *tops; } *tunnels, **tunnels_tail = &tunnels; +static ratelim wgt_limit; const tunnel_ops *dflttun; /*----- Main code ---------------------------------------------------------*/ @@ -229,6 +230,7 @@ static int p_decrypt(peer **pp, addr *a, size_t n, { peer *p, *q; int err = KSERR_DECRYPT; + buf b; /* --- If we have a match on the source address then try that first --- */ @@ -276,9 +278,17 @@ static int p_decrypt(peer **pp, addr *a, size_t n, 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); @@ -325,6 +335,9 @@ static void p_read(int fd, unsigned mode, void *v) 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]; @@ -445,7 +458,7 @@ static void p_read(int fd, unsigned mode, void *v) 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: @@ -467,6 +480,31 @@ static void p_read(int fd, unsigned mode, void *v) 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: @@ -565,7 +603,16 @@ static int p_dotxend(peer *p) 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); @@ -670,7 +717,7 @@ int p_pingsend(peer *p, ping *pg, unsigned type, 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(); @@ -729,7 +776,7 @@ void p_tun(peer *p, buf *b) if (BOK(bb) && BLEN(bb)) { p->st.n_ipout++; p->st.sz_ipout += BLEN(bb); - p_txend(p, 0); + p_txend(p, TXF_WGT); } } @@ -932,6 +979,7 @@ void p_init(void) { sym_create(&byname); am_create(&byaddr); + ratelim_init(&wgt_limit, 5, 100); } /* --- @p_addtun@ --- * @@ -1084,7 +1132,7 @@ peer *p_create(peerspec *spec) 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; @@ -1126,6 +1174,11 @@ peer *p_create(peerspec *spec) /* 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: