1 /* 2 * linux/fs/nfs/callback.c 3 * 4 * Copyright (C) 2004 Trond Myklebust 5 * 6 * NFSv4 callback handling 7 */ 8 9 #include <linux/completion.h> 10 #include <linux/ip.h> 11 #include <linux/module.h> 12 #include <linux/sunrpc/svc.h> 13 #include <linux/sunrpc/svcsock.h> 14 #include <linux/nfs_fs.h> 15 #include <linux/mutex.h> 16 #include <linux/freezer.h> 17 #include <linux/kthread.h> 18 #include <linux/sunrpc/svcauth_gss.h> 19 #include <linux/sunrpc/bc_xprt.h> 20 21 #include <net/inet_sock.h> 22 23 #include "nfs4_fs.h" 24 #include "callback.h" 25 #include "internal.h" 26 27 #define NFSDBG_FACILITY NFSDBG_CALLBACK 28 29 struct nfs_callback_data { 30 unsigned int users; 31 struct svc_serv *serv; 32 struct svc_rqst *rqst; 33 struct task_struct *task; 34 }; 35 36 static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1]; 37 static DEFINE_MUTEX(nfs_callback_mutex); 38 static struct svc_program nfs4_callback_program; 39 40 unsigned int nfs_callback_set_tcpport; 41 unsigned short nfs_callback_tcpport; 42 unsigned short nfs_callback_tcpport6; 43 #define NFS_CALLBACK_MAXPORTNR (65535U) 44 45 static int param_set_portnr(const char *val, const struct kernel_param *kp) 46 { 47 unsigned long num; 48 int ret; 49 50 if (!val) 51 return -EINVAL; 52 ret = strict_strtoul(val, 0, &num); 53 if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR) 54 return -EINVAL; 55 *((unsigned int *)kp->arg) = num; 56 return 0; 57 } 58 static struct kernel_param_ops param_ops_portnr = { 59 .set = param_set_portnr, 60 .get = param_get_uint, 61 }; 62 #define param_check_portnr(name, p) __param_check(name, p, unsigned int); 63 64 module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); 65 66 /* 67 * This is the NFSv4 callback kernel thread. 68 */ 69 static int 70 nfs4_callback_svc(void *vrqstp) 71 { 72 int err, preverr = 0; 73 struct svc_rqst *rqstp = vrqstp; 74 75 set_freezable(); 76 77 while (!kthread_should_stop()) { 78 /* 79 * Listen for a request on the socket 80 */ 81 err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); 82 if (err == -EAGAIN || err == -EINTR) { 83 preverr = err; 84 continue; 85 } 86 if (err < 0) { 87 if (err != preverr) { 88 printk(KERN_WARNING "NFS: %s: unexpected error " 89 "from svc_recv (%d)\n", __func__, err); 90 preverr = err; 91 } 92 schedule_timeout_uninterruptible(HZ); 93 continue; 94 } 95 preverr = err; 96 svc_process(rqstp); 97 } 98 return 0; 99 } 100 101 /* 102 * Prepare to bring up the NFSv4 callback service 103 */ 104 static struct svc_rqst * 105 nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) 106 { 107 int ret; 108 109 ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, 110 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 111 if (ret <= 0) 112 goto out_err; 113 nfs_callback_tcpport = ret; 114 dprintk("NFS: Callback listener port = %u (af %u)\n", 115 nfs_callback_tcpport, PF_INET); 116 117 ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, 118 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 119 if (ret > 0) { 120 nfs_callback_tcpport6 = ret; 121 dprintk("NFS: Callback listener port = %u (af %u)\n", 122 nfs_callback_tcpport6, PF_INET6); 123 } else if (ret == -EAFNOSUPPORT) 124 ret = 0; 125 else 126 goto out_err; 127 128 return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); 129 130 out_err: 131 if (ret == 0) 132 ret = -ENOMEM; 133 return ERR_PTR(ret); 134 } 135 136 #if defined(CONFIG_NFS_V4_1) 137 /* 138 * The callback service for NFSv4.1 callbacks 139 */ 140 static int 141 nfs41_callback_svc(void *vrqstp) 142 { 143 struct svc_rqst *rqstp = vrqstp; 144 struct svc_serv *serv = rqstp->rq_server; 145 struct rpc_rqst *req; 146 int error; 147 DEFINE_WAIT(wq); 148 149 set_freezable(); 150 151 while (!kthread_should_stop()) { 152 prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); 153 spin_lock_bh(&serv->sv_cb_lock); 154 if (!list_empty(&serv->sv_cb_list)) { 155 req = list_first_entry(&serv->sv_cb_list, 156 struct rpc_rqst, rq_bc_list); 157 list_del(&req->rq_bc_list); 158 spin_unlock_bh(&serv->sv_cb_lock); 159 dprintk("Invoking bc_svc_process()\n"); 160 error = bc_svc_process(serv, req, rqstp); 161 dprintk("bc_svc_process() returned w/ error code= %d\n", 162 error); 163 } else { 164 spin_unlock_bh(&serv->sv_cb_lock); 165 schedule(); 166 } 167 finish_wait(&serv->sv_cb_waitq, &wq); 168 } 169 return 0; 170 } 171 172 /* 173 * Bring up the NFSv4.1 callback service 174 */ 175 static struct svc_rqst * 176 nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) 177 { 178 struct svc_rqst *rqstp; 179 int ret; 180 181 /* 182 * Create an svc_sock for the back channel service that shares the 183 * fore channel connection. 184 * Returns the input port (0) and sets the svc_serv bc_xprt on success 185 */ 186 ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, 187 SVC_SOCK_ANONYMOUS); 188 if (ret < 0) { 189 rqstp = ERR_PTR(ret); 190 goto out; 191 } 192 193 /* 194 * Save the svc_serv in the transport so that it can 195 * be referenced when the session backchannel is initialized 196 */ 197 xprt->bc_serv = serv; 198 199 INIT_LIST_HEAD(&serv->sv_cb_list); 200 spin_lock_init(&serv->sv_cb_lock); 201 init_waitqueue_head(&serv->sv_cb_waitq); 202 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); 203 if (IS_ERR(rqstp)) { 204 svc_xprt_put(serv->sv_bc_xprt); 205 serv->sv_bc_xprt = NULL; 206 } 207 out: 208 dprintk("--> %s return %ld\n", __func__, 209 IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0); 210 return rqstp; 211 } 212 213 static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, 214 struct svc_serv *serv, struct rpc_xprt *xprt, 215 struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) 216 { 217 if (minorversion) { 218 *rqstpp = nfs41_callback_up(serv, xprt); 219 *callback_svc = nfs41_callback_svc; 220 } 221 return minorversion; 222 } 223 224 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 225 struct nfs_callback_data *cb_info) 226 { 227 if (minorversion) 228 xprt->bc_serv = cb_info->serv; 229 } 230 #else 231 static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, 232 struct svc_serv *serv, struct rpc_xprt *xprt, 233 struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) 234 { 235 return 0; 236 } 237 238 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 239 struct nfs_callback_data *cb_info) 240 { 241 } 242 #endif /* CONFIG_NFS_V4_1 */ 243 244 /* 245 * Bring up the callback thread if it is not already up. 246 */ 247 int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) 248 { 249 struct svc_serv *serv = NULL; 250 struct svc_rqst *rqstp; 251 int (*callback_svc)(void *vrqstp); 252 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 253 char svc_name[12]; 254 int ret = 0; 255 int minorversion_setup; 256 struct net *net = &init_net; 257 258 mutex_lock(&nfs_callback_mutex); 259 if (cb_info->users++ || cb_info->task != NULL) { 260 nfs_callback_bc_serv(minorversion, xprt, cb_info); 261 goto out; 262 } 263 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); 264 if (!serv) { 265 ret = -ENOMEM; 266 goto out_err; 267 } 268 269 ret = svc_bind(serv, net); 270 if (ret < 0) { 271 printk(KERN_WARNING "NFS: bind callback service failed\n"); 272 goto out_err; 273 } 274 275 minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, 276 serv, xprt, &rqstp, &callback_svc); 277 if (!minorversion_setup) { 278 /* v4.0 callback setup */ 279 rqstp = nfs4_callback_up(serv, xprt); 280 callback_svc = nfs4_callback_svc; 281 } 282 283 if (IS_ERR(rqstp)) { 284 ret = PTR_ERR(rqstp); 285 goto out_err; 286 } 287 288 svc_sock_update_bufs(serv); 289 290 sprintf(svc_name, "nfsv4.%u-svc", minorversion); 291 cb_info->serv = serv; 292 cb_info->rqst = rqstp; 293 cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name); 294 if (IS_ERR(cb_info->task)) { 295 ret = PTR_ERR(cb_info->task); 296 svc_exit_thread(cb_info->rqst); 297 cb_info->rqst = NULL; 298 cb_info->task = NULL; 299 goto out_err; 300 } 301 out: 302 /* 303 * svc_create creates the svc_serv with sv_nrthreads == 1, and then 304 * svc_prepare_thread increments that. So we need to call svc_destroy 305 * on both success and failure so that the refcount is 1 when the 306 * thread exits. 307 */ 308 if (serv) 309 svc_destroy(serv); 310 mutex_unlock(&nfs_callback_mutex); 311 return ret; 312 out_err: 313 dprintk("NFS: Couldn't create callback socket or server thread; " 314 "err = %d\n", ret); 315 cb_info->users--; 316 if (serv) 317 svc_shutdown_net(serv, net); 318 goto out; 319 } 320 321 /* 322 * Kill the callback thread if it's no longer being used. 323 */ 324 void nfs_callback_down(int minorversion) 325 { 326 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 327 328 mutex_lock(&nfs_callback_mutex); 329 cb_info->users--; 330 if (cb_info->users == 0 && cb_info->task != NULL) { 331 kthread_stop(cb_info->task); 332 svc_shutdown_net(cb_info->serv, &init_net); 333 svc_exit_thread(cb_info->rqst); 334 cb_info->serv = NULL; 335 cb_info->rqst = NULL; 336 cb_info->task = NULL; 337 } 338 mutex_unlock(&nfs_callback_mutex); 339 } 340 341 /* Boolean check of RPC_AUTH_GSS principal */ 342 int 343 check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp) 344 { 345 char *p = rqstp->rq_cred.cr_principal; 346 347 if (rqstp->rq_authop->flavour != RPC_AUTH_GSS) 348 return 1; 349 350 /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */ 351 if (clp->cl_minorversion != 0) 352 return 0; 353 /* 354 * It might just be a normal user principal, in which case 355 * userspace won't bother to tell us the name at all. 356 */ 357 if (p == NULL) 358 return 0; 359 360 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ 361 362 if (memcmp(p, "nfs@", 4) != 0) 363 return 0; 364 p += 4; 365 if (strcmp(p, clp->cl_hostname) != 0) 366 return 0; 367 return 1; 368 } 369 370 /* 371 * pg_authenticate method for nfsv4 callback threads. 372 * 373 * The authflavor has been negotiated, so an incorrect flavor is a server 374 * bug. Drop packets with incorrect authflavor. 375 * 376 * All other checking done after NFS decoding where the nfs_client can be 377 * found in nfs4_callback_compound 378 */ 379 static int nfs_callback_authenticate(struct svc_rqst *rqstp) 380 { 381 switch (rqstp->rq_authop->flavour) { 382 case RPC_AUTH_NULL: 383 if (rqstp->rq_proc != CB_NULL) 384 return SVC_DROP; 385 break; 386 case RPC_AUTH_GSS: 387 /* No RPC_AUTH_GSS support yet in NFSv4.1 */ 388 if (svc_is_backchannel(rqstp)) 389 return SVC_DROP; 390 } 391 return SVC_OK; 392 } 393 394 /* 395 * Define NFS4 callback program 396 */ 397 static struct svc_version *nfs4_callback_version[] = { 398 [1] = &nfs4_callback_version1, 399 [4] = &nfs4_callback_version4, 400 }; 401 402 static struct svc_stat nfs4_callback_stats; 403 404 static struct svc_program nfs4_callback_program = { 405 .pg_prog = NFS4_CALLBACK, /* RPC service number */ 406 .pg_nvers = ARRAY_SIZE(nfs4_callback_version), /* Number of entries */ 407 .pg_vers = nfs4_callback_version, /* version table */ 408 .pg_name = "NFSv4 callback", /* service name */ 409 .pg_class = "nfs", /* authentication class */ 410 .pg_stats = &nfs4_callback_stats, 411 .pg_authenticate = nfs_callback_authenticate, 412 }; 413