* scripts/amd.conf.5, doc/am-utils.texi (preferred_amq_port):
authorErez Zadok <ezk@cs.sunysb.edu>
Wed, 23 Feb 2005 03:59:08 +0000 (03:59 +0000)
committerErez Zadok <ezk@cs.sunysb.edu>
Wed, 23 Feb 2005 03:59:08 +0000 (03:59 +0000)
document new preferred_amq_port [global] option.

* scripts/amd.conf-sample (preferred_amq_port): example.

* include/am_utils.h: add preferred_amq_port to prototype.

* conf/transp/transp_tli.c (bind_preferred_amq_port): new function
to bind the Amq RPC service for UDP and TCP to a preferred port
(or to any port if preferred_amq_port==0).
(create_amq_service): decide if to bind to RPC_ANYFD, or to a
requested port.

* conf/transp/transp_sockets.c (create_amq_service): if
preferred_amq_port is greater than 0, then bind to that port for
both UDP and TCP.  If preferred_amq_port==0, then bind to any
port.

* amd/nfs_start.c (mount_automounter): pass global
preferred_amq_port value to create_amq_service().

* amd/conf.c (gopt_preferred_amq_port): new function to parse
amd.conf value for preferred_amq_port.

* amd/amd.h: placeholder for preferred_amq_port.

* conf/transp/transp_tli.c (bind_resv_port_only_udp): rename old
bindnfs_port to a more proper name.  This function binds the NFS
service to a specified port, and only for UDP.

* conf/transp/transp_tli.c: cleanup some code, rename some
functions, in preparation for RPC amq port specification code.

ChangeLog
NEWS
amd/amd.h
amd/conf.c
amd/nfs_start.c
conf/transp/transp_sockets.c
conf/transp/transp_tli.c
doc/am-utils.texi
include/am_utils.h
scripts/amd.conf-sample
scripts/amd.conf.5

index ff256de1932daa83056e024f59f7f7eb25e64fd3..0f34858603f49e05e4ac51fac705edc62a1136f3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2005-02-22  Erez Zadok  <ezk@cs.sunysb.edu>
+
+       * scripts/amd.conf.5, doc/am-utils.texi (preferred_amq_port):
+       document new preferred_amq_port [global] option.
+
+       * scripts/amd.conf-sample (preferred_amq_port): example.
+
+       * include/am_utils.h: add preferred_amq_port to prototype.
+
+       * conf/transp/transp_tli.c (bind_preferred_amq_port): new function
+       to bind the Amq RPC service for UDP and TCP to a preferred port
+       (or to any port if preferred_amq_port==0).
+       (create_amq_service): decide if to bind to RPC_ANYFD, or to a
+       requested port.
+
+       * conf/transp/transp_sockets.c (create_amq_service): if
+       preferred_amq_port is greater than 0, then bind to that port for
+       both UDP and TCP.  If preferred_amq_port==0, then bind to any
+       port.
+
+       * amd/nfs_start.c (mount_automounter): pass global
+       preferred_amq_port value to create_amq_service().
+
+       * amd/conf.c (gopt_preferred_amq_port): new function to parse
+       amd.conf value for preferred_amq_port.
+
+       * amd/amd.h: placeholder for preferred_amq_port.
+
+2005-02-21  Erez Zadok  <ezk@cs.sunysb.edu>
+
+       * conf/transp/transp_tli.c (bind_resv_port_only_udp): rename old
+       bindnfs_port to a more proper name.  This function binds the NFS
+       service to a specified port, and only for UDP.
+
+       * conf/transp/transp_tli.c: cleanup some code, rename some
+       functions, in preparation for RPC amq port specification code.
+
 2005-02-19  Erez Zadok  <ezk@cs.sunysb.edu>
 
        * */Makefile.am: don't redefine CFLAGS or LDFLAGS; they are
diff --git a/NEWS b/NEWS
index 509431179bfd68e7a8b7927f78daa350bc25579f..55c6bd329dd6f7e9e3a655618b7fddc89cc31d32 100644 (file)
--- a/NEWS
+++ b/NEWS
   nfs_retry_interval_udp, nfs_retransmit_counter_udp nfs_retry_interval_tcp,
   and nfs_retransmit_counter_tcp.
 
+- new amd.conf [global] parameter: preferred_amq_port.  Allows you to select
+  the UDP+TCP port that Amd's amq service will use with the RPC portmapper.
+  Useful with firewalls and NAT'ed environments.
+
 - new function selector xhost(ARG) which will match ARG against the current
   host name.  This works even if ARG is a CNAME (unlike the host==ARG
   selector).
index 0e163a5b715a92e6fe4367ae565b5ea94a2b20ec..0a07ac703107b0e03e80439373fa9b8a9919162d 100644 (file)
--- a/amd/amd.h
+++ b/amd/amd.h
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amd.h,v 1.57 2005/02/17 21:32:05 ezk Exp $
+ * $Id: amd.h,v 1.58 2005/02/23 03:59:08 ezk Exp $
  *
  */
 
@@ -270,6 +270,7 @@ struct amu_global_options {
   int am_timeo;                        /* cache duration */
   int am_timeo_w;              /* dismount interval */
   u_long portmap_program;      /* amd RPC program number */
+  u_short preferred_amq_port;  /* preferred amq service RPC port number (0 means "any") */
 #ifdef HAVE_MAP_HESIOD
   char *hesiod_base;           /* Hesiod rhs */
 #endif /* HAVE_MAP_HESIOD */
index 54d337106c4beb790f78b882fc28f8a3fb15301d..23e513a52a88a77adfda245d21235d4265618b6a 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: conf.c,v 1.28 2005/02/17 21:32:05 ezk Exp $
+ * $Id: conf.c,v 1.29 2005/02/23 03:59:08 ezk Exp $
  *
  */
 
@@ -104,6 +104,7 @@ static int gopt_map_type(const char *val);
 static int gopt_mount_type(const char *val);
 static int gopt_pid_file(const char *val);
 static int gopt_portmap_program(const char *val);
+static int gopt_preferred_amq_port(const char *val);
 static int gopt_nfs_allow_insecure_port(const char *val);
 static int gopt_nfs_proto(const char *val);
 static int gopt_nfs_retransmit_counter(const char *val);
@@ -177,6 +178,7 @@ static struct _func_map glob_functable[] = {
   {"mount_type",               gopt_mount_type},
   {"pid_file",                 gopt_pid_file},
   {"portmap_program",          gopt_portmap_program},
+  {"preferred_amq_port",       gopt_preferred_amq_port},
   {"nfs_allow_insecure_port",  gopt_nfs_allow_insecure_port},
   {"nfs_proto",                        gopt_nfs_proto},
   {"nfs_retransmit_counter",   gopt_nfs_retransmit_counter},
@@ -736,6 +738,19 @@ gopt_portmap_program(const char *val)
 }
 
 
+static int
+gopt_preferred_amq_port(const char *val)
+{
+  gopt.preferred_amq_port = atoi(val);
+
+  /*
+   * No need to check value: preferred_amq_port is an unsigned short and 0
+   * is a valid number, meaning "any port".
+   */
+  return 0;                    /* all is OK */
+}
+
+
 static int
 gopt_nfs_allow_insecure_port(const char *val)
 {
index 61fe39eed91a9d5f6cd6e2769f00781a173a9a29..7af406c48130f6b4a31f8aafeb1d070fa724bd94 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: nfs_start.c,v 1.23 2005/01/18 03:01:24 ib42 Exp $
+ * $Id: nfs_start.c,v 1.24 2005/02/23 03:59:08 ezk Exp $
  *
  */
 
@@ -377,7 +377,13 @@ mount_automounter(int ppid)
 
   /* security: if user sets -D amq, don't even create listening socket */
   if (!amuDebug(D_AMQ)) {
-    ret = create_amq_service(&udp_soAMQ, &udp_amqp, &udp_amqncp, &tcp_soAMQ, &tcp_amqp, &tcp_amqncp);
+    ret = create_amq_service(&udp_soAMQ,
+                            &udp_amqp,
+                            &udp_amqncp,
+                            &tcp_soAMQ,
+                            &tcp_amqp,
+                            &tcp_amqncp,
+                            gopt.preferred_amq_port);
     if (ret != 0)
       return ret;
   }
index ab260b4b335d4ce3b740a423d78b551c97b9d8b2..09885e3d79d5459bd5b2ea5ba874d26e4d39b306 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: transp_sockets.c,v 1.31 2005/01/18 03:01:24 ib42 Exp $
+ * $Id: transp_sockets.c,v 1.32 2005/02/23 03:59:08 ezk Exp $
  *
  * Socket specific utilities.
  *      -Erez Zadok <ezk@cs.columbia.edu>
@@ -118,6 +118,7 @@ amu_get_myaddress(struct in_addr *iap, const char *preferred_localhost)
 
 /*
  * How to bind to reserved ports.
+ * Note: if *pp is non-null and is greater than 0, then *pp will not be modified.
  */
 int
 bind_resv_port(int so, u_short *pp)
@@ -287,9 +288,13 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
  * Create the amq service for amd (both TCP and UDP)
  */
 int
-create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp,
-                  struct netconfig **dummy1, int *tcp_soAMQp,
-                  SVCXPRT **tcp_amqpp, struct netconfig **dummy2)
+create_amq_service(int *udp_soAMQp,
+                  SVCXPRT **udp_amqpp,
+                  struct netconfig **dummy1,
+                  int *tcp_soAMQp,
+                  SVCXPRT **tcp_amqpp,
+                  struct netconfig **dummy2,
+                  u_short preferred_amq_port)
 {
   /* first create TCP service */
   if (tcp_soAMQp) {
@@ -299,11 +304,25 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp,
       return 1;
     }
 
+    /* next, bind to a specific (TCP) port if asked for */
+    if (preferred_amq_port > 0) {
+      /*
+       * Note: if &preferred_amq_port is non-null and is greater than 0,
+       * then the pointer will not be modified.  We don't want it to be
+       * modified because it was passed down to create_amq_service as a
+       * non-pointer (a variable on the stack, not to be modified!)
+       */
+      if (bind_resv_port(*tcp_soAMQp, &preferred_amq_port) < 0) {
+       plog(XLOG_FATAL, "can't bind amq service to requested TCP port %d: %m)", preferred_amq_port);
+       return 1;
+      }
+    }
+
     /* now create RPC service handle for amq */
     if (tcp_amqpp &&
        (*tcp_amqpp = svctcp_create(*tcp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
       plog(XLOG_FATAL, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp);
-      return 2;
+      return 1;
     }
 
 #ifdef SVCSET_CONNMAXREC
@@ -327,14 +346,26 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp,
     *udp_soAMQp = socket(AF_INET, SOCK_DGRAM, 0);
     if (*udp_soAMQp < 0) {
       plog(XLOG_FATAL, "cannot create udp socket for amq service: %m");
-      return 3;
+      return 1;
+    }
+
+    /* next, bind to a specific (UDP) port if asked for */
+    if (preferred_amq_port > 0) {
+      /*
+       * Note: see comment about using &preferred_amq_port above in this
+       * function.
+       */
+      if (bind_resv_port(*udp_soAMQp, &preferred_amq_port) < 0) {
+       plog(XLOG_FATAL, "can't bind amq service to requested UDP port %d: %m)", preferred_amq_port);
+       return 1;
+      }
     }
 
     /* now create RPC service handle for amq */
     if (udp_amqpp &&
        (*udp_amqpp = svcudp_bufcreate(*udp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
       plog(XLOG_FATAL, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp);
-      return 4;
+      return 1;
     }
   }
 
index 565e1a539f1e559be342560921999e544d914bd9..d1a1b4513506e17c1d59b9981da2601b205c09d3 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: transp_tli.c,v 1.27 2005/02/22 01:33:37 ezk Exp $
+ * $Id: transp_tli.c,v 1.28 2005/02/23 03:59:08 ezk Exp $
  *
  * TLI specific utilities.
  *      -Erez Zadok <ezk@cs.columbia.edu>
@@ -119,7 +119,7 @@ bind_resv_port(int td, u_short *pp)
   memset((char *) treq->addr.buf, 0, treq->addr.len);
   sin = (struct sockaddr_in *) treq->addr.buf;
   sin->sin_family = AF_INET;
-  treq->qlen = 0;
+  treq->qlen = 0; /* 0 is ok for udp, for tcp you need qlen>0 */
   treq->addr.len = treq->addr.maxlen;
   errno = EADDRINUSE;
   port = IPPORT_RESERVED;
@@ -150,101 +150,6 @@ bind_resv_port(int td, u_short *pp)
 }
 
 
-/*
- * Bind to reserved UDP port, for NFS service only.
- * Port-only version.
- */
-static int
-bind_resv_port_only_udp(u_short *pp)
-{
-  int td, rc = -1, port;
-  struct t_bind *treq, *tret;
-  struct sockaddr_in *sin;
-  extern char *t_errlist[];
-  extern int t_errno;
-  struct netconfig *nc = (struct netconfig *) NULL;
-  voidp nc_handle;
-
-  if ((nc_handle = setnetconfig()) == (voidp) NULL) {
-    plog(XLOG_ERROR, "Cannot rewind netconfig: %s", nc_sperror());
-    return -1;
-  }
-  /*
-   * Search the netconfig table for INET/UDP.
-   * This loop will terminate if there was an error in the /etc/netconfig
-   * file or if you reached the end of the file without finding the udp
-   * device.  Either way your machine has probably far more problems (for
-   * example, you cannot have nfs v2 w/o UDP).
-   */
-  while (1) {
-    if ((nc = getnetconfig(nc_handle)) == (struct netconfig *) NULL) {
-      plog(XLOG_ERROR, "Error accessing getnetconfig: %s", nc_sperror());
-      endnetconfig(nc_handle);
-      return -1;
-    }
-    if (STREQ(nc->nc_protofmly, NC_INET) &&
-       STREQ(nc->nc_proto, NC_UDP))
-      break;
-  }
-
-  /*
-   * This is the primary reason for the getnetconfig code above: to get the
-   * correct device name to udp, and t_open a descriptor to be used in
-   * t_bind below.
-   */
-  td = t_open(nc->nc_device, O_RDWR, (struct t_info *) 0);
-  endnetconfig(nc_handle);
-
-  if (td < 0) {
-    plog(XLOG_ERROR, "t_open failed: %d: %s", t_errno, t_errlist[t_errno]);
-    return -1;
-  }
-  treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
-  if (!treq) {
-    plog(XLOG_ERROR, "t_alloc req");
-    return -1;
-  }
-  tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
-  if (!tret) {
-    t_free((char *) treq, T_BIND);
-    plog(XLOG_ERROR, "t_alloc ret");
-    return -1;
-  }
-  memset((char *) treq->addr.buf, 0, treq->addr.len);
-  sin = (struct sockaddr_in *) treq->addr.buf;
-  sin->sin_family = AF_INET;
-  treq->qlen = 0;
-  treq->addr.len = treq->addr.maxlen;
-  errno = EADDRINUSE;
-
-  if (pp && *pp > 0) {
-    sin->sin_port = htons(*pp);
-    rc = t_bind(td, treq, tret);
-  } else {
-    port = IPPORT_RESERVED;
-
-    do {
-      --port;
-      sin->sin_port = htons(port);
-      rc = t_bind(td, treq, tret);
-      if (rc < 0) {
-       plog(XLOG_ERROR, "t_bind for port %d: %s", port, t_errlist[t_errno]);
-      } else {
-       if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0)
-         break;
-       else
-         t_unbind(td);
-      }
-    } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2);
-
-    if (pp && rc == 0)
-      *pp = port;
-  }
-
-  t_free((char *) tret, T_BIND);
-  t_free((char *) treq, T_BIND);
-  return rc;
-}
 
 
 /*
@@ -394,6 +299,103 @@ amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, void (*dispatch)
 }
 
 
+/*
+ * Bind to reserved UDP port, for NFS service only.
+ * Port-only version.
+ */
+static int
+bind_resv_port_only_udp(u_short *pp)
+{
+  int td, rc = -1, port;
+  struct t_bind *treq, *tret;
+  struct sockaddr_in *sin;
+  extern char *t_errlist[];
+  extern int t_errno;
+  struct netconfig *nc = (struct netconfig *) NULL;
+  voidp nc_handle;
+
+  if ((nc_handle = setnetconfig()) == (voidp) NULL) {
+    plog(XLOG_ERROR, "Cannot rewind netconfig: %s", nc_sperror());
+    return -1;
+  }
+  /*
+   * Search the netconfig table for INET/UDP.
+   * This loop will terminate if there was an error in the /etc/netconfig
+   * file or if you reached the end of the file without finding the udp
+   * device.  Either way your machine has probably far more problems (for
+   * example, you cannot have nfs v2 w/o UDP).
+   */
+  while (1) {
+    if ((nc = getnetconfig(nc_handle)) == (struct netconfig *) NULL) {
+      plog(XLOG_ERROR, "Error accessing getnetconfig: %s", nc_sperror());
+      endnetconfig(nc_handle);
+      return -1;
+    }
+    if (STREQ(nc->nc_protofmly, NC_INET) &&
+       STREQ(nc->nc_proto, NC_UDP))
+      break;
+  }
+
+  /*
+   * This is the primary reason for the getnetconfig code above: to get the
+   * correct device name to udp, and t_open a descriptor to be used in
+   * t_bind below.
+   */
+  td = t_open(nc->nc_device, O_RDWR, (struct t_info *) 0);
+  endnetconfig(nc_handle);
+
+  if (td < 0) {
+    plog(XLOG_ERROR, "t_open failed: %d: %s", t_errno, t_errlist[t_errno]);
+    return -1;
+  }
+  treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
+  if (!treq) {
+    plog(XLOG_ERROR, "t_alloc req");
+    return -1;
+  }
+  tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
+  if (!tret) {
+    t_free((char *) treq, T_BIND);
+    plog(XLOG_ERROR, "t_alloc ret");
+    return -1;
+  }
+  memset((char *) treq->addr.buf, 0, treq->addr.len);
+  sin = (struct sockaddr_in *) treq->addr.buf;
+  sin->sin_family = AF_INET;
+  treq->qlen = 0; /* 0 is ok for udp, for tcp you need qlen>0 */
+  treq->addr.len = treq->addr.maxlen;
+  errno = EADDRINUSE;
+
+  if (pp && *pp > 0) {
+    sin->sin_port = htons(*pp);
+    rc = t_bind(td, treq, tret);
+  } else {
+    port = IPPORT_RESERVED;
+
+    do {
+      --port;
+      sin->sin_port = htons(port);
+      rc = t_bind(td, treq, tret);
+      if (rc < 0) {
+       plog(XLOG_ERROR, "t_bind for port %d: %s", port, t_errlist[t_errno]);
+      } else {
+       if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0)
+         break;
+       else
+         t_unbind(td);
+      }
+    } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2);
+
+    if (pp && rc == 0)
+      *pp = port;
+  }
+
+  t_free((char *) tret, T_BIND);
+  t_free((char *) treq, T_BIND);
+  return rc;
+}
+
+
 /*
  * Bind NFS to a reserved port.
  */
@@ -456,6 +458,78 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
 }
 
 
+/*
+ * Bind to preferred AMQ port.
+ */
+static int
+bind_preferred_amq_port(u_short pref_port,
+                       const struct netconfig *ncp,
+                       struct t_bind **tretpp)
+{
+  int td = -1, rc = -1;
+  struct t_bind *treq;
+  struct sockaddr_in *sin, *sin2;
+  extern char *t_errlist[];
+  extern int t_errno;
+
+  if (!ncp) {
+    plog(XLOG_ERROR, "null ncp");
+    return -1;
+  }
+
+  td = t_open(ncp->nc_device, O_RDWR, (struct t_info *) 0);
+  if (td < 0) {
+    plog(XLOG_ERROR, "t_open failed: %d: %s", t_errno, t_errlist[t_errno]);
+    return -1;
+  }
+  treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
+  if (!treq) {
+    plog(XLOG_ERROR, "t_alloc req");
+    return -1;
+  }
+  *tretpp = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
+  if (!*tretpp) {
+    t_free((char *) treq, T_BIND);
+    plog(XLOG_ERROR, "t_alloc tretpp");
+    return -1;
+  }
+  memset((char *) treq->addr.buf, 0, treq->addr.len);
+  sin = (struct sockaddr_in *) treq->addr.buf;
+  sin->sin_family = AF_INET;
+  treq->qlen = 64; /* must be greater than 0 to work for TCP connections */
+  treq->addr.len = treq->addr.maxlen;
+
+  if (pref_port > 0) {
+    sin->sin_port = htons(pref_port);
+    sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* XXX: may not be needed */
+    rc = t_bind(td, treq, *tretpp);
+    if (rc < 0) {
+      plog(XLOG_ERROR, "t_bind return err %d", rc);
+      goto out;
+    }
+    /* check if we got the port we asked for */
+    sin2 = (struct sockaddr_in *) (*tretpp)->addr.buf;
+    if (sin->sin_port != sin2->sin_port) {
+      plog(XLOG_ERROR, "asked for port %d, got different one (%d)",
+          ntohs(sin->sin_port), ntohs(sin2->sin_port));
+      t_errno = TNOADDR; /* XXX: is this correct? */
+      rc = -1;
+      goto out;
+    }
+    if (sin->sin_addr.s_addr != sin2->sin_addr.s_addr) {
+      plog(XLOG_ERROR, "asked for address %x, got different one (%x)",
+          (int) ntohl(sin->sin_addr.s_addr), (int) ntohl(sin2->sin_addr.s_addr));
+      t_errno = TNOADDR; /* XXX: is this correct? */
+      rc = -1;
+      goto out;
+    }
+  }
+out:
+  t_free((char *) treq, T_BIND);
+  return (rc < 0 ? rc : td);
+}
+
+
 /*
  * Create the amq service for amd (both TCP and UDP)
  */
@@ -480,8 +554,27 @@ create_amq_service(int *udp_soAMQp,
       plog(XLOG_ERROR, "cannot getnetconfigent for %s", NC_TCP);
       return 1;
     }
+
   if (tcp_amqpp) {
-    *tcp_amqpp = svc_tli_create(RPC_ANYFD, *tcp_amqncpp, NULL, 0, 0);
+    if (preferred_amq_port > 0) {
+      struct t_bind *tbp = NULL;
+      int sock;
+
+      plog(XLOG_INFO, "requesting preferred amq TCP port %d", preferred_amq_port);
+      sock = bind_preferred_amq_port(preferred_amq_port, *tcp_amqncpp, &tbp);
+      if (sock < 0) {
+       plog(XLOG_ERROR, "bind_preferred_amq_port failed for TCP port %d: %s",
+            preferred_amq_port, t_errlist[t_errno]);
+       return 1;
+      }
+      *tcp_amqpp = svc_tli_create(sock, *tcp_amqncpp, tbp, 0, 0);
+      if (*tcp_amqpp != NULL)
+       plog(XLOG_INFO, "amq service bound to TCP port %d", preferred_amq_port);
+      t_free((char *) tbp, T_BIND);
+    } else {
+      /* select any port */
+      *tcp_amqpp = svc_tli_create(RPC_ANYFD, *tcp_amqncpp, NULL, 0, 0);
+    }
     if (*tcp_amqpp == NULL) {
       plog(XLOG_ERROR, "cannot create (tcp) tli service for amq");
       return 1;
@@ -497,7 +590,25 @@ create_amq_service(int *udp_soAMQp,
       return 1;
     }
   if (udp_amqpp) {
-    *udp_amqpp = svc_tli_create(RPC_ANYFD, *udp_amqncpp, NULL, 0, 0);
+    if (preferred_amq_port > 0) {
+      struct t_bind *tbp = NULL;
+      int sock;
+
+      plog(XLOG_INFO, "requesting preferred amq UDP port %d", preferred_amq_port);
+      sock = bind_preferred_amq_port(preferred_amq_port, *udp_amqncpp, &tbp);
+      if (sock < 0) {
+       plog(XLOG_ERROR, "bind_preferred_amq_port failed for UDP port %d: %s",
+            preferred_amq_port, t_errlist[t_errno]);
+       return 1;
+      }
+      *udp_amqpp = svc_tli_create(sock, *udp_amqncpp, tbp, 0, 0);
+      if (*udp_amqpp != NULL)
+       plog(XLOG_INFO, "amq service bound to UDP port %d", preferred_amq_port);
+      t_free((char *) tbp, T_BIND);
+    } else {
+      /* select any port */
+      *udp_amqpp = svc_tli_create(RPC_ANYFD, *udp_amqncpp, NULL, 0, 0);
+    }
     if (*udp_amqpp == NULL) {
       plog(XLOG_ERROR, "cannot create (udp) tli service for amq");
       return 1;
@@ -702,7 +813,11 @@ get_autofs_address(struct netconfig *ncp, struct t_bind *tbp)
   tbp->addr.len = addrs->n_addrs->len;
   tbp->addr.maxlen = addrs->n_addrs->len;
   memcpy(tbp->addr.buf, addrs->n_addrs->buf, addrs->n_addrs->len);
-  tbp->qlen = 8;               /* arbitrary? who cares really */
+  tbp->qlen = 8;               /* arbitrary? who cares really. -ion
+                                  Actually, Ion, I found out that if
+                                  qlen==0, then TCP onnections fail, but UDP
+                                  works. -Erez.
+                                */
 
   /* all OK */
   netdir_free((voidp) addrs, ND_ADDRLIST);
index a7a0988a4583364c625e6cddbb4071e1ee01235f..e50c2e1d8e43c4585531328f04a339434ef44134 100644 (file)
@@ -38,7 +38,7 @@
 @c
 @c      %W% (Berkeley) %G%
 @c
-@c $Id: am-utils.texi,v 1.93 2005/02/17 21:32:05 ezk Exp $
+@c $Id: am-utils.texi,v 1.94 2005/02/23 03:59:09 ezk Exp $
 @c
 @setfilename am-utils.info
 
@@ -4242,6 +4242,7 @@ The following parameters are applicable to the @samp{[global]} section only.
 * pid_file Parameter::
 * plock Parameter::
 * portmap_program Parameter::
+* preferred_amq_port Parameter::
 * print_pid Parameter::
 * print_version Parameter::
 * restart_mounts Parameter::
@@ -4741,7 +4742,7 @@ cost of reserving the memory used by the @i{Amd} process (making it
 unavailable for other processes).
 
 @c ----------------------------------------------------------------
-@node portmap_program Parameter, print_pid Parameter, plock Parameter, Global Parameters
+@node portmap_program Parameter, preferred_amq_port Parameter, plock Parameter, Global Parameters
 @comment  node-name,  next,  previous,  up
 @subsection @t{portmap_program} Parameter
 @cindex portmap_program Parameter
@@ -4757,7 +4758,21 @@ number of an @i{Amd} to contact.  In this way, amq can fully control any
 number of @i{Amd} processes running on the same host.
 
 @c ----------------------------------------------------------------
-@node print_pid Parameter, print_version Parameter, portmap_program Parameter, Global Parameters
+@node preferred_amq_port Parameter, print_pid Parameter, portmap_program Parameter, Global Parameters
+@comment  node-name,  next,  previous,  up
+@subsection @t{preferred_amq_port} Parameter
+@cindex preferred_amq_port Parameter
+
+(type=numeric, default=0).  Specify an alternate Port-mapper RPC port
+number for @i{Amd}'s @i{Amq} service.  This is used for both UDP and
+TCP.  Setting this value to 0 (or not defining it) will cause @i{Amd}
+to select an arbitrary port number.  Setting the @i{Amq} RPC service
+port to a specific number is useful in firewalled or NAT'ed
+environments, where you need to know which port @i{Amd} will listen
+on.
+
+@c ----------------------------------------------------------------
+@node print_pid Parameter, print_version Parameter, preferred_amq_port Parameter, Global Parameters
 @comment  node-name,  next,  previous,  up
 @subsection @t{print_pid} Parameter
 @cindex print_pid Parameter
index 32bee75c3218085198aab9b6888b2de3a2ec7138..f6a2b302e0ccc37dd25d878bdcc7b8c194005500 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: am_utils.h,v 1.59 2005/02/17 21:32:05 ezk Exp $
+ * $Id: am_utils.h,v 1.60 2005/02/23 03:59:09 ezk Exp $
  *
  */
 
@@ -335,7 +335,7 @@ extern int syslogging;
 #endif /* defined(HAVE_SYSLOG_H) || defined(HAVE_SYS_SYSLOG_H) */
 
 extern void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name);
-extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp);
+extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port);
 extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
 extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *);
 
index 65a1b6a88b9bd11f197bc13ddf484d3d74de5a27..b12fa1e7da8115f3193c77f04a0ec3c3ffc2405f 100644 (file)
@@ -86,6 +86,9 @@ autofs_use_lofs =             yes | no
 search_path =                  /etc/local:/etc/amdmaps:/misc/yp
 # alternate RPC program number to register with the port mapper
 portmap_program =              300019-300029
+# Ask for a different Amq RPC port (both UDP and TCP).
+# If set to 0 (default), Amd will pick a port automatically.
+preferred_amq_port =           1234
 # use fully qualified host names
 fully_qualified_hosts =                no | yes
 # force NFS version or NFS protocol
index 6211e7634134479ebafcb2f4b52f04e1b9055a32..097261e78549736e54bf1cba53be398ecda1d51a 100644 (file)
@@ -38,7 +38,7 @@
 .\"
 .\"    %W% (Berkeley) %G%
 .\"
-.\" $Id: amd.conf.5,v 1.32 2005/02/17 21:32:06 ezk Exp $
+.\" $Id: amd.conf.5,v 1.33 2005/02/23 03:59:09 ezk Exp $
 .\"
 .TH AMD.CONF 5 "7 August 1997"
 .SH NAME
@@ -543,6 +543,20 @@ which can be used to specify an alternate program number of an amd to
 contact.  In this way, amq can fully control any number of amd processes
 running on the same host.
 
+.TP
+.BR preferred_amq_port " (numeric, default=0)"
+Specify an alternate Port-mapper RPC port number for Amd's
+.B amq
+service.  This is used for both UDP and TCP.  Setting this value to 0 (or
+not defining it) will cause
+.B amd
+to select an arbitrary port number.  Setting the
+.B amq
+RPC service port to a specific number is useful in firewalled or NAT'ed
+environments, where you need to know which port
+.B amd
+will listen on.
+
 .TP
 .BR print_pid " (boolean, default=no)"
 Same as the