root/fs/lockd/svc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_lockd_grace_period
  2. grace_ender
  3. set_grace_period
  4. restart_grace
  5. lockd
  6. create_lockd_listener
  7. create_lockd_family
  8. make_socks
  9. lockd_up_net
  10. lockd_down_net
  11. lockd_inetaddr_event
  12. lockd_inet6addr_event
  13. lockd_unregister_notifiers
  14. lockd_svc_exit_thread
  15. lockd_start_svc
  16. lockd_create_svc
  17. lockd_up
  18. lockd_down
  19. is_callback
  20. lockd_authenticate
  21. param_set_min_max
  22. lockd_exit_net
  23. init_nlm
  24. exit_nlm

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * linux/fs/lockd/svc.c
   4  *
   5  * This is the central lockd service.
   6  *
   7  * FIXME: Separate the lockd NFS server functionality from the lockd NFS
   8  *        client functionality. Oh why didn't Sun create two separate
   9  *        services in the first place?
  10  *
  11  * Authors:     Olaf Kirch (okir@monad.swb.de)
  12  *
  13  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  14  */
  15 
  16 #include <linux/module.h>
  17 #include <linux/init.h>
  18 #include <linux/sysctl.h>
  19 #include <linux/moduleparam.h>
  20 
  21 #include <linux/sched/signal.h>
  22 #include <linux/errno.h>
  23 #include <linux/in.h>
  24 #include <linux/uio.h>
  25 #include <linux/smp.h>
  26 #include <linux/mutex.h>
  27 #include <linux/kthread.h>
  28 #include <linux/freezer.h>
  29 #include <linux/inetdevice.h>
  30 
  31 #include <linux/sunrpc/types.h>
  32 #include <linux/sunrpc/stats.h>
  33 #include <linux/sunrpc/clnt.h>
  34 #include <linux/sunrpc/svc.h>
  35 #include <linux/sunrpc/svcsock.h>
  36 #include <linux/sunrpc/svc_xprt.h>
  37 #include <net/ip.h>
  38 #include <net/addrconf.h>
  39 #include <net/ipv6.h>
  40 #include <linux/lockd/lockd.h>
  41 #include <linux/nfs.h>
  42 
  43 #include "netns.h"
  44 #include "procfs.h"
  45 
  46 #define NLMDBG_FACILITY         NLMDBG_SVC
  47 #define LOCKD_BUFSIZE           (1024 + NLMSVC_XDRSIZE)
  48 #define ALLOWED_SIGS            (sigmask(SIGKILL))
  49 
  50 static struct svc_program       nlmsvc_program;
  51 
  52 const struct nlmsvc_binding     *nlmsvc_ops;
  53 EXPORT_SYMBOL_GPL(nlmsvc_ops);
  54 
  55 static DEFINE_MUTEX(nlmsvc_mutex);
  56 static unsigned int             nlmsvc_users;
  57 static struct task_struct       *nlmsvc_task;
  58 static struct svc_rqst          *nlmsvc_rqst;
  59 unsigned long                   nlmsvc_timeout;
  60 
  61 static atomic_t nlm_ntf_refcnt = ATOMIC_INIT(0);
  62 static DECLARE_WAIT_QUEUE_HEAD(nlm_ntf_wq);
  63 
  64 unsigned int lockd_net_id;
  65 
  66 /*
  67  * These can be set at insmod time (useful for NFS as root filesystem),
  68  * and also changed through the sysctl interface.  -- Jamie Lokier, Aug 2003
  69  */
  70 static unsigned long            nlm_grace_period;
  71 static unsigned long            nlm_timeout = LOCKD_DFLT_TIMEO;
  72 static int                      nlm_udpport, nlm_tcpport;
  73 
  74 /* RLIM_NOFILE defaults to 1024. That seems like a reasonable default here. */
  75 static unsigned int             nlm_max_connections = 1024;
  76 
  77 /*
  78  * Constants needed for the sysctl interface.
  79  */
  80 static const unsigned long      nlm_grace_period_min = 0;
  81 static const unsigned long      nlm_grace_period_max = 240;
  82 static const unsigned long      nlm_timeout_min = 3;
  83 static const unsigned long      nlm_timeout_max = 20;
  84 static const int                nlm_port_min = 0, nlm_port_max = 65535;
  85 
  86 #ifdef CONFIG_SYSCTL
  87 static struct ctl_table_header * nlm_sysctl_table;
  88 #endif
  89 
  90 static unsigned long get_lockd_grace_period(void)
  91 {
  92         /* Note: nlm_timeout should always be nonzero */
  93         if (nlm_grace_period)
  94                 return roundup(nlm_grace_period, nlm_timeout) * HZ;
  95         else
  96                 return nlm_timeout * 5 * HZ;
  97 }
  98 
  99 static void grace_ender(struct work_struct *grace)
 100 {
 101         struct delayed_work *dwork = to_delayed_work(grace);
 102         struct lockd_net *ln = container_of(dwork, struct lockd_net,
 103                                             grace_period_end);
 104 
 105         locks_end_grace(&ln->lockd_manager);
 106 }
 107 
 108 static void set_grace_period(struct net *net)
 109 {
 110         unsigned long grace_period = get_lockd_grace_period();
 111         struct lockd_net *ln = net_generic(net, lockd_net_id);
 112 
 113         locks_start_grace(net, &ln->lockd_manager);
 114         cancel_delayed_work_sync(&ln->grace_period_end);
 115         schedule_delayed_work(&ln->grace_period_end, grace_period);
 116 }
 117 
 118 static void restart_grace(void)
 119 {
 120         if (nlmsvc_ops) {
 121                 struct net *net = &init_net;
 122                 struct lockd_net *ln = net_generic(net, lockd_net_id);
 123 
 124                 cancel_delayed_work_sync(&ln->grace_period_end);
 125                 locks_end_grace(&ln->lockd_manager);
 126                 nlmsvc_invalidate_all();
 127                 set_grace_period(net);
 128         }
 129 }
 130 
 131 /*
 132  * This is the lockd kernel thread
 133  */
 134 static int
 135 lockd(void *vrqstp)
 136 {
 137         int             err = 0;
 138         struct svc_rqst *rqstp = vrqstp;
 139         struct net *net = &init_net;
 140         struct lockd_net *ln = net_generic(net, lockd_net_id);
 141 
 142         /* try_to_freeze() is called from svc_recv() */
 143         set_freezable();
 144 
 145         /* Allow SIGKILL to tell lockd to drop all of its locks */
 146         allow_signal(SIGKILL);
 147 
 148         dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
 149 
 150         /*
 151          * The main request loop. We don't terminate until the last
 152          * NFS mount or NFS daemon has gone away.
 153          */
 154         while (!kthread_should_stop()) {
 155                 long timeout = MAX_SCHEDULE_TIMEOUT;
 156                 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
 157 
 158                 /* update sv_maxconn if it has changed */
 159                 rqstp->rq_server->sv_maxconn = nlm_max_connections;
 160 
 161                 if (signalled()) {
 162                         flush_signals(current);
 163                         restart_grace();
 164                         continue;
 165                 }
 166 
 167                 timeout = nlmsvc_retry_blocked();
 168 
 169                 /*
 170                  * Find a socket with data available and call its
 171                  * recvfrom routine.
 172                  */
 173                 err = svc_recv(rqstp, timeout);
 174                 if (err == -EAGAIN || err == -EINTR)
 175                         continue;
 176                 dprintk("lockd: request from %s\n",
 177                                 svc_print_addr(rqstp, buf, sizeof(buf)));
 178 
 179                 svc_process(rqstp);
 180         }
 181         flush_signals(current);
 182         if (nlmsvc_ops)
 183                 nlmsvc_invalidate_all();
 184         nlm_shutdown_hosts();
 185         cancel_delayed_work_sync(&ln->grace_period_end);
 186         locks_end_grace(&ln->lockd_manager);
 187         return 0;
 188 }
 189 
 190 static int create_lockd_listener(struct svc_serv *serv, const char *name,
 191                                  struct net *net, const int family,
 192                                  const unsigned short port,
 193                                  const struct cred *cred)
 194 {
 195         struct svc_xprt *xprt;
 196 
 197         xprt = svc_find_xprt(serv, name, net, family, 0);
 198         if (xprt == NULL)
 199                 return svc_create_xprt(serv, name, net, family, port,
 200                                                 SVC_SOCK_DEFAULTS, cred);
 201         svc_xprt_put(xprt);
 202         return 0;
 203 }
 204 
 205 static int create_lockd_family(struct svc_serv *serv, struct net *net,
 206                                const int family, const struct cred *cred)
 207 {
 208         int err;
 209 
 210         err = create_lockd_listener(serv, "udp", net, family, nlm_udpport,
 211                         cred);
 212         if (err < 0)
 213                 return err;
 214 
 215         return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport,
 216                         cred);
 217 }
 218 
 219 /*
 220  * Ensure there are active UDP and TCP listeners for lockd.
 221  *
 222  * Even if we have only TCP NFS mounts and/or TCP NFSDs, some
 223  * local services (such as rpc.statd) still require UDP, and
 224  * some NFS servers do not yet support NLM over TCP.
 225  *
 226  * Returns zero if all listeners are available; otherwise a
 227  * negative errno value is returned.
 228  */
 229 static int make_socks(struct svc_serv *serv, struct net *net,
 230                 const struct cred *cred)
 231 {
 232         static int warned;
 233         int err;
 234 
 235         err = create_lockd_family(serv, net, PF_INET, cred);
 236         if (err < 0)
 237                 goto out_err;
 238 
 239         err = create_lockd_family(serv, net, PF_INET6, cred);
 240         if (err < 0 && err != -EAFNOSUPPORT)
 241                 goto out_err;
 242 
 243         warned = 0;
 244         return 0;
 245 
 246 out_err:
 247         if (warned++ == 0)
 248                 printk(KERN_WARNING
 249                         "lockd_up: makesock failed, error=%d\n", err);
 250         svc_shutdown_net(serv, net);
 251         return err;
 252 }
 253 
 254 static int lockd_up_net(struct svc_serv *serv, struct net *net,
 255                 const struct cred *cred)
 256 {
 257         struct lockd_net *ln = net_generic(net, lockd_net_id);
 258         int error;
 259 
 260         if (ln->nlmsvc_users++)
 261                 return 0;
 262 
 263         error = svc_bind(serv, net);
 264         if (error)
 265                 goto err_bind;
 266 
 267         error = make_socks(serv, net, cred);
 268         if (error < 0)
 269                 goto err_bind;
 270         set_grace_period(net);
 271         dprintk("%s: per-net data created; net=%x\n", __func__, net->ns.inum);
 272         return 0;
 273 
 274 err_bind:
 275         ln->nlmsvc_users--;
 276         return error;
 277 }
 278 
 279 static void lockd_down_net(struct svc_serv *serv, struct net *net)
 280 {
 281         struct lockd_net *ln = net_generic(net, lockd_net_id);
 282 
 283         if (ln->nlmsvc_users) {
 284                 if (--ln->nlmsvc_users == 0) {
 285                         nlm_shutdown_hosts_net(net);
 286                         cancel_delayed_work_sync(&ln->grace_period_end);
 287                         locks_end_grace(&ln->lockd_manager);
 288                         svc_shutdown_net(serv, net);
 289                         dprintk("%s: per-net data destroyed; net=%x\n",
 290                                 __func__, net->ns.inum);
 291                 }
 292         } else {
 293                 pr_err("%s: no users! task=%p, net=%x\n",
 294                         __func__, nlmsvc_task, net->ns.inum);
 295                 BUG();
 296         }
 297 }
 298 
 299 static int lockd_inetaddr_event(struct notifier_block *this,
 300         unsigned long event, void *ptr)
 301 {
 302         struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
 303         struct sockaddr_in sin;
 304 
 305         if ((event != NETDEV_DOWN) ||
 306             !atomic_inc_not_zero(&nlm_ntf_refcnt))
 307                 goto out;
 308 
 309         if (nlmsvc_rqst) {
 310                 dprintk("lockd_inetaddr_event: removed %pI4\n",
 311                         &ifa->ifa_local);
 312                 sin.sin_family = AF_INET;
 313                 sin.sin_addr.s_addr = ifa->ifa_local;
 314                 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
 315                         (struct sockaddr *)&sin);
 316         }
 317         atomic_dec(&nlm_ntf_refcnt);
 318         wake_up(&nlm_ntf_wq);
 319 
 320 out:
 321         return NOTIFY_DONE;
 322 }
 323 
 324 static struct notifier_block lockd_inetaddr_notifier = {
 325         .notifier_call = lockd_inetaddr_event,
 326 };
 327 
 328 #if IS_ENABLED(CONFIG_IPV6)
 329 static int lockd_inet6addr_event(struct notifier_block *this,
 330         unsigned long event, void *ptr)
 331 {
 332         struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
 333         struct sockaddr_in6 sin6;
 334 
 335         if ((event != NETDEV_DOWN) ||
 336             !atomic_inc_not_zero(&nlm_ntf_refcnt))
 337                 goto out;
 338 
 339         if (nlmsvc_rqst) {
 340                 dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
 341                 sin6.sin6_family = AF_INET6;
 342                 sin6.sin6_addr = ifa->addr;
 343                 if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
 344                         sin6.sin6_scope_id = ifa->idev->dev->ifindex;
 345                 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
 346                         (struct sockaddr *)&sin6);
 347         }
 348         atomic_dec(&nlm_ntf_refcnt);
 349         wake_up(&nlm_ntf_wq);
 350 
 351 out:
 352         return NOTIFY_DONE;
 353 }
 354 
 355 static struct notifier_block lockd_inet6addr_notifier = {
 356         .notifier_call = lockd_inet6addr_event,
 357 };
 358 #endif
 359 
 360 static void lockd_unregister_notifiers(void)
 361 {
 362         unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
 363 #if IS_ENABLED(CONFIG_IPV6)
 364         unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
 365 #endif
 366         wait_event(nlm_ntf_wq, atomic_read(&nlm_ntf_refcnt) == 0);
 367 }
 368 
 369 static void lockd_svc_exit_thread(void)
 370 {
 371         atomic_dec(&nlm_ntf_refcnt);
 372         lockd_unregister_notifiers();
 373         svc_exit_thread(nlmsvc_rqst);
 374 }
 375 
 376 static int lockd_start_svc(struct svc_serv *serv)
 377 {
 378         int error;
 379 
 380         if (nlmsvc_rqst)
 381                 return 0;
 382 
 383         /*
 384          * Create the kernel thread and wait for it to start.
 385          */
 386         nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
 387         if (IS_ERR(nlmsvc_rqst)) {
 388                 error = PTR_ERR(nlmsvc_rqst);
 389                 printk(KERN_WARNING
 390                         "lockd_up: svc_rqst allocation failed, error=%d\n",
 391                         error);
 392                 lockd_unregister_notifiers();
 393                 goto out_rqst;
 394         }
 395 
 396         atomic_inc(&nlm_ntf_refcnt);
 397         svc_sock_update_bufs(serv);
 398         serv->sv_maxconn = nlm_max_connections;
 399 
 400         nlmsvc_task = kthread_create(lockd, nlmsvc_rqst, "%s", serv->sv_name);
 401         if (IS_ERR(nlmsvc_task)) {
 402                 error = PTR_ERR(nlmsvc_task);
 403                 printk(KERN_WARNING
 404                         "lockd_up: kthread_run failed, error=%d\n", error);
 405                 goto out_task;
 406         }
 407         nlmsvc_rqst->rq_task = nlmsvc_task;
 408         wake_up_process(nlmsvc_task);
 409 
 410         dprintk("lockd_up: service started\n");
 411         return 0;
 412 
 413 out_task:
 414         lockd_svc_exit_thread();
 415         nlmsvc_task = NULL;
 416 out_rqst:
 417         nlmsvc_rqst = NULL;
 418         return error;
 419 }
 420 
 421 static const struct svc_serv_ops lockd_sv_ops = {
 422         .svo_shutdown           = svc_rpcb_cleanup,
 423         .svo_enqueue_xprt       = svc_xprt_do_enqueue,
 424 };
 425 
 426 static struct svc_serv *lockd_create_svc(void)
 427 {
 428         struct svc_serv *serv;
 429 
 430         /*
 431          * Check whether we're already up and running.
 432          */
 433         if (nlmsvc_rqst) {
 434                 /*
 435                  * Note: increase service usage, because later in case of error
 436                  * svc_destroy() will be called.
 437                  */
 438                 svc_get(nlmsvc_rqst->rq_server);
 439                 return nlmsvc_rqst->rq_server;
 440         }
 441 
 442         /*
 443          * Sanity check: if there's no pid,
 444          * we should be the first user ...
 445          */
 446         if (nlmsvc_users)
 447                 printk(KERN_WARNING
 448                         "lockd_up: no pid, %d users??\n", nlmsvc_users);
 449 
 450         if (!nlm_timeout)
 451                 nlm_timeout = LOCKD_DFLT_TIMEO;
 452         nlmsvc_timeout = nlm_timeout * HZ;
 453 
 454         serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, &lockd_sv_ops);
 455         if (!serv) {
 456                 printk(KERN_WARNING "lockd_up: create service failed\n");
 457                 return ERR_PTR(-ENOMEM);
 458         }
 459         register_inetaddr_notifier(&lockd_inetaddr_notifier);
 460 #if IS_ENABLED(CONFIG_IPV6)
 461         register_inet6addr_notifier(&lockd_inet6addr_notifier);
 462 #endif
 463         dprintk("lockd_up: service created\n");
 464         return serv;
 465 }
 466 
 467 /*
 468  * Bring up the lockd process if it's not already up.
 469  */
 470 int lockd_up(struct net *net, const struct cred *cred)
 471 {
 472         struct svc_serv *serv;
 473         int error;
 474 
 475         mutex_lock(&nlmsvc_mutex);
 476 
 477         serv = lockd_create_svc();
 478         if (IS_ERR(serv)) {
 479                 error = PTR_ERR(serv);
 480                 goto err_create;
 481         }
 482 
 483         error = lockd_up_net(serv, net, cred);
 484         if (error < 0) {
 485                 lockd_unregister_notifiers();
 486                 goto err_put;
 487         }
 488 
 489         error = lockd_start_svc(serv);
 490         if (error < 0) {
 491                 lockd_down_net(serv, net);
 492                 goto err_put;
 493         }
 494         nlmsvc_users++;
 495         /*
 496          * Note: svc_serv structures have an initial use count of 1,
 497          * so we exit through here on both success and failure.
 498          */
 499 err_put:
 500         svc_destroy(serv);
 501 err_create:
 502         mutex_unlock(&nlmsvc_mutex);
 503         return error;
 504 }
 505 EXPORT_SYMBOL_GPL(lockd_up);
 506 
 507 /*
 508  * Decrement the user count and bring down lockd if we're the last.
 509  */
 510 void
 511 lockd_down(struct net *net)
 512 {
 513         mutex_lock(&nlmsvc_mutex);
 514         lockd_down_net(nlmsvc_rqst->rq_server, net);
 515         if (nlmsvc_users) {
 516                 if (--nlmsvc_users)
 517                         goto out;
 518         } else {
 519                 printk(KERN_ERR "lockd_down: no users! task=%p\n",
 520                         nlmsvc_task);
 521                 BUG();
 522         }
 523 
 524         if (!nlmsvc_task) {
 525                 printk(KERN_ERR "lockd_down: no lockd running.\n");
 526                 BUG();
 527         }
 528         kthread_stop(nlmsvc_task);
 529         dprintk("lockd_down: service stopped\n");
 530         lockd_svc_exit_thread();
 531         dprintk("lockd_down: service destroyed\n");
 532         nlmsvc_task = NULL;
 533         nlmsvc_rqst = NULL;
 534 out:
 535         mutex_unlock(&nlmsvc_mutex);
 536 }
 537 EXPORT_SYMBOL_GPL(lockd_down);
 538 
 539 #ifdef CONFIG_SYSCTL
 540 
 541 /*
 542  * Sysctl parameters (same as module parameters, different interface).
 543  */
 544 
 545 static struct ctl_table nlm_sysctls[] = {
 546         {
 547                 .procname       = "nlm_grace_period",
 548                 .data           = &nlm_grace_period,
 549                 .maxlen         = sizeof(unsigned long),
 550                 .mode           = 0644,
 551                 .proc_handler   = proc_doulongvec_minmax,
 552                 .extra1         = (unsigned long *) &nlm_grace_period_min,
 553                 .extra2         = (unsigned long *) &nlm_grace_period_max,
 554         },
 555         {
 556                 .procname       = "nlm_timeout",
 557                 .data           = &nlm_timeout,
 558                 .maxlen         = sizeof(unsigned long),
 559                 .mode           = 0644,
 560                 .proc_handler   = proc_doulongvec_minmax,
 561                 .extra1         = (unsigned long *) &nlm_timeout_min,
 562                 .extra2         = (unsigned long *) &nlm_timeout_max,
 563         },
 564         {
 565                 .procname       = "nlm_udpport",
 566                 .data           = &nlm_udpport,
 567                 .maxlen         = sizeof(int),
 568                 .mode           = 0644,
 569                 .proc_handler   = proc_dointvec_minmax,
 570                 .extra1         = (int *) &nlm_port_min,
 571                 .extra2         = (int *) &nlm_port_max,
 572         },
 573         {
 574                 .procname       = "nlm_tcpport",
 575                 .data           = &nlm_tcpport,
 576                 .maxlen         = sizeof(int),
 577                 .mode           = 0644,
 578                 .proc_handler   = proc_dointvec_minmax,
 579                 .extra1         = (int *) &nlm_port_min,
 580                 .extra2         = (int *) &nlm_port_max,
 581         },
 582         {
 583                 .procname       = "nsm_use_hostnames",
 584                 .data           = &nsm_use_hostnames,
 585                 .maxlen         = sizeof(int),
 586                 .mode           = 0644,
 587                 .proc_handler   = proc_dointvec,
 588         },
 589         {
 590                 .procname       = "nsm_local_state",
 591                 .data           = &nsm_local_state,
 592                 .maxlen         = sizeof(int),
 593                 .mode           = 0644,
 594                 .proc_handler   = proc_dointvec,
 595         },
 596         { }
 597 };
 598 
 599 static struct ctl_table nlm_sysctl_dir[] = {
 600         {
 601                 .procname       = "nfs",
 602                 .mode           = 0555,
 603                 .child          = nlm_sysctls,
 604         },
 605         { }
 606 };
 607 
 608 static struct ctl_table nlm_sysctl_root[] = {
 609         {
 610                 .procname       = "fs",
 611                 .mode           = 0555,
 612                 .child          = nlm_sysctl_dir,
 613         },
 614         { }
 615 };
 616 
 617 #endif  /* CONFIG_SYSCTL */
 618 
 619 /*
 620  * Module (and sysfs) parameters.
 621  */
 622 
 623 #define param_set_min_max(name, type, which_strtol, min, max)           \
 624 static int param_set_##name(const char *val, const struct kernel_param *kp) \
 625 {                                                                       \
 626         char *endp;                                                     \
 627         __typeof__(type) num = which_strtol(val, &endp, 0);             \
 628         if (endp == val || *endp || num < (min) || num > (max))         \
 629                 return -EINVAL;                                         \
 630         *((type *) kp->arg) = num;                                      \
 631         return 0;                                                       \
 632 }
 633 
 634 static inline int is_callback(u32 proc)
 635 {
 636         return proc == NLMPROC_GRANTED
 637                 || proc == NLMPROC_GRANTED_MSG
 638                 || proc == NLMPROC_TEST_RES
 639                 || proc == NLMPROC_LOCK_RES
 640                 || proc == NLMPROC_CANCEL_RES
 641                 || proc == NLMPROC_UNLOCK_RES
 642                 || proc == NLMPROC_NSM_NOTIFY;
 643 }
 644 
 645 
 646 static int lockd_authenticate(struct svc_rqst *rqstp)
 647 {
 648         rqstp->rq_client = NULL;
 649         switch (rqstp->rq_authop->flavour) {
 650                 case RPC_AUTH_NULL:
 651                 case RPC_AUTH_UNIX:
 652                         if (rqstp->rq_proc == 0)
 653                                 return SVC_OK;
 654                         if (is_callback(rqstp->rq_proc)) {
 655                                 /* Leave it to individual procedures to
 656                                  * call nlmsvc_lookup_host(rqstp)
 657                                  */
 658                                 return SVC_OK;
 659                         }
 660                         return svc_set_client(rqstp);
 661         }
 662         return SVC_DENIED;
 663 }
 664 
 665 
 666 param_set_min_max(port, int, simple_strtol, 0, 65535)
 667 param_set_min_max(grace_period, unsigned long, simple_strtoul,
 668                   nlm_grace_period_min, nlm_grace_period_max)
 669 param_set_min_max(timeout, unsigned long, simple_strtoul,
 670                   nlm_timeout_min, nlm_timeout_max)
 671 
 672 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
 673 MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
 674 MODULE_LICENSE("GPL");
 675 
 676 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
 677                   &nlm_grace_period, 0644);
 678 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
 679                   &nlm_timeout, 0644);
 680 module_param_call(nlm_udpport, param_set_port, param_get_int,
 681                   &nlm_udpport, 0644);
 682 module_param_call(nlm_tcpport, param_set_port, param_get_int,
 683                   &nlm_tcpport, 0644);
 684 module_param(nsm_use_hostnames, bool, 0644);
 685 module_param(nlm_max_connections, uint, 0644);
 686 
 687 static int lockd_init_net(struct net *net)
 688 {
 689         struct lockd_net *ln = net_generic(net, lockd_net_id);
 690 
 691         INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
 692         INIT_LIST_HEAD(&ln->lockd_manager.list);
 693         ln->lockd_manager.block_opens = false;
 694         INIT_LIST_HEAD(&ln->nsm_handles);
 695         return 0;
 696 }
 697 
 698 static void lockd_exit_net(struct net *net)
 699 {
 700         struct lockd_net *ln = net_generic(net, lockd_net_id);
 701 
 702         WARN_ONCE(!list_empty(&ln->lockd_manager.list),
 703                   "net %x %s: lockd_manager.list is not empty\n",
 704                   net->ns.inum, __func__);
 705         WARN_ONCE(!list_empty(&ln->nsm_handles),
 706                   "net %x %s: nsm_handles list is not empty\n",
 707                   net->ns.inum, __func__);
 708         WARN_ONCE(delayed_work_pending(&ln->grace_period_end),
 709                   "net %x %s: grace_period_end was not cancelled\n",
 710                   net->ns.inum, __func__);
 711 }
 712 
 713 static struct pernet_operations lockd_net_ops = {
 714         .init = lockd_init_net,
 715         .exit = lockd_exit_net,
 716         .id = &lockd_net_id,
 717         .size = sizeof(struct lockd_net),
 718 };
 719 
 720 
 721 /*
 722  * Initialising and terminating the module.
 723  */
 724 
 725 static int __init init_nlm(void)
 726 {
 727         int err;
 728 
 729 #ifdef CONFIG_SYSCTL
 730         err = -ENOMEM;
 731         nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
 732         if (nlm_sysctl_table == NULL)
 733                 goto err_sysctl;
 734 #endif
 735         err = register_pernet_subsys(&lockd_net_ops);
 736         if (err)
 737                 goto err_pernet;
 738 
 739         err = lockd_create_procfs();
 740         if (err)
 741                 goto err_procfs;
 742 
 743         return 0;
 744 
 745 err_procfs:
 746         unregister_pernet_subsys(&lockd_net_ops);
 747 err_pernet:
 748 #ifdef CONFIG_SYSCTL
 749         unregister_sysctl_table(nlm_sysctl_table);
 750 err_sysctl:
 751 #endif
 752         return err;
 753 }
 754 
 755 static void __exit exit_nlm(void)
 756 {
 757         /* FIXME: delete all NLM clients */
 758         nlm_shutdown_hosts();
 759         lockd_remove_procfs();
 760         unregister_pernet_subsys(&lockd_net_ops);
 761 #ifdef CONFIG_SYSCTL
 762         unregister_sysctl_table(nlm_sysctl_table);
 763 #endif
 764 }
 765 
 766 module_init(init_nlm);
 767 module_exit(exit_nlm);
 768 
 769 /*
 770  * Define NLM program and procedures
 771  */
 772 static unsigned int nlmsvc_version1_count[17];
 773 static const struct svc_version nlmsvc_version1 = {
 774         .vs_vers        = 1,
 775         .vs_nproc       = 17,
 776         .vs_proc        = nlmsvc_procedures,
 777         .vs_count       = nlmsvc_version1_count,
 778         .vs_xdrsize     = NLMSVC_XDRSIZE,
 779 };
 780 static unsigned int nlmsvc_version3_count[24];
 781 static const struct svc_version nlmsvc_version3 = {
 782         .vs_vers        = 3,
 783         .vs_nproc       = 24,
 784         .vs_proc        = nlmsvc_procedures,
 785         .vs_count       = nlmsvc_version3_count,
 786         .vs_xdrsize     = NLMSVC_XDRSIZE,
 787 };
 788 #ifdef CONFIG_LOCKD_V4
 789 static unsigned int nlmsvc_version4_count[24];
 790 static const struct svc_version nlmsvc_version4 = {
 791         .vs_vers        = 4,
 792         .vs_nproc       = 24,
 793         .vs_proc        = nlmsvc_procedures4,
 794         .vs_count       = nlmsvc_version4_count,
 795         .vs_xdrsize     = NLMSVC_XDRSIZE,
 796 };
 797 #endif
 798 static const struct svc_version *nlmsvc_version[] = {
 799         [1] = &nlmsvc_version1,
 800         [3] = &nlmsvc_version3,
 801 #ifdef CONFIG_LOCKD_V4
 802         [4] = &nlmsvc_version4,
 803 #endif
 804 };
 805 
 806 static struct svc_stat          nlmsvc_stats;
 807 
 808 #define NLM_NRVERS      ARRAY_SIZE(nlmsvc_version)
 809 static struct svc_program       nlmsvc_program = {
 810         .pg_prog                = NLM_PROGRAM,          /* program number */
 811         .pg_nvers               = NLM_NRVERS,           /* number of entries in nlmsvc_version */
 812         .pg_vers                = nlmsvc_version,       /* version table */
 813         .pg_name                = "lockd",              /* service name */
 814         .pg_class               = "nfsd",               /* share authentication with nfsd */
 815         .pg_stats               = &nlmsvc_stats,        /* stats table */
 816         .pg_authenticate        = &lockd_authenticate,  /* export authentication */
 817         .pg_init_request        = svc_generic_init_request,
 818         .pg_rpcbind_set         = svc_generic_rpcbind_set,
 819 };

/* [<][>][^][v][top][bottom][index][help] */