X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/786989941b7b4504f0234c4a318f929802e981ad..5fb10b44d547dfcb3612b85e7115355301535ca0:/server/peer.c diff --git a/server/peer.c b/server/peer.c index 50dec936..b23ef7bf 100644 --- a/server/peer.c +++ b/server/peer.c @@ -1,13 +1,11 @@ /* -*-c-*- - * - * $Id$ * * Communication with the peer * * (c) 2001 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Trivial IP Encryption (TrIPE). * @@ -15,12 +13,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * TrIPE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with TrIPE; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -32,7 +30,8 @@ /*----- Static variables --------------------------------------------------*/ -static peer *peers = 0; +static sym_table byname; +static addrmap byaddr; static sel_file sock; /*----- Tunnel table ------------------------------------------------------*/ @@ -90,7 +89,7 @@ static void p_ponged(peer *p, unsigned msg, buf *b) uint32 id; const octet *magic; ping *pg; - + IF_TRACING(T_PEER, { trace(T_PEER, "peer: received %s reply from %s", p_pingtype(msg), p->spec.name); @@ -177,16 +176,11 @@ static void p_read(int fd, unsigned mode, void *v) /* --- Find the appropriate peer --- */ - assert(a.sa.sa_family == AF_INET); - for (p = peers; p; p = p->next) { - if (p->spec.sa.sin.sin_addr.s_addr == a.sin.sin_addr.s_addr && - p->spec.sa.sin.sin_port == a.sin.sin_port) - goto found; + if ((p = p_findbyaddr(&a)) == 0) { + a_warn("PEER", "-", "unexpected-source", "?ADDR", &a, A_END); + return; } - a_warn("PEER", "-", "unexpected-source", "?ADDR", &a, A_END); - return; -found: IF_TRACING(T_PEER, { trace(T_PEER, "peer: packet received from `%s'", p->spec.name); trace_block(T_PACKET, "peer: packet contents", buf_i, n); @@ -239,7 +233,7 @@ found: case MISC_PING: buf_put(p_txstart(p, MSG_MISC | MISC_PONG), BCUR(&b), BLEFT(&b)); p_txend(p); - break; + break; case MISC_PONG: p_ponged(p, MISC_PONG, &b); break; @@ -247,7 +241,7 @@ found: buf_init(&bb, buf_t, sizeof(buf_t)); if (ksl_decrypt(&p->ks, ch, &b, &bb)) { p->st.n_reject++; - a_warn("PEER", "?PEER", "decrypt-failed", A_END); + a_warn("PEER", "?PEER", p, "decrypt-failed", A_END); return; } if (BOK(&bb)) { @@ -512,12 +506,8 @@ void p_tun(peer *p, buf *b) void p_keyreload(void) { - peer *p; - - if (km_reload()) { - for (p = peers; p; p = p->next) - kx_newkeys(&p->kx); - } + if (km_reload()) + FOREACH_PEER(p, { kx_newkeys(&p->kx); }); } /* --- @p_interval@ --- * @@ -531,11 +521,8 @@ void p_keyreload(void) void p_interval(void) { - peer *p; - p_keyreload(); - for (p = peers; p; p = p->next) - ksl_prune(&p->ks); + FOREACH_PEER(p, { ksl_prune(&p->ks); }); } /* --- @p_stats@ --- * @@ -554,7 +541,25 @@ stats *p_stats(peer *p) { return (&p->st); } * Returns: A pointer to the peer's interface name. */ -const char *p_ifname(peer *p) { return (p->t->ops->ifname(p->t)); } +const char *p_ifname(peer *p) { return (p->ifname); } + +/* --- @p_setifname@ --- * + * + * Arguments: @peer *p@ = pointer to a peer block + * @const char *name@ = pointer to the new name + * + * Returns: --- + * + * Use: Changes the name held for a peer's interface. + */ + +void p_setifname(peer *p, const char *name) +{ + xfree(p->ifname); + p->ifname = xstrdup(name); + if (p->spec.tops->setifname) + p->spec.tops->setifname(p->t, name); +} /* --- @p_addr@ --- * * @@ -606,6 +611,9 @@ void p_init(struct in_addr addr, unsigned port) sel_initfile(&sel, &sock, fd, SEL_READ, p_read, 0); sel_addfile(&sock); T( trace(T_PEER, "peer: created socket"); ) + + sym_create(&byname); + am_create(&byaddr); } /* --- @p_port@ --- * @@ -677,39 +685,48 @@ static void p_setkatimer(peer *p) peer *p_create(peerspec *spec) { peer *p = CREATE(peer); + unsigned f; + + p->byname = sym_find(&byname, spec->name, -1, sizeof(peer_byname), &f); + if (f) goto tidy_0; + p->byaddr = am_find(&byaddr, &spec->sa, sizeof(peer_byaddr), &f); + if (f) goto tidy_1; + p->byname->p = p->byaddr->p = p; T( trace(T_PEER, "peer: creating new peer `%s'", spec->name); ) p->spec = *spec; - p->spec.name = xstrdup(spec->name); + p->spec.name = (/*unconst*/ char *)SYM_NAME(p->byname); p->ks = 0; - p->prev = 0; p->pings = 0; + p->ifname = 0; memset(&p->st, 0, sizeof(stats)); p->st.t_start = time(0); - if ((p->t = spec->tops->create(p)) == 0) - goto tidy_0; + if ((p->t = spec->tops->create(p, &p->ifname)) == 0) + goto tidy_2; p_setkatimer(p); - if (kx_init(&p->kx, p, &p->ks)) - goto tidy_1; - p->next = peers; - if (peers) - peers->prev = p; - peers = p; + if (kx_init(&p->kx, p, &p->ks, p->spec.kxf)) + goto tidy_3; a_notify("ADD", - "?PEER", p, - "%s", p->t->ops->ifname(p->t), - "?ADDR", &p->spec.sa, - A_END); - a_notify("KXSTART", "?PEER", p, A_END); + "?PEER", p, + "%s", p->ifname, + "?ADDR", &p->spec.sa, + A_END); + if (!(p->spec.kxf & KXF_CORK)) { + a_notify("KXSTART", "?PEER", p, A_END); /* Couldn't tell anyone before */ + } return (p); -tidy_1: +tidy_3: if (spec->t_ka) sel_rmtimer(&p->tka); + xfree(p->ifname); p->t->ops->destroy(p->t); +tidy_2: + am_remove(&byaddr, p->byaddr); +tidy_1: + sym_remove(&byname, p->byname); tidy_0: - xfree(p->spec.name); DESTROY(p); return (0); } @@ -732,6 +749,24 @@ const char *p_name(peer *p) { return (p->spec.name); } const peerspec *p_spec(peer *p) { return (&p->spec); } +/* --- @p_findbyaddr@ --- * + * + * Arguments: @const addr *a@ = address to look up + * + * Returns: Pointer to the peer block, or null if not found. + * + * Use: Finds a peer by address. + */ + +peer *p_findbyaddr(const addr *a) +{ + peer_byaddr *pa; + + if ((pa = am_find(&byaddr, a, 0, 0)) != 0) + return (pa->p); + return (0); +} + /* --- @p_find@ --- * * * Arguments: @const char *name@ = name to look up @@ -743,12 +778,11 @@ const peerspec *p_spec(peer *p) { return (&p->spec); } peer *p_find(const char *name) { - peer *p; - for (p = peers; p; p = p->next) { - if (strcmp(name, p->spec.name) == 0) - return (p); - } - return (0); + peer_byname *pn; + + if ((pn = sym_find(&byname, name, -1, 0, 0)) != 0) + return (pn->p); + return (0); } /* --- @p_destroy@ --- * @@ -768,33 +802,47 @@ void p_destroy(peer *p) a_notify("KILL", "%s", p->spec.name, A_END); ksl_free(&p->ks); kx_free(&p->kx); + if (p->ifname) + xfree(p->ifname); p->t->ops->destroy(p->t); if (p->spec.t_ka) sel_rmtimer(&p->tka); - xfree(p->spec.name); for (pg = p->pings; pg; pg = ppg) { ppg = pg->next; p_pingdone(pg, PING_PEERDIED); } - if (p->next) - p->next->prev = p->prev; - if (p->prev) - p->prev->next = p->next; - else - peers = p->next; + sym_remove(&byname, p->byname); + am_remove(&byaddr, p->byaddr); DESTROY(p); } -/* --- @p_first@, @p_next@ --- * +/* --- @p_mkiter@ --- * + * + * Arguments: @peer_iter *i@ = pointer to an iterator * - * Arguments: @peer *p@ = a peer block + * Returns: --- * - * Returns: @peer_first@ returns the first peer in some ordering; - * @peer_next@ returns the peer following a given one in the - * same ordering. Null is returned for the end of the list. + * Use: Initializes the iterator. */ -peer *p_first(void) { return (peers); } -peer *p_next(peer *p) { return (p->next); } +void p_mkiter(peer_iter *i) { sym_mkiter(&i->i, &byname); } + +/* --- @p_next@ --- * + * + * Arguments: @peer_iter *i@ = pointer to an iterator + * + * Returns: Next peer, or null if at the end. + * + * Use: Returns the next peer. + */ + +peer *p_next(peer_iter *i) +{ + peer_byname *pn; + + if ((pn = sym_next(&i->i)) == 0) + return (0); + return (pn->p); +} /*----- That's all, folks -------------------------------------------------*/