nfsctl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/nfsd/nfsctl.c
  3.  *
  4.  * Syscall interface to knfsd.
  5.  *
  6.  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  7.  */
  8. #include <linux/config.h>
  9. #include <linux/module.h>
  10. #include <linux/version.h>
  11. #include <linux/linkage.h>
  12. #include <linux/sched.h>
  13. #include <linux/errno.h>
  14. #include <linux/fs.h>
  15. #include <linux/fcntl.h>
  16. #include <linux/net.h>
  17. #include <linux/in.h>
  18. #include <linux/unistd.h>
  19. #include <linux/slab.h>
  20. #include <linux/proc_fs.h>
  21. #include <linux/seq_file.h>
  22. #include <linux/nfs.h>
  23. #include <linux/sunrpc/svc.h>
  24. #include <linux/nfsd/nfsd.h>
  25. #include <linux/nfsd/cache.h>
  26. #include <linux/nfsd/xdr.h>
  27. #include <linux/nfsd/syscall.h>
  28. #include <asm/uaccess.h>
  29. #include <linux/smp.h>
  30. #include <linux/smp_lock.h>
  31. #include <linux/init.h>
  32. static int nfsctl_svc(struct nfsctl_svc *data);
  33. static int nfsctl_addclient(struct nfsctl_client *data);
  34. static int nfsctl_delclient(struct nfsctl_client *data);
  35. static int nfsctl_export(struct nfsctl_export *data);
  36. static int nfsctl_unexport(struct nfsctl_export *data);
  37. static int nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
  38. static int nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
  39. static int nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
  40. #ifdef notyet
  41. static int nfsctl_ugidupdate(struct nfsctl_ugidmap *data);
  42. #endif
  43. extern struct seq_operations nfs_exports_op;
  44. static int exports_open(struct inode *inode, struct file *file)
  45. {
  46. return seq_open(file, &nfs_exports_op);
  47. }
  48. static struct file_operations exports_operations = {
  49. open: exports_open,
  50. read: seq_read,
  51. llseek: seq_lseek,
  52. release: seq_release,
  53. };
  54. void proc_export_init(void)
  55. {
  56. struct proc_dir_entry *entry;
  57. if (!proc_mkdir("fs/nfs", 0))
  58. return;
  59. entry = create_proc_entry("fs/nfs/exports", 0, NULL);
  60. if (entry)
  61. entry->proc_fops =  &exports_operations;
  62. }
  63. static inline int
  64. nfsctl_svc(struct nfsctl_svc *data)
  65. {
  66. return nfsd_svc(data->svc_port, data->svc_nthreads);
  67. }
  68. static inline int
  69. nfsctl_addclient(struct nfsctl_client *data)
  70. {
  71. return exp_addclient(data);
  72. }
  73. static inline int
  74. nfsctl_delclient(struct nfsctl_client *data)
  75. {
  76. return exp_delclient(data);
  77. }
  78. static inline int
  79. nfsctl_export(struct nfsctl_export *data)
  80. {
  81. return exp_export(data);
  82. }
  83. static inline int
  84. nfsctl_unexport(struct nfsctl_export *data)
  85. {
  86. return exp_unexport(data);
  87. }
  88. #ifdef notyet
  89. static inline int
  90. nfsctl_ugidupdate(nfs_ugidmap *data)
  91. {
  92. return -EINVAL;
  93. }
  94. #endif
  95. static inline int
  96. nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
  97. {
  98. struct sockaddr_in *sin;
  99. struct svc_client *clp;
  100. int err = 0;
  101. if (data->gd_addr.sa_family != AF_INET)
  102. return -EPROTONOSUPPORT;
  103. sin = (struct sockaddr_in *)&data->gd_addr;
  104. if (data->gd_maxlen > NFS3_FHSIZE)
  105. data->gd_maxlen = NFS3_FHSIZE;
  106. exp_readlock();
  107. if (!(clp = exp_getclient(sin)))
  108. err = -EPERM;
  109. else
  110. err = exp_rootfh(clp, 0, 0, data->gd_path, res, data->gd_maxlen);
  111. exp_unlock();
  112. return err;
  113. }
  114. static inline int
  115. nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
  116. {
  117. struct sockaddr_in *sin;
  118. struct svc_client *clp;
  119. int err = 0;
  120. struct knfsd_fh fh;
  121. if (data->gd_addr.sa_family != AF_INET)
  122. return -EPROTONOSUPPORT;
  123. if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
  124. return -EINVAL;
  125. sin = (struct sockaddr_in *)&data->gd_addr;
  126. exp_readlock();
  127. if (!(clp = exp_getclient(sin)))
  128. err = -EPERM;
  129. else
  130. err = exp_rootfh(clp, 0, 0, data->gd_path, &fh, NFS_FHSIZE);
  131. exp_unlock();
  132. if (err == 0) {
  133. if (fh.fh_size > NFS_FHSIZE)
  134. err = -EINVAL;
  135. else {
  136. memset(res,0, NFS_FHSIZE);
  137. memcpy(res, &fh.fh_base, fh.fh_size);
  138. }
  139. }
  140. return err;
  141. }
  142. static inline int
  143. nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
  144. {
  145. struct sockaddr_in *sin;
  146. struct svc_client *clp;
  147. int err = 0;
  148. struct knfsd_fh fh;
  149. if (data->gf_addr.sa_family != AF_INET)
  150. return -EPROTONOSUPPORT;
  151. if (data->gf_version < 2 || data->gf_version > NFSSVC_MAXVERS)
  152. return -EINVAL;
  153. sin = (struct sockaddr_in *)&data->gf_addr;
  154. exp_readlock();
  155. if (!(clp = exp_getclient(sin)))
  156. err = -EPERM;
  157. else
  158. err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
  159. exp_unlock();
  160. if (err == 0) {
  161. if (fh.fh_size > NFS_FHSIZE)
  162. err = -EINVAL;
  163. else {
  164. memset(res,0, NFS_FHSIZE);
  165. memcpy(res, &fh.fh_base, fh.fh_size);
  166. }
  167. }
  168. return err;
  169. }
  170. #ifdef CONFIG_NFSD
  171. #define handle_sys_nfsservctl sys_nfsservctl
  172. #endif
  173. static struct {
  174. int argsize, respsize;
  175. }  sizes[] = {
  176. /* NFSCTL_SVC        */ { sizeof(struct nfsctl_svc), 0 },
  177. /* NFSCTL_ADDCLIENT  */ { sizeof(struct nfsctl_client), 0},
  178. /* NFSCTL_DELCLIENT  */ { sizeof(struct nfsctl_client), 0},
  179. /* NFSCTL_EXPORT     */ { sizeof(struct nfsctl_export), 0},
  180. /* NFSCTL_UNEXPORT   */ { sizeof(struct nfsctl_export), 0},
  181. /* NFSCTL_UGIDUPDATE */ { sizeof(struct nfsctl_uidmap), 0},
  182. /* NFSCTL_GETFH      */ { sizeof(struct nfsctl_fhparm), NFS_FHSIZE},
  183. /* NFSCTL_GETFD      */ { sizeof(struct nfsctl_fdparm), NFS_FHSIZE},
  184. /* NFSCTL_GETFS      */ { sizeof(struct nfsctl_fsparm), sizeof(struct knfsd_fh)},
  185. };
  186. #define CMD_MAX (sizeof(sizes)/sizeof(sizes[0])-1)
  187. long
  188. asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
  189. {
  190. struct nfsctl_arg * argp = opaque_argp;
  191. union nfsctl_res * resp = opaque_resp;
  192. struct nfsctl_arg * arg = NULL;
  193. union nfsctl_res * res = NULL;
  194. int err;
  195. int argsize, respsize;
  196. lock_kernel ();
  197. err = -EPERM;
  198. if (!capable(CAP_SYS_ADMIN)) {
  199. goto done;
  200. }
  201. err = -EINVAL;
  202. if (cmd<0 || cmd > CMD_MAX)
  203. goto done;
  204. err = -EFAULT;
  205. argsize = sizes[cmd].argsize + (int)&((struct nfsctl_arg *)0)->u;
  206. respsize = sizes[cmd].respsize; /* maximum */
  207. if (!access_ok(VERIFY_READ, argp, argsize)
  208.  || (resp && !access_ok(VERIFY_WRITE, resp, respsize))) {
  209. goto done;
  210. }
  211. err = -ENOMEM; /* ??? */
  212. if (!(arg = kmalloc(sizeof(*arg), GFP_USER)) ||
  213.     (resp && !(res = kmalloc(sizeof(*res), GFP_USER)))) {
  214. goto done;
  215. }
  216. err = -EINVAL;
  217. copy_from_user(arg, argp, argsize);
  218. if (arg->ca_version != NFSCTL_VERSION) {
  219. printk(KERN_WARNING "nfsd: incompatible version in syscall.n");
  220. goto done;
  221. }
  222. switch(cmd) {
  223. case NFSCTL_SVC:
  224. err = nfsctl_svc(&arg->ca_svc);
  225. break;
  226. case NFSCTL_ADDCLIENT:
  227. err = nfsctl_addclient(&arg->ca_client);
  228. break;
  229. case NFSCTL_DELCLIENT:
  230. err = nfsctl_delclient(&arg->ca_client);
  231. break;
  232. case NFSCTL_EXPORT:
  233. err = nfsctl_export(&arg->ca_export);
  234. break;
  235. case NFSCTL_UNEXPORT:
  236. err = nfsctl_unexport(&arg->ca_export);
  237. break;
  238. #ifdef notyet
  239. case NFSCTL_UGIDUPDATE:
  240. err = nfsctl_ugidupdate(&arg->ca_umap);
  241. break;
  242. #endif
  243. case NFSCTL_GETFH:
  244. err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
  245. break;
  246. case NFSCTL_GETFD:
  247. err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
  248. break;
  249. case NFSCTL_GETFS:
  250. err = nfsctl_getfs(&arg->ca_getfs, &res->cr_getfs);
  251. respsize = res->cr_getfs.fh_size+ (int)&((struct knfsd_fh*)0)->fh_base;
  252. break;
  253. default:
  254. err = -EINVAL;
  255. }
  256. if (!err && resp && respsize)
  257. copy_to_user(resp, res, respsize);
  258. done:
  259. if (arg)
  260. kfree(arg);
  261. if (res)
  262. kfree(res);
  263. unlock_kernel ();
  264. return err;
  265. }
  266. EXPORT_NO_SYMBOLS;
  267. MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
  268. MODULE_LICENSE("GPL");
  269. #ifdef MODULE
  270. struct nfsd_linkage nfsd_linkage_s = {
  271. do_nfsservctl: handle_sys_nfsservctl,
  272. owner: THIS_MODULE,
  273. };
  274. #endif
  275. /*
  276.  * Initialize the module
  277.  */
  278. static int __init
  279. nfsd_init(void)
  280. {
  281. printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).n");
  282. #ifdef MODULE
  283. nfsd_linkage = &nfsd_linkage_s;
  284. #endif
  285. nfsd_stat_init(); /* Statistics */
  286. nfsd_cache_init(); /* RPC reply cache */
  287. nfsd_export_init(); /* Exports table */
  288. nfsd_lockd_init(); /* lockd->nfsd callbacks */
  289. proc_export_init();
  290. return 0;
  291. }
  292. /*
  293.  * Clean up the mess before unloading the module
  294.  */
  295. static void __exit
  296. nfsd_exit(void)
  297. {
  298. #ifdef MODULE
  299. nfsd_linkage = NULL;
  300. #endif
  301. nfsd_export_shutdown();
  302. nfsd_cache_shutdown();
  303. remove_proc_entry("fs/nfs/exports", NULL);
  304. remove_proc_entry("fs/nfs", NULL);
  305. nfsd_stat_shutdown();
  306. nfsd_lockd_shutdown();
  307. }
  308. module_init(nfsd_init);
  309. module_exit(nfsd_exit);