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
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);
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);
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);
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);
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);
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,
- "?ADDR", &p->spec.sa,
- 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_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: