@@ -1796,6 +1796,156 @@ int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info)
17961796 return err ;
17971797}
17981798
1799+ /**
1800+ * nfsd_nl_version_set_doit - set the nfs enabled versions
1801+ * @skb: reply buffer
1802+ * @info: netlink metadata and command arguments
1803+ *
1804+ * Return 0 on success or a negative errno.
1805+ */
1806+ int nfsd_nl_version_set_doit (struct sk_buff * skb , struct genl_info * info )
1807+ {
1808+ const struct nlattr * attr ;
1809+ struct nfsd_net * nn ;
1810+ int i , rem ;
1811+
1812+ if (GENL_REQ_ATTR_CHECK (info , NFSD_A_SERVER_PROTO_VERSION ))
1813+ return - EINVAL ;
1814+
1815+ mutex_lock (& nfsd_mutex );
1816+
1817+ nn = net_generic (genl_info_net (info ), nfsd_net_id );
1818+ if (nn -> nfsd_serv ) {
1819+ mutex_unlock (& nfsd_mutex );
1820+ return - EBUSY ;
1821+ }
1822+
1823+ /* clear current supported versions. */
1824+ nfsd_vers (nn , 2 , NFSD_CLEAR );
1825+ nfsd_vers (nn , 3 , NFSD_CLEAR );
1826+ for (i = 0 ; i <= NFSD_SUPPORTED_MINOR_VERSION ; i ++ )
1827+ nfsd_minorversion (nn , i , NFSD_CLEAR );
1828+
1829+ nlmsg_for_each_attr (attr , info -> nlhdr , GENL_HDRLEN , rem ) {
1830+ struct nlattr * tb [NFSD_A_VERSION_MAX + 1 ];
1831+ u32 major , minor = 0 ;
1832+ bool enabled ;
1833+
1834+ if (nla_type (attr ) != NFSD_A_SERVER_PROTO_VERSION )
1835+ continue ;
1836+
1837+ if (nla_parse_nested (tb , NFSD_A_VERSION_MAX , attr ,
1838+ nfsd_version_nl_policy , info -> extack ) < 0 )
1839+ continue ;
1840+
1841+ if (!tb [NFSD_A_VERSION_MAJOR ])
1842+ continue ;
1843+
1844+ major = nla_get_u32 (tb [NFSD_A_VERSION_MAJOR ]);
1845+ if (tb [NFSD_A_VERSION_MINOR ])
1846+ minor = nla_get_u32 (tb [NFSD_A_VERSION_MINOR ]);
1847+
1848+ enabled = nla_get_flag (tb [NFSD_A_VERSION_ENABLED ]);
1849+
1850+ switch (major ) {
1851+ case 4 :
1852+ nfsd_minorversion (nn , minor , enabled ? NFSD_SET : NFSD_CLEAR );
1853+ break ;
1854+ case 3 :
1855+ case 2 :
1856+ if (!minor )
1857+ nfsd_vers (nn , major , enabled ? NFSD_SET : NFSD_CLEAR );
1858+ break ;
1859+ default :
1860+ break ;
1861+ }
1862+ }
1863+
1864+ mutex_unlock (& nfsd_mutex );
1865+
1866+ return 0 ;
1867+ }
1868+
1869+ /**
1870+ * nfsd_nl_version_get_doit - get the enabled status for all supported nfs versions
1871+ * @skb: reply buffer
1872+ * @info: netlink metadata and command arguments
1873+ *
1874+ * Return 0 on success or a negative errno.
1875+ */
1876+ int nfsd_nl_version_get_doit (struct sk_buff * skb , struct genl_info * info )
1877+ {
1878+ struct nfsd_net * nn ;
1879+ int i , err ;
1880+ void * hdr ;
1881+
1882+ skb = genlmsg_new (GENLMSG_DEFAULT_SIZE , GFP_KERNEL );
1883+ if (!skb )
1884+ return - ENOMEM ;
1885+
1886+ hdr = genlmsg_iput (skb , info );
1887+ if (!hdr ) {
1888+ err = - EMSGSIZE ;
1889+ goto err_free_msg ;
1890+ }
1891+
1892+ mutex_lock (& nfsd_mutex );
1893+ nn = net_generic (genl_info_net (info ), nfsd_net_id );
1894+
1895+ for (i = 2 ; i <= 4 ; i ++ ) {
1896+ int j ;
1897+
1898+ for (j = 0 ; j <= NFSD_SUPPORTED_MINOR_VERSION ; j ++ ) {
1899+ struct nlattr * attr ;
1900+
1901+ /* Don't record any versions the kernel doesn't have
1902+ * compiled in
1903+ */
1904+ if (!nfsd_support_version (i ))
1905+ continue ;
1906+
1907+ /* NFSv{2,3} does not support minor numbers */
1908+ if (i < 4 && j )
1909+ continue ;
1910+
1911+ attr = nla_nest_start (skb ,
1912+ NFSD_A_SERVER_PROTO_VERSION );
1913+ if (!attr ) {
1914+ err = - EINVAL ;
1915+ goto err_nfsd_unlock ;
1916+ }
1917+
1918+ if (nla_put_u32 (skb , NFSD_A_VERSION_MAJOR , i ) ||
1919+ nla_put_u32 (skb , NFSD_A_VERSION_MINOR , j )) {
1920+ err = - EINVAL ;
1921+ goto err_nfsd_unlock ;
1922+ }
1923+
1924+ /* Set the enabled flag if the version is enabled */
1925+ if (nfsd_vers (nn , i , NFSD_TEST ) &&
1926+ (i < 4 || nfsd_minorversion (nn , j , NFSD_TEST )) &&
1927+ nla_put_flag (skb , NFSD_A_VERSION_ENABLED )) {
1928+ err = - EINVAL ;
1929+ goto err_nfsd_unlock ;
1930+ }
1931+
1932+ nla_nest_end (skb , attr );
1933+ }
1934+ }
1935+
1936+ mutex_unlock (& nfsd_mutex );
1937+ genlmsg_end (skb , hdr );
1938+
1939+ return genlmsg_reply (skb , info );
1940+
1941+ err_nfsd_unlock :
1942+ mutex_unlock (& nfsd_mutex );
1943+ err_free_msg :
1944+ nlmsg_free (skb );
1945+
1946+ return err ;
1947+ }
1948+
17991949/**
18001950 * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace
18011951 * @net: a freshly-created network namespace
0 commit comments