svc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  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. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/sysctl.h>
  18. #include <linux/moduleparam.h>
  19. #include <linux/sched/signal.h>
  20. #include <linux/errno.h>
  21. #include <linux/in.h>
  22. #include <linux/uio.h>
  23. #include <linux/smp.h>
  24. #include <linux/mutex.h>
  25. #include <linux/freezer.h>
  26. #include <linux/inetdevice.h>
  27. #include <linux/sunrpc/types.h>
  28. #include <linux/sunrpc/stats.h>
  29. #include <linux/sunrpc/clnt.h>
  30. #include <linux/sunrpc/svc.h>
  31. #include <linux/sunrpc/svcsock.h>
  32. #include <linux/sunrpc/svc_xprt.h>
  33. #include <net/ip.h>
  34. #include <net/addrconf.h>
  35. #include <net/ipv6.h>
  36. #include <linux/lockd/lockd.h>
  37. #include <linux/nfs.h>
  38. #include "netns.h"
  39. #include "procfs.h"
  40. #include "netlink.h"
  41. #define NLMDBG_FACILITY NLMDBG_SVC
  42. #define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
  43. static struct svc_program nlmsvc_program;
  44. const struct nlmsvc_binding *nlmsvc_ops;
  45. EXPORT_SYMBOL_GPL(nlmsvc_ops);
  46. static DEFINE_MUTEX(nlmsvc_mutex);
  47. static unsigned int nlmsvc_users;
  48. static struct svc_serv *nlmsvc_serv;
  49. static void nlmsvc_request_retry(struct timer_list *tl)
  50. {
  51. svc_wake_up(nlmsvc_serv);
  52. }
  53. DEFINE_TIMER(nlmsvc_retry, nlmsvc_request_retry);
  54. unsigned int lockd_net_id;
  55. /*
  56. * These can be set at insmod time (useful for NFS as root filesystem),
  57. * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
  58. */
  59. static unsigned long nlm_grace_period;
  60. unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
  61. static int nlm_udpport, nlm_tcpport;
  62. /*
  63. * Constants needed for the sysctl interface.
  64. */
  65. static const unsigned long nlm_grace_period_min = 0;
  66. static const unsigned long nlm_grace_period_max = 240;
  67. static const unsigned long nlm_timeout_min = 3;
  68. static const unsigned long nlm_timeout_max = 20;
  69. #ifdef CONFIG_SYSCTL
  70. static const int nlm_port_min = 0, nlm_port_max = 65535;
  71. static struct ctl_table_header * nlm_sysctl_table;
  72. #endif
  73. static unsigned long get_lockd_grace_period(struct net *net)
  74. {
  75. struct lockd_net *ln = net_generic(net, lockd_net_id);
  76. /* Return the net-ns specific grace period, if there is one */
  77. if (ln->gracetime)
  78. return ln->gracetime * HZ;
  79. /* Note: nlm_timeout should always be nonzero */
  80. if (nlm_grace_period)
  81. return roundup(nlm_grace_period, nlm_timeout) * HZ;
  82. else
  83. return nlm_timeout * 5 * HZ;
  84. }
  85. static void grace_ender(struct work_struct *grace)
  86. {
  87. struct delayed_work *dwork = to_delayed_work(grace);
  88. struct lockd_net *ln = container_of(dwork, struct lockd_net,
  89. grace_period_end);
  90. locks_end_grace(&ln->lockd_manager);
  91. }
  92. static void set_grace_period(struct net *net)
  93. {
  94. unsigned long grace_period = get_lockd_grace_period(net);
  95. struct lockd_net *ln = net_generic(net, lockd_net_id);
  96. locks_start_grace(net, &ln->lockd_manager);
  97. cancel_delayed_work_sync(&ln->grace_period_end);
  98. schedule_delayed_work(&ln->grace_period_end, grace_period);
  99. }
  100. /*
  101. * This is the lockd kernel thread
  102. */
  103. static int
  104. lockd(void *vrqstp)
  105. {
  106. struct svc_rqst *rqstp = vrqstp;
  107. struct net *net = &init_net;
  108. struct lockd_net *ln = net_generic(net, lockd_net_id);
  109. svc_thread_init_status(rqstp, 0);
  110. /* try_to_freeze() is called from svc_recv() */
  111. set_freezable();
  112. dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
  113. /*
  114. * The main request loop. We don't terminate until the last
  115. * NFS mount or NFS daemon has gone away.
  116. */
  117. while (!svc_thread_should_stop(rqstp)) {
  118. nlmsvc_retry_blocked(rqstp);
  119. svc_recv(rqstp, 0);
  120. }
  121. if (nlmsvc_ops)
  122. nlmsvc_invalidate_all();
  123. nlm_shutdown_hosts();
  124. cancel_delayed_work_sync(&ln->grace_period_end);
  125. locks_end_grace(&ln->lockd_manager);
  126. dprintk("lockd_down: service stopped\n");
  127. svc_exit_thread(rqstp);
  128. return 0;
  129. }
  130. static int create_lockd_listener(struct svc_serv *serv, const char *name,
  131. struct net *net, const int family,
  132. const unsigned short port,
  133. const struct cred *cred)
  134. {
  135. struct svc_xprt *xprt;
  136. xprt = svc_find_xprt(serv, name, net, family, 0);
  137. if (xprt == NULL)
  138. return svc_xprt_create(serv, name, net, family, port,
  139. SVC_SOCK_DEFAULTS, cred);
  140. svc_xprt_put(xprt);
  141. return 0;
  142. }
  143. static int create_lockd_family(struct svc_serv *serv, struct net *net,
  144. const int family, const struct cred *cred)
  145. {
  146. struct lockd_net *ln = net_generic(net, lockd_net_id);
  147. int err;
  148. err = create_lockd_listener(serv, "udp", net, family,
  149. ln->udp_port ? ln->udp_port : nlm_udpport, cred);
  150. if (err < 0)
  151. return err;
  152. return create_lockd_listener(serv, "tcp", net, family,
  153. ln->tcp_port ? ln->tcp_port : nlm_tcpport, cred);
  154. }
  155. /*
  156. * Ensure there are active UDP and TCP listeners for lockd.
  157. *
  158. * Even if we have only TCP NFS mounts and/or TCP NFSDs, some
  159. * local services (such as rpc.statd) still require UDP, and
  160. * some NFS servers do not yet support NLM over TCP.
  161. *
  162. * Returns zero if all listeners are available; otherwise a
  163. * negative errno value is returned.
  164. */
  165. static int make_socks(struct svc_serv *serv, struct net *net,
  166. const struct cred *cred)
  167. {
  168. static int warned;
  169. int err;
  170. err = create_lockd_family(serv, net, PF_INET, cred);
  171. if (err < 0)
  172. goto out_err;
  173. err = create_lockd_family(serv, net, PF_INET6, cred);
  174. if (err < 0 && err != -EAFNOSUPPORT)
  175. goto out_err;
  176. warned = 0;
  177. return 0;
  178. out_err:
  179. if (warned++ == 0)
  180. printk(KERN_WARNING
  181. "lockd_up: makesock failed, error=%d\n", err);
  182. svc_xprt_destroy_all(serv, net, true);
  183. return err;
  184. }
  185. static int lockd_up_net(struct svc_serv *serv, struct net *net,
  186. const struct cred *cred)
  187. {
  188. struct lockd_net *ln = net_generic(net, lockd_net_id);
  189. int error;
  190. if (ln->nlmsvc_users++)
  191. return 0;
  192. error = svc_bind(serv, net);
  193. if (error)
  194. goto err_bind;
  195. error = make_socks(serv, net, cred);
  196. if (error < 0)
  197. goto err_bind;
  198. set_grace_period(net);
  199. dprintk("%s: per-net data created; net=%x\n", __func__, net->ns.inum);
  200. return 0;
  201. err_bind:
  202. ln->nlmsvc_users--;
  203. return error;
  204. }
  205. static void lockd_down_net(struct svc_serv *serv, struct net *net)
  206. {
  207. struct lockd_net *ln = net_generic(net, lockd_net_id);
  208. if (ln->nlmsvc_users) {
  209. if (--ln->nlmsvc_users == 0) {
  210. nlm_shutdown_hosts_net(net);
  211. cancel_delayed_work_sync(&ln->grace_period_end);
  212. locks_end_grace(&ln->lockd_manager);
  213. svc_xprt_destroy_all(serv, net, true);
  214. }
  215. } else {
  216. pr_err("%s: no users! net=%x\n",
  217. __func__, net->ns.inum);
  218. BUG();
  219. }
  220. }
  221. static int lockd_inetaddr_event(struct notifier_block *this,
  222. unsigned long event, void *ptr)
  223. {
  224. struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
  225. struct sockaddr_in sin;
  226. if (event != NETDEV_DOWN)
  227. goto out;
  228. if (nlmsvc_serv) {
  229. dprintk("lockd_inetaddr_event: removed %pI4\n",
  230. &ifa->ifa_local);
  231. sin.sin_family = AF_INET;
  232. sin.sin_addr.s_addr = ifa->ifa_local;
  233. svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin);
  234. }
  235. out:
  236. return NOTIFY_DONE;
  237. }
  238. static struct notifier_block lockd_inetaddr_notifier = {
  239. .notifier_call = lockd_inetaddr_event,
  240. };
  241. #if IS_ENABLED(CONFIG_IPV6)
  242. static int lockd_inet6addr_event(struct notifier_block *this,
  243. unsigned long event, void *ptr)
  244. {
  245. struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
  246. struct sockaddr_in6 sin6;
  247. if (event != NETDEV_DOWN)
  248. goto out;
  249. if (nlmsvc_serv) {
  250. dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
  251. sin6.sin6_family = AF_INET6;
  252. sin6.sin6_addr = ifa->addr;
  253. if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
  254. sin6.sin6_scope_id = ifa->idev->dev->ifindex;
  255. svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin6);
  256. }
  257. out:
  258. return NOTIFY_DONE;
  259. }
  260. static struct notifier_block lockd_inet6addr_notifier = {
  261. .notifier_call = lockd_inet6addr_event,
  262. };
  263. #endif
  264. static int lockd_get(void)
  265. {
  266. struct svc_serv *serv;
  267. int error;
  268. if (nlmsvc_serv) {
  269. nlmsvc_users++;
  270. return 0;
  271. }
  272. /*
  273. * Sanity check: if there's no pid,
  274. * we should be the first user ...
  275. */
  276. if (nlmsvc_users)
  277. printk(KERN_WARNING
  278. "lockd_up: no pid, %d users??\n", nlmsvc_users);
  279. serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, lockd);
  280. if (!serv) {
  281. printk(KERN_WARNING "lockd_up: create service failed\n");
  282. return -ENOMEM;
  283. }
  284. error = svc_set_num_threads(serv, 0, 1);
  285. if (error < 0) {
  286. svc_destroy(&serv);
  287. return error;
  288. }
  289. nlmsvc_serv = serv;
  290. register_inetaddr_notifier(&lockd_inetaddr_notifier);
  291. #if IS_ENABLED(CONFIG_IPV6)
  292. register_inet6addr_notifier(&lockd_inet6addr_notifier);
  293. #endif
  294. dprintk("lockd_up: service created\n");
  295. nlmsvc_users++;
  296. return 0;
  297. }
  298. static void lockd_put(void)
  299. {
  300. if (WARN(nlmsvc_users <= 0, "lockd_down: no users!\n"))
  301. return;
  302. if (--nlmsvc_users)
  303. return;
  304. unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
  305. #if IS_ENABLED(CONFIG_IPV6)
  306. unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
  307. #endif
  308. svc_set_num_threads(nlmsvc_serv, 0, 0);
  309. timer_delete_sync(&nlmsvc_retry);
  310. svc_destroy(&nlmsvc_serv);
  311. dprintk("lockd_down: service destroyed\n");
  312. }
  313. /*
  314. * Bring up the lockd process if it's not already up.
  315. */
  316. int lockd_up(struct net *net, const struct cred *cred)
  317. {
  318. int error;
  319. mutex_lock(&nlmsvc_mutex);
  320. error = lockd_get();
  321. if (error)
  322. goto err;
  323. error = lockd_up_net(nlmsvc_serv, net, cred);
  324. if (error < 0) {
  325. lockd_put();
  326. goto err;
  327. }
  328. err:
  329. mutex_unlock(&nlmsvc_mutex);
  330. return error;
  331. }
  332. EXPORT_SYMBOL_GPL(lockd_up);
  333. /*
  334. * Decrement the user count and bring down lockd if we're the last.
  335. */
  336. void
  337. lockd_down(struct net *net)
  338. {
  339. mutex_lock(&nlmsvc_mutex);
  340. lockd_down_net(nlmsvc_serv, net);
  341. lockd_put();
  342. mutex_unlock(&nlmsvc_mutex);
  343. }
  344. EXPORT_SYMBOL_GPL(lockd_down);
  345. #ifdef CONFIG_SYSCTL
  346. /*
  347. * Sysctl parameters (same as module parameters, different interface).
  348. */
  349. static const struct ctl_table nlm_sysctls[] = {
  350. {
  351. .procname = "nlm_grace_period",
  352. .data = &nlm_grace_period,
  353. .maxlen = sizeof(unsigned long),
  354. .mode = 0644,
  355. .proc_handler = proc_doulongvec_minmax,
  356. .extra1 = (unsigned long *) &nlm_grace_period_min,
  357. .extra2 = (unsigned long *) &nlm_grace_period_max,
  358. },
  359. {
  360. .procname = "nlm_timeout",
  361. .data = &nlm_timeout,
  362. .maxlen = sizeof(unsigned long),
  363. .mode = 0644,
  364. .proc_handler = proc_doulongvec_minmax,
  365. .extra1 = (unsigned long *) &nlm_timeout_min,
  366. .extra2 = (unsigned long *) &nlm_timeout_max,
  367. },
  368. {
  369. .procname = "nlm_udpport",
  370. .data = &nlm_udpport,
  371. .maxlen = sizeof(int),
  372. .mode = 0644,
  373. .proc_handler = proc_dointvec_minmax,
  374. .extra1 = (int *) &nlm_port_min,
  375. .extra2 = (int *) &nlm_port_max,
  376. },
  377. {
  378. .procname = "nlm_tcpport",
  379. .data = &nlm_tcpport,
  380. .maxlen = sizeof(int),
  381. .mode = 0644,
  382. .proc_handler = proc_dointvec_minmax,
  383. .extra1 = (int *) &nlm_port_min,
  384. .extra2 = (int *) &nlm_port_max,
  385. },
  386. {
  387. .procname = "nsm_use_hostnames",
  388. .data = &nsm_use_hostnames,
  389. .maxlen = sizeof(bool),
  390. .mode = 0644,
  391. .proc_handler = proc_dobool,
  392. },
  393. {
  394. .procname = "nsm_local_state",
  395. .data = &nsm_local_state,
  396. .maxlen = sizeof(nsm_local_state),
  397. .mode = 0644,
  398. .proc_handler = proc_douintvec,
  399. .extra1 = SYSCTL_ZERO,
  400. },
  401. };
  402. #endif /* CONFIG_SYSCTL */
  403. /*
  404. * Module (and sysfs) parameters.
  405. */
  406. #define param_set_min_max(name, type, which_strtol, min, max) \
  407. static int param_set_##name(const char *val, const struct kernel_param *kp) \
  408. { \
  409. char *endp; \
  410. __typeof__(type) num = which_strtol(val, &endp, 0); \
  411. if (endp == val || *endp || num < (min) || num > (max)) \
  412. return -EINVAL; \
  413. *((type *) kp->arg) = num; \
  414. return 0; \
  415. }
  416. static inline int is_callback(u32 proc)
  417. {
  418. return proc == NLMPROC_GRANTED
  419. || proc == NLMPROC_GRANTED_MSG
  420. || proc == NLMPROC_TEST_RES
  421. || proc == NLMPROC_LOCK_RES
  422. || proc == NLMPROC_CANCEL_RES
  423. || proc == NLMPROC_UNLOCK_RES
  424. || proc == NLMPROC_NSM_NOTIFY;
  425. }
  426. static enum svc_auth_status lockd_authenticate(struct svc_rqst *rqstp)
  427. {
  428. rqstp->rq_client = NULL;
  429. switch (rqstp->rq_authop->flavour) {
  430. case RPC_AUTH_NULL:
  431. case RPC_AUTH_UNIX:
  432. rqstp->rq_auth_stat = rpc_auth_ok;
  433. if (rqstp->rq_proc == 0)
  434. return SVC_OK;
  435. if (is_callback(rqstp->rq_proc)) {
  436. /* Leave it to individual procedures to
  437. * call nlmsvc_lookup_host(rqstp)
  438. */
  439. return SVC_OK;
  440. }
  441. return svc_set_client(rqstp);
  442. }
  443. rqstp->rq_auth_stat = rpc_autherr_badcred;
  444. return SVC_DENIED;
  445. }
  446. param_set_min_max(port, int, simple_strtol, 0, 65535)
  447. param_set_min_max(grace_period, unsigned long, simple_strtoul,
  448. nlm_grace_period_min, nlm_grace_period_max)
  449. param_set_min_max(timeout, unsigned long, simple_strtoul,
  450. nlm_timeout_min, nlm_timeout_max)
  451. MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
  452. MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
  453. MODULE_LICENSE("GPL");
  454. module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
  455. &nlm_grace_period, 0644);
  456. module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
  457. &nlm_timeout, 0644);
  458. module_param_call(nlm_udpport, param_set_port, param_get_int,
  459. &nlm_udpport, 0644);
  460. module_param_call(nlm_tcpport, param_set_port, param_get_int,
  461. &nlm_tcpport, 0644);
  462. module_param(nsm_use_hostnames, bool, 0644);
  463. static int lockd_init_net(struct net *net)
  464. {
  465. struct lockd_net *ln = net_generic(net, lockd_net_id);
  466. INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
  467. INIT_LIST_HEAD(&ln->lockd_manager.list);
  468. ln->lockd_manager.block_opens = false;
  469. INIT_LIST_HEAD(&ln->nsm_handles);
  470. return 0;
  471. }
  472. static void lockd_exit_net(struct net *net)
  473. {
  474. struct lockd_net *ln = net_generic(net, lockd_net_id);
  475. WARN_ONCE(!list_empty(&ln->lockd_manager.list),
  476. "net %x %s: lockd_manager.list is not empty\n",
  477. net->ns.inum, __func__);
  478. WARN_ONCE(!list_empty(&ln->nsm_handles),
  479. "net %x %s: nsm_handles list is not empty\n",
  480. net->ns.inum, __func__);
  481. WARN_ONCE(delayed_work_pending(&ln->grace_period_end),
  482. "net %x %s: grace_period_end was not cancelled\n",
  483. net->ns.inum, __func__);
  484. }
  485. static struct pernet_operations lockd_net_ops = {
  486. .init = lockd_init_net,
  487. .exit = lockd_exit_net,
  488. .id = &lockd_net_id,
  489. .size = sizeof(struct lockd_net),
  490. };
  491. /*
  492. * Initialising and terminating the module.
  493. */
  494. static int __init init_nlm(void)
  495. {
  496. int err;
  497. #ifdef CONFIG_SYSCTL
  498. err = -ENOMEM;
  499. nlm_sysctl_table = register_sysctl("fs/nfs", nlm_sysctls);
  500. if (nlm_sysctl_table == NULL)
  501. goto err_sysctl;
  502. #endif
  503. err = register_pernet_subsys(&lockd_net_ops);
  504. if (err)
  505. goto err_pernet;
  506. err = genl_register_family(&lockd_nl_family);
  507. if (err)
  508. goto err_netlink;
  509. err = lockd_create_procfs();
  510. if (err)
  511. goto err_procfs;
  512. return 0;
  513. err_procfs:
  514. genl_unregister_family(&lockd_nl_family);
  515. err_netlink:
  516. unregister_pernet_subsys(&lockd_net_ops);
  517. err_pernet:
  518. #ifdef CONFIG_SYSCTL
  519. unregister_sysctl_table(nlm_sysctl_table);
  520. err_sysctl:
  521. #endif
  522. return err;
  523. }
  524. static void __exit exit_nlm(void)
  525. {
  526. /* FIXME: delete all NLM clients */
  527. nlm_shutdown_hosts();
  528. genl_unregister_family(&lockd_nl_family);
  529. lockd_remove_procfs();
  530. unregister_pernet_subsys(&lockd_net_ops);
  531. #ifdef CONFIG_SYSCTL
  532. unregister_sysctl_table(nlm_sysctl_table);
  533. #endif
  534. }
  535. module_init(init_nlm);
  536. module_exit(exit_nlm);
  537. /**
  538. * nlmsvc_dispatch - Process an NLM Request
  539. * @rqstp: incoming request
  540. *
  541. * Return values:
  542. * %0: Processing complete; do not send a Reply
  543. * %1: Processing complete; send Reply in rqstp->rq_res
  544. */
  545. static int nlmsvc_dispatch(struct svc_rqst *rqstp)
  546. {
  547. const struct svc_procedure *procp = rqstp->rq_procinfo;
  548. __be32 *statp = rqstp->rq_accept_statp;
  549. if (!procp->pc_decode(rqstp, &rqstp->rq_arg_stream))
  550. goto out_decode_err;
  551. *statp = procp->pc_func(rqstp);
  552. if (*statp == rpc_drop_reply)
  553. return 0;
  554. if (*statp != rpc_success)
  555. return 1;
  556. if (!procp->pc_encode(rqstp, &rqstp->rq_res_stream))
  557. goto out_encode_err;
  558. return 1;
  559. out_decode_err:
  560. *statp = rpc_garbage_args;
  561. return 1;
  562. out_encode_err:
  563. *statp = rpc_system_err;
  564. return 1;
  565. }
  566. /*
  567. * Define NLM program and procedures
  568. */
  569. static DEFINE_PER_CPU_ALIGNED(unsigned long, nlmsvc_version1_count[17]);
  570. static const struct svc_version nlmsvc_version1 = {
  571. .vs_vers = 1,
  572. .vs_nproc = 17,
  573. .vs_proc = nlmsvc_procedures,
  574. .vs_count = nlmsvc_version1_count,
  575. .vs_dispatch = nlmsvc_dispatch,
  576. .vs_xdrsize = NLMSVC_XDRSIZE,
  577. };
  578. static DEFINE_PER_CPU_ALIGNED(unsigned long,
  579. nlmsvc_version3_count[ARRAY_SIZE(nlmsvc_procedures)]);
  580. static const struct svc_version nlmsvc_version3 = {
  581. .vs_vers = 3,
  582. .vs_nproc = ARRAY_SIZE(nlmsvc_procedures),
  583. .vs_proc = nlmsvc_procedures,
  584. .vs_count = nlmsvc_version3_count,
  585. .vs_dispatch = nlmsvc_dispatch,
  586. .vs_xdrsize = NLMSVC_XDRSIZE,
  587. };
  588. #ifdef CONFIG_LOCKD_V4
  589. static DEFINE_PER_CPU_ALIGNED(unsigned long,
  590. nlmsvc_version4_count[ARRAY_SIZE(nlmsvc_procedures4)]);
  591. static const struct svc_version nlmsvc_version4 = {
  592. .vs_vers = 4,
  593. .vs_nproc = ARRAY_SIZE(nlmsvc_procedures4),
  594. .vs_proc = nlmsvc_procedures4,
  595. .vs_count = nlmsvc_version4_count,
  596. .vs_dispatch = nlmsvc_dispatch,
  597. .vs_xdrsize = NLMSVC_XDRSIZE,
  598. };
  599. #endif
  600. static const struct svc_version *nlmsvc_version[] = {
  601. [1] = &nlmsvc_version1,
  602. [3] = &nlmsvc_version3,
  603. #ifdef CONFIG_LOCKD_V4
  604. [4] = &nlmsvc_version4,
  605. #endif
  606. };
  607. #define NLM_NRVERS ARRAY_SIZE(nlmsvc_version)
  608. static struct svc_program nlmsvc_program = {
  609. .pg_prog = NLM_PROGRAM, /* program number */
  610. .pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
  611. .pg_vers = nlmsvc_version, /* version table */
  612. .pg_name = "lockd", /* service name */
  613. .pg_class = "nfsd", /* share authentication with nfsd */
  614. .pg_authenticate = &lockd_authenticate, /* export authentication */
  615. .pg_init_request = svc_generic_init_request,
  616. .pg_rpcbind_set = svc_generic_rpcbind_set,
  617. };
  618. /**
  619. * lockd_nl_server_set_doit - set the lockd server parameters via netlink
  620. * @skb: reply buffer
  621. * @info: netlink metadata and command arguments
  622. *
  623. * This updates the per-net values. When updating the values in the init_net
  624. * namespace, also update the "legacy" global values.
  625. *
  626. * Return 0 on success or a negative errno.
  627. */
  628. int lockd_nl_server_set_doit(struct sk_buff *skb, struct genl_info *info)
  629. {
  630. struct net *net = genl_info_net(info);
  631. struct lockd_net *ln = net_generic(net, lockd_net_id);
  632. const struct nlattr *attr;
  633. if (GENL_REQ_ATTR_CHECK(info, LOCKD_A_SERVER_GRACETIME))
  634. return -EINVAL;
  635. if (info->attrs[LOCKD_A_SERVER_GRACETIME] ||
  636. info->attrs[LOCKD_A_SERVER_TCP_PORT] ||
  637. info->attrs[LOCKD_A_SERVER_UDP_PORT]) {
  638. attr = info->attrs[LOCKD_A_SERVER_GRACETIME];
  639. if (attr) {
  640. u32 gracetime = nla_get_u32(attr);
  641. if (gracetime > nlm_grace_period_max)
  642. return -EINVAL;
  643. ln->gracetime = gracetime;
  644. if (net == &init_net)
  645. nlm_grace_period = gracetime;
  646. }
  647. attr = info->attrs[LOCKD_A_SERVER_TCP_PORT];
  648. if (attr) {
  649. ln->tcp_port = nla_get_u16(attr);
  650. if (net == &init_net)
  651. nlm_tcpport = ln->tcp_port;
  652. }
  653. attr = info->attrs[LOCKD_A_SERVER_UDP_PORT];
  654. if (attr) {
  655. ln->udp_port = nla_get_u16(attr);
  656. if (net == &init_net)
  657. nlm_udpport = ln->udp_port;
  658. }
  659. }
  660. return 0;
  661. }
  662. /**
  663. * lockd_nl_server_get_doit - get lockd server parameters via netlink
  664. * @skb: reply buffer
  665. * @info: netlink metadata and command arguments
  666. *
  667. * Return 0 on success or a negative errno.
  668. */
  669. int lockd_nl_server_get_doit(struct sk_buff *skb, struct genl_info *info)
  670. {
  671. struct net *net = genl_info_net(info);
  672. struct lockd_net *ln = net_generic(net, lockd_net_id);
  673. void *hdr;
  674. int err;
  675. skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
  676. if (!skb)
  677. return -ENOMEM;
  678. hdr = genlmsg_iput(skb, info);
  679. if (!hdr) {
  680. err = -EMSGSIZE;
  681. goto err_free_msg;
  682. }
  683. err = nla_put_u32(skb, LOCKD_A_SERVER_GRACETIME, ln->gracetime) ||
  684. nla_put_u16(skb, LOCKD_A_SERVER_TCP_PORT, ln->tcp_port) ||
  685. nla_put_u16(skb, LOCKD_A_SERVER_UDP_PORT, ln->udp_port);
  686. if (err)
  687. goto err_free_msg;
  688. genlmsg_end(skb, hdr);
  689. return genlmsg_reply(skb, info);
  690. err_free_msg:
  691. nlmsg_free(skb);
  692. return err;
  693. }