X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/6047fbac6ecdaa13a13ea71f7f62eb77b2361eec..a62f8e8a94bf56194539f7140a1215bc74309b36:/server/peer.c diff --git a/server/peer.c b/server/peer.c index b23ef7bf..4bb2c82c 100644 --- a/server/peer.c +++ b/server/peer.c @@ -122,6 +122,57 @@ found: p_pingdone(pg, PING_OK); } +/* --- @p_encrypt@ --- * + * + * Arguments: @peer *p@ = peer to encrypt message to + * @int ty@ message type to send + * @buf *bin, *bout@ = input and output buffers + * + * Returns: --- + * + * Use: Convenience function for packet encryption. Forces + * renegotiation when necessary. Check for the output buffer + * being broken to find out whether the encryption was + * successful. + */ + +static int p_encrypt(peer *p, int ty, buf *bin, buf *bout) +{ + int err = ksl_encrypt(&p->ks, ty, bin, bout); + + if (err == KSERR_REGEN) { + kx_start(&p->kx, 1); + err = 0; + } + if (!BOK(bout)) + err = -1; + return (err); +} + +/* --- @p_decrypt@ --- * + * + * Arguments: @peer *p@ = peer to decrypt message from + * @int ty@ = message type to expect + * @buf *bin, *bout@ = input and output buffers + * + * Returns: Zero on success; nonzero on error. + * + * Use: Convenience function for packet decryption. Reports errors + * and updates statistics appropriately. + */ + +static int p_decrypt(peer *p, int ty, buf *bin, buf *bout) +{ + if (ksl_decrypt(&p->ks, ty, bin, bout)) { + p->st.n_reject++; + a_warn("PEER", "?PEER", p, "decrypt-failed", A_END); + return (-1); + } + if (!BOK(bout)) + return (-1); + return (0); +} + /* --- @p_read@ --- * * * Arguments: @int fd@ = file descriptor to read from @@ -208,11 +259,8 @@ static void p_read(int fd, unsigned mode, void *v) return; } buf_init(&bb, buf_o, sizeof(buf_o)); - if (ksl_decrypt(&p->ks, MSG_PACKET, &b, &bb)) { - p->st.n_reject++; - a_warn("PEER", "?PEER", p, "decrypt-failed", A_END); + if (p_decrypt(p, MSG_PACKET, &b, &bb)) return; - } if (BOK(&bb)) { p->st.n_ipin++; p->st.sz_ipin += BSZ(&b); @@ -239,26 +287,19 @@ static void p_read(int fd, unsigned mode, void *v) break; case MISC_EPING: buf_init(&bb, buf_t, sizeof(buf_t)); - if (ksl_decrypt(&p->ks, ch, &b, &bb)) { - p->st.n_reject++; - a_warn("PEER", "?PEER", p, "decrypt-failed", A_END); + if (p_decrypt(p, ch, &b, &bb)) return; - } if (BOK(&bb)) { buf_flip(&bb); - if (ksl_encrypt(&p->ks, MSG_MISC | MISC_EPONG, &bb, - p_txstart(p, MSG_MISC | MISC_EPONG))) - kx_start(&p->kx, 0); + p_encrypt(p, MSG_MISC | MISC_EPONG, &bb, + p_txstart(p, MSG_MISC | MISC_EPONG)); p_txend(p); } break; case MISC_EPONG: buf_init(&bb, buf_t, sizeof(buf_t)); - if (ksl_decrypt(&p->ks, ch, &b, &bb)) { - p->st.n_reject++; - a_warn("PEER", "?PEER", p, "decrypt-failed", A_END); + if (p_decrypt(p, ch, &b, &bb)) return; - } if (BOK(&bb)) { buf_flip(&bb); p_ponged(p, MISC_EPONG, &bb); @@ -427,8 +468,7 @@ int p_pingsend(peer *p, ping *pg, unsigned type, buf_init(&bb, buf_t, sizeof(buf_t)); p_pingwrite(pg, &bb); buf_flip(&bb); - if (ksl_encrypt(&p->ks, MSG_MISC | MISC_EPING, &bb, b)) - kx_start(&p->kx, 0); + p_encrypt(p, MSG_MISC | MISC_EPING, &bb, b); if (!BOK(b)) return (-1); p_txend(p); @@ -486,8 +526,7 @@ void p_tun(peer *p, buf *b) buf *bb = p_txstart(p, MSG_PACKET); TIMER; - if (ksl_encrypt(&p->ks, MSG_PACKET, b, bb)) - kx_start(&p->kx, 0); + p_encrypt(p, MSG_PACKET, b, bb); if (BOK(bb) && BLEN(bb)) { p->st.n_ipout++; p->st.sz_ipout += BLEN(bb); @@ -685,6 +724,8 @@ static void p_setkatimer(peer *p) peer *p_create(peerspec *spec) { peer *p = CREATE(peer); + const tunnel_ops *tops = spec->tops; + int fd; unsigned f; p->byname = sym_find(&byname, spec->name, -1, sizeof(peer_byname), &f); @@ -701,11 +742,17 @@ peer *p_create(peerspec *spec) p->ifname = 0; memset(&p->st, 0, sizeof(stats)); p->st.t_start = time(0); - if ((p->t = spec->tops->create(p, &p->ifname)) == 0) + if (!(tops->flags & TUNF_PRIVOPEN)) + fd = -1; + else if ((fd = ps_tunfd(tops, &p->ifname)) < 0) goto tidy_2; + if ((p->t = tops->create(p, fd, &p->ifname)) == 0) + goto tidy_3; + T( trace(T_TUNNEL, "peer: attached interface %s to peer `%s'", + p->ifname, p_name(p)); ) p_setkatimer(p); if (kx_init(&p->kx, p, &p->ks, p->spec.kxf)) - goto tidy_3; + goto tidy_4; a_notify("ADD", "?PEER", p, "%s", p->ifname, @@ -717,11 +764,13 @@ peer *p_create(peerspec *spec) } return (p); -tidy_3: +tidy_4: if (spec->t_ka) sel_rmtimer(&p->tka); xfree(p->ifname); p->t->ops->destroy(p->t); +tidy_3: + if (fd >= 0) close(fd); tidy_2: am_remove(&byaddr, p->byaddr); tidy_1: