1 /*
   2  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
   3  * Authors: Doug Rabson <dfr@rabson.org>
   4  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  * 1. Redistributions of source code must retain the above copyright
  10  *    notice, this list of conditions and the following disclaimer.
  11  * 2. Redistributions in binary form must reproduce the above copyright
  12  *    notice, this list of conditions and the following disclaimer in the
  13  *    documentation and/or other materials provided with the distribution.
  14  *
  15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25  * SUCH DAMAGE.
  26  */
  27 
  28 /*
  29  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  30  */
  31 
  32 /*
  33  * Client-side RPC wrappers (nlm_..._rpc)
  34  * Called from nlm_client.c
  35  *
  36  * Source code derived from FreeBSD nlm_advlock.c
  37  */
  38 
  39 #include <sys/param.h>
  40 #include <sys/fcntl.h>
  41 #include <sys/lock.h>
  42 #include <sys/flock.h>
  43 #include <sys/mount.h>
  44 #include <sys/mutex.h>
  45 #include <sys/proc.h>
  46 #include <sys/syslog.h>
  47 #include <sys/systm.h>
  48 #include <sys/unistd.h>
  49 #include <sys/vnode.h>
  50 #include <sys/queue.h>
  51 
  52 #include <rpcsvc/nlm_prot.h>
  53 
  54 #include <nfs/nfs.h>
  55 #include <nfs/nfs_clnt.h>
  56 #include <nfs/export.h>
  57 #include <nfs/rnode.h>
  58 
  59 #include "nlm_impl.h"
  60 
  61 static void
  62 nlm_convert_to_nlm_lock(struct nlm_lock *dst, struct nlm4_lock *src)
  63 {
  64         dst->caller_name = src->caller_name;
  65         dst->fh = src->fh;
  66         dst->oh = src->oh;
  67         dst->svid = src->svid;
  68         dst->l_offset = src->l_offset;
  69         dst->l_len = src->l_len;
  70 }
  71 
  72 static void
  73 nlm_convert_to_nlm4_holder(struct nlm4_holder *dst, struct nlm_holder *src)
  74 {
  75         dst->exclusive = src->exclusive;
  76         dst->svid = src->svid;
  77         dst->oh = src->oh;
  78         dst->l_offset = src->l_offset;
  79         dst->l_len = src->l_len;
  80 }
  81 
  82 static void
  83 nlm_convert_to_nlm4_res(struct nlm4_res *dst, struct nlm_res *src)
  84 {
  85         dst->cookie = src->cookie;
  86         dst->stat.stat = (enum nlm4_stats) src->stat.stat;
  87 }
  88 
  89 enum clnt_stat
  90 nlm_test_rpc(nlm4_testargs *args, nlm4_testres *res,
  91     CLIENT *client, rpcvers_t vers)
  92 {
  93         if (vers == NLM4_VERS) {
  94                 return (nlm4_test_4(args, res, client));
  95         } else {
  96                 nlm_testargs args1;
  97                 nlm_testres res1;
  98                 enum clnt_stat stat;
  99 
 100                 args1.cookie = args->cookie;
 101                 args1.exclusive = args->exclusive;
 102                 nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
 103                 (void) memset(&res1, 0, sizeof (res1));
 104 
 105                 stat = nlm_test_1(&args1, &res1, client);
 106 
 107                 if (stat == RPC_SUCCESS) {
 108                         res->cookie = res1.cookie;
 109                         res->stat.stat = (enum nlm4_stats) res1.stat.stat;
 110                         if (res1.stat.stat == nlm_denied)
 111                                 nlm_convert_to_nlm4_holder(
 112                                     &res->stat.nlm4_testrply_u.holder,
 113                                     &res1.stat.nlm_testrply_u.holder);
 114                 }
 115 
 116                 return (stat);
 117         }
 118 }
 119 
 120 enum clnt_stat
 121 nlm_lock_rpc(nlm4_lockargs *args, nlm4_res *res,
 122     CLIENT *client, rpcvers_t vers)
 123 {
 124         if (vers == NLM4_VERS) {
 125                 return (nlm4_lock_4(args, res, client));
 126         } else {
 127                 nlm_lockargs args1;
 128                 nlm_res res1;
 129                 enum clnt_stat stat;
 130 
 131                 args1.cookie = args->cookie;
 132                 args1.block = args->block;
 133                 args1.exclusive = args->exclusive;
 134                 nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
 135                 args1.reclaim = args->reclaim;
 136                 args1.state = args->state;
 137                 (void) memset(&res1, 0, sizeof (res1));
 138 
 139                 stat = nlm_lock_1(&args1, &res1, client);
 140 
 141                 if (stat == RPC_SUCCESS) {
 142                         nlm_convert_to_nlm4_res(res, &res1);
 143                 }
 144 
 145                 return (stat);
 146         }
 147 }
 148 
 149 enum clnt_stat
 150 nlm_cancel_rpc(nlm4_cancargs *args, nlm4_res *res,
 151     CLIENT *client, rpcvers_t vers)
 152 {
 153         if (vers == NLM4_VERS) {
 154                 return (nlm4_cancel_4(args, res, client));
 155         } else {
 156                 nlm_cancargs args1;
 157                 nlm_res res1;
 158                 enum clnt_stat stat;
 159 
 160                 args1.cookie = args->cookie;
 161                 args1.block = args->block;
 162                 args1.exclusive = args->exclusive;
 163                 nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
 164                 (void) memset(&res1, 0, sizeof (res1));
 165 
 166                 stat = nlm_cancel_1(&args1, &res1, client);
 167 
 168                 if (stat == RPC_SUCCESS) {
 169                         nlm_convert_to_nlm4_res(res, &res1);
 170                 }
 171 
 172                 return (stat);
 173         }
 174 }
 175 
 176 enum clnt_stat
 177 nlm_unlock_rpc(nlm4_unlockargs *args, nlm4_res *res,
 178     CLIENT *client, rpcvers_t vers)
 179 {
 180         if (vers == NLM4_VERS) {
 181                 return (nlm4_unlock_4(args, res, client));
 182         } else {
 183                 nlm_unlockargs args1;
 184                 nlm_res res1;
 185                 enum clnt_stat stat;
 186 
 187                 args1.cookie = args->cookie;
 188                 nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
 189                 (void) memset(&res1, 0, sizeof (res1));
 190 
 191                 stat = nlm_unlock_1(&args1, &res1, client);
 192 
 193                 if (stat == RPC_SUCCESS) {
 194                         nlm_convert_to_nlm4_res(res, &res1);
 195                 }
 196 
 197                 return (stat);
 198         }
 199 }
 200 
 201 enum clnt_stat
 202 nlm_null_rpc(CLIENT *client, rpcvers_t vers)
 203 {
 204         if (vers == NLM4_VERS)
 205                 return (nlm4_null_4(NULL, NULL, client));
 206 
 207         return (nlm_null_1(NULL, NULL, client));
 208 }
 209 
 210 /*
 211  * Share reservations
 212  */
 213 
 214 static void
 215 nlm_convert_to_nlm_share(struct nlm_share *dst, struct nlm4_share *src)
 216 {
 217 
 218         dst->caller_name = src->caller_name;
 219         dst->fh = src->fh;
 220         dst->oh = src->oh;
 221         dst->mode = src->mode;
 222         dst->access = src->access;
 223 }
 224 
 225 static void
 226 nlm_convert_to_nlm4_shres(struct nlm4_shareres *dst,
 227         struct nlm_shareres *src)
 228 {
 229         dst->cookie = src->cookie;
 230         dst->stat = (enum nlm4_stats) src->stat;
 231         dst->sequence = src->sequence;
 232 }
 233 
 234 
 235 enum clnt_stat
 236 nlm_share_rpc(nlm4_shareargs *args, nlm4_shareres *res,
 237     CLIENT *client, rpcvers_t vers)
 238 {
 239         if (vers == NLM4_VERS) {
 240                 return (nlm4_share_4(args, res, client));
 241         } else {
 242                 nlm_shareargs args3;
 243                 nlm_shareres res3;
 244                 enum clnt_stat stat;
 245 
 246                 args3.cookie = args->cookie;
 247                 nlm_convert_to_nlm_share(&args3.share, &args->share);
 248                 args3.reclaim = args->reclaim;
 249                 (void) memset(&res3, 0, sizeof (res3));
 250 
 251                 stat = nlm_share_3(&args3, &res3, client);
 252 
 253                 if (stat == RPC_SUCCESS) {
 254                         nlm_convert_to_nlm4_shres(res, &res3);
 255                 }
 256 
 257                 return (stat);
 258         }
 259 }
 260 
 261 enum clnt_stat
 262 nlm_unshare_rpc(nlm4_shareargs *args, nlm4_shareres *res,
 263     CLIENT *client, rpcvers_t vers)
 264 {
 265         if (vers == NLM4_VERS) {
 266                 return (nlm4_unshare_4(args, res, client));
 267         } else {
 268                 nlm_shareargs args3;
 269                 nlm_shareres res3;
 270                 enum clnt_stat stat;
 271 
 272                 args3.cookie = args->cookie;
 273                 nlm_convert_to_nlm_share(&args3.share, &args->share);
 274                 args3.reclaim = args->reclaim;
 275                 (void) memset(&res3, 0, sizeof (res3));
 276 
 277                 stat = nlm_unshare_3(&args3, &res3, client);
 278 
 279                 if (stat == RPC_SUCCESS) {
 280                         nlm_convert_to_nlm4_shres(res, &res3);
 281                 }
 282 
 283                 return (stat);
 284         }
 285 }