if (!p) goto unexp;
p_rxupdstats(p, n);
buf_put(p_txstart(p, MSG_MISC | MISC_PONG), BCUR(&b), BLEFT(&b));
- p_txend(p);
+ p_txend(p, 0);
break;
case MISC_PONG:
if (!p) goto unexp;
buf_flip(&bb);
p_encrypt(p, MSG_MISC | MISC_EPONG, &bb,
p_txstart(p, MSG_MISC | MISC_EPONG));
- p_txend(p);
+ p_txend(p, 0);
}
break;
case MISC_EPONG:
/* --- @p_txend@ --- *
*
* Arguments: @peer *p@ = pointer to peer block
+ * @unsigned f@ = flags
*
* Returns: ---
*
}
}
-void p_txend(peer *p)
+void p_txend(peer *p, unsigned f)
{
- if (p_dotxend(p) && p->spec.t_ka) {
- sel_rmtimer(&p->tka);
- p_setkatimer(p);
+ if (p_dotxend(p)) {
+ if (p->spec.t_ka) {
+ sel_rmtimer(&p->tka);
+ p_setkatimer(p);
+ }
}
}
pg->msg = MISC_PONG;
b = p_txstart(p, MSG_MISC | MISC_PING);
p_pingwrite(pg, b);
- p_txend(p);
+ p_txend(p, 0);
break;
case MISC_EPING:
pg->msg = MISC_EPONG;
p_encrypt(p, MSG_MISC | MISC_EPING, &bb, b);
if (!BOK(b))
return (-1);
- p_txend(p);
+ p_txend(p, 0);
break;
default:
abort();
{
buf *b = p_txstart(p, MSG_MISC | MISC_GREET);
buf_put(b, c, sz);
- p_txend(p);
+ p_txend(p, 0);
}
/* --- @p_tun@ --- *
if (BOK(bb) && BLEN(bb)) {
p->st.n_ipout++;
p->st.sz_ipout += BLEN(bb);
- p_txend(p);
+ p_txend(p, 0);
}
}
*
* Arguments: @struct addrinfo *ailist@ = addresses to bind to
*
- * Returns: ---
+ * Returns: Zero on success, @-1@ on failure.
*
- * Use: Initializes the peer system; creates the socket.
+ * Use: Binds to the main UDP sockets.
*/
-void p_bind(struct addrinfo *ailist)
+int p_bind(struct addrinfo *ailist)
{
- int fd;
+ int fd = -1;
int len = PKBUFSZ;
int yes = 1;
int i;
if ((fd = socket(ai->ai_family, SOCK_DGRAM, 0)) < 0) {
a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
"create-failed", "?ERRNO", A_END);
- exit(EXIT_FAILURE);
+ goto fail;
}
if (i == AFIX_INET6 &&
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes))) {
a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
"set-v6only-failed", "?ERRNO", A_END);
- exit(EXIT_FAILURE);
+ goto fail;
}
assert(ai->ai_addrlen <= sizeof(a));
memcpy(&a, ai->ai_addr, ai->ai_addrlen);
if (bind(fd, &a.sa, addrsz(&a))) {
a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
"bind-failed", "?ERRNO", A_END);
- exit(EXIT_FAILURE);
+ goto fail;
}
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) ||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len))) {
a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
"set-buffers-failed", "?ERRNO", A_END);
- exit(EXIT_FAILURE);
+ goto fail;
}
fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
if (port)
if (getsockname(fd, &a.sa, &sz)) {
a_warn("PEER", "-", "udp-socket", "%s", aftab[i].name,
"read-local-address-failed", "?ERRNO", A_END);
- exit(EXIT_FAILURE);
+ goto fail;
}
udpsock[i].port = lastport = getport(&a);
}
T( trace(T_PEER, "peer: created %s socket", aftab[i].name); )
sel_initfile(&sel, &udpsock[i].sf, fd, SEL_READ, p_read, 0);
sel_addfile(&udpsock[i].sf);
+ fd = -1;
}
+ return (0);
+
+fail:
+ if (fd != -1) close(fd);
+ p_unbind();
+ return (-1);
}
/* --- @p_unbind@ --- *
*
* Arguments: @const tunnel_ops *tops@ = tunnel ops to add
*
- * Returns: ---
+ * Returns: Zero on success, @-1@ on failure.
*
- * Use: Adds a tunnel class to the list of known classes. If there
- * is no current default tunnel, then this one is made the
- * default.
+ * Use: Adds a tunnel class to the list of known classes, if it
+ * initializes properly. If there is no current default tunnel,
+ * then this one is made the default.
*
* Does nothing if the tunnel class is already known. So adding
* a bunch of tunnels takes quadratic time, but there will be
* too few to care about.
*/
-void p_addtun(const tunnel_ops *tops)
+int p_addtun(const tunnel_ops *tops)
{
struct tunnel_node *tn;
for (tn = tunnels; tn; tn = tn->next)
- if (tn->tops == tops) return;
- tops->init();
+ if (tn->tops == tops) return (0);
+ if (tops->init()) return (-1);
tn = CREATE(struct tunnel_node);
tn->next = 0; tn->tops = tops;
*tunnels_tail = tn; tunnels_tail = &tn->next;
if (!dflttun) dflttun = tops;
+ return (0);
}
/* --- @p_setdflttun@ --- *
T( trace(T_PEER, "peer: destroying peer `%s'", p->spec.name); )
- if (bye && (p->spec.f&PSF_EPHEM)) {
+ if (bye) {
b = p_txstart(p, MSG_MISC | MISC_BYE);
buf_init(&bb, buf_t, sizeof(buf_t));
assert(BOK(&bb)); buf_flip(&bb);
p_encrypt(p, MSG_MISC | MISC_BYE, &bb, b);
- p_txend(p);
+ p_txend(p, 0);
}
a_notify("KILL", "%s", p->spec.name, A_END);