]> git.saurik.com Git - apple/network_cmds.git/commitdiff
network_cmds-176.3.1.tar.gz mac-os-x-1034 v176.3.1
authorApple <opensource@apple.com>
Thu, 22 Apr 2004 22:54:50 +0000 (22:54 +0000)
committerApple <opensource@apple.com>
Thu, 22 Apr 2004 22:54:50 +0000 (22:54 +0000)
18 files changed:
ifconfig.tproj/Makefile
ifconfig.tproj/Makefile.preamble
ifconfig.tproj/PB.project
ifconfig.tproj/ifconfig.8
ifconfig.tproj/ifconfig.c
ifconfig.tproj/ifconfig.h
ifconfig.tproj/ifvlan.c [new file with mode: 0644]
racoon.tproj/crypto_openssl.c
racoon.tproj/crypto_openssl.h
racoon.tproj/isakmp.c
rpc_lockd.tproj/kern.c
rpc_lockd.tproj/lock_proc.c
rpc_lockd.tproj/lockd.c
rpc_lockd.tproj/lockd.h
rpc_lockd.tproj/lockd_lock.c
rpc_lockd.tproj/lockd_lock.h
rpc_lockd.tproj/nlm_prot_svc.c
rpc_lockd.tproj/rpc.lockd.8

index 2ae172df9caf35a62627b3d1a03c118b511b78cf..0f7f623e5f34fdd5b4dc3b0c9255c0afda40ba92 100644 (file)
@@ -14,7 +14,7 @@ PROJECT_TYPE = Tool
 
 HFILES = ifconfig.h
 
-CFILES = ifconfig.c ifmedia.c
+CFILES = ifconfig.c ifmedia.c ifvlan.c
 
 OTHERSRCS = Makefile.preamble Makefile Makefile.dist ifconfig.8\
             Makefile.postamble
@@ -31,6 +31,7 @@ DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
 
+HEADER_PATHS = -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders
 
 
 NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
@@ -49,3 +50,4 @@ include $(MAKEFILEDIR)/$(MAKEFILE)
 -include Makefile.postamble
 
 -include Makefile.dependencies
+
index bf2aff82fd26df862a2b10b008ace8b9baf012d6..7100e374b2fb362aa41876d54a21ac94d1938fbc 100644 (file)
@@ -1,3 +1,3 @@
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
 -include ../Makefile.include
-OTHER_CFLAGS += -DUSE_IF_MEDIA -DINET6 -DNO_IPX
+OTHER_CFLAGS += -DUSE_IF_MEDIA -DINET6 -DNO_IPX -DUSE_VLANS
index e699c93af8ed943302fde44e19f77107b1326b96..e5cc832d7199d35577992c852d3ec4df9775dcde 100644 (file)
@@ -5,7 +5,7 @@
         H_FILES = (ifconfig.h); 
         M_FILES = (); 
         OTHER_LIBS = (); 
-        OTHER_LINKED = (ifconfig.c, ifmedia.c); 
+        OTHER_LINKED = (ifconfig.c, ifmedia.c, ifvlan.c); 
         OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, ifconfig.8, Makefile.postamble); 
         PRECOMPILED_HEADERS = (); 
         PROJECT_HEADERS = (); 
index 5f7828a76750086cdb5946e058fc88af51682602..d9a3c35a9b508715e2e18940a598e39085434f50 100644 (file)
@@ -288,7 +288,7 @@ interfaces previously configured with
 Create the specified network pseudo-device.
 If the interface is given without a unit number, try to create a new
 device with an arbitrary unit number.
-If creation of an arbitrary device is sucessful, the new device name is
+If creation of an arbitrary device is successful, the new device name is
 printed to standard output.
 .It Cm destroy
 Destroy the specified network pseudo-device.
@@ -306,6 +306,54 @@ parameter.
 Included for
 .Tn Solaris
 compatibility.
+.It Cm vlan Ar vlan_tag
+If the interface is a vlan pseudo interface, set the vlan tag value
+to
+.Ar vlan_tag .
+This value is a 16-bit number which is used to create an 802.1Q
+vlan header for packets sent from the vlan interface.
+Note that
+.Cm vlan
+and
+.Cm vlandev
+must both be set at the same time.
+.It Cm vlandev Ar iface
+If the interface is a vlan pseudo device, associate physical interface
+.Ar iface
+with it.
+Packets transmitted through the vlan interface will be
+diverted to the specified physical interface
+.Ar iface
+with 802.1Q vlan encapsulation.
+Packets with 802.1Q encapsulation received
+by the parent interface with the correct vlan tag will be diverted to
+the associated vlan pseudo-interface.
+The vlan interface is assigned a
+copy of the parent interface's flags and the parent's ethernet address.
+The
+.Cm vlandev
+and
+.Cm vlan
+must both be set at the same time.
+If the vlan interface already has
+a physical interface associated with it, this command will fail.
+To
+change the association to another physical interface, the existing
+association must be cleared first.
+.Pp
+Note: if the hardware tagging capability
+is set on the vlan interface, the vlan pseudo
+interface's behavior changes:
+the vlan interface recognizes that the
+parent interface supports insertion and extraction of vlan tags on its
+own (usually in firmware) and that it should pass packets to and from
+the parent unaltered.
+.It Fl vlandev Ar iface
+If the driver is a vlan pseudo device, disassociate the physical interface
+.Ar iface
+from it.
+This breaks the link between the vlan interface and its parent,
+clears its vlan tag, flags and its link address and shuts the interface down.
 .It Cm metric Ar n
 Set the routing metric of the interface to
 .Ar n ,
index 6444c62204824e80b7135fb6b93e09105a57830f..8d71e8645db3d1822a98cf57240a7267bb687746 100644 (file)
@@ -42,11 +42,13 @@ static const char copyright[] =
 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
 #endif
 static const char rcsid[] =
-       "$Id: ifconfig.c,v 1.5 2003/07/02 01:22:29 lindak Exp $";
+       "$Id: ifconfig.c,v 1.5.28.1 2004/04/14 00:27:17 lindak Exp $";
 #endif /* not lint */
 
 #include <sys/param.h>
+#define KERNEL_PRIVATE
 #include <sys/ioctl.h>
+#undef KERNEL_PRIVATE
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 #include <sys/time.h>
@@ -86,6 +88,8 @@ static const char rcsid[] =
 #include <string.h>
 #include <unistd.h>
 
+struct ether_addr *ether_aton __P((const char *));
+
 #include "ifconfig.h"
 
 /* wrapper for KAME-special getnameinfo() */
@@ -164,8 +168,10 @@ c_func2    setip6lifetime;
 #endif
 c_func setifipdst;
 c_func setifflags, setifmetric, setifmtu, setiflladdr;
+c_func clone_destroy;
 
 
+void clone_create(void);
 #define        NEXTARG         0xffffff
 #define        NEXTARG2        0xfffffe
 
@@ -231,10 +237,8 @@ struct     cmd {
        {"create",      0,              clone_create },
        {"plumb",       0,              clone_create },
 #endif
-#ifndef __APPLE__
        {"destroy",     0,              clone_destroy },
        {"unplumb",     0,              clone_destroy },
-#endif
 #ifdef USE_IEEE80211
        { "ssid",       NEXTARG,        set80211ssid },
        { "nwid",       NEXTARG,        set80211ssid },
@@ -357,21 +361,21 @@ void
 usage()
 {
 #ifndef INET6
-       fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-       "usage: ifconfig interface address_family [address [dest_address]]",
-       "                [parameters]",
-       "       ifconfig interface create",
-       "       ifconfig -a [-d] [-m] [-u] [address_family]",
-       "       ifconfig -l [-d] [-u] [address_family]",
-       "       ifconfig [-d] [-m] [-u]");
+       fprintf(stderr, "%s",
+       "usage: ifconfig interface address_family [address [dest_address]]\n"
+       "                [parameters]\n"
+       "       ifconfig interface create\n"
+       "       ifconfig -a [-d] [-m] [-u] [address_family]\n"
+       "       ifconfig -l [-d] [-u] [address_family]\n"
+       "       ifconfig [-d] [-m] [-u]\n");
 #else
-       fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-       "usage: ifconfig [-L] interface address_family [address [dest_address]]",
-       "                [parameters]",
-       "       ifconfig interface create",
-       "       ifconfig -a [-L] [-d] [-m] [-u] [address_family]",
-       "       ifconfig -l [-d] [-u] [address_family]",
-       "       ifconfig [-L] [-d] [-m] [-u]");
+       fprintf(stderr, "%s",
+       "usage: ifconfig [-L] interface address_family [address [dest_address]]\n"
+       "                [parameters]\n"
+       "       ifconfig interface create\n"
+       "       ifconfig -a [-L] [-d] [-m] [-u] [address_family]\n"
+       "       ifconfig -l [-d] [-u] [address_family]\n"
+       "       ifconfig [-L] [-d] [-m] [-u]\n");
 #endif
        exit(1);
 }
@@ -473,9 +477,7 @@ main(argc, argv)
                 */
                if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
                    strcmp(argv[0], "plumb") == 0)) {
-#ifndef __APPLE__
                        clone_create();
-#endif
                        argc--, argv++;
                        if (argc == 0)
                                exit(0);
@@ -694,7 +696,7 @@ ifconfig(argc, argv, afp)
 }
 #define RIDADDR 0
 #define ADDR   1
-#define MASK   2
+#define NMASK  2
 #define DSTADDR        3
 
 /*ARGSUSED*/
@@ -804,7 +806,7 @@ setifnetmask(addr, dummy, s, afp)
        if (*afp->af_getaddr == NULL)
                return;
        setmask++;
-       (*afp->af_getaddr)(addr, MASK);
+       (*afp->af_getaddr)(addr, NMASK);
 }
 
 #ifdef INET6
@@ -816,7 +818,7 @@ setifprefixlen(addr, dummy, s, afp)
        const struct afswtch *afp;
 {
         if (*afp->af_getprefix)
-                (*afp->af_getprefix)(addr, MASK);
+                (*afp->af_getprefix)(addr, NMASK);
        explicit_prefix = 1;
 }
 
@@ -1463,7 +1465,7 @@ in_getaddr(s, which)
        struct netent *np;
 
        sin->sin_len = sizeof(*sin);
-       if (which != MASK)
+       if (which != NMASK)
                sin->sin_family = AF_INET;
 
        if (which == ADDR) {
@@ -1473,7 +1475,7 @@ in_getaddr(s, which)
                        /* address is `name/masklen' */
                        int masklen;
                        int ret;
-                       struct sockaddr_in *min = sintab[MASK];
+                       struct sockaddr_in *min = sintab[NMASK];
                        *p = '\0';
                        ret = sscanf(p+1, "%u", &masklen);
                        if(ret != 1 || (masklen < 0 || masklen > 32)) {
@@ -1515,14 +1517,14 @@ in6_getaddr(s, which)
        newaddr &= 1;
 
        sin->sin6_len = sizeof(*sin);
-       if (which != MASK)
+       if (which != NMASK)
                sin->sin6_family = AF_INET6;
 
        if (which == ADDR) {
                char *p = NULL;
                if((p = strrchr(s, '/')) != NULL) {
                        *p = '\0';
-                       in6_getprefix(p + 1, MASK);
+                       in6_getprefix(p + 1, NMASK);
                        explicit_prefix = 1;
                }
        }
@@ -1551,7 +1553,7 @@ in6_getprefix(plen, which)
        if ((len < 0) || (len > 128))
                errx(1, "%s: bad value", plen);
        sin->sin6_len = sizeof(*sin);
-       if (which != MASK)
+       if (which != NMASK)
                sin->sin6_family = AF_INET6;
        if ((len == 0) || (len == 128)) {
                memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr));
@@ -1609,7 +1611,7 @@ ether_getaddr(addr, which)
         ea = ether_aton(addr);
         if (ea == NULL)
                 errx(1, "malformed ether address");
-        if (which == MASK)
+        if (which == NMASK)
                 errx(1, "Ethernet does not use netmasks");
         sea->sa_family = AF_LINK;
         sea->sa_len = ETHER_ADDR_LEN;      
@@ -1678,3 +1680,33 @@ sec2str(total)
 }
 #endif /*INET6*/
 
+void
+clone_create(void)
+{
+       int s;
+       
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s == -1)
+               err(1, "socket");
+       
+       memset(&ifr, 0, sizeof(ifr));
+       (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
+               err(1, "SIOCIFCREATE");
+       
+       if (strcmp(name, ifr.ifr_name) != 0) {
+               printf("%s\n", ifr.ifr_name);
+               strlcpy(name, ifr.ifr_name, sizeof(name));
+       }
+       
+       close(s);
+}
+
+void
+clone_destroy(const char *val, int d, int s, const struct afswtch *rafp)
+{
+       
+       (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
+               err(1, "SIOCIFDESTROY");
+}
index a088b7a91f9d4bc41fe925ee2ce86a5951ad7b5f..cc6a5ea089bdf7acc805250dc93cf80f7bc39f95 100644 (file)
@@ -31,7 +31,7 @@
  *
  * so there!
  *
- * $Id: ifconfig.h,v 1.1.1.1 2000/01/11 01:48:49 wsanchez Exp $
+ * $Id: ifconfig.h,v 1.1.1.1.140.1 2004/04/14 00:27:17 lindak Exp $
  */
 
 extern struct ifreq ifr;
@@ -44,3 +44,9 @@ extern void setmedia(const char *, int, int, const struct afswtch *rafp);
 extern void setmediaopt(const char *, int, int, const struct afswtch *rafp);
 extern void unsetmediaopt(const char *, int, int, const struct afswtch *rafp);
 extern void media_status(int s, struct rt_addrinfo *);
+
+extern void setvlantag(const char *, int, int, const struct afswtch *rafp);
+extern void setvlandev(const char *, int, int, const struct afswtch *rafp);
+extern void unsetvlandev(const char *, int, int, const struct afswtch *rafp);
+extern void vlan_status(int s, struct rt_addrinfo *);
+
diff --git a/ifconfig.tproj/ifvlan.c b/ifconfig.tproj/ifvlan.c
new file mode 100644 (file)
index 0000000..1a547df
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1999
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#define KERNEL_PRIVATE
+#include <sys/ioctl.h>
+#undef KERNEL_PRIVATE
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_vlan_var.h>
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+static int                     __tag = 0;
+static int                     __have_tag = 0;
+
+void
+vlan_status(int s, struct rt_addrinfo *info __unused)
+{
+       struct vlanreq          vreq;
+
+       bzero((char *)&vreq, sizeof(struct vlanreq));
+       ifr.ifr_data = (caddr_t)&vreq;
+
+       if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
+               return;
+
+       printf("\tvlan: %d parent interface: %s\n",
+           vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
+           "<none>" : vreq.vlr_parent);
+
+       return;
+}
+
+void
+setvlantag(const char *val, int d, int s, const struct afswtch *afp)
+{
+       u_int16_t               tag;
+       struct vlanreq          vreq;
+
+       __tag = tag = atoi(val);
+       __have_tag = 1;
+
+       bzero((char *)&vreq, sizeof(struct vlanreq));
+       ifr.ifr_data = (caddr_t)&vreq;
+
+       if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
+               err(1, "SIOCGETVLAN");
+
+       vreq.vlr_tag = tag;
+
+       if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+               err(1, "SIOCSETVLAN");
+
+       return;
+}
+
+void
+setvlandev(const char *val, int d, int s, const struct afswtch *afp)
+{
+       struct vlanreq          vreq;
+
+       if (!__have_tag)
+               errx(1, "must specify both vlan tag and device");
+
+       bzero((char *)&vreq, sizeof(struct vlanreq));
+       ifr.ifr_data = (caddr_t)&vreq;
+
+       if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
+               err(1, "SIOCGETVLAN");
+
+       strncpy(vreq.vlr_parent, val, sizeof(vreq.vlr_parent));
+       vreq.vlr_tag = __tag;
+
+       if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+               err(1, "SIOCSETVLAN");
+
+       return;
+}
+
+void
+unsetvlandev(const char *val, int d, int s, const struct afswtch *afp)
+{
+       struct vlanreq          vreq;
+
+       bzero((char *)&vreq, sizeof(struct vlanreq));
+       ifr.ifr_data = (caddr_t)&vreq;
+
+       if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
+               err(1, "SIOCGETVLAN");
+
+       bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
+       vreq.vlr_tag = 0;
+
+       if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+               err(1, "SIOCSETVLAN");
+
+       return;
+}
index b5699869fd6c272a6550dbba32da08c9aa361444..cb4da6543da626bee3ec5963b7639cb2cb05f68c 100644 (file)
@@ -686,7 +686,7 @@ eay_check_x509sign(source, sig, cert)
 {
        X509 *x509;
        u_char *bp;
-       vchar_t pubkey;
+       EVP_PKEY *evp;
 
        bp = cert->v;
 
@@ -698,10 +698,13 @@ eay_check_x509sign(source, sig, cert)
                return -1;
        }
 
-       pubkey.v = x509->cert_info->key->public_key->data;
-       pubkey.l = x509->cert_info->key->public_key->length;
-       
-       return eay_rsa_verify(source, sig, &pubkey);
+       evp = X509_get_pubkey(x509);
+       if (!evp) {
+         plog(LLV_ERROR, LOCATION, NULL, "X509_get_pubkey: %s\n", eay_strerror());
+         return -1;
+       }
+
+       return eay_rsa_verify(source, sig, evp);
 }
 
 /*
@@ -902,22 +905,15 @@ eay_rsa_sign(src, privkey)
 }
 
 int
-eay_rsa_verify(src, sig, pubkey)
-       vchar_t *src, *sig, *pubkey;
-{
+eay_rsa_verify(src, sig, evp)
+        vchar_t *src, *sig;
        EVP_PKEY *evp;
-       u_char *bp = pubkey->v;
+{
        vchar_t *xbuf = NULL;
        int pad = RSA_PKCS1_PADDING;
        int len = 0;
        int error;
 
-       evp = d2i_PUBKEY(NULL, &bp, pubkey->l);
-       if (evp == NULL)
-#ifndef EAYDEBUG
-               return NULL;
-#endif
-
        len = RSA_size(evp->pkey.rsa);
 
        xbuf = vmalloc(len);
index 6b3661e685bff71741d93e7c59256866282eaff2..7e2e20ae14a693d3214e6d6f8482b04b4949107b 100644 (file)
  * SUCH DAMAGE.
  */
 
+#ifdef HAVE_OPENSSL_EVP_H
+#include <openssl/evp.h>
+#endif
+
 #ifdef HAVE_SIGNING_C
 /* X509 Certificate */
 #define GENT_OTHERNAME 0
@@ -54,7 +58,7 @@ extern int eay_check_pkcs7sign __P((vchar_t *, vchar_t *, vchar_t *));
 
 /* RSA */
 extern vchar_t *eay_rsa_sign __P((vchar_t *, vchar_t *));
-extern int eay_rsa_verify __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_rsa_verify __P((vchar_t *, vchar_t *, EVP_PKEY *));
 
 /* ASN.1 */
 extern vchar_t *eay_get_pkcs1privkey __P((char *));
index 218f3ddc02123e876febbdb919a7cd220325c8d1..0f6b38bd5305f0473fdcf47213b1b966ca840d69 100644 (file)
@@ -181,6 +181,18 @@ isakmp_handler(so_isakmp)
                plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
                        "packet shorter than isakmp header size.\n");
                /* dummy receive */
+               if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
+                               0, (struct sockaddr *)&remote, &remote_len)) < 0) {
+                       plog(LLV_ERROR, LOCATION, NULL,
+                               "failed to receive isakmp packet\n");
+               }
+               goto end;
+       }
+       
+       /* reject if the size is toooo big */
+       if (ntohl(isakmp.len) > 0xffff) {
+               plog(LLV_ERROR, LOCATION, NULL,
+                       "the length of the isakmp header is too big.\n");
                if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
                            0, (struct sockaddr *)&remote, &remote_len)) < 0) {
                        plog(LLV_ERROR, LOCATION, NULL,
index cd4213dab84124a56031ca1379a209baed243a7e..a231b87b6b44ba427bb3b503be08ea70e13b9ec4 100644 (file)
 #include "lockd.h"
 #include "lockd_lock.h"
 
-#define DAEMON_USERNAME        "daemon"
-
 #define nfslockdans(_v, _ansp) \
-       ((_ansp)->la_vers = (_v), \
+       ((_ansp)->la_version = (_v), \
        nfsclnt(NFSCLNT_LOCKDANS, (_ansp)))
 
 
@@ -77,15 +75,11 @@ static char hostname[MAXHOSTNAMELEN + 1];   /* Hostname. */
 static void    client_cleanup(void);
 static void    set_auth(CLIENT *cl, struct xucred *ucred);
 int    lock_request(LOCKD_MSG *);
+int    cancel_request(LOCKD_MSG *);
 int    test_request(LOCKD_MSG *);
 void   show(LOCKD_MSG *);
 int    unlock_request(LOCKD_MSG *);
 
-/*
- * will break because fifo needs to be repopened when EOF'd
- */
-#define lockd_seteuid(uid)     seteuid(uid)
-
 #define d_calls (debug_level > 1)
 #define d_args (debug_level > 2)
 
@@ -116,7 +110,6 @@ client_kern_wait(void)
 void
 client_cleanup(void)
 {
-       (void)lockd_seteuid(0);
        (void) nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)-1);
        exit(-1);
 }
@@ -140,9 +133,7 @@ client_request(void)
 #endif
        int fd, nr, ret;
        pid_t child;
-       uid_t daemon_uid;
        mode_t old_umask;
-       struct passwd *pw;
 
        /* Recreate the NLM fifo. */
        (void)unlink(_PATH_LCKFIFO);
@@ -177,21 +168,13 @@ client_request(void)
        /* Open the fifo for reading. */
        if ((fd = open(_PATH_LCKFIFO, O_RDONLY | O_NONBLOCK)) == -1) {
                syslog(LOG_ERR, "open: %s: %m", _PATH_LCKFIFO);
-               goto err;
+               _exit (1);
        }
        (void)unlink(_PATH_LCKFIFO);
        if (nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)fd)) {
                syslog(LOG_ERR, "nfsclnt_fd: %d: %m", fd);
-               goto err;
+               _exit (1);
        }
-       pw = getpwnam(DAEMON_USERNAME);
-       if (pw == NULL) {
-               syslog(LOG_ERR, "getpwnam: %s: %m", DAEMON_USERNAME);
-               goto err;
-       }
-       daemon_uid = pw->pw_uid;
-       /* drop our root priviledges */
-       (void)lockd_seteuid(daemon_uid);
 
        for (;;) {
 #ifndef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
@@ -220,8 +203,10 @@ client_request(void)
                        switch (msg.lm_fl.l_type) {
                        case F_RDLCK:
                        case F_WRLCK:
-                               if (msg.lm_getlk)
+                               if (msg.lm_flags & LOCKD_MSG_TEST)
                                        ret = test_request(&msg);
+                               else if (msg.lm_flags & LOCKD_MSG_CANCEL)
+                                       ret = cancel_request(&msg);
                                else
                                        ret = lock_request(&msg);
                                break;
@@ -237,12 +222,12 @@ client_request(void)
                        if (ret) {
                                struct lockd_ans ans;
 
-                               ans.la_msg_ident = msg.lm_msg_ident;
+                               ans.la_xid = msg.lm_xid;
                                ans.la_errno = ENOTSUP;
 
                                if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
                                        syslog(LOG_DEBUG, "process %lu: %m",
-                                               (u_long)msg.lm_msg_ident.pid);
+                                               (u_long)msg.lm_fl.l_pid);
                                }
                        }
                } else if (nr == -1) {
@@ -266,7 +251,6 @@ client_request(void)
 
        /* Reached only on error. */
 err:
-       (void)lockd_seteuid(0);
        (void) nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)-1);
        _exit (1);
        return 0;
@@ -300,22 +284,22 @@ test_request(LOCKD_MSG *msg)
 
        if (d_calls)
                syslog(LOG_DEBUG, "test request: %s: %s to %s",
-                   msg->lm_nfsv3 ? "V4" : "V1/3",
+                   (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
                    msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
                    from_addr((struct sockaddr *)&msg->lm_addr));
 
-       if (msg->lm_nfsv3) {
+       if (msg->lm_flags & LOCKD_MSG_NFSV3) {
                struct nlm4_testargs arg4;
 
-               arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
-               arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
+               arg4.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg4.cookie.n_len = sizeof(msg->lm_xid);
                arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
                arg4.alock.caller_name = hostname;
                arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
                arg4.alock.fh.n_len = msg->lm_fh_len;
                arg4.alock.oh.n_bytes = (char *)&owner;
                arg4.alock.oh.n_len = sizeof(owner);
-               arg4.alock.svid = msg->lm_msg_ident.pid;
+               arg4.alock.svid = msg->lm_fl.l_pid;
                arg4.alock.l_offset = msg->lm_fl.l_start;
                arg4.alock.l_len = msg->lm_fl.l_len;
 
@@ -325,20 +309,20 @@ test_request(LOCKD_MSG *msg)
                        return (1);
 
                set_auth(cli, &msg->lm_cred);
-               (void)clnt_call(cli, NLM_TEST_MSG,
+               (void)clnt_call(cli, NLM4_TEST_MSG,
                    xdr_nlm4_testargs, &arg4, xdr_void, &dummy, timeout);
        } else {
                struct nlm_testargs arg;
 
-               arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
-               arg.cookie.n_len = sizeof(msg->lm_msg_ident);
+               arg.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg.cookie.n_len = sizeof(msg->lm_xid);
                arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
                arg.alock.caller_name = hostname;
                arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
                arg.alock.fh.n_len = msg->lm_fh_len;
                arg.alock.oh.n_bytes = (char *)&owner;
                arg.alock.oh.n_len = sizeof(owner);
-               arg.alock.svid = msg->lm_msg_ident.pid;
+               arg.alock.svid = msg->lm_fl.l_pid;
                arg.alock.l_offset = msg->lm_fl.l_start;
                arg.alock.l_len = msg->lm_fl.l_len;
 
@@ -369,21 +353,21 @@ lock_request(LOCKD_MSG *msg)
 
        if (d_calls)
                syslog(LOG_DEBUG, "lock request: %s: %s to %s",
-                   msg->lm_nfsv3 ? "V4" : "V1/3",
+                   (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
                    msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
                    from_addr((struct sockaddr *)&msg->lm_addr));
 
-       if (msg->lm_nfsv3) {
-               arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
-               arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
-               arg4.block = msg->lm_wait ? 1 : 0;
+       if (msg->lm_flags & LOCKD_MSG_NFSV3) {
+               arg4.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg4.cookie.n_len = sizeof(msg->lm_xid);
+               arg4.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
                arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
                arg4.alock.caller_name = hostname;
                arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
                arg4.alock.fh.n_len = msg->lm_fh_len;
                arg4.alock.oh.n_bytes = (char *)&owner;
                arg4.alock.oh.n_len = sizeof(owner);
-               arg4.alock.svid = msg->lm_msg_ident.pid;
+               arg4.alock.svid = msg->lm_fl.l_pid;
                arg4.alock.l_offset = msg->lm_fl.l_start;
                arg4.alock.l_len = msg->lm_fl.l_len;
                arg4.reclaim = 0;
@@ -395,19 +379,19 @@ lock_request(LOCKD_MSG *msg)
                        return (1);
 
                set_auth(cli, &msg->lm_cred);
-               (void)clnt_call(cli, NLM_LOCK_MSG,
+               (void)clnt_call(cli, NLM4_LOCK_MSG,
                    xdr_nlm4_lockargs, &arg4, xdr_void, &dummy, timeout);
        } else {
-               arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
-               arg.cookie.n_len = sizeof(msg->lm_msg_ident);
-               arg.block = msg->lm_wait ? 1 : 0;
+               arg.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg.cookie.n_len = sizeof(msg->lm_xid);
+               arg.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
                arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
                arg.alock.caller_name = hostname;
                arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
                arg.alock.fh.n_len = msg->lm_fh_len;
                arg.alock.oh.n_bytes = (char *)&owner;
                arg.alock.oh.n_len = sizeof(owner);
-               arg.alock.svid = msg->lm_msg_ident.pid;
+               arg.alock.svid = msg->lm_fl.l_pid;
                arg.alock.l_offset = msg->lm_fl.l_start;
                arg.alock.l_len = msg->lm_fl.l_len;
                arg.reclaim = 0;
@@ -425,6 +409,71 @@ lock_request(LOCKD_MSG *msg)
        return (0);
 }
 
+/*
+ * cancel_request --
+ *     Convert a lock LOCKD_MSG into an NLM request, and send it off.
+ */
+int
+cancel_request(LOCKD_MSG *msg)
+{
+       CLIENT *cli;
+       struct nlm4_cancargs arg4;
+       struct nlm_cancargs arg;
+       struct timeval timeout = {0, 0};        /* No timeout, no response. */
+       char dummy;
+
+       if (d_calls)
+               syslog(LOG_DEBUG, "cancel request: %s: %s to %s",
+                   (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
+                   msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
+                   from_addr((struct sockaddr *)&msg->lm_addr));
+
+       if (msg->lm_flags & LOCKD_MSG_NFSV3) {
+               arg4.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg4.cookie.n_len = sizeof(msg->lm_xid);
+               arg4.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
+               arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
+               arg4.alock.caller_name = hostname;
+               arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
+               arg4.alock.fh.n_len = msg->lm_fh_len;
+               arg4.alock.oh.n_bytes = (char *)&owner;
+               arg4.alock.oh.n_len = sizeof(owner);
+               arg4.alock.svid = msg->lm_fl.l_pid;
+               arg4.alock.l_offset = msg->lm_fl.l_start;
+               arg4.alock.l_len = msg->lm_fl.l_len;
+
+               if ((cli = get_client(
+                   (struct sockaddr *)&msg->lm_addr, NLM_VERS4)) == NULL)
+                       return (1);
+
+               set_auth(cli, &msg->lm_cred);
+               (void)clnt_call(cli, NLM4_CANCEL_MSG,
+                   xdr_nlm4_cancargs, &arg4, xdr_void, &dummy, timeout);
+       } else {
+               arg.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg.cookie.n_len = sizeof(msg->lm_xid);
+               arg.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
+               arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
+               arg.alock.caller_name = hostname;
+               arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
+               arg.alock.fh.n_len = msg->lm_fh_len;
+               arg.alock.oh.n_bytes = (char *)&owner;
+               arg.alock.oh.n_len = sizeof(owner);
+               arg.alock.svid = msg->lm_fl.l_pid;
+               arg.alock.l_offset = msg->lm_fl.l_start;
+               arg.alock.l_len = msg->lm_fl.l_len;
+
+               if ((cli = get_client(
+                   (struct sockaddr *)&msg->lm_addr, NLM_VERS)) == NULL)
+                       return (1);
+
+               set_auth(cli, &msg->lm_cred);
+               (void)clnt_call(cli, NLM_CANCEL_MSG,
+                   xdr_nlm_cancargs, &arg, xdr_void, &dummy, timeout);
+       }
+       return (0);
+}
+
 /*
  * unlock_request --
  *     Convert an unlock LOCKD_MSG into an NLM request, and send it off.
@@ -440,18 +489,18 @@ unlock_request(LOCKD_MSG *msg)
 
        if (d_calls)
                syslog(LOG_DEBUG, "unlock request: %s: to %s",
-                   msg->lm_nfsv3 ? "V4" : "V1/3",
+                   (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
                    from_addr((struct sockaddr *)&msg->lm_addr));
 
-       if (msg->lm_nfsv3) {
-               arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
-               arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
+       if (msg->lm_flags & LOCKD_MSG_NFSV3) {
+               arg4.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg4.cookie.n_len = sizeof(msg->lm_xid);
                arg4.alock.caller_name = hostname;
                arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
                arg4.alock.fh.n_len = msg->lm_fh_len;
                arg4.alock.oh.n_bytes = (char *)&owner;
                arg4.alock.oh.n_len = sizeof(owner);
-               arg4.alock.svid = msg->lm_msg_ident.pid;
+               arg4.alock.svid = msg->lm_fl.l_pid;
                arg4.alock.l_offset = msg->lm_fl.l_start;
                arg4.alock.l_len = msg->lm_fl.l_len;
 
@@ -461,17 +510,17 @@ unlock_request(LOCKD_MSG *msg)
                        return (1);
 
                set_auth(cli, &msg->lm_cred);
-               (void)clnt_call(cli, NLM_UNLOCK_MSG,
+               (void)clnt_call(cli, NLM4_UNLOCK_MSG,
                    xdr_nlm4_unlockargs, &arg4, xdr_void, &dummy, timeout);
        } else {
-               arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
-               arg.cookie.n_len = sizeof(msg->lm_msg_ident);
+               arg.cookie.n_bytes = (char *)&msg->lm_xid;
+               arg.cookie.n_len = sizeof(msg->lm_xid);
                arg.alock.caller_name = hostname;
                arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
                arg.alock.fh.n_len = msg->lm_fh_len;
                arg.alock.oh.n_bytes = (char *)&owner;
                arg.alock.oh.n_len = sizeof(owner);
-               arg.alock.svid = msg->lm_msg_ident.pid;
+               arg.alock.svid = msg->lm_fl.l_pid;
                arg.alock.l_offset = msg->lm_fl.l_start;
                arg.alock.l_len = msg->lm_fl.l_len;
 
@@ -489,47 +538,80 @@ unlock_request(LOCKD_MSG *msg)
 }
 
 int
-lock_answer(int pid, netobj *netcookie, int result, int version,
-       int *pid_p, off_t l_start, off_t l_len)
+lock_answer(int version, netobj *netcookie, nlm4_lock *lock, int flags, int result)
 {
        struct lockd_ans ans;
 
-       if (netcookie->n_len != sizeof(ans.la_msg_ident)) {
-               if (pid == -1) {        /* we're screwed */
+       ans.la_flags = 0;
+       if (flags & LOCK_ANSWER_GRANTED)
+               ans.la_flags |= LOCKD_ANS_GRANTED;
+
+       if (netcookie->n_len != sizeof(ans.la_xid)) {
+               if (lock == NULL) {     /* we're screwed */
                        syslog(LOG_ERR, "inedible nlm cookie");
                        return -1;
                }
-               ans.la_msg_ident.pid = pid;
-               ans.la_msg_ident.msg_seq = -1;
+               /* no/bad cookie - need to copy lock info to identify request */
+               ans.la_xid = 0;
+               /* copy lock info */
+               ans.la_fh_len = lock->fh.n_len;
+               if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
+                       syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
+                       return -1;
+               }
+               memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
+               ans.la_pid = lock->svid;
+               ans.la_start = lock->l_offset;
+               ans.la_len = lock->l_len;
+               ans.la_flags |= LOCKD_ANS_LOCK_INFO;
+               if (flags & LOCK_ANSWER_LOCK_EXCL)
+                       ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
        } else {
-               memcpy(&ans.la_msg_ident, netcookie->n_bytes,
-                   sizeof(ans.la_msg_ident));
+               memcpy(&ans.la_xid, netcookie->n_bytes, sizeof(ans.la_xid));
+               ans.la_fh_len = 0;
        }
 
        if (d_calls)
                syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d",
-                   (unsigned long)ans.la_msg_ident.pid,
+                   (unsigned long)ans.la_pid,
                    version == NLM_VERS4 ? "nlmv4" : "nlmv3",
                    result);
 
-       ans.la_getlk_set = 0;
        if (version == NLM_VERS4)
                switch (result) {
                case nlm4_granted:
                        ans.la_errno = 0;
+                       if ((flags & LOCK_ANSWER_GRANTED) && lock &&
+                           !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
+                               /* copy lock info */
+                               ans.la_fh_len = lock->fh.n_len;
+                               if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
+                                       syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
+                                       return -1;
+                               }
+                               memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
+                               ans.la_pid = lock->svid;
+                               ans.la_start = lock->l_offset;
+                               ans.la_len = lock->l_len;
+                               ans.la_flags |= LOCKD_ANS_LOCK_INFO;
+                               if (flags & LOCK_ANSWER_LOCK_EXCL)
+                                       ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
+                       }
                        break;
                default:
                        ans.la_errno = EACCES;
                        break;
                case nlm4_denied:
-                       if (pid_p == NULL)
+                       if (lock == NULL)
                                ans.la_errno = EACCES;
                        else {
                                /* this is an answer to a nlm_test msg */
-                               ans.la_getlk_set = 1;
-                               ans.la_getlk_pid = *pid_p;
-                               ans.la_getlk_start = l_start;
-                               ans.la_getlk_len = l_len;
+                               ans.la_pid = lock->svid;
+                               ans.la_start = lock->l_offset;
+                               ans.la_len = lock->l_len;
+                               ans.la_flags |= LOCKD_ANS_LOCK_INFO;
+                               if (flags & LOCK_ANSWER_LOCK_EXCL)
+                                       ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
                                ans.la_errno = 0;
                        }
                        break;
@@ -537,8 +619,8 @@ lock_answer(int pid, netobj *netcookie, int result, int version,
                        ans.la_errno = ENOLCK;
                        break;
                case nlm4_blocked:
-                       return -1;
-                       /* NOTREACHED */
+                       ans.la_errno = EINPROGRESS;
+                       break;
                case nlm4_denied_grace_period:
                        ans.la_errno = EAGAIN;
                        break;
@@ -562,19 +644,37 @@ lock_answer(int pid, netobj *netcookie, int result, int version,
                switch (result) {
                case nlm_granted:
                        ans.la_errno = 0;
+                       if ((flags & LOCK_ANSWER_GRANTED) && lock &&
+                           !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
+                               /* copy lock info */
+                               ans.la_fh_len = lock->fh.n_len;
+                               if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
+                                       syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
+                                       return -1;
+                               }
+                               memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
+                               ans.la_pid = lock->svid;
+                               ans.la_start = lock->l_offset;
+                               ans.la_len = lock->l_len;
+                               ans.la_flags |= LOCKD_ANS_LOCK_INFO;
+                               if (flags & LOCK_ANSWER_LOCK_EXCL)
+                                       ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
+                       }
                        break;
                default:
                        ans.la_errno = EACCES;
                        break;
                case nlm_denied:
-                       if (pid_p == NULL)
+                       if (lock == NULL)
                                ans.la_errno = EACCES;
                        else {
                                /* this is an answer to a nlm_test msg */
-                               ans.la_getlk_set = 1;
-                               ans.la_getlk_pid = *pid_p;
-                               ans.la_getlk_start = l_start;
-                               ans.la_getlk_len = l_len;
+                               ans.la_pid = lock->svid;
+                               ans.la_start = lock->l_offset;
+                               ans.la_len = lock->l_len;
+                               ans.la_flags |= LOCKD_ANS_LOCK_INFO;
+                               if (flags & LOCK_ANSWER_LOCK_EXCL)
+                                       ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
                                ans.la_errno = 0;
                        }
                        break;
@@ -582,8 +682,8 @@ lock_answer(int pid, netobj *netcookie, int result, int version,
                        ans.la_errno = ENOLCK;
                        break;
                case nlm_blocked:
-                       return -1;
-                       /* NOTREACHED */
+                       ans.la_errno = EINPROGRESS;
+                       break;
                case nlm_denied_grace_period:
                        ans.la_errno = EAGAIN;
                        break;
@@ -594,7 +694,7 @@ lock_answer(int pid, netobj *netcookie, int result, int version,
 
        if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
                syslog(LOG_DEBUG, "lock_answer(%d): process %lu: %m",
-                       result, (u_long)ans.la_msg_ident.pid);
+                       result, (u_long)ans.la_pid);
                return -1;
        }
        return 0;
@@ -613,7 +713,7 @@ show(LOCKD_MSG *mp)
        size_t len;
        u_int8_t *p, *t, buf[NFS_SMALLFH*3+1];
 
-       syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_msg_ident.pid);
+       syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_fl.l_pid);
 
        fsidp = (fsid_t *)&mp->lm_fh;
        fidp = (struct fid *)((u_int8_t *)&mp->lm_fh + sizeof(fsid_t));
@@ -635,5 +735,5 @@ show(LOCKD_MSG *mp)
            mp->lm_fl.l_type, mp->lm_fl.l_whence);
 
        /* Show wait flag. */
-       syslog(LOG_DEBUG, "wait was %s\n", mp->lm_wait ? "set" : "not set");
+       syslog(LOG_DEBUG, "wait was %s\n", (mp->lm_flags & LOCKD_MSG_BLOCK) ? "set" : "not set");
 }
index 9a4ee115ebb1f209a79b3deec2baae618e9c1908..2029deb86bc1adc1a5fab037dc42775a3fd0bdfa 100644 (file)
@@ -194,7 +194,6 @@ get_client(host_addr, vers)
        struct timeval retry_time, time_now;
        int i;
        int sock_no;
-       char host[NI_MAXHOST];
 
        gettimeofday(&time_now, NULL);
 
@@ -265,7 +264,8 @@ get_client(host_addr, vers)
        clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
 
        if (debug_level > 3)
-               syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
+               syslog(LOG_DEBUG, "Created CLIENT* for %s",
+                   inet_ntoa(((struct sockaddr_in *)host_addr)->sin_addr));
        return client;
 }
 
@@ -531,9 +531,12 @@ nlm_cancel_1_svc(arg, rqstp)
        struct svc_req *rqstp;
 {
        static nlm_res res;
-       struct nlm4_lock arg4;
+       struct nlm4_cancargs arg4;
 
-       nlmtonlm4(&arg->alock, &arg4);
+       arg4.cookie = arg->cookie;
+       arg4.block = arg->block;
+       arg4.exclusive = arg->exclusive;
+       nlmtonlm4(&arg->alock, &arg4.alock);
 
        if (debug_level)
                log_from_addr("nlm_cancel", rqstp);
@@ -541,11 +544,7 @@ nlm_cancel_1_svc(arg, rqstp)
        /* copy cookie from arg to result.  See comment in nlm_test_1() */
        res.cookie = arg->cookie;
 
-       /*
-        * Since at present we never return 'nlm_blocked', there can never be
-        * a lock to cancel, so this call always fails.
-        */
-       res.stat.stat = unlock(&arg4, LOCK_CANCEL);
+       res.stat.stat = cancellock(&arg4, 0);
        return (&res);
 }
 
@@ -555,19 +554,18 @@ nlm_cancel_msg_1_svc(arg, rqstp)
        struct svc_req *rqstp;
 {
        static nlm_res res;
-       struct nlm4_lock arg4;
+       struct nlm4_cancargs arg4;
 
-       nlmtonlm4(&arg->alock, &arg4);
+       arg4.cookie = arg->cookie;
+       arg4.block = arg->block;
+       arg4.exclusive = arg->exclusive;
+       nlmtonlm4(&arg->alock, &arg4.alock);
 
        if (debug_level)
                log_from_addr("nlm_cancel_msg", rqstp);
 
        res.cookie = arg->cookie;
-       /*
-        * Since at present we never return 'nlm_blocked', there can never be
-        * a lock to cancel, so this call always fails.
-        */
-       res.stat.stat = unlock(&arg4, LOCK_CANCEL);
+       res.stat.stat = cancellock(&arg4, 0);
        transmit_result(NLM_CANCEL_RES, &res,
            (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
        return (NULL);
@@ -645,13 +643,25 @@ nlm_granted_1_svc(arg, rqstp)
        struct svc_req *rqstp;
 {
        static nlm_res res;
+       nlm4_lock lock4;
+       int flags;
 
        if (debug_level)
                log_from_addr("nlm_granted", rqstp);
 
-       res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
-               nlm_granted, NLM_VERS, NULL, 0, 0) == 0 ?
-               nlm_granted : nlm_denied;
+       lock4.fh = arg->alock.fh;
+       lock4.svid = arg->alock.svid;
+       lock4.l_offset = arg->alock.l_offset;
+       lock4.l_len = arg->alock.l_len;
+
+       flags = LOCK_ANSWER_GRANTED;
+       if (arg->exclusive)
+               flags |= LOCK_ANSWER_LOCK_EXCL;
+
+       if (lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, nlm_granted))
+               res.stat.stat = nlm_denied;
+       else
+               res.stat.stat = nlm_granted;
 
        /* copy cookie from arg to result.  See comment in nlm_test_1() */
        res.cookie = arg->cookie;
@@ -665,13 +675,25 @@ nlm_granted_msg_1_svc(arg, rqstp)
        struct svc_req *rqstp;
 {
        static nlm_res res;
+       nlm4_lock lock4;
+       int flags;
 
        if (debug_level)
                log_from_addr("nlm_granted_msg", rqstp);
 
-       res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
-               nlm_granted, NLM_VERS, NULL, 0, 0) == 0 ?
-               nlm_granted : nlm_denied;
+       lock4.fh = arg->alock.fh;
+       lock4.svid = arg->alock.svid;
+       lock4.l_offset = arg->alock.l_offset;
+       lock4.l_len = arg->alock.l_len;
+
+       flags = LOCK_ANSWER_GRANTED;
+       if (arg->exclusive)
+               flags |= LOCK_ANSWER_LOCK_EXCL;
+
+       if (lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, nlm_granted))
+               res.stat.stat = nlm_denied;
+       else
+               res.stat.stat = nlm_granted;
 
        res.cookie = arg->cookie;
 
@@ -690,12 +712,23 @@ nlm_test_res_1_svc(arg, rqstp)
        nlm_testres *arg;
        struct svc_req *rqstp;
 {
+       nlm4_lock lock4;
+       int flags = 0;
+
        if (debug_level)
                log_from_addr("nlm_test_res", rqstp);
-       (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NLM_VERS,
-               &arg->stat.nlm_testrply_u.holder.svid,
-               arg->stat.nlm_testrply_u.holder.l_offset,
-               arg->stat.nlm_testrply_u.holder.l_len);
+
+       if (arg->stat.stat == nlm_denied) {
+               lock4.fh.n_len = 0;
+               lock4.svid = arg->stat.nlm_testrply_u.holder.svid;
+               lock4.l_offset = arg->stat.nlm_testrply_u.holder.l_offset;
+               lock4.l_len = arg->stat.nlm_testrply_u.holder.l_len;
+               if (arg->stat.nlm_testrply_u.holder.exclusive)
+                       flags |= LOCK_ANSWER_LOCK_EXCL;
+               lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, arg->stat.stat);
+       } else
+               lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
+
        return (NULL);
 }
 
@@ -712,7 +745,7 @@ nlm_lock_res_1_svc(arg, rqstp)
        if (debug_level)
                log_from_addr("nlm_lock_res", rqstp);
 
-       (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NLM_VERS, NULL, 0, 0);
+       lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
 
        return (NULL);
 }
@@ -724,11 +757,14 @@ nlm_lock_res_1_svc(arg, rqstp)
  */
 void *
 nlm_cancel_res_1_svc(arg, rqstp)
-       nlm_res *arg __unused;
+       nlm_res *arg;
        struct svc_req *rqstp;
 {
        if (debug_level)
                log_from_addr("nlm_cancel_res", rqstp);
+
+       lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
+
        return (NULL);
 }
 
@@ -745,7 +781,7 @@ nlm_unlock_res_1_svc(arg, rqstp)
        if (debug_level)
                log_from_addr("nlm_unlock_res", rqstp);
 
-       lock_answer(-1, &arg->cookie, arg->stat.stat, NLM_VERS, NULL, 0, 0);
+       lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
 
        return (NULL);
 }
@@ -757,12 +793,18 @@ nlm_unlock_res_1_svc(arg, rqstp)
  */
 void *
 nlm_granted_res_1_svc(arg, rqstp)
-       nlm_res *arg __unused;
+       nlm_res *arg;
        struct svc_req *rqstp;
 {
        if (debug_level)
                log_from_addr("nlm_granted_res", rqstp);
-       /* XXX should undo lock if granted msg wasn't accepted! */
+       /* need to undo lock if granted msg wasn't accepted! */
+       if (arg->stat.stat != nlm_granted) {
+               nlm4_res arg4;
+               arg4.cookie = arg->cookie;
+               arg4.stat.stat = arg->stat.stat;
+               granted_failed(&arg4);
+       }
        return (NULL);
 }
 
@@ -1061,11 +1103,7 @@ nlm4_cancel_4_svc(arg, rqstp)
        /* copy cookie from arg to result.  See comment in nlm_test_1() */
        res.cookie = arg->cookie;
 
-       /*
-        * Since at present we never return 'nlm_blocked', there can never be
-        * a lock to cancel, so this call always fails.
-        */
-       res.stat.stat = unlock(&arg->alock, LOCK_CANCEL);
+       res.stat.stat = cancellock(arg, LOCK_V4);
        return (&res);
 }
 
@@ -1080,11 +1118,7 @@ nlm4_cancel_msg_4_svc(arg, rqstp)
                log_from_addr("nlm4_cancel_msg", rqstp);
 
        res.cookie = arg->cookie;
-       /*
-        * Since at present we never return 'nlm_blocked', there can never be
-        * a lock to cancel, so this call always fails.
-        */
-       res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4);
+       res.stat.stat = cancellock(arg, LOCK_V4);
        transmit4_result(NLM4_CANCEL_RES, &res,
            (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
        return (NULL);
@@ -1156,13 +1190,19 @@ nlm4_granted_4_svc(arg, rqstp)
        struct svc_req *rqstp;
 {
        static nlm4_res res;
+       int flags;
 
        if (debug_level)
                log_from_addr("nlm4_granted", rqstp);
 
-       res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
-               nlm4_granted, NLM_VERS4, NULL, 0, 0) == 0 ?
-               nlm4_granted : nlm4_denied;
+       flags = LOCK_ANSWER_GRANTED;
+       if (arg->exclusive)
+               flags |= LOCK_ANSWER_LOCK_EXCL;
+
+       if (lock_answer(NLM_VERS4, &arg->cookie, &arg->alock, flags, nlm4_granted))
+               res.stat.stat = nlm4_denied;
+       else
+               res.stat.stat = nlm4_granted;
 
        /* copy cookie from arg to result.  See comment in nlm_test_1() */
        res.cookie = arg->cookie;
@@ -1176,13 +1216,19 @@ nlm4_granted_msg_4_svc(arg, rqstp)
        struct svc_req *rqstp;
 {
        static nlm4_res res;
+       int flags;
 
        if (debug_level)
                log_from_addr("nlm4_granted_msg", rqstp);
 
-       res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
-               nlm4_granted, NLM_VERS4, NULL, 0, 0) == 0 ?
-               nlm4_granted : nlm4_denied;
+       flags = LOCK_ANSWER_GRANTED;
+       if (arg->exclusive)
+               flags |= LOCK_ANSWER_LOCK_EXCL;
+
+       if (lock_answer(NLM_VERS4, &arg->cookie, &arg->alock, flags, nlm4_granted))
+               res.stat.stat = nlm4_denied;
+       else
+               res.stat.stat = nlm4_granted;
 
        res.cookie = arg->cookie;
 
@@ -1201,13 +1247,23 @@ nlm4_test_res_4_svc(arg, rqstp)
        nlm4_testres *arg;
        struct svc_req *rqstp;
 {
+       nlm4_lock lock4;
+       int flags = 0;
+
        if (debug_level)
                log_from_addr("nlm4_test_res", rqstp);
 
-       (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NLM_VERS4,
-               (int *)&arg->stat.nlm4_testrply_u.holder.svid,
-               arg->stat.nlm4_testrply_u.holder.l_offset,
-               arg->stat.nlm4_testrply_u.holder.l_len);
+       if (arg->stat.stat == nlm4_denied) {
+               lock4.fh.n_len = 0;
+               lock4.svid = arg->stat.nlm4_testrply_u.holder.svid;
+               lock4.l_offset = arg->stat.nlm4_testrply_u.holder.l_offset;
+               lock4.l_len = arg->stat.nlm4_testrply_u.holder.l_len;
+               if (arg->stat.nlm4_testrply_u.holder.exclusive)
+                       flags |= LOCK_ANSWER_LOCK_EXCL;
+               lock_answer(NLM_VERS4, &arg->cookie, &lock4, flags, arg->stat.stat);
+       } else
+               lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
+
        return (NULL);
 }
 
@@ -1224,7 +1280,7 @@ nlm4_lock_res_4_svc(arg, rqstp)
        if (debug_level)
                log_from_addr("nlm4_lock_res", rqstp);
 
-       (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NLM_VERS4, NULL, 0, 0);
+       lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
 
        return (NULL);
 }
@@ -1236,11 +1292,14 @@ nlm4_lock_res_4_svc(arg, rqstp)
  */
 void *
 nlm4_cancel_res_4_svc(arg, rqstp)
-       nlm4_res *arg __unused;
+       nlm4_res *arg;
        struct svc_req *rqstp;
 {
        if (debug_level)
                log_from_addr("nlm4_cancel_res", rqstp);
+
+       lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
+
        return (NULL);
 }
 
@@ -1256,6 +1315,9 @@ nlm4_unlock_res_4_svc(arg, rqstp)
 {
        if (debug_level)
                log_from_addr("nlm4_unlock_res", rqstp);
+
+       lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
+
        return (NULL);
 }
 
@@ -1271,7 +1333,9 @@ nlm4_granted_res_4_svc(arg, rqstp)
 {
        if (debug_level)
                log_from_addr("nlm4_granted_res", rqstp);
-       /* XXX should undo lock if granted msg wasn't accepted! */
+       /* need to undo lock if granted msg wasn't accepted! */
+       if (arg->stat.stat != nlm4_granted)
+               granted_failed(arg);
        return (NULL);
 }
 
index f8e46db5ef62334797bbba5118d03e98c419a8d2..f2d9ef2668ee288e258c0bf45620609d324636ca 100644 (file)
@@ -90,6 +90,7 @@ void cleanup_pid_file(void);
 void handle_sig_cleanup(int);
 
 void sigalarm_handler(void);
+void my_svc_run(void);
 
 const char *transports[] = { "udp", "tcp", "udp6", "tcp6" };
 
@@ -103,7 +104,7 @@ main(argc, argv)
        struct sigaction sigalarm;
        int grace_period = 30;
        
-       while ((ch = getopt(argc, argv, "d:g:w")) != (-1)) {
+       while ((ch = getopt(argc, argv, "d:g:wx:")) != (-1)) {
                switch (ch) {
                case 'd':
                        debug_level = atoi(optarg);
@@ -122,6 +123,9 @@ main(argc, argv)
                case 'w':
                        waitkern = 1;
                        break;
+               case 'x':
+                       host_expire = atoi(optarg);
+                       break;
                default:
                case '?':
                        usage();
@@ -164,7 +168,7 @@ main(argc, argv)
                nanosleep(&ts, NULL);
        }
 
-       openlog("rpc.lockd", 0, LOG_DAEMON);
+       openlog("rpc.lockd", debug_level == 99 ? LOG_PERROR : 0, LOG_DAEMON);
        if (debug_level)
                syslog(LOG_INFO, "Starting, debug level %d", debug_level);
        else
@@ -211,7 +215,7 @@ main(argc, argv)
 
        client_pid = client_request();
 
-       svc_run();              /* Should never return */
+       my_svc_run();           /* Should never return */
        exit(1);
 }
 
@@ -225,7 +229,8 @@ sigalarm_handler(void)
 void
 usage()
 {
-       errx(1, "usage: rpc.lockd [-d <debuglevel>] [-g <grace period>] [-w]");
+       errx(1, "usage: rpc.lockd [-d <debuglevel>] [-g <grace period>] "
+           " [-x <statd cache timeout>] [-w]");
 }
 
 /*
@@ -369,3 +374,45 @@ handle_sig_cleanup(int sig __unused)
        exit(1);
 }
 
+void
+my_svc_run(void)
+{
+        fd_set readfds;
+        struct timeval timeout;
+       struct timeval now;
+       int error;
+       int hashosts = 0;
+       int tsize = 0;
+       struct timeval *top;
+
+
+       for( ;; ) {
+               timeout.tv_sec = host_expire + 1;
+               timeout.tv_usec = 0;
+
+               tsize = getdtablesize();
+               bcopy(&svc_fdset, &readfds, sizeof(svc_fdset));
+               /*
+                * If there are any expired hosts then sleep with a
+                * timeout to expire them.
+                */
+               if (hashosts && (timeout.tv_sec >= 0))
+                       top = &timeout;
+               else
+                       top = NULL;
+               error = select(tsize, &readfds, NULL, NULL, top);
+               if (error == -1) {
+                       if (errno == EINTR)
+                               continue;
+                        perror("rpc.lockd: my_svc_run: select failed");
+                        return;
+               }
+               gettimeofday(&now, NULL);
+               currsec = now.tv_sec;
+               if (error > 0)
+                       svc_getreqset(&readfds);
+               if (debug_level > 3 && error == 0)
+                       fprintf(stderr, "my_svc_run: select timeout\n");
+               hashosts = expire_lock_hosts();
+       }
+}
index 2799058742218c798debdcf37acd0b370cf7d300..a649c691cee5aaa35b68d28e56118de235f901b4 100644 (file)
@@ -40,8 +40,12 @@ void client_kern_wait(void);
 pid_t  client_request(void);
 extern int nsm_state;
 extern pid_t client_pid;
+extern time_t currsec;
+extern int host_expire;
 
 /* XXX these should be in some system headers */
 typedef u_int32_t rpcvers_t;
 int nfsclnt(int, void *);
 extern int callrpc(const char *, int, int, int, xdrproc_t, void *, xdrproc_t , void *);
+int    expire_lock_hosts(void);
+
index f1fe265ed714933e049e1213fb6ad0271d7652fe..29a77c56f636ae9d03e3da111566de00d7d8b24a 100644 (file)
@@ -82,8 +82,7 @@ struct file_lock {
        netobj filehandle; /* NFS filehandle */
        struct sockaddr *addr;
        struct nlm4_holder client; /* lock holder */
-       /* XXX: client_cookie used *only* in send_granted */ 
-       netobj client_cookie; /* cookie sent by the client */
+       u_int64_t granted_cookie;
        char client_name[SM_MAXSTRLEN];
        int nsm_status; /* status from the remote lock manager */
        int status; /* lock status, see below */
@@ -129,13 +128,19 @@ struct nfssharefilelist_head nfssharefilelist_head = LIST_HEAD_INITIALIZER(nfssh
 
 /* struct describing a monitored host */
 struct host {
-       LIST_ENTRY(host) hostlst;
+       TAILQ_ENTRY(host) hostlst;
        char name[SM_MAXSTRLEN];
        int refcnt;
+       time_t lastuse;
 };
 /* list of hosts we monitor */
-LIST_HEAD(hostlst_head, host);
-struct hostlst_head hostlst_head = LIST_HEAD_INITIALIZER(hostlst_head);
+TAILQ_HEAD(hostlst_head, host);
+struct hostlst_head hostlst_head = TAILQ_HEAD_INITIALIZER(hostlst_head);
+struct hostlst_head hostlst_unref = TAILQ_HEAD_INITIALIZER(hostlst_unref);
+
+int host_expire = 60;  /* seconds */
+time_t currsec;
+u_int64_t send_granted_cookie = 0;
 
 /*
  * File monitoring handlers
@@ -178,16 +183,17 @@ enum split_status {SPL_DISJOINT=0, SPL_LOCK1=1, SPL_LOCK2=2, SPL_CONTAINED=4, SP
 
 enum partialfilelock_status lock_partialfilelock(struct file_lock *fl);
 
-void send_granted(struct file_lock *fl, int opcode);
+int send_granted(struct file_lock *fl, int opcode);
 void siglock(void);
 void sigunlock(void);
+void destroy_lock_host(struct host *ihp);
 void monitor_lock_host(const char *hostname);
 void unmonitor_lock_host(const char *hostname);
 
 void   copy_nlm4_lock_to_nlm4_holder(const struct nlm4_lock *src,
     const bool_t exclusive, struct nlm4_holder *dest);
 struct file_lock *     allocate_file_lock(const netobj *lockowner,
-    const netobj *matchcookie, const netobj *filehandle);
+    const netobj *filehandle);
 void   deallocate_file_lock(struct file_lock *fl);
 void   fill_file_lock(struct file_lock *fl,
     struct sockaddr *addr, const bool_t exclusive, const int32_t svid,
@@ -226,7 +232,7 @@ enum hwlock_status  test_hwlock(const struct file_lock *fl,
     struct file_lock **conflicting_fl); 
 void   remove_blockingfilelock(struct file_lock *fl);
 void   clear_blockingfilelock(const char *hostname);
-void   retry_blockingfilelocklist(void);
+void   retry_blockingfilelocklist(netobj *fh);
 enum partialfilelock_status    unlock_partialfilelock(
     const struct file_lock *fl);
 void   clear_partialfilelock(const char *hostname);
@@ -366,9 +372,6 @@ dump_filelock(const struct file_lock *fl)
                debuglog("Dumping client identity:\n");
                dump_netobj(&fl->client.oh);
                
-               debuglog("Dumping client cookie:\n");
-               dump_netobj(&fl->client_cookie);
-               
                debuglog("nsm: %d  status: %d  flags: %d  locker: %d"
                    "  fd:  %d\n", fl->nsm_status, fl->status,
                    fl->flags, fl->locker, fl->fd);
@@ -399,7 +402,7 @@ copy_nlm4_lock_to_nlm4_holder(src, exclusive, dest)
  */
 
 struct file_lock *
-allocate_file_lock(const netobj *lockowner, const netobj *matchcookie, const netobj *filehandle)
+allocate_file_lock(const netobj *lockowner, const netobj *filehandle)
 {
        struct file_lock *newfl;
 
@@ -417,18 +420,8 @@ allocate_file_lock(const netobj *lockowner, const netobj *matchcookie, const net
        newfl->client.oh.n_len = lockowner->n_len;
        bcopy(lockowner->n_bytes, newfl->client.oh.n_bytes, lockowner->n_len);
 
-       newfl->client_cookie.n_bytes = malloc(matchcookie->n_len);
-       if (newfl->client_cookie.n_bytes == NULL) {
-               free(newfl->client.oh.n_bytes);
-               free(newfl);
-               return NULL;
-       }
-       newfl->client_cookie.n_len = matchcookie->n_len;
-       bcopy(matchcookie->n_bytes, newfl->client_cookie.n_bytes, matchcookie->n_len);
-
        newfl->filehandle.n_bytes = malloc(filehandle->n_len);
        if (newfl->filehandle.n_bytes == NULL) {
-               free(newfl->client_cookie.n_bytes);
                free(newfl->client.oh.n_bytes);
                free(newfl);
                return NULL;
@@ -470,7 +463,6 @@ void
 deallocate_file_lock(struct file_lock *fl)
 {
        free(fl->client.oh.n_bytes);
-       free(fl->client_cookie.n_bytes);
        free(fl->filehandle.n_bytes);
        free(fl);
 }
@@ -726,7 +718,7 @@ same_filelock_identity(fl0, fl1)
 
 /*
  * get_lock_matching_unlock: Return a lock which matches the given unlock lock
- *                           or NULL otehrwise
+ *                           or NULL otherwise
  * XXX: It is a shame that this duplicates so much code from test_nfslock.
  */
 struct file_lock *
@@ -956,8 +948,7 @@ split_nfslock(exist_lock, unlock_lock, left_lock, right_lock)
            &start1, &len1, &start2, &len2);
 
        if ((spstatus & SPL_LOCK1) != 0) {
-               *left_lock = allocate_file_lock(&exist_lock->client.oh, &exist_lock->client_cookie,
-                       &exist_lock->filehandle);
+               *left_lock = allocate_file_lock(&exist_lock->client.oh, &exist_lock->filehandle);
                if (*left_lock == NULL) {
                        debuglog("Unable to allocate resource for split 1\n");
                        return SPL_RESERR;
@@ -972,8 +963,7 @@ split_nfslock(exist_lock, unlock_lock, left_lock, right_lock)
        }
 
        if ((spstatus & SPL_LOCK2) != 0) {
-               *right_lock = allocate_file_lock(&exist_lock->client.oh, &exist_lock->client_cookie,
-                       &exist_lock->filehandle);
+               *right_lock = allocate_file_lock(&exist_lock->client.oh, &exist_lock->filehandle);
                if (*right_lock == NULL) {
                        debuglog("Unable to allocate resource for split 1\n");
                        if (*left_lock != NULL) {
@@ -1225,9 +1215,44 @@ test_hwlock(fl, conflicting_fl)
 void
 add_blockingfilelock(struct file_lock *fl)
 {
+       struct file_lock *ifl, *nfl;
 
        debuglog("Entering add_blockingfilelock\n");
 
+       /*
+        * Check for a duplicate lock request.
+        * If found, deallocate the older request.
+        */
+       ifl = LIST_FIRST(&blockedlocklist_head);
+       for (; ifl != NULL; ifl = nfl) {
+               debuglog("Pointer to file lock: %p\n",ifl);
+               debuglog("****Dump of ifl****\n");
+               dump_filelock(ifl);
+               debuglog("*******************\n");
+
+               nfl = LIST_NEXT(ifl, nfslocklist);
+
+               if (fl->filehandle.n_len != ifl->filehandle.n_len)
+                       continue;
+               if (bcmp(fl->filehandle.n_bytes, ifl->filehandle.n_bytes,
+                       fl->filehandle.n_len))
+                       continue;
+
+               /* Filehandles match, check region */
+               if ((fl->client.l_offset != ifl->client.l_offset) ||
+                   (fl->client.l_len != ifl->client.l_len))
+                       continue;
+
+               /* Regions match, check the identity */
+               if (!same_filelock_identity(fl,ifl))
+                       continue;
+
+               debuglog("add_blockingfilelock: removing duplicate lock request.\n");
+               remove_blockingfilelock(ifl);
+               deallocate_file_lock(ifl);
+               break;
+       }
+
        /*
         * Clear the blocking flag so that it can be reused without
         * adding it to the blocking queue a second time
@@ -1276,15 +1301,24 @@ clear_blockingfilelock(const char *hostname)
        }
 }
 
+int need_retry_blocked_locks = 0; /* need to call retry_blockingfilelocklist() */
+
 void
-retry_blockingfilelocklist(void)
+retry_blockingfilelocklist(netobj *fh)
 {
-       /* Retry all locks in the blocked list */
+       /*
+        * If fh is given, then retry just the locks with the
+        * same filehandle in the blocked list.
+        * Otherwise, simply retry all locks in the blocked list.
+        */
        struct file_lock *ifl, *nfl, *pfl; /* Iterator */
        enum partialfilelock_status pflstatus;
+       int rv;
 
        debuglog("Entering retry_blockingfilelocklist\n");
 
+       need_retry_blocked_locks = 0;
+
        pfl = NULL;
        ifl = LIST_FIRST(&blockedlocklist_head);
        debuglog("Iterator choice %p\n",ifl);
@@ -1299,6 +1333,12 @@ retry_blockingfilelocklist(void)
                debuglog("Prev iterator choice %p\n",pfl);
                debuglog("Next iterator choice %p\n",nfl);
 
+               /* if given a filehandle, only retry locks for the same filehandle */
+               if (fh && !same_netobj(fh, &ifl->filehandle)) {
+                       ifl = nfl;
+                       continue;
+               }
+
                /*
                 * SUBTLE BUG: The file_lock must be removed from the
                 * old list so that it's list pointers get disconnected
@@ -1312,8 +1352,18 @@ retry_blockingfilelocklist(void)
                if (pflstatus == PFL_GRANTED || pflstatus == PFL_GRANTED_DUPLICATE) {
                        debuglog("Granted blocked lock\n");
                        /* lock granted and is now being used */
-                       send_granted(ifl,0);
-                       /* XXX should undo lock if send_granted fails */
+                       rv = send_granted(ifl, 0);
+                       if (rv) {
+                               /*
+                                * Uh oh... the NLM_GRANTED message failed.
+                                * About the only thing we can do is drop the lock.
+                                * Note: this could be bad if the error was only
+                                * transient.  Hopefully, if the client is still
+                                * waiting for the lock, they will resend the request.
+                                */
+                               do_unlock(ifl);
+                               /* ifl is NO LONGER VALID AT THIS POINT */
+                       }
                } else {
                        /* Reinsert lock back into same place in blocked list */
                        debuglog("Replacing blocked lock\n");
@@ -1324,13 +1374,16 @@ retry_blockingfilelocklist(void)
                                LIST_INSERT_HEAD(&blockedlocklist_head, ifl, nfslocklist);
                }
 
+               if (pflstatus == PFL_GRANTED || pflstatus == PFL_GRANTED_DUPLICATE) {
+                       /* If ifl was permanently removed from the list, (e.g the */
+                       /* lock was granted), pfl should remain where it's at. */
+               } else {
+                       /* If ifl was left in the list, (e.g it was reinserted back */
+                       /* in place), pfl should simply be moved forward to be ifl */
+                       pfl = ifl;
+               }
                /* Valid increment behavior regardless of state of ifl */
                ifl = nfl;
-               /* if a lock was granted incrementing pfl would make it nfl */
-               if (pfl != NULL && (LIST_NEXT(pfl, nfslocklist) != nfl))
-                       pfl = LIST_NEXT(pfl, nfslocklist);
-               else
-                       pfl = LIST_FIRST(&blockedlocklist_head);
        }
 
        debuglog("Exiting retry_blockingfilelocklist\n");
@@ -1583,6 +1636,7 @@ unlock_partialfilelock(const struct file_lock *fl)
                        // XXX Workaround is to move this to nlm_prot_svc.c
                        // XXX after the unlock response is sent.
                        // retry_blockingfilelocklist();
+                       need_retry_blocked_locks = 1;
                        break;
                case NFS_DENIED_NOLOCK:
                        retval = PFL_GRANTED;
@@ -1949,7 +2003,7 @@ getlock(nlm4_lockargs *lckarg, struct svc_req *rqstp, const int flags)
                    nlm4_denied_grace_period : nlm_denied_grace_period;
 
        /* allocate new file_lock for this request */
-       newfl = allocate_file_lock(&lckarg->alock.oh, &lckarg->cookie, &lckarg->alock.fh);
+       newfl = allocate_file_lock(&lckarg->alock.oh, &lckarg->alock.fh);
        if (newfl == NULL) {
                syslog(LOG_NOTICE, "lock allocate failed: %s", strerror(errno));
                /* failed */
@@ -2028,12 +2082,108 @@ unlock(nlm4_lock *lock, const int flags __unused)
        return err;
 }
 
+/* cancel a blocked lock request */
+enum nlm_stats
+cancellock(nlm4_cancargs *args, const int flags __unused)
+{
+       struct file_lock *ifl, *nfl;
+       enum nlm_stats err;
+
+       siglock();
+
+       debuglog("Entering cancellock...\n");
+
+       err = nlm_denied;
+
+       /*
+        * scan blocked lock list for matching request and remove/destroy
+        */
+       ifl = LIST_FIRST(&blockedlocklist_head);
+       for ( ; ifl != NULL; ifl = nfl) {
+               nfl = LIST_NEXT(ifl, nfslocklist);
+
+               /* compare lock fh - filehandle */
+               if (!same_netobj(&args->alock.fh, &ifl->filehandle))
+                       continue;
+
+               /* compare lock caller_name - client_name */
+               if (strncmp(args->alock.caller_name, ifl->client_name, SM_MAXSTRLEN))
+                       continue;
+
+               /* Note: done't compare cookie - client_cookie */
+               /* The cookie may be specific to the cancel request */
+               /* and not be the same as the one in the original lock request. */
+
+               /* compare lock oh - client.oh */
+               if (!same_netobj(&args->alock.oh, &ifl->client.oh))
+                       continue;
+
+               /* compare lock svid - client.svid */
+               if (args->alock.svid != ifl->client.svid)
+                       continue;
+
+               /* compare lock l_offset - client.l_offset */
+               if (args->alock.l_offset != ifl->client.l_offset)
+                       continue;
+
+               /* compare lock l_len - client.l_len */
+               if (args->alock.l_len != ifl->client.l_len)
+                       continue;
+
+               /* compare exclusive - client.exclusive */
+               if (args->exclusive != ifl->client.exclusive)
+                       continue;
+
+               /* got it */
+               remove_blockingfilelock(ifl);
+               deallocate_file_lock(ifl);
+               err = nlm_granted;
+               break;
+       }
+
+       sigunlock();
+
+       debuglog("Exiting cancellock...\n");
+
+       return err;
+}
+
+
 /*
  * XXX: The following monitor/unmonitor routines 
  * have not been extensively tested (ie. no regression
  * script exists like for the locking sections
  */
 
+/*
+ * Find a lock host on a queue.  If found:
+ *    bump the ref,
+ *    bump the access time,
+ *    dequeue it from the queue it was found on,
+ *    enqueue it at the front of the "in use" queue.
+ */
+struct host *
+get_lock_host(struct hostlst_head *hd, const char *hostname)
+{
+       struct host *ihp;
+
+       debuglog("get_lock_host %s\n", hostname);
+       TAILQ_FOREACH(ihp, hd, hostlst) {
+               if (strncmp(hostname, ihp->name, SM_MAXSTRLEN) == 0) {
+                       TAILQ_REMOVE(hd, ihp, hostlst);
+                       /* Host is already monitored, bump refcount */
+                       ++ihp->refcnt;
+                       ihp->lastuse = currsec;
+                       /* Host should only be in the monitor list once */
+                       TAILQ_INSERT_HEAD(&hostlst_head, ihp, hostlst);
+                       break;
+               }
+       }
+       debuglog("get_lock_host %s %s\n",
+           ihp == NULL ? "did not find" : "found", hostname);
+       return (ihp);
+}
+
 /*
  * monitor_lock_host: monitor lock hosts locally with a ref count and
  * inform statd
@@ -2045,22 +2195,23 @@ monitor_lock_host(const char *hostname)
        struct mon smon;
        struct sm_stat_res sres;
        int rpcret, statflag;
-       
+
        rpcret = 0;
        statflag = 0;
 
-       LIST_FOREACH(ihp, &hostlst_head, hostlst) {
-               if (strncmp(hostname, ihp->name, SM_MAXSTRLEN) == 0) {
-                       /* Host is already monitored, bump refcount */
-                       ++ihp->refcnt;
-                       /* Host should only be in the monitor list once */
-                       return;
-               }
+       debuglog("monitor_lock_host: %s\n", hostname);
+       ihp = get_lock_host(&hostlst_head, hostname);
+       if (ihp == NULL)
+               ihp = get_lock_host(&hostlst_unref, hostname);
+       if (ihp != NULL) {
+               debuglog("Monitor_lock_host: %s (cached)\n", hostname);
+               return;
        }
 
+       debuglog("Monitor_lock_host: %s (not found, creating)\n", hostname);
        /* Host is not yet monitored, add it */
        nhp = malloc(sizeof(struct host));
-               
+
        if (nhp == NULL) {
                debuglog("Unable to allocate entry for statd mon\n");
                return;
@@ -2069,22 +2220,23 @@ monitor_lock_host(const char *hostname)
        /* Allocated new host entry, now fill the fields */
        strncpy(nhp->name, hostname, SM_MAXSTRLEN);
        nhp->refcnt = 1;
+       nhp->lastuse = currsec;
        debuglog("Locally Monitoring host %16s\n",hostname);
-                       
+
        debuglog("Attempting to tell statd\n");
-                       
+
        bzero(&smon,sizeof(smon));
-         
+
        smon.mon_id.mon_name = nhp->name;
        smon.mon_id.my_id.my_name = "localhost\0";
 
        smon.mon_id.my_id.my_prog = NLM_PROG;
        smon.mon_id.my_id.my_vers = NLM_SM;
        smon.mon_id.my_id.my_proc = NLM_SM_NOTIFY;
-                         
+
        rpcret = callrpc("localhost", SM_PROG, SM_VERS, SM_MON, xdr_mon,
            &smon, xdr_sm_stat_res, &sres);
-                         
+
        if (rpcret == 0) {
                if (sres.res_stat == stat_fail) {
                        debuglog("Statd call failed\n");
@@ -2097,13 +2249,12 @@ monitor_lock_host(const char *hostname)
                    rpcret);
                statflag = 0;
        }
-                       
+
        if (statflag == 1) {
-               LIST_INSERT_HEAD(&hostlst_head, nhp, hostlst);
+               TAILQ_INSERT_HEAD(&hostlst_head, nhp, hostlst);
        } else {
                free(nhp);
        }
-
 }
 
 /*
@@ -2113,14 +2264,8 @@ void
 unmonitor_lock_host(const char *hostname)
 {
        struct host *ihp;
-       struct mon_id smon_id;
-       struct sm_stat smstat;
-       int rpcret;
-       
-       rpcret = 0;
 
-       for( ihp=LIST_FIRST(&hostlst_head); ihp != NULL;
-            ihp=LIST_NEXT(ihp, hostlst)) {
+       TAILQ_FOREACH(ihp, &hostlst_head, hostlst) {
                if (strncmp(hostname, ihp->name, SM_MAXSTRLEN) == 0) {
                        /* Host is monitored, bump refcount */
                        --ihp->refcnt;
@@ -2138,32 +2283,69 @@ unmonitor_lock_host(const char *hostname)
                return;
 
        if (ihp->refcnt < 0) {
-               debuglog("Negative refcount!: %d\n",
-                   ihp->refcnt);
+               debuglog("Negative refcount!: %d\n", ihp->refcnt);
        }
 
-       debuglog("Attempting to unmonitor host %16s\n", hostname);
+       TAILQ_REMOVE(&hostlst_head, ihp, hostlst);
+       TAILQ_INSERT_HEAD(&hostlst_unref, ihp, hostlst);
+       if (host_expire <= 0)
+               destroy_lock_host(ihp);
+}
+
+void
+destroy_lock_host(struct host *ihp)
+{
+       struct mon_id smon_id;
+       struct sm_stat smstat;
+       int rpcret;
+
+       debuglog("Attempting to unmonitor host %16s\n", ihp->name);
 
        bzero(&smon_id,sizeof(smon_id));
 
-       smon_id.mon_name = (char *)hostname;
+       smon_id.mon_name = (char *)ihp->name;
        smon_id.my_id.my_name = "localhost";
        smon_id.my_id.my_prog = NLM_PROG;
        smon_id.my_id.my_vers = NLM_SM;
        smon_id.my_id.my_proc = NLM_SM_NOTIFY;
                          
-       rpcret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON, xdr_mon,
-           &smon_id, xdr_sm_stat_res, &smstat);
+       rpcret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON, xdr_mon_id,
+           &smon_id, xdr_sm_stat, &smstat);
                          
        if (rpcret != 0) {
                debuglog("Rpc call to unmonitor statd failed with "
-                  " return value: %d\n", rpcret);
+                  " return value: %d: %s", rpcret, clnt_sperrno(rpcret));
+       } else {
+               debuglog("Succeeded unmonitoring %16s\n", ihp->name);
        }
 
-       LIST_REMOVE(ihp, hostlst);
+       TAILQ_REMOVE(&hostlst_unref, ihp, hostlst);
        free(ihp);
 }
 
+/*
+ * returns 1 if there are hosts to expire or 0 if there are none.
+ */
+int
+expire_lock_hosts(void)
+{
+       struct host *ihp;
+
+       debuglog("expire_lock_hosts: called\n");
+       for ( ;; ) {
+               ihp = TAILQ_LAST(&hostlst_unref, hostlst_head);
+               if (ihp == NULL)
+                       break;
+               if (host_expire > 0 && ihp->lastuse >= currsec - host_expire)
+                       break;
+               debuglog("expire_lock_hosts: expiring %s %d %d %d\n",
+                   ihp->name, (int)ihp->lastuse,
+                   (int)currsec, (int)currsec - host_expire);
+               destroy_lock_host(ihp);
+       }
+       return (TAILQ_LAST(&hostlst_unref, hostlst_head) != NULL);
+}
+
 /*
  * notify: Clear all locks from a host if statd complains
  *
@@ -2192,7 +2374,7 @@ notify(const char *hostname, const int state)
        debuglog("Leaving notify\n");
 }
 
-void
+int
 send_granted(fl, opcode)
        struct file_lock *fl;
        int opcode __unused;
@@ -2200,13 +2382,11 @@ send_granted(fl, opcode)
        CLIENT *cli;
        static char dummy;
        struct timeval timeo;
-       int success;
+       enum clnt_stat rv;
        static struct nlm_res retval;
        static struct nlm4_res retval4;
 
        debuglog("About to send granted on blocked lock\n");
-       //sleep(1);
-       debuglog("Blowing off return send\n");
 
        cli = get_client(fl->addr,
            (fl->flags & LOCK_V4) ? NLM_VERS4 : NLM_VERS);
@@ -2218,14 +2398,19 @@ send_granted(fl, opcode)
                 * The client will timeout and retry, the lock will be
                 * granted at this time.
                 */
-               return;
+               return -1;
        }
        timeo.tv_sec = 0;
        timeo.tv_usec = (fl->flags & LOCK_ASYNC) ? 0 : 500000; /* 0.5s */
 
+       fl->granted_cookie = ++send_granted_cookie;
+       if (!send_granted_cookie)
+               send_granted_cookie++;
+
        if (fl->flags & LOCK_V4) {
                static nlm4_testargs res;
-               res.cookie = fl->client_cookie;
+               res.cookie.n_len = sizeof(fl->granted_cookie);
+               res.cookie.n_bytes = (char*)&fl->granted_cookie;
                res.exclusive = fl->client.exclusive;
                res.alock.caller_name = fl->client_name;
                res.alock.fh.n_len = fl->filehandle.n_len;
@@ -2237,17 +2422,18 @@ send_granted(fl, opcode)
                debuglog("sending v4 reply%s",
                         (fl->flags & LOCK_ASYNC) ? " (async)":"");
                if (fl->flags & LOCK_ASYNC) {
-                       success = clnt_call(cli, NLM4_GRANTED_MSG,
+                       rv = clnt_call(cli, NLM4_GRANTED_MSG,
                            xdr_nlm4_testargs, &res, xdr_void, &dummy, timeo);
                } else {
-                       success = clnt_call(cli, NLM4_GRANTED,
+                       rv = clnt_call(cli, NLM4_GRANTED,
                            xdr_nlm4_testargs, &res, xdr_nlm4_res,
                            &retval4, timeo);
                }
        } else {
                static nlm_testargs res;
 
-               res.cookie = fl->client_cookie;
+               res.cookie.n_len = sizeof(fl->granted_cookie);
+               res.cookie.n_bytes = (char*)&fl->granted_cookie;
                res.exclusive = fl->client.exclusive;
                res.alock.caller_name = fl->client_name;
                res.alock.fh.n_len = fl->filehandle.n_len;
@@ -2259,18 +2445,65 @@ send_granted(fl, opcode)
                debuglog("sending v1 reply%s",
                         (fl->flags & LOCK_ASYNC) ? " (async)":"");
                if (fl->flags & LOCK_ASYNC) {
-                       success = clnt_call(cli, NLM_GRANTED_MSG,
+                       rv = clnt_call(cli, NLM_GRANTED_MSG,
                            xdr_nlm_testargs, &res, xdr_void, &dummy, timeo);
                } else {
-                       success = clnt_call(cli, NLM_GRANTED,
+                       rv = clnt_call(cli, NLM_GRANTED,
                            xdr_nlm_testargs, &res, xdr_nlm_res,
                            &retval, timeo);
                }
        }
        if (debug_level > 2)
                debuglog("clnt_call returns %d(%s) for granted",
-                        success, clnt_sperrno(success));
+                        rv, clnt_sperrno(rv));
+
+       if ((rv != RPC_SUCCESS) &&
+           !((fl->flags & LOCK_ASYNC) && (rv == RPC_TIMEDOUT)))
+               return -1;
+       return 0;
+}
+
+/*
+ * granted_failed: remove a granted lock that wasn't successfully
+ * accepted by the client
+ */
+void
+granted_failed(nlm4_res *arg)
+{
+       u_int64_t cookie;
+       struct file_lock *ifl;
+
+       debuglog("Entering granted_failed, status %d\n", arg->stat.stat);
+
+       if (arg->cookie.n_len != sizeof(cookie)) {
+               debuglog("Exiting granted_failed: bogus cookie size %d\n",
+                       arg->cookie.n_len);
+               return;
+       }
+       bcopy(arg->cookie.n_bytes, &cookie, sizeof(cookie));
+       debuglog("granted_failed, cookie 0x%llx\n", cookie);
+
+       LIST_FOREACH(ifl, &nfslocklist_head, nfslocklist) {
+               debuglog("Pointer to file lock: %p\n",ifl);
+
+               debuglog("****Dump of ifl****\n");
+               dump_filelock(ifl);
+
+               if (ifl->granted_cookie != cookie)
+                       continue;
+
+               debuglog("granted_failed: cookie found\n");
+               break;
+       }
+
+       if (ifl) {
+               do_unlock(ifl);
+               /* ifl is NO LONGER VALID AT THIS POINT */
+       } else {
+               debuglog("granted_failed: cookie NOT FOUND\n");
+       }
 
+       debuglog("Exiting granted_failed\n");
 }
 
 /*
index fc54f32ca7701d08590154c7cdca54aa420beffc..4d93c7dec1f65f6be32b4605f231b915ca2a7ead 100644 (file)
@@ -3,14 +3,17 @@
 
 /* Headers and function declarations for file-locking utilities */
 
+#ifndef LOCKD_LOCK_H
+#define LOCKD_LOCK_H
 struct nlm4_holder * testlock(struct nlm4_lock *lock, bool_t exclusive, int flags);
 enum nlm_stats getlock(nlm4_lockargs *lckarg, struct svc_req *rqstp, const int flags);
 enum nlm_stats unlock(nlm4_lock *lock, const int flags);
-int lock_answer(int pid, netobj *netcookie, int result, int version,
-       int *pid_p, off_t l_start, off_t l_len);
+enum nlm_stats cancellock(nlm4_cancargs *args, const int flags);
+int lock_answer(int version, netobj *netcookie, nlm4_lock *lock, int flags, int result);
 enum nlm_stats getshare(nlm_shareargs *shrarg, struct svc_req *rqstp, const int flags);
 enum nlm_stats unshare(nlm_shareargs *shrarg, struct svc_req *rqstp);
 void do_free_all(const char *hostname);
+void granted_failed(nlm4_res *arg);
 
 void notify(const char *hostname, const int state);
 
@@ -18,9 +21,16 @@ void notify(const char *hostname, const int state);
 #define LOCK_ASYNC     0x01 /* async version (getlock only) */
 #define LOCK_V4        0x02 /* v4 version */
 #define LOCK_MON       0x04 /* monitored lock (getlock only) */
-#define LOCK_CANCEL 0x08 /* cancel, not unlock request (unlock only) */
+
+/* flags for lock_answer */
+#define LOCK_ANSWER_GRANTED    0x0001  /* NLM_GRANTED request */
+#define LOCK_ANSWER_LOCK_EXCL  0x0004  /* lock is exclusive */
 
 /* callbacks from lock_proc.c */
 void   transmit_result(int, nlm_res *, struct sockaddr *);
 void   transmit4_result(int, nlm4_res *, struct sockaddr *);
 CLIENT  *get_client(struct sockaddr *, rpcvers_t);
+
+extern time_t currsec;
+
+#endif /* !LOCKD_LOCK_H */
index 1e0dd9d728af92f99fcab1d79974bd4c0d506120..c395643b7615ccd6cf0b4a653f067463227544b6 100644 (file)
 #endif
 
 // XXX
-void retry_blockingfilelocklist(void);
+void retry_blockingfilelocklist(netobj *fh);
+extern int need_retry_blocked_locks; /* need to call retry_blockingfilelocklist() */
 
 #define _RPCSVC_CLOSEDOWN 120
 #ifndef lint
 /*static char sccsid[] = "from: @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro";*/
 /*static char sccsid[] = "from: * @(#)nlm_prot.x       2.1 88/08/01 4.0 RPCSRC";*/
-static char rcsid[] = "$Id: nlm_prot_svc.c,v 1.4 2003/07/24 05:11:22 lindak Exp $";
+static char rcsid[] = "$Id: nlm_prot_svc.c,v 1.4.36.1 2004/04/16 15:50:05 lindak Exp $";
 #endif /* not lint */
 extern int _rpcpmstart;                /* Started by a port monitor ? */
 extern int _rpcfdtype;         /* Whether Stream or Datagram ? */
@@ -230,18 +231,21 @@ nlm_prog_1(struct svc_req *rqstp, SVCXPRT *transp)
        if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
                svcerr_systemerr(transp);
        }
+       if (need_retry_blocked_locks) {
+               // XXX sending granted messages before unlock response
+               // XXX causes unlock response to be corrupted?
+               // XXX so do this after we send any response
+               netobj *fh = NULL;
+               if ((local == (char *(*)(char *, struct svc_req *)) nlm_unlock_1_svc) ||
+                   (local == (char *(*)(char *, struct svc_req *)) nlm_unlock_msg_1_svc))
+                       fh = &argument.nlm_unlock_1_arg.alock.fh;
+               retry_blockingfilelocklist(fh);
+       }
        if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
                syslog(LOG_ERR, "unable to free arguments");
                exit(1);
        }
        _rpcsvcdirty = 0;
-       if ((local == (char *(*)(char *, struct svc_req *)) nlm_unlock_1_svc) ||
-           (local == (char *(*)(char *, struct svc_req *)) nlm_unlock_msg_1_svc)) {
-               // XXX sending granted messages before unlock response
-               // XXX causes unlock response to be corrupted?
-               // XXX so do this after we send any response
-               retry_blockingfilelocklist();
-       }
        return;
 }
 
@@ -411,19 +415,21 @@ nlm_prog_3(struct svc_req *rqstp, SVCXPRT *transp)
        if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
                svcerr_systemerr(transp);
        }
+       if (need_retry_blocked_locks) {
+               // XXX sending granted messages before unlock response
+               // XXX causes unlock response to be corrupted?
+               // XXX so do this after we send any response
+               netobj *fh = NULL;
+               if ((local == (char *(*)(char *, struct svc_req *)) nlm_unlock_1_svc) ||
+                   (local == (char *(*)(char *, struct svc_req *)) nlm_unlock_msg_1_svc))
+                       fh = &argument.nlm_unlock_3_arg.alock.fh;
+               retry_blockingfilelocklist(fh);
+       }
        if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
                syslog(LOG_ERR, "unable to free arguments");
                exit(1);
        }
        _rpcsvcdirty = 0;
-       if ((local == (char *(*)(char *, struct svc_req *)) nlm_unlock_1_svc) ||
-           (local == (char *(*)(char *, struct svc_req *)) nlm_unlock_msg_1_svc) ||
-           (local == (char *(*)(char *, struct svc_req *)) nlm_free_all_3_svc)) {
-               // XXX sending granted messages before unlock response
-               // XXX causes unlock response to be corrupted?
-               // XXX so do this after we send any response
-               retry_blockingfilelocklist();
-       }
        return;
 }
 
@@ -593,18 +599,20 @@ nlm_prog_4(struct svc_req *rqstp, SVCXPRT *transp)
        if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
                svcerr_systemerr(transp);
        }
+       if (need_retry_blocked_locks) {
+               // XXX sending granted messages before unlock response
+               // XXX causes unlock response to be corrupted?
+               // XXX so do this after we send any response
+               netobj *fh = NULL;
+               if ((local == (char *(*)(char *, struct svc_req *)) nlm4_unlock_4_svc) ||
+                   (local == (char *(*)(char *, struct svc_req *)) nlm4_unlock_msg_4_svc))
+                       fh = &argument.nlm4_unlock_4_arg.alock.fh;
+               retry_blockingfilelocklist(fh);
+       }
        if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
                syslog(LOG_ERR, "unable to free arguments");
                exit(1);
        }
        _rpcsvcdirty = 0;
-       if ((local == (char *(*)(char *, struct svc_req *)) nlm4_unlock_4_svc) ||
-           (local == (char *(*)(char *, struct svc_req *)) nlm4_unlock_msg_4_svc) ||
-           (local == (char *(*)(char *, struct svc_req *)) nlm4_free_all_4_svc)) {
-               // XXX sending granted messages before unlock response
-               // XXX causes unlock response to be corrupted?
-               // XXX so do this after we send any response
-               retry_blockingfilelocklist();
-       }
        return;
 }
index e4172df6d321e395521a3117e33aecf7ff1ef0e8..191bbec43ffdb12b5297bac8739b5352bcc5f064 100644 (file)
@@ -43,6 +43,7 @@
 .Nm
 .Op Fl d Ar debug_level
 .Op Fl g Ar grace period
+.Op Fl x Ar statd cache period
 .Sh DESCRIPTION
 The
 .Nm
@@ -93,6 +94,16 @@ locking daemon(s).  This may be used on NFS clients to defer starting the
 NFS locking daemons until it is known that they will be needed.  (Note:
 .Xr rpc.statd 8
 will also be started if it isn't already running)
+.It Fl x
+The
+.Fl x
+option tells rpc.lockd how long to cache state records for contacting
+client
+.Xr rpc.statd 8
+implementations.  Setting it to zero will disable the cache which will
+make lock and unlock requests from a single client more expensive because
+of additional interaction with the client's statd.  The default cache time
+is 60 seconds.
 .El
 .Pp
 Error conditions are logged to syslog, irrespective of the debug level,