*
* 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);