1 /* 2 * linux/fs/lockd/xdr.c 3 * 4 * XDR support for lockd and the lock client. 5 * 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 */ 8 9 #include <linux/types.h> 10 #include <linux/sched.h> 11 #include <linux/nfs.h> 12 13 #include <linux/sunrpc/xdr.h> 14 #include <linux/sunrpc/clnt.h> 15 #include <linux/sunrpc/svc.h> 16 #include <linux/sunrpc/stats.h> 17 #include <linux/lockd/lockd.h> 18 19 #define NLMDBG_FACILITY NLMDBG_XDR 20 21 22 static inline loff_t 23 s32_to_loff_t(__s32 offset) 24 { 25 return (loff_t)offset; 26 } 27 28 static inline __s32 29 loff_t_to_s32(loff_t offset) 30 { 31 __s32 res; 32 if (offset >= NLM_OFFSET_MAX) 33 res = NLM_OFFSET_MAX; 34 else if (offset <= -NLM_OFFSET_MAX) 35 res = -NLM_OFFSET_MAX; 36 else 37 res = offset; 38 return res; 39 } 40 41 /* 42 * XDR functions for basic NLM types 43 */ 44 static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c) 45 { 46 unsigned int len; 47 48 len = ntohl(*p++); 49 50 if(len==0) 51 { 52 c->len=4; 53 memset(c->data, 0, 4); /* hockeypux brain damage */ 54 } 55 else if(len<=NLM_MAXCOOKIELEN) 56 { 57 c->len=len; 58 memcpy(c->data, p, len); 59 p+=XDR_QUADLEN(len); 60 } 61 else 62 { 63 dprintk("lockd: bad cookie size %d (only cookies under " 64 "%d bytes are supported.)\n", 65 len, NLM_MAXCOOKIELEN); 66 return NULL; 67 } 68 return p; 69 } 70 71 static inline __be32 * 72 nlm_encode_cookie(__be32 *p, struct nlm_cookie *c) 73 { 74 *p++ = htonl(c->len); 75 memcpy(p, c->data, c->len); 76 p+=XDR_QUADLEN(c->len); 77 return p; 78 } 79 80 static __be32 * 81 nlm_decode_fh(__be32 *p, struct nfs_fh *f) 82 { 83 unsigned int len; 84 85 if ((len = ntohl(*p++)) != NFS2_FHSIZE) { 86 dprintk("lockd: bad fhandle size %d (should be %d)\n", 87 len, NFS2_FHSIZE); 88 return NULL; 89 } 90 f->size = NFS2_FHSIZE; 91 memset(f->data, 0, sizeof(f->data)); 92 memcpy(f->data, p, NFS2_FHSIZE); 93 return p + XDR_QUADLEN(NFS2_FHSIZE); 94 } 95 96 static inline __be32 * 97 nlm_encode_fh(__be32 *p, struct nfs_fh *f) 98 { 99 *p++ = htonl(NFS2_FHSIZE); 100 memcpy(p, f->data, NFS2_FHSIZE); 101 return p + XDR_QUADLEN(NFS2_FHSIZE); 102 } 103 104 /* 105 * Encode and decode owner handle 106 */ 107 static inline __be32 * 108 nlm_decode_oh(__be32 *p, struct xdr_netobj *oh) 109 { 110 return xdr_decode_netobj(p, oh); 111 } 112 113 static inline __be32 * 114 nlm_encode_oh(__be32 *p, struct xdr_netobj *oh) 115 { 116 return xdr_encode_netobj(p, oh); 117 } 118 119 static __be32 * 120 nlm_decode_lock(__be32 *p, struct nlm_lock *lock) 121 { 122 struct file_lock *fl = &lock->fl; 123 s32 start, len, end; 124 125 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 126 &lock->len, 127 NLM_MAXSTRLEN)) 128 || !(p = nlm_decode_fh(p, &lock->fh)) 129 || !(p = nlm_decode_oh(p, &lock->oh))) 130 return NULL; 131 lock->svid = ntohl(*p++); 132 133 locks_init_lock(fl); 134 fl->fl_owner = current->files; 135 fl->fl_pid = (pid_t)lock->svid; 136 fl->fl_flags = FL_POSIX; 137 fl->fl_type = F_RDLCK; /* as good as anything else */ 138 start = ntohl(*p++); 139 len = ntohl(*p++); 140 end = start + len - 1; 141 142 fl->fl_start = s32_to_loff_t(start); 143 144 if (len == 0 || end < 0) 145 fl->fl_end = OFFSET_MAX; 146 else 147 fl->fl_end = s32_to_loff_t(end); 148 return p; 149 } 150 151 /* 152 * Encode result of a TEST/TEST_MSG call 153 */ 154 static __be32 * 155 nlm_encode_testres(__be32 *p, struct nlm_res *resp) 156 { 157 s32 start, len; 158 159 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 160 return NULL; 161 *p++ = resp->status; 162 163 if (resp->status == nlm_lck_denied) { 164 struct file_lock *fl = &resp->lock.fl; 165 166 *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; 167 *p++ = htonl(resp->lock.svid); 168 169 /* Encode owner handle. */ 170 if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) 171 return NULL; 172 173 start = loff_t_to_s32(fl->fl_start); 174 if (fl->fl_end == OFFSET_MAX) 175 len = 0; 176 else 177 len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); 178 179 *p++ = htonl(start); 180 *p++ = htonl(len); 181 } 182 183 return p; 184 } 185 186 187 /* 188 * First, the server side XDR functions 189 */ 190 int 191 nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 192 { 193 u32 exclusive; 194 195 if (!(p = nlm_decode_cookie(p, &argp->cookie))) 196 return 0; 197 198 exclusive = ntohl(*p++); 199 if (!(p = nlm_decode_lock(p, &argp->lock))) 200 return 0; 201 if (exclusive) 202 argp->lock.fl.fl_type = F_WRLCK; 203 204 return xdr_argsize_check(rqstp, p); 205 } 206 207 int 208 nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 209 { 210 if (!(p = nlm_encode_testres(p, resp))) 211 return 0; 212 return xdr_ressize_check(rqstp, p); 213 } 214 215 int 216 nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 217 { 218 u32 exclusive; 219 220 if (!(p = nlm_decode_cookie(p, &argp->cookie))) 221 return 0; 222 argp->block = ntohl(*p++); 223 exclusive = ntohl(*p++); 224 if (!(p = nlm_decode_lock(p, &argp->lock))) 225 return 0; 226 if (exclusive) 227 argp->lock.fl.fl_type = F_WRLCK; 228 argp->reclaim = ntohl(*p++); 229 argp->state = ntohl(*p++); 230 argp->monitor = 1; /* monitor client by default */ 231 232 return xdr_argsize_check(rqstp, p); 233 } 234 235 int 236 nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 237 { 238 u32 exclusive; 239 240 if (!(p = nlm_decode_cookie(p, &argp->cookie))) 241 return 0; 242 argp->block = ntohl(*p++); 243 exclusive = ntohl(*p++); 244 if (!(p = nlm_decode_lock(p, &argp->lock))) 245 return 0; 246 if (exclusive) 247 argp->lock.fl.fl_type = F_WRLCK; 248 return xdr_argsize_check(rqstp, p); 249 } 250 251 int 252 nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 253 { 254 if (!(p = nlm_decode_cookie(p, &argp->cookie)) 255 || !(p = nlm_decode_lock(p, &argp->lock))) 256 return 0; 257 argp->lock.fl.fl_type = F_UNLCK; 258 return xdr_argsize_check(rqstp, p); 259 } 260 261 int 262 nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 263 { 264 struct nlm_lock *lock = &argp->lock; 265 266 memset(lock, 0, sizeof(*lock)); 267 locks_init_lock(&lock->fl); 268 lock->svid = ~(u32) 0; 269 lock->fl.fl_pid = (pid_t)lock->svid; 270 271 if (!(p = nlm_decode_cookie(p, &argp->cookie)) 272 || !(p = xdr_decode_string_inplace(p, &lock->caller, 273 &lock->len, NLM_MAXSTRLEN)) 274 || !(p = nlm_decode_fh(p, &lock->fh)) 275 || !(p = nlm_decode_oh(p, &lock->oh))) 276 return 0; 277 argp->fsm_mode = ntohl(*p++); 278 argp->fsm_access = ntohl(*p++); 279 return xdr_argsize_check(rqstp, p); 280 } 281 282 int 283 nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 284 { 285 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 286 return 0; 287 *p++ = resp->status; 288 *p++ = xdr_zero; /* sequence argument */ 289 return xdr_ressize_check(rqstp, p); 290 } 291 292 int 293 nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 294 { 295 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 296 return 0; 297 *p++ = resp->status; 298 return xdr_ressize_check(rqstp, p); 299 } 300 301 int 302 nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp) 303 { 304 struct nlm_lock *lock = &argp->lock; 305 306 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 307 &lock->len, NLM_MAXSTRLEN))) 308 return 0; 309 argp->state = ntohl(*p++); 310 return xdr_argsize_check(rqstp, p); 311 } 312 313 int 314 nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp) 315 { 316 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 317 return 0; 318 argp->state = ntohl(*p++); 319 memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 320 p += XDR_QUADLEN(SM_PRIV_SIZE); 321 return xdr_argsize_check(rqstp, p); 322 } 323 324 int 325 nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 326 { 327 if (!(p = nlm_decode_cookie(p, &resp->cookie))) 328 return 0; 329 resp->status = *p++; 330 return xdr_argsize_check(rqstp, p); 331 } 332 333 int 334 nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 335 { 336 return xdr_argsize_check(rqstp, p); 337 } 338 339 int 340 nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 341 { 342 return xdr_ressize_check(rqstp, p); 343 } 344