0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/types.h>
0014 #include <linux/sunrpc/xdr.h>
0015 #include <linux/sunrpc/clnt.h>
0016 #include <linux/sunrpc/stats.h>
0017 #include <linux/lockd/lockd.h>
0018
0019 #include <uapi/linux/nfs2.h>
0020
0021 #define NLMDBG_FACILITY NLMDBG_XDR
0022
0023 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
0024 # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
0025 #endif
0026
0027
0028
0029
0030
0031 #define NLM_cookie_sz (1+(NLM_MAXCOOKIELEN>>2))
0032 #define NLM_caller_sz (1+(NLMCLNT_OHSIZE>>2))
0033 #define NLM_owner_sz (1+(NLMCLNT_OHSIZE>>2))
0034 #define NLM_fhandle_sz (1+(NFS2_FHSIZE>>2))
0035 #define NLM_lock_sz (3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz)
0036 #define NLM_holder_sz (4+NLM_owner_sz)
0037
0038 #define NLM_testargs_sz (NLM_cookie_sz+1+NLM_lock_sz)
0039 #define NLM_lockargs_sz (NLM_cookie_sz+4+NLM_lock_sz)
0040 #define NLM_cancargs_sz (NLM_cookie_sz+2+NLM_lock_sz)
0041 #define NLM_unlockargs_sz (NLM_cookie_sz+NLM_lock_sz)
0042
0043 #define NLM_testres_sz (NLM_cookie_sz+1+NLM_holder_sz)
0044 #define NLM_res_sz (NLM_cookie_sz+1)
0045 #define NLM_norep_sz (0)
0046
0047
0048 static s32 loff_t_to_s32(loff_t offset)
0049 {
0050 s32 res;
0051
0052 if (offset >= NLM_OFFSET_MAX)
0053 res = NLM_OFFSET_MAX;
0054 else if (offset <= -NLM_OFFSET_MAX)
0055 res = -NLM_OFFSET_MAX;
0056 else
0057 res = offset;
0058 return res;
0059 }
0060
0061 static void nlm_compute_offsets(const struct nlm_lock *lock,
0062 u32 *l_offset, u32 *l_len)
0063 {
0064 const struct file_lock *fl = &lock->fl;
0065
0066 *l_offset = loff_t_to_s32(fl->fl_start);
0067 if (fl->fl_end == OFFSET_MAX)
0068 *l_len = 0;
0069 else
0070 *l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 static void encode_bool(struct xdr_stream *xdr, const int value)
0087 {
0088 __be32 *p;
0089
0090 p = xdr_reserve_space(xdr, 4);
0091 *p = value ? xdr_one : xdr_zero;
0092 }
0093
0094 static void encode_int32(struct xdr_stream *xdr, const s32 value)
0095 {
0096 __be32 *p;
0097
0098 p = xdr_reserve_space(xdr, 4);
0099 *p = cpu_to_be32(value);
0100 }
0101
0102
0103
0104
0105 static void encode_netobj(struct xdr_stream *xdr,
0106 const u8 *data, const unsigned int length)
0107 {
0108 __be32 *p;
0109
0110 p = xdr_reserve_space(xdr, 4 + length);
0111 xdr_encode_opaque(p, data, length);
0112 }
0113
0114 static int decode_netobj(struct xdr_stream *xdr,
0115 struct xdr_netobj *obj)
0116 {
0117 ssize_t ret;
0118
0119 ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
0120 XDR_MAX_NETOBJ);
0121 if (unlikely(ret < 0))
0122 return -EIO;
0123 obj->len = ret;
0124 return 0;
0125 }
0126
0127
0128
0129
0130 static void encode_cookie(struct xdr_stream *xdr,
0131 const struct nlm_cookie *cookie)
0132 {
0133 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
0134 }
0135
0136 static int decode_cookie(struct xdr_stream *xdr,
0137 struct nlm_cookie *cookie)
0138 {
0139 u32 length;
0140 __be32 *p;
0141
0142 p = xdr_inline_decode(xdr, 4);
0143 if (unlikely(p == NULL))
0144 goto out_overflow;
0145 length = be32_to_cpup(p++);
0146
0147 if (length == 0)
0148 goto out_hpux;
0149 if (length > NLM_MAXCOOKIELEN)
0150 goto out_size;
0151 p = xdr_inline_decode(xdr, length);
0152 if (unlikely(p == NULL))
0153 goto out_overflow;
0154 cookie->len = length;
0155 memcpy(cookie->data, p, length);
0156 return 0;
0157 out_hpux:
0158 cookie->len = 4;
0159 memset(cookie->data, 0, 4);
0160 return 0;
0161 out_size:
0162 dprintk("NFS: returned cookie was too long: %u\n", length);
0163 return -EIO;
0164 out_overflow:
0165 return -EIO;
0166 }
0167
0168
0169
0170
0171 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
0172 {
0173 encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195 static void encode_nlm_stat(struct xdr_stream *xdr,
0196 const __be32 stat)
0197 {
0198 __be32 *p;
0199
0200 WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
0201 p = xdr_reserve_space(xdr, 4);
0202 *p = stat;
0203 }
0204
0205 static int decode_nlm_stat(struct xdr_stream *xdr,
0206 __be32 *stat)
0207 {
0208 __be32 *p;
0209
0210 p = xdr_inline_decode(xdr, 4);
0211 if (unlikely(p == NULL))
0212 goto out_overflow;
0213 if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
0214 goto out_enum;
0215 *stat = *p;
0216 return 0;
0217 out_enum:
0218 dprintk("%s: server returned invalid nlm_stats value: %u\n",
0219 __func__, be32_to_cpup(p));
0220 return -EIO;
0221 out_overflow:
0222 return -EIO;
0223 }
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 static void encode_nlm_holder(struct xdr_stream *xdr,
0235 const struct nlm_res *result)
0236 {
0237 const struct nlm_lock *lock = &result->lock;
0238 u32 l_offset, l_len;
0239 __be32 *p;
0240
0241 encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
0242 encode_int32(xdr, lock->svid);
0243 encode_netobj(xdr, lock->oh.data, lock->oh.len);
0244
0245 p = xdr_reserve_space(xdr, 4 + 4);
0246 nlm_compute_offsets(lock, &l_offset, &l_len);
0247 *p++ = cpu_to_be32(l_offset);
0248 *p = cpu_to_be32(l_len);
0249 }
0250
0251 static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result)
0252 {
0253 struct nlm_lock *lock = &result->lock;
0254 struct file_lock *fl = &lock->fl;
0255 u32 exclusive, l_offset, l_len;
0256 int error;
0257 __be32 *p;
0258 s32 end;
0259
0260 memset(lock, 0, sizeof(*lock));
0261 locks_init_lock(fl);
0262
0263 p = xdr_inline_decode(xdr, 4 + 4);
0264 if (unlikely(p == NULL))
0265 goto out_overflow;
0266 exclusive = be32_to_cpup(p++);
0267 lock->svid = be32_to_cpup(p);
0268 fl->fl_pid = (pid_t)lock->svid;
0269
0270 error = decode_netobj(xdr, &lock->oh);
0271 if (unlikely(error))
0272 goto out;
0273
0274 p = xdr_inline_decode(xdr, 4 + 4);
0275 if (unlikely(p == NULL))
0276 goto out_overflow;
0277
0278 fl->fl_flags = FL_POSIX;
0279 fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK;
0280 l_offset = be32_to_cpup(p++);
0281 l_len = be32_to_cpup(p);
0282 end = l_offset + l_len - 1;
0283
0284 fl->fl_start = (loff_t)l_offset;
0285 if (l_len == 0 || end < 0)
0286 fl->fl_end = OFFSET_MAX;
0287 else
0288 fl->fl_end = (loff_t)end;
0289 error = 0;
0290 out:
0291 return error;
0292 out_overflow:
0293 return -EIO;
0294 }
0295
0296
0297
0298
0299 static void encode_caller_name(struct xdr_stream *xdr, const char *name)
0300 {
0301
0302 u32 length = strlen(name);
0303 __be32 *p;
0304
0305 p = xdr_reserve_space(xdr, 4 + length);
0306 xdr_encode_opaque(p, name, length);
0307 }
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319 static void encode_nlm_lock(struct xdr_stream *xdr,
0320 const struct nlm_lock *lock)
0321 {
0322 u32 l_offset, l_len;
0323 __be32 *p;
0324
0325 encode_caller_name(xdr, lock->caller);
0326 encode_fh(xdr, &lock->fh);
0327 encode_netobj(xdr, lock->oh.data, lock->oh.len);
0328
0329 p = xdr_reserve_space(xdr, 4 + 4 + 4);
0330 *p++ = cpu_to_be32(lock->svid);
0331
0332 nlm_compute_offsets(lock, &l_offset, &l_len);
0333 *p++ = cpu_to_be32(l_offset);
0334 *p = cpu_to_be32(l_len);
0335 }
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 static void nlm_xdr_enc_testargs(struct rpc_rqst *req,
0353 struct xdr_stream *xdr,
0354 const void *data)
0355 {
0356 const struct nlm_args *args = data;
0357 const struct nlm_lock *lock = &args->lock;
0358
0359 encode_cookie(xdr, &args->cookie);
0360 encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0361 encode_nlm_lock(xdr, lock);
0362 }
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 static void nlm_xdr_enc_lockargs(struct rpc_rqst *req,
0375 struct xdr_stream *xdr,
0376 const void *data)
0377 {
0378 const struct nlm_args *args = data;
0379 const struct nlm_lock *lock = &args->lock;
0380
0381 encode_cookie(xdr, &args->cookie);
0382 encode_bool(xdr, args->block);
0383 encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0384 encode_nlm_lock(xdr, lock);
0385 encode_bool(xdr, args->reclaim);
0386 encode_int32(xdr, args->state);
0387 }
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 static void nlm_xdr_enc_cancargs(struct rpc_rqst *req,
0398 struct xdr_stream *xdr,
0399 const void *data)
0400 {
0401 const struct nlm_args *args = data;
0402 const struct nlm_lock *lock = &args->lock;
0403
0404 encode_cookie(xdr, &args->cookie);
0405 encode_bool(xdr, args->block);
0406 encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0407 encode_nlm_lock(xdr, lock);
0408 }
0409
0410
0411
0412
0413
0414
0415
0416 static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req,
0417 struct xdr_stream *xdr,
0418 const void *data)
0419 {
0420 const struct nlm_args *args = data;
0421 const struct nlm_lock *lock = &args->lock;
0422
0423 encode_cookie(xdr, &args->cookie);
0424 encode_nlm_lock(xdr, lock);
0425 }
0426
0427
0428
0429
0430
0431
0432
0433 static void nlm_xdr_enc_res(struct rpc_rqst *req,
0434 struct xdr_stream *xdr,
0435 const void *data)
0436 {
0437 const struct nlm_res *result = data;
0438
0439 encode_cookie(xdr, &result->cookie);
0440 encode_nlm_stat(xdr, result->status);
0441 }
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 static void encode_nlm_testrply(struct xdr_stream *xdr,
0457 const struct nlm_res *result)
0458 {
0459 if (result->status == nlm_lck_denied)
0460 encode_nlm_holder(xdr, result);
0461 }
0462
0463 static void nlm_xdr_enc_testres(struct rpc_rqst *req,
0464 struct xdr_stream *xdr,
0465 const void *data)
0466 {
0467 const struct nlm_res *result = data;
0468
0469 encode_cookie(xdr, &result->cookie);
0470 encode_nlm_stat(xdr, result->status);
0471 encode_nlm_testrply(xdr, result);
0472 }
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495 static int decode_nlm_testrply(struct xdr_stream *xdr,
0496 struct nlm_res *result)
0497 {
0498 int error;
0499
0500 error = decode_nlm_stat(xdr, &result->status);
0501 if (unlikely(error))
0502 goto out;
0503 if (result->status == nlm_lck_denied)
0504 error = decode_nlm_holder(xdr, result);
0505 out:
0506 return error;
0507 }
0508
0509 static int nlm_xdr_dec_testres(struct rpc_rqst *req,
0510 struct xdr_stream *xdr,
0511 void *data)
0512 {
0513 struct nlm_res *result = data;
0514 int error;
0515
0516 error = decode_cookie(xdr, &result->cookie);
0517 if (unlikely(error))
0518 goto out;
0519 error = decode_nlm_testrply(xdr, result);
0520 out:
0521 return error;
0522 }
0523
0524
0525
0526
0527
0528
0529
0530 static int nlm_xdr_dec_res(struct rpc_rqst *req,
0531 struct xdr_stream *xdr,
0532 void *data)
0533 {
0534 struct nlm_res *result = data;
0535 int error;
0536
0537 error = decode_cookie(xdr, &result->cookie);
0538 if (unlikely(error))
0539 goto out;
0540 error = decode_nlm_stat(xdr, &result->status);
0541 out:
0542 return error;
0543 }
0544
0545
0546
0547
0548
0549 #define nlm_xdr_dec_norep NULL
0550
0551 #define PROC(proc, argtype, restype) \
0552 [NLMPROC_##proc] = { \
0553 .p_proc = NLMPROC_##proc, \
0554 .p_encode = nlm_xdr_enc_##argtype, \
0555 .p_decode = nlm_xdr_dec_##restype, \
0556 .p_arglen = NLM_##argtype##_sz, \
0557 .p_replen = NLM_##restype##_sz, \
0558 .p_statidx = NLMPROC_##proc, \
0559 .p_name = #proc, \
0560 }
0561
0562 static const struct rpc_procinfo nlm_procedures[] = {
0563 PROC(TEST, testargs, testres),
0564 PROC(LOCK, lockargs, res),
0565 PROC(CANCEL, cancargs, res),
0566 PROC(UNLOCK, unlockargs, res),
0567 PROC(GRANTED, testargs, res),
0568 PROC(TEST_MSG, testargs, norep),
0569 PROC(LOCK_MSG, lockargs, norep),
0570 PROC(CANCEL_MSG, cancargs, norep),
0571 PROC(UNLOCK_MSG, unlockargs, norep),
0572 PROC(GRANTED_MSG, testargs, norep),
0573 PROC(TEST_RES, testres, norep),
0574 PROC(LOCK_RES, res, norep),
0575 PROC(CANCEL_RES, res, norep),
0576 PROC(UNLOCK_RES, res, norep),
0577 PROC(GRANTED_RES, res, norep),
0578 };
0579
0580 static unsigned int nlm_version1_counts[ARRAY_SIZE(nlm_procedures)];
0581 static const struct rpc_version nlm_version1 = {
0582 .number = 1,
0583 .nrprocs = ARRAY_SIZE(nlm_procedures),
0584 .procs = nlm_procedures,
0585 .counts = nlm_version1_counts,
0586 };
0587
0588 static unsigned int nlm_version3_counts[ARRAY_SIZE(nlm_procedures)];
0589 static const struct rpc_version nlm_version3 = {
0590 .number = 3,
0591 .nrprocs = ARRAY_SIZE(nlm_procedures),
0592 .procs = nlm_procedures,
0593 .counts = nlm_version3_counts,
0594 };
0595
0596 static const struct rpc_version *nlm_versions[] = {
0597 [1] = &nlm_version1,
0598 [3] = &nlm_version3,
0599 #ifdef CONFIG_LOCKD_V4
0600 [4] = &nlm_version4,
0601 #endif
0602 };
0603
0604 static struct rpc_stat nlm_rpc_stats;
0605
0606 const struct rpc_program nlm_program = {
0607 .name = "lockd",
0608 .number = NLM_PROGRAM,
0609 .nrvers = ARRAY_SIZE(nlm_versions),
0610 .version = nlm_versions,
0611 .stats = &nlm_rpc_stats,
0612 };