4141
4242#include "netns.h"
4343#include "procfs.h"
44+ #include "netlink.h"
4445
4546#define NLMDBG_FACILITY NLMDBG_SVC
4647#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
@@ -83,8 +84,14 @@ static const int nlm_port_min = 0, nlm_port_max = 65535;
8384static struct ctl_table_header * nlm_sysctl_table ;
8485#endif
8586
86- static unsigned long get_lockd_grace_period (void )
87+ static unsigned long get_lockd_grace_period (struct net * net )
8788{
89+ struct lockd_net * ln = net_generic (net , lockd_net_id );
90+
91+ /* Return the net-ns specific grace period, if there is one */
92+ if (ln -> gracetime )
93+ return ln -> gracetime * HZ ;
94+
8895 /* Note: nlm_timeout should always be nonzero */
8996 if (nlm_grace_period )
9097 return roundup (nlm_grace_period , nlm_timeout ) * HZ ;
@@ -103,7 +110,7 @@ static void grace_ender(struct work_struct *grace)
103110
104111static void set_grace_period (struct net * net )
105112{
106- unsigned long grace_period = get_lockd_grace_period ();
113+ unsigned long grace_period = get_lockd_grace_period (net );
107114 struct lockd_net * ln = net_generic (net , lockd_net_id );
108115
109116 locks_start_grace (net , & ln -> lockd_manager );
@@ -166,15 +173,16 @@ static int create_lockd_listener(struct svc_serv *serv, const char *name,
166173static int create_lockd_family (struct svc_serv * serv , struct net * net ,
167174 const int family , const struct cred * cred )
168175{
176+ struct lockd_net * ln = net_generic (net , lockd_net_id );
169177 int err ;
170178
171- err = create_lockd_listener (serv , "udp" , net , family , nlm_udpport ,
172- cred );
179+ err = create_lockd_listener (serv , "udp" , net , family ,
180+ ln -> udp_port ? ln -> udp_port : nlm_udpport , cred );
173181 if (err < 0 )
174182 return err ;
175183
176- return create_lockd_listener (serv , "tcp" , net , family , nlm_tcpport ,
177- cred );
184+ return create_lockd_listener (serv , "tcp" , net , family ,
185+ ln -> tcp_port ? ln -> tcp_port : nlm_tcpport , cred );
178186}
179187
180188/*
@@ -588,13 +596,19 @@ static int __init init_nlm(void)
588596 if (err )
589597 goto err_pernet ;
590598
599+ err = genl_register_family (& lockd_nl_family );
600+ if (err )
601+ goto err_netlink ;
602+
591603 err = lockd_create_procfs ();
592604 if (err )
593605 goto err_procfs ;
594606
595607 return 0 ;
596608
597609err_procfs :
610+ genl_unregister_family (& lockd_nl_family );
611+ err_netlink :
598612 unregister_pernet_subsys (& lockd_net_ops );
599613err_pernet :
600614#ifdef CONFIG_SYSCTL
@@ -608,6 +622,7 @@ static void __exit exit_nlm(void)
608622{
609623 /* FIXME: delete all NLM clients */
610624 nlm_shutdown_hosts ();
625+ genl_unregister_family (& lockd_nl_family );
611626 lockd_remove_procfs ();
612627 unregister_pernet_subsys (& lockd_net_ops );
613628#ifdef CONFIG_SYSCTL
@@ -710,3 +725,94 @@ static struct svc_program nlmsvc_program = {
710725 .pg_init_request = svc_generic_init_request ,
711726 .pg_rpcbind_set = svc_generic_rpcbind_set ,
712727};
728+
729+ /**
730+ * lockd_nl_server_set_doit - set the lockd server parameters via netlink
731+ * @skb: reply buffer
732+ * @info: netlink metadata and command arguments
733+ *
734+ * This updates the per-net values. When updating the values in the init_net
735+ * namespace, also update the "legacy" global values.
736+ *
737+ * Return 0 on success or a negative errno.
738+ */
739+ int lockd_nl_server_set_doit (struct sk_buff * skb , struct genl_info * info )
740+ {
741+ struct net * net = genl_info_net (info );
742+ struct lockd_net * ln = net_generic (net , lockd_net_id );
743+ const struct nlattr * attr ;
744+
745+ if (GENL_REQ_ATTR_CHECK (info , LOCKD_A_SERVER_GRACETIME ))
746+ return - EINVAL ;
747+
748+ if (info -> attrs [LOCKD_A_SERVER_GRACETIME ] ||
749+ info -> attrs [LOCKD_A_SERVER_TCP_PORT ] ||
750+ info -> attrs [LOCKD_A_SERVER_UDP_PORT ]) {
751+ attr = info -> attrs [LOCKD_A_SERVER_GRACETIME ];
752+ if (attr ) {
753+ u32 gracetime = nla_get_u32 (attr );
754+
755+ if (gracetime > nlm_grace_period_max )
756+ return - EINVAL ;
757+
758+ ln -> gracetime = gracetime ;
759+
760+ if (net == & init_net )
761+ nlm_grace_period = gracetime ;
762+ }
763+
764+ attr = info -> attrs [LOCKD_A_SERVER_TCP_PORT ];
765+ if (attr ) {
766+ ln -> tcp_port = nla_get_u16 (attr );
767+ if (net == & init_net )
768+ nlm_tcpport = ln -> tcp_port ;
769+ }
770+
771+ attr = info -> attrs [LOCKD_A_SERVER_UDP_PORT ];
772+ if (attr ) {
773+ ln -> udp_port = nla_get_u16 (attr );
774+ if (net == & init_net )
775+ nlm_udpport = ln -> udp_port ;
776+ }
777+ }
778+ return 0 ;
779+ }
780+
781+ /**
782+ * lockd_nl_server_get_doit - get lockd server parameters via netlink
783+ * @skb: reply buffer
784+ * @info: netlink metadata and command arguments
785+ *
786+ * Return 0 on success or a negative errno.
787+ */
788+ int lockd_nl_server_get_doit (struct sk_buff * skb , struct genl_info * info )
789+ {
790+ struct net * net = genl_info_net (info );
791+ struct lockd_net * ln = net_generic (net , lockd_net_id );
792+ void * hdr ;
793+ int err ;
794+
795+ skb = genlmsg_new (GENLMSG_DEFAULT_SIZE , GFP_KERNEL );
796+ if (!skb )
797+ return - ENOMEM ;
798+
799+ hdr = genlmsg_iput (skb , info );
800+ if (!hdr ) {
801+ err = - EMSGSIZE ;
802+ goto err_free_msg ;
803+ }
804+
805+ err = nla_put_u32 (skb , LOCKD_A_SERVER_GRACETIME , ln -> gracetime ) ||
806+ nla_put_u16 (skb , LOCKD_A_SERVER_TCP_PORT , ln -> tcp_port ) ||
807+ nla_put_u16 (skb , LOCKD_A_SERVER_UDP_PORT , ln -> udp_port );
808+ if (err )
809+ goto err_free_msg ;
810+
811+ genlmsg_end (skb , hdr );
812+
813+ return genlmsg_reply (skb , info );
814+ err_free_msg :
815+ nlmsg_free (skb );
816+
817+ return err ;
818+ }
0 commit comments