chiark / gitweb /
server/: Make initialization errors be non-fatal and restartable.
[tripe] / server / peer.c
index 278a6b2a5377304f46647a3380f0e689fd3d6979..95306836d3211519bb1e8a76a62bbbc38352bd01 100644 (file)
@@ -809,14 +809,14 @@ const addr *p_addr(peer *p) { return (&p->spec.sa); }
  *
  * 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;
@@ -842,13 +842,13 @@ void p_bind(struct addrinfo *ailist)
     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);
@@ -856,13 +856,13 @@ void p_bind(struct addrinfo *ailist)
     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)
@@ -872,15 +872,22 @@ void p_bind(struct addrinfo *ailist)
       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@ --- *
@@ -928,28 +935,29 @@ void p_init(void)
  *
  * 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@ --- *