Correctly cast uid and gid sentinel values.
[fwd] / socket.c
index 9263ac9..87b3d96 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: socket.c,v 1.4 1999/12/22 15:44:25 mdw Exp $
+ * $Id: socket.c,v 1.9 2002/02/23 00:08:00 mdw Exp $
  *
  * Socket source and target definitions
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: socket.c,v $
+ * Revision 1.9  2002/02/23 00:08:00  mdw
+ * Fix stupid bugs from the listen(2) change.
+ *
+ * Revision 1.8  2002/02/22 23:44:44  mdw
+ * Call @xfree@ rather than @free@.  Add option to change the listen(2)
+ * parameter.
+ *
+ * Revision 1.7  2001/06/22 19:37:00  mdw
+ * New @conn_init@ interface.
+ *
+ * Revision 1.6  2001/02/03 20:30:03  mdw
+ * Support re-reading config files on SIGHUP.
+ *
+ * Revision 1.5  2000/03/23 23:20:42  mdw
+ * Remove listener even if connection option isn't SOCKOPT_LIMITED.
+ *
  * Revision 1.4  1999/12/22 15:44:25  mdw
  * Fix log message.
  *
 typedef struct ssource_opts {
   unsigned opt;
   unsigned conn;
+  unsigned listen;
 } ssource_opts;
 
-static ssource_opts ssgo = { 256, 0 };
+static ssource_opts ssgo = { 256, 0, 5 };
 
 #define SOCKOPT_LIMIT 0u
 #define SOCKOPT_NOLIMIT 1u
@@ -120,7 +137,7 @@ typedef struct starget {
 typedef struct stept {
   endpt e;
   conn c;
-  const char *desc;
+  char *desc;
 } stept;
 
 /* --- Socket source endpoint --- */
@@ -130,9 +147,6 @@ typedef struct ssept {
   ssource *s;
 } ssept;
 
-#define SKF_CONN 16u
-#define SKF_BROKEN 32u
-
 /*----- Protocol table ----------------------------------------------------*/
 
 static addr_ops *addrs[] = { &inet_ops, &un_ops, 0 };
@@ -243,14 +257,14 @@ static void stept_close(endpt *e)
 {
   stept *ee = (stept *)e;
 
-  if (ee->e.f & EPF_PENDING) {
-    if (ee->e.f & SKF_CONN)
-      conn_kill(&ee->c);
-  } else {
+  if (ee->e.f & EPF_PENDING)
+    conn_kill(&ee->c);
+  else {
     REFFD_DEC(ee->e.in);
     REFFD_DEC(ee->e.out);
   }
 
+  xfree(ee->desc);
   fw_dec();
   DESTROY(ee);
 }
@@ -269,35 +283,14 @@ static void stept_go(int fd, void *p)
 {
   stept *e = p;
 
-  /* --- Complicated and subtle --- *
-   *
-   * This code interacts quite closely with @starget_create@, mainly through
-   * flags in the endpoint block.
-   *
-   * If the connection failed, I log a message (that's easy enough).  The
-   * behaviour then depends on whether the endpoints have been joined yet.
-   * If not, I set @SKF_BROKEN@ and return, so that @starget_create@ can
-   * clean up the mess and return an immediate failure.  If they have, I kill
-   * the connection and everything ought to work.
-   *
-   * If the connection worked, I clear @EPF_PENDING@ (as expected, because
-   * my endpoint is now ready), and @SKF_CONN@ (to let @starget_create@ know
-   * that the connection is already going).  Then, only if this isn't the
-   * first attempt, I rejoin this endpoint to its partner.
-   */
-
   if (fd == -1) {
     fw_log(-1, "[%s] connection failed: %s", e->desc, strerror(errno));
-    e->e.f &= ~SKF_CONN;
-    if (e->e.f & EPF_PENDING)
-      endpt_kill(&e->e);
-    else
-      e->e.f |= SKF_BROKEN;
+    endpt_kill(&e->e);
   } else {
     reffd *r = reffd_init(fd);
     REFFD_INC(r);
     e->e.in = e->e.out = r;
-    e->e.f &= ~(EPF_PENDING | SKF_CONN);
+    e->e.f &= ~EPF_PENDING;
     if (e->e.other)
       endpt_join(&e->e, e->e.other);
   }
@@ -352,6 +345,19 @@ static int ssource_option(source *s, scanner *sc)
     CONF_ACCEPT;
   }
 
+  if (strcmp(sc->d.buf, "listen") == 0) {
+    token(sc);
+    if (sc->t == '=')
+      token(sc);
+    if (sc->t != CTOK_WORD || !isdigit((unsigned char)sc->d.buf[0]))
+      error(sc, "parse error, expected number");
+    sso->listen = atoi(sc->d.buf);
+    if (sso->listen == 0)
+      error(sc, "argument of `listen' must be positive");
+    token(sc);
+    CONF_ACCEPT;
+  }
+
   if (strcmp(sc->d.buf, "logging") == 0 ||
       strcmp(sc->d.buf, "log") == 0) {
     addr_opts *ao = ss ? ss->ao : &gao;
@@ -533,7 +539,7 @@ static void ss_listen(ssource *ss)
 
   /* --- Set it to listen for connections --- */
 
-  if (listen(fd, 5)) {
+  if (listen(fd, ss->o.listen)) {
     fw_log(-1, "[%s] couldn't listen on socket: %s",
           ss->s.desc, strerror(errno));
     goto fail_1;
@@ -605,7 +611,7 @@ static void ssource_attach(source *s, scanner *sc, target *t)
 
     /* --- Set it to listen for connections --- */
 
-    if (listen(fd, 5))
+    if (listen(fd, ss->o.listen))
       error(sc, "couldn't listen on socket: %s", strerror(errno));
   }
 
@@ -623,7 +629,7 @@ static void ssource_destroy(source *s)
 {
   ssource *ss = (ssource *)s;
 
-  if (ss->o.conn) {
+  if (ss->o.conn || ss->o.opt != SOCKOPT_LIMIT) {
     sel_rmfile(&ss->r);
     close(ss->r.fd);
     if (ss->a->ops->unbind)
@@ -633,7 +639,7 @@ static void ssource_destroy(source *s)
     ss->a->ops->freeopts(ss->ao);
   else
     DESTROY(ss->ao);
-  /* free(ss->s.desc); */
+  xfree(ss->s.desc);
   ss->a->ops->destroy(ss->a);
   ss->t->ops->destroy(ss->t);
   source_remove(&ss->s);
@@ -692,30 +698,15 @@ static endpt *starget_create(target *t, const char *desc)
   fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
   e->e.ops = &stept_ops;
   e->e.other = 0;
-  e->e.f = EPF_FILE | SKF_CONN;
+  e->e.f = EPF_FILE | EPF_PENDING;
   e->e.t = 0;
-  e->desc = desc;
-
-  /* --- Pay attention --- *
-   *
-   * This bit is quite subtle.  The connect can succeed or fail later: that's
-   * fine.  The problem comes if it makes its mind up right now.  The flag
-   * @SKF_CONN@ signifies that I'm trying to connect.  I set it up to begin
-   * with and @stept_go@ turns it off when it's done: @stept_close@ uses it
-   * to decide whether to kill the connection.  The flag @EPF_PENDING@ is
-   * only set after @conn_init@ returns and @SKF_CONN@ is still set (meaning
-   * that the connection is still in progress).  That's used to let
-   * @stept_go@ know whether to kill the other endpoint.  The flag
-   * @SKF_BROKEN@ is used to signify an immediate failure.
-   */
+  e->desc = xstrdup(desc);
 
-  conn_init(&e->c, sel, fd, &ga->sa, ga->a.sz, stept_go, e);
-  if (e->e.f & SKF_BROKEN) {
+  if (conn_init(&e->c, sel, fd, &ga->sa, ga->a.sz, stept_go, e)) {
+    fw_log(-1, "[%s] connection failed: %s", e->desc, strerror(errno));
     DESTROY(e);
     return (0);
   }
-  if (e->e.f & SKF_CONN)
-    e->e.f |= EPF_PENDING;
   fw_inc();
   return (&e->e);
 }
@@ -726,7 +717,7 @@ static void starget_destroy(target *t)
 {
   starget *st = (starget *)t;
   st->a->ops->destroy(st->a);
-  /* free(st->t.desc); */
+  xfree(st->t.desc);
   DESTROY(st);
 }