0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/types.h>
0011 #include <linux/sched.h>
0012 #include <linux/nfs.h>
0013
0014 #include <linux/sunrpc/xdr.h>
0015 #include <linux/sunrpc/clnt.h>
0016 #include <linux/sunrpc/svc.h>
0017 #include <linux/sunrpc/stats.h>
0018 #include <linux/lockd/lockd.h>
0019
0020 #include <uapi/linux/nfs2.h>
0021
0022 #include "svcxdr.h"
0023
0024
0025 static inline loff_t
0026 s32_to_loff_t(__s32 offset)
0027 {
0028 return (loff_t)offset;
0029 }
0030
0031 static inline __s32
0032 loff_t_to_s32(loff_t offset)
0033 {
0034 __s32 res;
0035 if (offset >= NLM_OFFSET_MAX)
0036 res = NLM_OFFSET_MAX;
0037 else if (offset <= -NLM_OFFSET_MAX)
0038 res = -NLM_OFFSET_MAX;
0039 else
0040 res = offset;
0041 return res;
0042 }
0043
0044
0045
0046
0047
0048
0049
0050 static bool
0051 svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
0052 {
0053 __be32 *p;
0054 u32 len;
0055
0056 if (xdr_stream_decode_u32(xdr, &len) < 0)
0057 return false;
0058 if (len != NFS2_FHSIZE)
0059 return false;
0060
0061 p = xdr_inline_decode(xdr, len);
0062 if (!p)
0063 return false;
0064 fh->size = NFS2_FHSIZE;
0065 memcpy(fh->data, p, len);
0066 memset(fh->data + NFS2_FHSIZE, 0, sizeof(fh->data) - NFS2_FHSIZE);
0067
0068 return true;
0069 }
0070
0071 static bool
0072 svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
0073 {
0074 struct file_lock *fl = &lock->fl;
0075 s32 start, len, end;
0076
0077 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
0078 return false;
0079 if (!svcxdr_decode_fhandle(xdr, &lock->fh))
0080 return false;
0081 if (!svcxdr_decode_owner(xdr, &lock->oh))
0082 return false;
0083 if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
0084 return false;
0085 if (xdr_stream_decode_u32(xdr, &start) < 0)
0086 return false;
0087 if (xdr_stream_decode_u32(xdr, &len) < 0)
0088 return false;
0089
0090 locks_init_lock(fl);
0091 fl->fl_flags = FL_POSIX;
0092 fl->fl_type = F_RDLCK;
0093 end = start + len - 1;
0094 fl->fl_start = s32_to_loff_t(start);
0095 if (len == 0 || end < 0)
0096 fl->fl_end = OFFSET_MAX;
0097 else
0098 fl->fl_end = s32_to_loff_t(end);
0099
0100 return true;
0101 }
0102
0103 static bool
0104 svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
0105 {
0106 const struct file_lock *fl = &lock->fl;
0107 s32 start, len;
0108
0109
0110 if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
0111 return false;
0112 if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
0113 return false;
0114 if (!svcxdr_encode_owner(xdr, &lock->oh))
0115 return false;
0116 start = loff_t_to_s32(fl->fl_start);
0117 if (fl->fl_end == OFFSET_MAX)
0118 len = 0;
0119 else
0120 len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
0121 if (xdr_stream_encode_u32(xdr, start) < 0)
0122 return false;
0123 if (xdr_stream_encode_u32(xdr, len) < 0)
0124 return false;
0125
0126 return true;
0127 }
0128
0129 static bool
0130 svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
0131 {
0132 if (!svcxdr_encode_stats(xdr, resp->status))
0133 return false;
0134 switch (resp->status) {
0135 case nlm_lck_denied:
0136 if (!svcxdr_encode_holder(xdr, &resp->lock))
0137 return false;
0138 }
0139
0140 return true;
0141 }
0142
0143
0144
0145
0146
0147
0148 bool
0149 nlmsvc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0150 {
0151 return true;
0152 }
0153
0154 bool
0155 nlmsvc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0156 {
0157 struct nlm_args *argp = rqstp->rq_argp;
0158 u32 exclusive;
0159
0160 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0161 return false;
0162 if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
0163 return false;
0164 if (!svcxdr_decode_lock(xdr, &argp->lock))
0165 return false;
0166 if (exclusive)
0167 argp->lock.fl.fl_type = F_WRLCK;
0168
0169 return true;
0170 }
0171
0172 bool
0173 nlmsvc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0174 {
0175 struct nlm_args *argp = rqstp->rq_argp;
0176 u32 exclusive;
0177
0178 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0179 return false;
0180 if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
0181 return false;
0182 if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
0183 return false;
0184 if (!svcxdr_decode_lock(xdr, &argp->lock))
0185 return false;
0186 if (exclusive)
0187 argp->lock.fl.fl_type = F_WRLCK;
0188 if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
0189 return false;
0190 if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
0191 return false;
0192 argp->monitor = 1;
0193
0194 return true;
0195 }
0196
0197 bool
0198 nlmsvc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0199 {
0200 struct nlm_args *argp = rqstp->rq_argp;
0201 u32 exclusive;
0202
0203 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0204 return false;
0205 if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
0206 return false;
0207 if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
0208 return false;
0209 if (!svcxdr_decode_lock(xdr, &argp->lock))
0210 return false;
0211 if (exclusive)
0212 argp->lock.fl.fl_type = F_WRLCK;
0213
0214 return true;
0215 }
0216
0217 bool
0218 nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0219 {
0220 struct nlm_args *argp = rqstp->rq_argp;
0221
0222 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0223 return false;
0224 if (!svcxdr_decode_lock(xdr, &argp->lock))
0225 return false;
0226 argp->lock.fl.fl_type = F_UNLCK;
0227
0228 return true;
0229 }
0230
0231 bool
0232 nlmsvc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0233 {
0234 struct nlm_res *resp = rqstp->rq_argp;
0235
0236 if (!svcxdr_decode_cookie(xdr, &resp->cookie))
0237 return false;
0238 if (!svcxdr_decode_stats(xdr, &resp->status))
0239 return false;
0240
0241 return true;
0242 }
0243
0244 bool
0245 nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0246 {
0247 struct nlm_reboot *argp = rqstp->rq_argp;
0248 __be32 *p;
0249 u32 len;
0250
0251 if (xdr_stream_decode_u32(xdr, &len) < 0)
0252 return false;
0253 if (len > SM_MAXSTRLEN)
0254 return false;
0255 p = xdr_inline_decode(xdr, len);
0256 if (!p)
0257 return false;
0258 argp->len = len;
0259 argp->mon = (char *)p;
0260 if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
0261 return false;
0262 p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
0263 if (!p)
0264 return false;
0265 memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
0266
0267 return true;
0268 }
0269
0270 bool
0271 nlmsvc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0272 {
0273 struct nlm_args *argp = rqstp->rq_argp;
0274 struct nlm_lock *lock = &argp->lock;
0275
0276 memset(lock, 0, sizeof(*lock));
0277 locks_init_lock(&lock->fl);
0278 lock->svid = ~(u32)0;
0279
0280 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0281 return false;
0282 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
0283 return false;
0284 if (!svcxdr_decode_fhandle(xdr, &lock->fh))
0285 return false;
0286 if (!svcxdr_decode_owner(xdr, &lock->oh))
0287 return false;
0288
0289 if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
0290 return false;
0291 if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
0292 return false;
0293
0294 return true;
0295 }
0296
0297 bool
0298 nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0299 {
0300 struct nlm_args *argp = rqstp->rq_argp;
0301 struct nlm_lock *lock = &argp->lock;
0302
0303 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
0304 return false;
0305 if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
0306 return false;
0307
0308 return true;
0309 }
0310
0311
0312
0313
0314
0315
0316 bool
0317 nlmsvc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0318 {
0319 return true;
0320 }
0321
0322 bool
0323 nlmsvc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0324 {
0325 struct nlm_res *resp = rqstp->rq_resp;
0326
0327 return svcxdr_encode_cookie(xdr, &resp->cookie) &&
0328 svcxdr_encode_testrply(xdr, resp);
0329 }
0330
0331 bool
0332 nlmsvc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0333 {
0334 struct nlm_res *resp = rqstp->rq_resp;
0335
0336 return svcxdr_encode_cookie(xdr, &resp->cookie) &&
0337 svcxdr_encode_stats(xdr, resp->status);
0338 }
0339
0340 bool
0341 nlmsvc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0342 {
0343 struct nlm_res *resp = rqstp->rq_resp;
0344
0345 if (!svcxdr_encode_cookie(xdr, &resp->cookie))
0346 return false;
0347 if (!svcxdr_encode_stats(xdr, resp->status))
0348 return false;
0349
0350 if (xdr_stream_encode_u32(xdr, 0) < 0)
0351 return false;
0352
0353 return true;
0354 }