Debianization. Socket target options. Internet binding.
authormdw <mdw>
Tue, 25 Nov 2003 14:08:23 +0000 (14:08 +0000)
committermdw <mdw>
Tue, 25 Nov 2003 14:08:23 +0000 (14:08 +0000)
17 files changed:
.cvsignore
Makefile.am
acl.c
acl.h
addr.h
conf.h
configure.in
debian/.cvsignore [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/rules [new file with mode: 0755]
inet.c
socket.c
socket.h
target.h
un.c

index 19a3c54..4b605eb 100644 (file)
@@ -5,3 +5,4 @@ build
 config.h.in
 configure
 stamp-h.in
+deb-build
index 2c270c7..c9598c6 100644 (file)
@@ -1,6 +1,6 @@
 ## -*-makefile-*-
 ##
-## $Id: Makefile.am,v 1.5 1999/11/11 19:08:27 mdw Exp $
+## $Id: Makefile.am,v 1.6 2003/11/25 14:08:23 mdw Exp $
 ##
 ## Makefile for fw
 ##
@@ -28,6 +28,9 @@
 ##----- Revision history ----------------------------------------------------
 ##
 ## $Log: Makefile.am,v $
+## Revision 1.6  2003/11/25 14:08:23  mdw
+## Debianization.  Socket target options.  Internet binding.
+##
 ## Revision 1.5  1999/11/11 19:08:27  mdw
 ## Build separately from mLib.
 ##
@@ -49,7 +52,9 @@ AUTOMAKE_OPTIONS = foreign
 bin_PROGRAMS = fw
 man_MANS = fw.1
 
-EXTRA_DIST = $(man_MANS)
+EXTRA_DIST = \
+       $(man_MANS) \
+       debian/changelog debian/copyright debian/control debian/rules
 
 fw_SOURCES = \
        chan.c conf.c endpt.c fw.c reffd.c scan.c \
diff --git a/acl.c b/acl.c
index 059ec9c..29dd2db 100644 (file)
--- a/acl.c
+++ b/acl.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: acl.c,v 1.3 1999/07/27 18:30:53 mdw Exp $
+ * $Id: acl.c,v 1.4 2003/11/25 14:08:23 mdw Exp $
  *
  * Access control list handling
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: acl.c,v $
+ * Revision 1.4  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.3  1999/07/27 18:30:53  mdw
  * Various minor portability fixes.
  *
 
 #include "acl.h"
 
-/*----- Static variables --------------------------------------------------*/
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @acl_addhost@ --- *
+ *
+ * Arguments:  @acl_entry ***a@ = address of pointer to list tail
+ *             @unsigned act@ = what to do with matching addresses
+ *             @struct in_addr addr, mask@ = address and mask to match
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a host-authentication entry to the end of an access
+ *             control list.
+ */
+
+static int acl_checkhost(void *aa, struct in_addr addr, unsigned port)
+{
+  acl_host *a = aa;
+  return ((addr.s_addr & a->mask.s_addr) == a->addr.s_addr);
+}
 
-static acl_entry *global = 0;
-static acl_entry **gtail = &global;
+static void acl_dumphost(void *aa, FILE *fp)
+{
+  acl_host *a = aa;
+  
+  fputs("from ", fp);
+  fputs(inet_ntoa(a->addr), fp);
+  fputc('/', fp);
+  fputs(inet_ntoa(a->mask), fp);
+}
 
-/*----- Main code ---------------------------------------------------------*/
+static void acl_freehost(void *aa)
+{
+  acl_host *a = aa;
+  DESTROY(a);
+}
+
+static const acl_ops acl_hostops = {
+  acl_checkhost, acl_dumphost, acl_freehost
+};
+
+void acl_addhost(acl_entry ***a, unsigned act,
+                struct in_addr addr, struct in_addr mask)
+{
+  acl_host *aa = CREATE(acl_host);
+  aa->a.next = 0;
+  aa->a.ops = &acl_hostops;
+  aa->a.act = act;
+  aa->addr.s_addr = addr.s_addr & mask.s_addr;
+  aa->mask = mask;
+  **a = &aa->a;
+  *a = &aa->a.next;
+}
+
+/* --- @acl_addpriv@ --- *
+ *
+ * Arguments:  @acl_entry ***a@ = address of pointer to list tail
+ *             @unsigned act@ = what to do with matching addresses
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a privileged-port check to the end of an access control
+ *             list.
+ */
+
+static int acl_checkpriv(void *aa, struct in_addr addr, unsigned port)
+{
+  return (port < 1024);
+}
+
+static void acl_dumppriv(void *aa, FILE *fp)
+{
+  fputs("from privileged ports", fp);
+}
+
+static void acl_freepriv(void *aa)
+{
+  acl_entry *a = aa;
+  DESTROY(a);
+}
+
+static const acl_ops acl_privops = {
+  acl_checkpriv, acl_dumppriv, acl_freepriv
+};
+
+void acl_addpriv(acl_entry ***a, unsigned act)
+{
+  acl_entry *aa = CREATE(acl_entry);
+  aa->next = 0;
+  aa->ops = &acl_privops;
+  aa->act = act;
+  **a = aa;
+  *a = &aa->next;
+}
 
 /* --- @acl_check@ --- *
  *
  * Arguments:  @acl_entry *a@ = pointer to ACL to check against
  *             @struct in_addr addr@ = address to check
+ *             @unsigned port@ = port number to check
+ *             @int *act@ = verdict (should initially be @ACT_ALLOW@)
  *
- * Returns:    Nonzero if allowed.
+ * Returns:    Zero if undecided, nonzero if a rule matched.
  *
  * Use:                Checks an address against an ACL.
  */
 
-int acl_check(acl_entry *a, struct in_addr addr)
+int acl_check(acl_entry *a, struct in_addr addr, unsigned port, int *act)
 {
-  int act = ACL_ALLOW;
-  int i;
-
-  for (i = 0; i < 2; i++) {
-    for (; a; a = a->next) {
-      if ((addr.s_addr & a->mask.s_addr) == a->addr.s_addr)
-       return (a->act & ACL_PERM);
-      act = (a->act & ACL_PERM) ^ 1;
+  for (; a; a = a->next) {
+    if (a->ops->check(a, addr, port)) {
+      *act = a->act & ACL_PERM;
+      return (1);
     }
-    a = global;
+    *act = (a->act & ACL_PERM) ^ 1;
   }
-
-  return (act);
+  return (0);
 }
 
 /* --- @acl_dump@ --- *
@@ -107,14 +194,10 @@ int acl_check(acl_entry *a, struct in_addr addr)
 
 void acl_dump(acl_entry *a, FILE *fp)
 {
-  if (!a)
-    a = global;
   for (; a; a = a->next) {
-    fprintf(fp, "  %s from ",
+    fprintf(fp, "  %s ",
            (a->act & ACL_PERM) == ACL_ALLOW ? "allow" : "deny");
-    fputs(inet_ntoa(a->addr), fp);
-    fputc('/', fp);
-    fputs(inet_ntoa(a->mask), fp);
+    a->ops->dump(a, fp);
     fputc('\n', fp);
   }
 }
@@ -133,33 +216,8 @@ void acl_free(acl_entry *a)
   while (a) {
     acl_entry *aa = a;
     a = a->next;
-    DESTROY(aa);
+    aa->ops->free(aa);
   }
 }
 
-/* --- @acl_add@ --- *
- *
- * Arguments:  @acl_entry ***a@ = address of pointer to list tail
- *             @unsigned act@ = what to do with matching addresses
- *             @struct in_addr addr, mask@ = address and mask to match
- *
- * Returns:    ---
- *
- * Use:                Adds an entry to the end of an access control list.
- */
-
-void acl_add(acl_entry ***a, unsigned act,
-            struct in_addr addr, struct in_addr mask)
-{
-  acl_entry *aa = CREATE(acl_entry);
-  aa->act = act;
-  aa->addr.s_addr = addr.s_addr & mask.s_addr;
-  aa->mask = mask;
-  aa->next = 0;
-  if (!a)
-    a = &gtail;
-  **a = aa;
-  *a = &aa->next;
-}
-
 /*----- That's all, folks -------------------------------------------------*/
diff --git a/acl.h b/acl.h
index 21f398d..373df4b 100644 (file)
--- a/acl.h
+++ b/acl.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: acl.h,v 1.3 1999/07/27 18:30:53 mdw Exp $
+ * $Id: acl.h,v 1.4 2003/11/25 14:08:23 mdw Exp $
  *
  * Access control list handling
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: acl.h,v $
+ * Revision 1.4  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.3  1999/07/27 18:30:53  mdw
  * Various minor portability fixes.
  *
 
 typedef struct acl_entry {
   struct acl_entry *next;              /* Next entry in the list */
+  const struct acl_ops *ops;           /* Operations for the ACL entry */
   unsigned act;                                /* What to do with matching hosts */
-  struct in_addr addr, mask;           /* Address and netmask */
 } acl_entry;
 
-#define ACL_DENY 0                     /* Deny access to matching hosts */
-#define ACL_ALLOW 1                    /* Allow access to matching hosts */
+#define ACL_DENY 0                     /* Deny access to matching conns */
+#define ACL_ALLOW 1                    /* Allow access to matching conns */
 #define ACL_PERM 1u                    /* Bit mask for permission bit */
 
+/* --- Host-based access control --- */
+
+typedef struct acl_host {
+  acl_entry a;                         /* Base structure */
+  struct in_addr addr, mask;           /* Address and netmask */
+} acl_host;
+
+/* --- ACL methods --- */
+
+typedef struct acl_ops {
+  int (*check)(void */*a*/, struct in_addr /*addr*/, unsigned /*port*/);
+  void (*dump)(void */*a*/, FILE */*fp*/);
+  void (*free)(void */*a*/);
+} acl_ops;
+
 /*----- Functions provided ------------------------------------------------*/
 
 /* --- @acl_check@ --- *
  *
  * Arguments:  @acl_entry *a@ = pointer to ACL to check against
  *             @struct in_addr addr@ = address to check
+ *             @unsigned port@ = port number to check
+ *             @int *act@ = verdict (should initially be @ACT_ALLOW@)
  *
- * Returns:    Nonzero if allowed.
+ * Returns:    Zero if undecided, nonzero if a rule matched.
  *
  * Use:                Checks an address against an ACL.
  */
 
-extern int acl_check(acl_entry */*a*/, struct in_addr /*addr*/);
+extern int acl_check(acl_entry */*a*/,
+                    struct in_addr /*addr*/, unsigned /*port*/,
+                    int */*act*/);
 
 /* --- @acl_dump@ --- *
  *
@@ -106,7 +128,7 @@ extern void acl_dump(acl_entry */*a*/, FILE */*fp*/);
 
 extern void acl_free(acl_entry */*a*/);
 
-/* --- @acl_add@ --- *
+/* --- @acl_addhost@ --- *
  *
  * Arguments:  @acl_entry ***a@ = address of pointer to list tail
  *             @unsigned act@ = what to do with matching addresses
@@ -114,11 +136,25 @@ extern void acl_free(acl_entry */*a*/);
  *
  * Returns:    ---
  *
- * Use:                Adds an entry to the end of an access control list.
+ * Use:                Adds a host-authentication entry to the end of an access
+ *             control list.
+ */
+
+extern void acl_addhost(acl_entry ***/*a*/, unsigned /*act*/,
+                       struct in_addr /*addr*/, struct in_addr /*mask*/);
+
+/* --- @acl_addpriv@ --- *
+ *
+ * Arguments:  @acl_entry ***a@ = address of pointer to list tail
+ *             @unsigned act@ = what to do with matching addresses
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a privileged-port check to the end of an access control 
+ *             list.
  */
 
-extern void acl_add(acl_entry ***/*a*/, unsigned /*act*/,
-                   struct in_addr /*addr*/, struct in_addr /*mask*/);
+extern void acl_addpriv(acl_entry ***/*a*/, unsigned /*act*/);
 
 /*----- That's all, folks -------------------------------------------------*/
 
diff --git a/addr.h b/addr.h
index cc5b790..adc4cd1 100644 (file)
--- a/addr.h
+++ b/addr.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: addr.h,v 1.2 1999/07/27 18:30:53 mdw Exp $
+ * $Id: addr.h,v 1.3 2003/11/25 14:08:23 mdw Exp $
  *
  * Generic interface to network address handlers
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: addr.h,v $
+ * Revision 1.3  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.2  1999/07/27 18:30:53  mdw
  * Various minor portability fixes.
  *
 #include <sys/socket.h>
 
 #include <mLib/dstr.h>
+#include <mLib/conn.h>
 
 #ifndef REFFD_H
 #  include "reffd.h"
 #endif
 
+#ifndef ENDPT_H
+#  include "endpt.h"
+#endif
+
 #ifndef SCAN_H
 #  include "scan.h"
 #endif
@@ -73,11 +81,6 @@ typedef struct addr {
   size_t sz;
 } addr;
 
-typedef struct gen_addr {
-  addr a;
-  struct sockaddr sa;
-} gen_addr;
-
 #define ADDRSZ(sz) (sizeof(addr) + (sz))
 
 /* --- Address configuration --- *
@@ -99,14 +102,14 @@ typedef struct addr_opts {
 
 enum {
   ADDR_SRC,
-  ADDR_DEST
+  ADDR_DEST,
+  ADDR_GLOBAL
 };
 
 /* --- Description of an address type handler --- */
 
 typedef struct addr_ops {
   const char *name;                    /* Protocol's internal name */
-  int pf;                              /* Protocol family number */
 
   /* --- @read@ --- *
    *
@@ -145,7 +148,7 @@ typedef struct addr_ops {
 
   void (*print)(addr */*a*/, unsigned /*type*/, dstr */*d*/);
 
-  /* --- @initopts@ --- *
+  /* --- @initsrcopts@ --- *
    *
    * Arguments:        ---
    *
@@ -156,19 +159,57 @@ typedef struct addr_ops {
    *           are added to the block when necessary.
    */
 
-  addr_opts *(*initopts)(void);
+  addr_opts *(*initsrcopts)(void);
 
   /* --- @option@ --- *
    *
    * Arguments:        @scanner *sc@ = pointer to a scanner to read from
+   *           @unsigned type@ = kind of option this is
    *           @addr_opts *ao@ = data block to modify (from @init@), or null
    *
    * Returns:  Nonzero to claim the option.
    *
-   * Use:      Parses an option, either global or listener-specific.
+   * Use:      Parses a source option, either global or listener-specific.
+   */
+
+  int (*option)(scanner */*sc*/, addr_opts */*ao*/, unsigned /*type*/);
+
+  /* --- @freesrcopts@ --- *
+   *
+   * Arguments:        @addr_opts *ao@ = data block to remove
+   *
+   * Returns:  ---
+   *
+   * Use:      Throws away all the configuration data for an address type.
+   */
+
+  void (*freesrcopts)(addr_opts */*ao*/);
+
+  /* --- @bind@ --- *
+   *
+   * Arguments:        @addr *a@ = the address to bind to
+   *           @addr_opts *ao@ = the address options
+   *
+   * Returns:  File descriptor of bound socket if OK, or @-1@ on error.
+   *
+   * Use:      Binds a listening socket.  The tedious stuff with @listen@
+   *           isn't necessary.
+   */
+
+  int (*bind)(addr */*a*/, addr_opts */*ao*/);
+
+  /* --- @unbind@ --- *
+   *
+   * Arguments:        @addr *a@ = pointer to an address
+   *
+   * Returns:  ---
+   *
+   * Use:      Unbinds an address.  This is used when tidying up.  The main
+   *           purpose is to let the Unix-domain handler remove its socket
+   *           node from the filesystem.
    */
 
-  int (*option)(scanner */*sc*/, addr_opts */*ao*/);
+  void (*unbind)(addr */*a*/);
 
   /* --- @accept@ --- *
    *
@@ -183,42 +224,52 @@ typedef struct addr_ops {
 
   reffd *(*accept)(int /*fd*/, addr_opts */*ao*/, const char */*desc*/);
 
-  /* --- @freeopts@ --- *
+  /* --- @inittargopts@ --- *
    *
-   * Arguments:        @addr_opts *ao@ = data block to remove
+   * Arguments:        ---
    *
-   * Returns:  ---
+   * Returns:  A pointer to a protocol-specific data block for a connecter
    *
-   * Use:      Throws away all the configuration data for an address type.
+   * Use:      Creates a data block for a target.  This is attached to the
+   *           target data structure.  Options can then be requested, and
+   *           are added to the block when necessary.
    */
 
-  void (*freeopts)(addr_opts */*ao*/);
+  addr_opts *(*inittargopts)(void);
 
-  /* --- @bound@ --- *
+  /* --- @freetargopts@ --- *
    *
-   * Arguments:        @addr *a@ = pointer to an address
-   *           @addr_opts *ao@ = pointer to attributes block
+   * Arguments:        @addr_opts *ao@ = data block to remove
    *
    * Returns:  ---
    *
-   * Use:      Reports that a file descriptor has been (successfully) bound
-   *           to an address.
+   * Use:      Throws away all the configuration data for an address type.
    */
 
-  void (*bound)(addr */*a*/, addr_opts */*ao*/);
+  void (*freetargopts)(addr_opts */*ao*/);
 
-  /* --- @unbind@ --- *
+  /* --- @connect@ --- *
    *
-   * Arguments:        @addr *a@ = pointer to an address
+   * Arguments:        @addr *a@ = destination address
+   *           @addr_opts *ao@ = target address options
+   *           @conn *c@ = connection structure
+   *           @endpt *e@ = endpoint structure
    *
-   * Returns:  ---
+   * Returns:  Zero if OK, @-1@ on some error.
    *
-   * Use:      Unbinds an address.  This is used when tidying up.  The main
-   *           purpose is to let the Unix-domain handler remove its socket
-   *           node from the filesystem.
+   * Use:      Requests that a connection be made, or at least set in
+   *           motion.  An address may do one of these things:
+   *
+   *             * Return @-1@.
+   *
+   *             * Call @starget_connected@ with @-1@ or a connected file
+   *               descriptor and the pointer @e@.
+   *
+   *             * Call @conn_init@ or @conn_fd@, giving @starget_connected@
+   *               and @e@ as the function to call.
    */
 
-  void (*unbind)(addr */*a*/);
+  int (*connect)(addr */*a*/, addr_opts */*ao*/, conn */*c*/, endpt */*e*/);
 
 } addr_ops;
   
diff --git a/conf.h b/conf.h
index f9e25e9..7b656e0 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: conf.h,v 1.7 2002/02/22 23:42:56 mdw Exp $
+ * $Id: conf.h,v 1.8 2003/11/25 14:08:23 mdw Exp $
  *
  * Configuration parsing
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: conf.h,v $
+ * Revision 1.8  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.7  2002/02/22 23:42:56  mdw
  * `fw'-specific configuration code moved out.  This file might become part
  * of a library some day.
@@ -232,7 +235,7 @@ extern int conf_prefix(scanner */*sc*/, const char */*p*/);
      * because the option wasn't accepted.                             \
      */                                                                        \
                                                                        \
-     goto _conf_reject;                                                        \
+    goto _conf_reject;                                                 \
   _conf_reject:                                                                \
     if (_conf_state == CS_PLAIN)                                       \
       _conf_state = CS_UNKNOWN;                                                \
index 6b7f0f3..446e361 100644 (file)
@@ -1,6 +1,6 @@
-dnl -*-fundamental-*-
+dnl -*-m4-*-
 dnl
-dnl $Id: configure.in,v 1.14 2003/05/17 12:33:55 mdw Exp $
+dnl $Id: configure.in,v 1.15 2003/11/25 14:08:23 mdw Exp $
 dnl
 dnl Configuration script for fw
 dnl
@@ -28,6 +28,9 @@ dnl Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 dnl ----- Revision history --------------------------------------------------
 dnl
 dnl $Log: configure.in,v $
+dnl Revision 1.15  2003/11/25 14:08:23  mdw
+dnl Debianization.  Socket target options.  Internet binding.
+dnl
 dnl Revision 1.14  2003/05/17 12:33:55  mdw
 dnl Version bump.
 dnl
@@ -73,7 +76,7 @@ mdw_DECL_ENVIRON
 
 mdw_CHECK_MANYLIBS(socket, socket)
 mdw_CHECK_MANYLIBS(gethostbyname, nsl resolv)
-mdw_MLIB(1.7.0)
+mdw_MLIB(2.0.2)
 
 AC_CHECK_FUNCS(inet_aton)
 AC_CHECK_FUNCS(setrlimit)
diff --git a/debian/.cvsignore b/debian/.cvsignore
new file mode 100644 (file)
index 0000000..fd2495d
--- /dev/null
@@ -0,0 +1,2 @@
+files tmp substvars *.substvars *.debhelper
+fw
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..edbda91
--- /dev/null
@@ -0,0 +1,11 @@
+fw (1.2.7) experimental; urgency=low
+
+  * Debianization!
+
+  * Fix data corruption in chan.c.
+  
+  * Socket target option support.  Currently there's just bind address.
+  
+  * Support binding to specific addresses for inet sources and targets.
+
+ -- Mark Wooding <mdw@nsict.org>  Tue, 25 Nov 2003 14:07:42 +0000
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..d0a1a28
--- /dev/null
@@ -0,0 +1,17 @@
+Source: fw
+Section: net
+Priority: extra
+Build-Depends: mlib-dev (>= 2.0.2), debhelper (>= 4.0.2)
+Maintainer: Mark Wooding <mdw@nsict.org>
+Standards-Version: 3.1.1
+
+Package: fw
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Excessive port forwarder
+ fw can forward connections to and from: TCP sockets, Unix-domain sockets,
+ locally-executed programs, and file descriptors.  It can do host-based
+ access control.  It will log incoming TCP connections by hostname and
+ username (as reported by identd on the connecting host).  It subsumes the
+ basic functionality of inetd, cat, netcat and others.  It runs as a 
+ single nonblocking process.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..6401701
--- /dev/null
@@ -0,0 +1,16 @@
+fw is copyright (c) 2003 Straylight/Edgeware.
+
+fw is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+fw is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have a copy of the GNU General Public License in
+/usr/share/common-licenses/GPL; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+USA.
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..d592b5b
--- /dev/null
@@ -0,0 +1,45 @@
+#! /usr/bin/make -f
+
+export DH_COMPAT = 4
+
+build:
+       rm -rf build deb-build
+       mkdir deb-build
+       cd deb-build; ../configure --prefix=/usr --mandir=/usr/share/man
+       make -C deb-build
+       touch build
+
+clean:
+       dh_clean
+       rm -rf deb-build build
+
+install: build
+       dh_clean
+       make -C deb-build install DESTDIR=`pwd`/debian/fw
+
+binary-indep:
+
+binary-arch: install
+       dh_testdir -a
+       dh_testroot -a
+       dh_compress -a
+       dh_installdocs -a
+       dh_strip -a
+       dh_shlibdeps -a
+       dh_gencontrol -a
+       dh_fixperms -a
+       dh_installdeb -a
+       dh_md5sums -a
+       dh_builddeb -a
+
+binary: binary-indep binary-arch
+
+source:
+       rm -rf deb-build/*.tar.gz deb-build/=deb=
+       make -C deb-build dist
+       mkdir deb-build/=deb=
+       cd deb-build/=deb=; tar xvfz ../*.tar.gz
+       d=`pwd`; cd ..; dpkg-source -i -b $$d/deb-build/=deb=/*
+       rm -rf deb-build/=deb=
+
+.PHONY: binary binary-arch binary-indep clean install source 
diff --git a/inet.c b/inet.c
index f98c7fa..70e5c90 100644 (file)
--- a/inet.c
+++ b/inet.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: inet.c,v 1.4 2002/01/13 14:49:56 mdw Exp $
+ * $Id: inet.c,v 1.5 2003/11/25 14:08:23 mdw Exp $
  *
  * Protocol specific definitions for IPv4 sockets
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: inet.c,v $
+ * Revision 1.5  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.4  2002/01/13 14:49:56  mdw
  * Conditional compilation for @getnetbyname@, since Cygwin doesn't have
  * it.
 
 #include <mLib/alloc.h>
 #include <mLib/dstr.h>
+#include <mLib/fdflags.h>
 #include <mLib/report.h>
 #include <mLib/sub.h>
 
 #include "acl.h"
 #include "addr.h"
 #include "conf.h"
+#include "fw.h"
 #include "identify.h"
 #include "inet.h"
 #include "reffd.h"
 #include "scan.h"
+#include "socket.h"
 
 /*----- Data structures ---------------------------------------------------*/
 
@@ -84,9 +90,23 @@ typedef struct inet_addrx {
 
 typedef struct inet_opts {
   addr_opts ao;
+  struct in_addr bind;
+} inet_opts;
+
+typedef struct inet_srcopts {
+  inet_opts io;
   acl_entry *acl;
   acl_entry **acltail;
-} inet_opts;
+} inet_srcopts;
+
+typedef struct inet_targopts {
+  inet_opts io;
+} inet_targopts;
+
+static inet_srcopts inet_globalsrc =
+  { { { 0 }, { INADDR_ANY } }, 0, &inet_globalsrc.acl };
+static inet_targopts inet_globaltarg =
+  { { { 0 }, { INADDR_ANY } } };
 
 /*----- Protocol operations -----------------------------------------------*/
 
@@ -168,24 +188,64 @@ static void inet_print(addr *a, unsigned type, dstr *d)
 
 /* --- @initopts@ --- */
 
-static addr_opts *inet_initopts(void)
+static addr_opts *inet_initsrcopts(void)
 {
-  inet_opts *io = CREATE(inet_opts);
+  inet_srcopts *io = CREATE(inet_srcopts);
+  *io = inet_globalsrc;
   io->acl = 0;
   io->acltail = &io->acl;
-  return (&io->ao);
+  return (&io->io.ao);
+}
+
+static addr_opts *inet_inittargopts(void)
+{
+  inet_targopts *io = CREATE(inet_targopts);
+  *io = inet_globaltarg;
+  return (&io->io.ao);
 }
 
 /* --- @option@ --- */
 
-static int inet_option(scanner *sc, addr_opts *ao)
+static void addropt(scanner *sc, inet_opts *io)
 {
-  inet_opts *io = (inet_opts *)ao;
+  dstr d = DSTR_INIT;
+  struct hostent *h;
 
-  CONF_BEGIN(sc, "inet", "Internet socket")
+  token(sc);
+  if (sc->t == '=')
+    token(sc);
+  if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "any") == 0)
+    io->bind.s_addr = INADDR_ANY;
+  else {
+    conf_name(sc, '.', &d);
+    if ((h = gethostbyname(d.buf)) == 0)
+      error(sc, "couldn't resolve address `%s'", d.buf);
+    memcpy(&io->bind, h->h_addr, sizeof(struct in_addr));
+  }
+}
 
+static int srcopt(scanner *sc, addr_opts *ao)
+{
+  inet_srcopts *io = (inet_srcopts *)ao;
   unsigned act;
 
+  CONF_BEGIN(sc, "source", "Internet socket source")
+
+  /* --- Initialization --- */
+
+  if (!io) {
+    if (!inet_globalsrc.acltail)
+      inet_globalsrc.acltail = &inet_globalsrc.acl;
+    io = &inet_globalsrc;
+  }
+
+  /* --- Source address configuration --- */
+
+  if (strcmp(sc->d.buf, "addr") == 0) {
+    addropt(sc, &io->io);
+    CONF_ACCEPT;
+  }
+
   /* --- Access control limitations --- */
 
   if ((strcmp(sc->d.buf, "allow") == 0 && (act = ACL_ALLOW, 1)) ||
@@ -195,50 +255,61 @@ static int inet_option(scanner *sc, addr_opts *ao)
     struct in_addr a, m;
     dstr d = DSTR_INIT;
 
-    /* --- Find the host or network address --- */
+    /* --- Find out what's going on --- */
 
     token(sc);
     if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "from") == 0)
       token(sc);
-    conf_name(sc, '.', &d);
-#ifdef HAVE_GETNETBYNAME
-    if ((n = getnetbyname(d.buf)) != 0)
-      a.s_addr = htonl(n->n_net);
-    else
-#endif
-    if ((h = gethostbyname(d.buf)) == 0)
-      error(sc, "couldn't resolve address `%s'", d.buf);
-    else
-      memcpy(&a, h->h_addr, sizeof(struct in_addr));
-
-    /* --- Find the netmask, if any --- */
 
-    if (sc->t != '/')
-      m.s_addr = ~0ul;
-    else {
+    if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "priv-port") == 0) {
+      acl_addpriv(&io->acltail, act);
       token(sc);
-      DRESET(&d);
+    } else {
+      if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "host") == 0)
+       token(sc);
+
+      /* --- Find the host or network address --- */
+
       conf_name(sc, '.', &d);
-      if (strchr(d.buf, '.') == 0) {
-       int n = atoi(d.buf);
-       if (n == 0)
-         m.s_addr = 0;
+#ifdef HAVE_GETNETBYNAME
+      if ((n = getnetbyname(d.buf)) != 0)
+       a.s_addr = htonl(n->n_net);
+      else
+#endif
+       if ((h = gethostbyname(d.buf)) == 0)
+         error(sc, "couldn't resolve address `%s'", d.buf);
        else
-         m.s_addr = htonl((~0ul << (32 - n)) & 0xffffffff);
-      } else {
+         memcpy(&a, h->h_addr, sizeof(struct in_addr));
+
+      /* --- Find the netmask, if any --- */
+
+      if (sc->t != '/')
+       m.s_addr = ~0ul;
+      else {
+       token(sc);
+       DRESET(&d);
+       conf_name(sc, '.', &d);
+       if (strchr(d.buf, '.') == 0) {
+         int n = atoi(d.buf);
+         if (n == 0)
+           m.s_addr = 0;
+         else
+           m.s_addr = htonl((~0ul << (32 - n)) & 0xffffffff);
+       } else {
 #ifdef HAVE_INET_ATON
-       if (!inet_aton(d.buf, &m))
-         error(sc, "bad netmask `%s'", d.buf);
+         if (!inet_aton(d.buf, &m))
+           error(sc, "bad netmask `%s'", d.buf);
 #else
-       m.s_addr = inet_addr(d.buf);
+         m.s_addr = inet_addr(d.buf);
 #endif
+       }
       }
-    }
-    dstr_destroy(&d);
+      dstr_destroy(&d);
 
-    /* --- Add the access control entry --- */
+      /* --- Add the access control entry --- */
 
-    acl_add(io ? &io->acltail : 0, act, a, m);
+      acl_addhost(&io->acltail, act, a, m);
+    }
     CONF_ACCEPT;
   }
 
@@ -247,14 +318,78 @@ static int inet_option(scanner *sc, addr_opts *ao)
   CONF_END;
 }
 
+static int targopt(scanner *sc, addr_opts *ao)
+{
+  inet_targopts *io = (inet_targopts *)ao;
+
+  CONF_BEGIN(sc, "dest", "Internet socket target");
+  if (strcmp(sc->d.buf, "addr") == 0) {
+    addropt(sc, &io->io);
+    CONF_ACCEPT;
+  }
+  CONF_END;
+}
+
+static int inet_option(scanner *sc, addr_opts *ao, unsigned type)
+{
+  CONF_BEGIN(sc, "inet", "Internet socket");
+  if (type != ADDR_DEST && srcopt(sc, ao))
+    CONF_ACCEPT;
+  if (type != ADDR_SRC && targopt(sc, ao))
+    CONF_ACCEPT;
+  CONF_END;
+}
+
+/* --- @freeopts@ --- */
+
+static void inet_freesrcopts(addr_opts *ao)
+{
+  inet_srcopts *io = (inet_srcopts *)ao;
+  acl_free(io->acl);
+  DESTROY(io);
+}
+
+static void inet_freetargopts(addr_opts *ao)
+{
+  inet_targopts *io = (inet_targopts *)ao;
+  DESTROY(io);
+}
+
+/* --- @bind@ --- */
+
+static int inet_bind(addr *a, addr_opts *ao)
+{
+  inet_addrx *ia = (inet_addrx *)a;
+  inet_srcopts *io = (inet_srcopts *)ao;
+  struct sockaddr_in sin;
+  int opt = 1;
+  int fd;
+
+  if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+    goto fail_0;
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+  sin = ia->sin;
+  sin.sin_addr = io->io.bind;
+  if (bind(fd, (struct sockaddr *)&sin, sizeof(ia->sin)))
+    goto fail_1;
+  return (fd);
+
+fail_1:
+  close(fd);
+fail_0:
+  return (-1);
+}
+
 /* --- @accept@ --- */
 
 static reffd *inet_accept(int fd, addr_opts *ao, const char *desc)
 {
-  inet_opts *io = (inet_opts *)ao;
+  inet_srcopts *io = (inet_srcopts *)ao;
   int nfd;
   id_req q;
   size_t lsinsz = sizeof(q.lsin), rsinsz = sizeof(q.rsin);
+  int act = ACL_ALLOW;
 
   /* --- Accept the new connection --- */
 
@@ -269,9 +404,12 @@ static reffd *inet_accept(int fd, addr_opts *ao, const char *desc)
 
   /* --- Find out whether this connection is allowed --- */
 
-  if (!acl_check(io->acl, q.rsin.sin_addr)) {
+  if (!acl_check(io->acl, q.rsin.sin_addr, ntohs(q.rsin.sin_port), &act))
+    acl_check(inet_globalsrc.acl, q.rsin.sin_addr,
+             ntohs(q.rsin.sin_port), &act);
+  if (act != ACL_ALLOW) {
     q.act = "refused";
-    if (!(io->ao.f & ADDRF_NOLOG))
+    if (!(io->io.ao.f & ADDRF_NOLOG))
       identify(&q);
     REFFD_DEC(q.r);
     return (0);
@@ -280,26 +418,48 @@ static reffd *inet_accept(int fd, addr_opts *ao, const char *desc)
   /* --- Everything seems to be OK --- */
 
   q.act = "accepted";
-  if (!(io->ao.f & ADDRF_NOLOG))
+  if (!(io->io.ao.f & ADDRF_NOLOG))
     identify(&q);
   return (q.r);
 }
 
-/* --- @freeopts@ --- */
+/* --- @connect@ --- */
 
-static void inet_freeopts(addr_opts *ao)
+static int inet_connect(addr *a, addr_opts *ao, conn *c, endpt *e)
 {
-  inet_opts *io = (inet_opts *)ao;
-  acl_free(io->acl);
-  DESTROY(ao);
+  inet_addrx *ia = (inet_addrx *)a;
+  inet_targopts *io = (inet_targopts *)ao;
+  int fd;
+
+  if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+    goto fail_0;
+  if (io->io.bind.s_addr != INADDR_ANY) {
+    struct sockaddr_in sin;
+    memset(&sin, 0, sizeof(sin));
+    sin.sin_family = AF_INET;
+    sin.sin_addr = io->io.bind;
+    sin.sin_port = 0;
+    if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)))
+      goto fail_1;
+  }
+  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+  return (conn_init(c, sel, fd, (struct sockaddr *)&ia->sin, sizeof(ia->sin),
+                   starget_connected, e));
+fail_1:
+  close(fd);
+fail_0:
+  return (-1);
 }
 
 /* --- Ops table --- */
 
 addr_ops inet_ops = {
-  "inet", PF_INET,
+  "inet",
   inet_read, inet_destroy, inet_print,
-  inet_initopts, inet_option, inet_accept, inet_freeopts, 0, 0
+  inet_initsrcopts, inet_option, inet_freesrcopts,
+  inet_bind, 0, inet_accept,
+  inet_inittargopts, inet_freetargopts,
+  inet_connect  
 };
 
 /*----- That's all, folks -------------------------------------------------*/
index 87b3d96..5f1a731 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: socket.c,v 1.9 2002/02/23 00:08:00 mdw Exp $
+ * $Id: socket.c,v 1.10 2003/11/25 14:08:23 mdw Exp $
  *
  * Socket source and target definitions
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: socket.c,v $
+ * Revision 1.10  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.9  2002/02/23 00:08:00  mdw
  * Fix stupid bugs from the listen(2) change.
  *
@@ -153,7 +156,7 @@ static addr_ops *addrs[] = { &inet_ops, &un_ops, 0 };
 
 /*----- Other persistent variables ----------------------------------------*/
 
-static addr_opts gao = { 0 };
+static addr_opts gsao = { 0 }, gtao = { 0 };
 
 /*----- Parsing address types ---------------------------------------------*/
 
@@ -269,7 +272,7 @@ static void stept_close(endpt *e)
   DESTROY(ee);
 }
 
-/* --- @stept_go@ --- *
+/* --- @starget_connected@ --- *
  *
  * Arguments:  @int fd@ = file descriptor now ready for use
  *             @void *p@ = pointer to an endpoint structure
@@ -279,7 +282,7 @@ static void stept_close(endpt *e)
  * Use:                Handles successful connection of the target endpoint.
  */
 
-static void stept_go(int fd, void *p)
+void starget_connected(int fd, void *p)
 {
   stept *e = p;
 
@@ -288,7 +291,10 @@ static void stept_go(int fd, void *p)
     endpt_kill(&e->e);
   } else {
     reffd *r = reffd_init(fd);
+    int opt = 1;
     REFFD_INC(r);
+    fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+    setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
     e->e.in = e->e.out = r;
     e->e.f &= ~EPF_PENDING;
     if (e->e.other)
@@ -315,7 +321,7 @@ static int ssource_option(source *s, scanner *sc)
   ssource *ss = (ssource *)s;
   ssource_opts *sso = ss ? &ss->o : &ssgo;
 
-  CONF_BEGIN(sc, "socket", "socket")
+  CONF_BEGIN(sc, "socket", "socket source")
 
   /* --- Make sure the next token is a word --- */
 
@@ -360,7 +366,7 @@ static int ssource_option(source *s, scanner *sc)
 
   if (strcmp(sc->d.buf, "logging") == 0 ||
       strcmp(sc->d.buf, "log") == 0) {
-    addr_opts *ao = ss ? ss->ao : &gao;
+    addr_opts *ao = ss ? ss->ao : &gsao;
     token(sc);
     if (sc->t == '=')
       token(sc);
@@ -374,12 +380,12 @@ static int ssource_option(source *s, scanner *sc)
   /* --- Pass the option around the various address types --- */
 
   if (ss) {
-    if (ss->a->ops->option && ss->a->ops->option(sc, ss ? ss->ao : 0))
+    if (ss->a->ops->option && ss->a->ops->option(sc, ss->ao, ADDR_SRC))
       CONF_ACCEPT;
   } else {
     addr_ops **a;
     for (a = addrs; *a; a++) {
-      if ((*a)->option && (*a)->option(sc, 0))
+      if ((*a)->option && (*a)->option(sc, 0, ADDR_GLOBAL))
        CONF_ACCEPT;
     }
   }
@@ -401,11 +407,11 @@ static source *ssource_read(scanner *sc)
   ss->s.desc = 0;
   ss->t = 0;
   ss->a = getaddr(sc, ADDR_SRC);
-  if (ss->a->ops->initopts)
-    ss->ao = ss->a->ops->initopts();
+  if (ss->a->ops->initsrcopts)
+    ss->ao = ss->a->ops->initsrcopts();
   else
     ss->ao = CREATE(addr_opts);
-  *ss->ao = gao;
+  *ss->ao = gsao;
   ss->o = ssgo;
   return (&ss->s);
 }
@@ -506,39 +512,24 @@ static void ss_accept(int fd, unsigned mode, void *p)
 
 static void ss_listen(ssource *ss)
 {
-  gen_addr *ga = (gen_addr *)ss->a;
   int fd;
+  int opt = 1;
 
   if (!(ss->ao->f & ADDRF_NOLOG))
     fw_log(-1, "[%s] reattaching listener", ss->s.desc);
 
   /* --- Make the socket --- */
 
-  if ((fd = socket(ga->a.ops->pf, SOCK_STREAM, 0)) < 0) {
+  if ((fd = ss->a->ops->bind(ss->a, ss->ao)) < 0) {
     fw_log(-1, "[%s] couldn't create socket: %s",
           ss->s.desc, strerror(errno));
     goto fail_0;
   }
 
-  /* --- Set it to allow address reuse --- */
-
-  {
-    int opt = 1;
-    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
-    fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
-  }
-
-  /* --- Bind it to the right port --- */
-
-  if (bind(fd, &ga->sa, ga->a.sz)) {
-    fw_log(-1, "[%s] couldn't bind socket: %s", ss->s.desc, strerror(errno));
-    goto fail_1;
-  }
-  if (ga->a.ops->bound)
-    ga->a.ops->bound(&ga->a, ss->ao);
-
   /* --- Set it to listen for connections --- */
 
+  setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
+  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
   if (listen(fd, ss->o.listen)) {
     fw_log(-1, "[%s] couldn't listen on socket: %s",
           ss->s.desc, strerror(errno));
@@ -569,6 +560,7 @@ static void ssource_attach(source *s, scanner *sc, target *t)
 {
   ssource *ss = (ssource *)s;
   int fd;
+  int opt = 1;
 
   ss->t = t;
 
@@ -586,33 +578,16 @@ static void ssource_attach(source *s, scanner *sc, target *t)
 
   /* --- Initialize the socket for listening --- */
 
-  {
-    gen_addr *ga = (gen_addr *)ss->a;
-
-    /* --- Make the socket --- */
-
-    if ((fd = socket(ga->a.ops->pf, SOCK_STREAM, 0)) < 0)
-      error(sc, "couldn't create socket: %s", strerror(errno));
-
-    /* --- Set it to allow address reuse --- */
+  if ((fd = ss->a->ops->bind(ss->a, ss->ao)) < 0)
+    error(sc, "couldn't bind socket `%s': %s", ss->s.desc, strerror(errno));
 
-    {
-      int opt = 1;
-      setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
-      fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
-    }
-
-    /* --- Bind it to the right port --- */
-
-    if (bind(fd, &ga->sa, ga->a.sz))
-      error(sc, "couldn't bind to %s: %s", ss->s.desc, strerror(errno));
-    if (ga->a.ops->bound)
-      ga->a.ops->bound(&ga->a, ss->ao);
-
-    /* --- Set it to listen for connections --- */
+  /* --- Set it to listen for connections --- */
 
-    if (listen(fd, ss->o.listen))
-      error(sc, "couldn't listen on socket: %s", strerror(errno));
+  setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
+  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+  if (listen(fd, ss->o.listen)) {
+    error(sc, "couldn't listen on socket `%s': %s",
+         ss->s.desc, strerror(errno));
   }
 
   /* --- We're ready to go now --- */
@@ -635,8 +610,8 @@ static void ssource_destroy(source *s)
     if (ss->a->ops->unbind)
       ss->a->ops->unbind(ss->a);
   }
-  if (ss->a->ops->freeopts)
-    ss->a->ops->freeopts(ss->ao);
+  if (ss->a->ops->freesrcopts)
+    ss->a->ops->freesrcopts(ss->ao);
   else
     DESTROY(ss->ao);
   xfree(ss->s.desc);
@@ -656,6 +631,27 @@ source_ops ssource_ops = {
 
 /*----- Target definition -------------------------------------------------*/
 
+/* --- @options@ --- */
+
+static int starget_option(target *t, scanner *sc)
+{
+  starget *st = (starget *)t;
+
+  CONF_BEGIN(sc, "starget", "socket target")
+
+  /* --- Pass the option around the various address types --- */
+
+  if (st) {
+    if (st->a->ops->option && st->a->ops->option(sc, st->ao, ADDR_DEST))
+      CONF_ACCEPT;
+  }
+  /* We'd have done it already if it was global */
+
+  /* --- Done --- */
+
+  CONF_END;
+}
+
 /* --- @read@ --- */
 
 static target *starget_read(scanner *sc)
@@ -667,6 +663,11 @@ static target *starget_read(scanner *sc)
   st = CREATE(starget);
   st->t.ops = &starget_ops;
   st->a = getaddr(sc, ADDR_DEST);
+  if (st->a->ops->inittargopts)
+    st->ao = st->a->ops->inittargopts();
+  else
+    st->ao = CREATE(addr_opts);
+  *st->ao = gtao;
   dstr_puts(&d, "socket.");
   st->a->ops->print(st->a, ADDR_DEST, &d);
   st->t.desc = xstrdup(d.buf);
@@ -688,22 +689,14 @@ static endpt *starget_create(target *t, const char *desc)
 {
   starget *st = (starget *)t;
   stept *e = CREATE(stept);
-  int fd;
-  gen_addr *ga = (gen_addr *)st->a;
-  int opt;
 
-  if ((fd = socket(st->a->ops->pf, SOCK_STREAM, 0)) < 0)
-    return (0);
-  setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
-  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
   e->e.ops = &stept_ops;
   e->e.other = 0;
   e->e.f = EPF_FILE | EPF_PENDING;
   e->e.t = 0;
   e->desc = xstrdup(desc);
-
-  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));
+  if (st->a->ops->connect(st->a, st->ao, &e->c, &e->e)) {
+    fw_log(-1, "[%s] couldn't connect: %s", e->desc, strerror(errno));
     DESTROY(e);
     return (0);
   }
@@ -716,6 +709,10 @@ static endpt *starget_create(target *t, const char *desc)
 static void starget_destroy(target *t)
 {
   starget *st = (starget *)t;
+  if (st->a->ops->freetargopts)
+    st->a->ops->freetargopts(st->ao);
+  else
+    DESTROY(st->ao);
   st->a->ops->destroy(st->a);
   xfree(st->t.desc);
   DESTROY(st);
@@ -725,7 +722,7 @@ static void starget_destroy(target *t)
 
 target_ops starget_ops = {
   "socket",
-  0, starget_read, starget_create, starget_destroy
+  starget_option, starget_read, starget_create, starget_destroy
 };
 
 /*----- That's all, folks -------------------------------------------------*/
index b64bd5e..e85d455 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: socket.h,v 1.1 1999/07/26 23:33:32 mdw Exp $
+ * $Id: socket.h,v 1.2 2003/11/25 14:08:23 mdw Exp $
  *
  * Socket source and target definitions
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: socket.h,v $
+ * Revision 1.2  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.1  1999/07/26 23:33:32  mdw
  * New sources and targets.
  *
 extern source_ops ssource_ops;
 extern target_ops starget_ops;
 
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @starget_connected@ --- *
+ *
+ * Arguments:  @int fd@ = file descriptor now ready for use
+ *             @void *p@ = pointer to an endpoint structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Handles successful connection of the target endpoint.
+ */
+
+extern void starget_connected(int /*fd*/, void */*p*/);
+
 /*----- That's all, folks -------------------------------------------------*/
 
 #ifdef __cplusplus
index 5077c39..862527a 100644 (file)
--- a/target.h
+++ b/target.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: target.h,v 1.1 1999/07/26 23:33:01 mdw Exp $
+ * $Id: target.h,v 1.2 2003/11/25 14:08:23 mdw Exp $
  *
  * Description of forwarding targets
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: target.h,v $
+ * Revision 1.2  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.1  1999/07/26 23:33:01  mdw
  * Infrastructure for the new design.
  *
@@ -69,8 +72,8 @@ typedef struct target_ops {
 
   /* --- @option@ --- *
    *
-   * Arguments:        @scanner *sc@ = scanner to read from
-   *           @target *t@ = pointer to target object, or zero if global
+   * Arguments:        @target *t@ = pointer to target object, or zero if global
+   *           @scanner *sc@ = scanner to read from
    *
    * Returns:  Nonzero to claim the option.
    *
diff --git a/un.c b/un.c
index e120f95..e415256 100644 (file)
--- a/un.c
+++ b/un.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: un.c,v 1.5 2002/02/22 23:43:32 mdw Exp $
+ * $Id: un.c,v 1.6 2003/11/25 14:08:23 mdw Exp $
  *
  * Protocol specific definitions for Unix-domain sockets
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: un.c,v $
+ * Revision 1.6  2003/11/25 14:08:23  mdw
+ * Debianization.  Socket target options.  Internet binding.
+ *
  * Revision 1.5  2002/02/22 23:43:32  mdw
  * Call @xfree@ rather than @free@.
  *
@@ -77,6 +80,7 @@
 #include "fw.h"
 #include "reffd.h"
 #include "scan.h"
+#include "socket.h"
 #include "un.h"
 
 /*----- Data structures ---------------------------------------------------*/
@@ -141,7 +145,7 @@ static addr_opts *un_initopts(void)
 
 /* --- @option@ --- */
 
-static int un_option(scanner *sc, addr_opts *ao)
+static int srcopt(scanner *sc, addr_opts *ao)
 {
   un_opts *uo = (un_opts *)ao;
   CONF_BEGIN(sc, "unix", "Unix domain socket")
@@ -152,6 +156,14 @@ static int un_option(scanner *sc, addr_opts *ao)
   CONF_END;
 }
 
+static int un_option(scanner *sc, addr_opts *ao, unsigned type)
+{
+  CONF_BEGIN(sc, "unix", "Unix domain socket");
+  if (type != ADDR_DEST && srcopt(sc, ao))
+    CONF_ACCEPT;
+  CONF_END;
+}
+
 /* --- @accept@ --- */
 
 static reffd *un_accept(int fd, addr_opts *ao, const char *desc)
@@ -189,19 +201,26 @@ static void un_freeopts(addr_opts *ao)
   DESTROY(uo);
 }
 
-/* --- @bound@ --- */
+/* --- @bind@ --- */
 
-static void un_bound(addr *a, addr_opts *ao)
+static int un_bind(addr *a, addr_opts *ao)
 {
   un_addr *ua = (un_addr *)a;
   un_opts *uo = (un_opts *)ao;
-  if (fattr_apply(ua->sun.sun_path, &uo->f)) {
-    dstr d = DSTR_INIT;
-    un_print(a, ADDR_SRC, &d);
-    fw_log(-1, "[%s] couldn't apply file attributes: %s",
-          d.buf, strerror(errno));
-    dstr_destroy(&d);
-  }
+  int fd;
+
+  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+    goto fail_0;
+  if (bind(fd, (struct sockaddr *)&ua->sun, sizeof(ua->sun)))
+    goto fail_1;
+  if (fattr_apply(ua->sun.sun_path, &uo->f))
+    goto fail_1;
+  return (fd);
+
+fail_1:
+  close(fd);
+fail_0:
+  return (-1);
 }
 
 /* --- @unbind@ --- */
@@ -212,12 +231,28 @@ static void un_unbind(addr *a)
   unlink(ua->sun.sun_path);
 }
 
+/* --- @connect@ --- */
+
+static int un_connect(addr *a, addr_opts *ao, conn *c, endpt *e)
+{
+  un_addr *ua = (un_addr *)a;
+  int fd;
+
+  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+    goto fail_0;
+  return (conn_init(c, sel, fd, (struct sockaddr *)&ua->sun, sizeof(ua->sun),
+                   starget_connected, e));
+fail_0:
+  return (-1);
+}
+
 /* --- Protocol definition --- */
 
 addr_ops un_ops = {
-  "unix", PF_UNIX,
+  "unix",
   un_read, un_destroy, un_print,
-  un_initopts, un_option, un_accept, un_freeopts, un_bound, un_unbind
+  un_initopts, un_option, un_freeopts, un_bind, un_unbind, un_accept,
+  0, 0, un_connect
 };
 
 /*----- That's all, folks -------------------------------------------------*/