2 * linux/fs/nfsd/nfsctl.c
4 * Syscall interface to knfsd.
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/version.h>
13 #include <linux/linkage.h>
14 #include <linux/sched.h>
15 #include <linux/errno.h>
17 #include <linux/fcntl.h>
18 #include <linux/net.h>
20 #include <linux/unistd.h>
21 #include <linux/slab.h>
22 #include <linux/proc_fs.h>
23 #include <linux/seq_file.h>
24 #include <linux/init.h>
26 #include <linux/nfs.h>
27 #include <linux/sunrpc/svc.h>
28 #include <linux/nfsd/nfsd.h>
29 #include <linux/nfsd/cache.h>
30 #include <linux/nfsd/xdr.h>
31 #include <linux/nfsd/syscall.h>
33 #include <asm/uaccess.h>
34 #include <linux/smp.h>
35 #include <linux/smp_lock.h>
36 #include <linux/init.h>
38 static int nfsctl_svc(struct nfsctl_svc *data);
39 static int nfsctl_addclient(struct nfsctl_client *data);
40 static int nfsctl_delclient(struct nfsctl_client *data);
41 static int nfsctl_export(struct nfsctl_export *data);
42 static int nfsctl_unexport(struct nfsctl_export *data);
43 static int nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
44 static int nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
45 static int nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
47 static int nfsctl_ugidupdate(struct nfsctl_ugidmap *data);
50 extern struct seq_operations nfs_exports_op;
51 static int exports_open(struct inode *inode, struct file *file)
53 return seq_open(file, &nfs_exports_op);
55 static struct file_operations exports_operations = {
62 void proc_export_init(void)
64 struct proc_dir_entry *entry;
65 if (!proc_mkdir("fs/nfs", 0))
67 entry = create_proc_entry("fs/nfs/exports", 0, NULL);
69 entry->proc_fops = &exports_operations;
73 nfsctl_svc(struct nfsctl_svc *data)
75 return nfsd_svc(data->svc_port, data->svc_nthreads);
79 nfsctl_addclient(struct nfsctl_client *data)
81 return exp_addclient(data);
85 nfsctl_delclient(struct nfsctl_client *data)
87 return exp_delclient(data);
91 nfsctl_export(struct nfsctl_export *data)
93 return exp_export(data);
97 nfsctl_unexport(struct nfsctl_export *data)
99 return exp_unexport(data);
104 nfsctl_ugidupdate(nfs_ugidmap *data)
111 nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
113 struct sockaddr_in *sin;
114 struct svc_client *clp;
117 if (data->gd_addr.sa_family != AF_INET)
118 return -EPROTONOSUPPORT;
119 sin = (struct sockaddr_in *)&data->gd_addr;
120 if (data->gd_maxlen > NFS3_FHSIZE)
121 data->gd_maxlen = NFS3_FHSIZE;
123 if (!(clp = exp_getclient(sin)))
126 err = exp_rootfh(clp, 0, 0, data->gd_path, res, data->gd_maxlen);
132 nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
134 struct sockaddr_in *sin;
135 struct svc_client *clp;
139 if (data->gd_addr.sa_family != AF_INET)
140 return -EPROTONOSUPPORT;
141 if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
143 sin = (struct sockaddr_in *)&data->gd_addr;
146 if (!(clp = exp_getclient(sin)))
149 err = exp_rootfh(clp, 0, 0, data->gd_path, &fh, NFS_FHSIZE);
153 if (fh.fh_size > NFS_FHSIZE)
156 memset(res,0, NFS_FHSIZE);
157 memcpy(res, &fh.fh_base, fh.fh_size);
165 nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
167 struct sockaddr_in *sin;
168 struct svc_client *clp;
172 if (data->gf_addr.sa_family != AF_INET)
173 return -EPROTONOSUPPORT;
174 if (data->gf_version < 2 || data->gf_version > NFSSVC_MAXVERS)
176 sin = (struct sockaddr_in *)&data->gf_addr;
179 if (!(clp = exp_getclient(sin)))
182 err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
186 if (fh.fh_size > NFS_FHSIZE)
189 memset(res,0, NFS_FHSIZE);
190 memcpy(res, &fh.fh_base, fh.fh_size);
198 #define handle_sys_nfsservctl sys_nfsservctl
202 int argsize, respsize;
204 /* NFSCTL_SVC */ { sizeof(struct nfsctl_svc), 0 },
205 /* NFSCTL_ADDCLIENT */ { sizeof(struct nfsctl_client), 0},
206 /* NFSCTL_DELCLIENT */ { sizeof(struct nfsctl_client), 0},
207 /* NFSCTL_EXPORT */ { sizeof(struct nfsctl_export), 0},
208 /* NFSCTL_UNEXPORT */ { sizeof(struct nfsctl_export), 0},
209 /* NFSCTL_UGIDUPDATE */ { sizeof(struct nfsctl_uidmap), 0},
210 /* NFSCTL_GETFH */ { sizeof(struct nfsctl_fhparm), NFS_FHSIZE},
211 /* NFSCTL_GETFD */ { sizeof(struct nfsctl_fdparm), NFS_FHSIZE},
212 /* NFSCTL_GETFS */ { sizeof(struct nfsctl_fsparm), sizeof(struct knfsd_fh)},
214 #define CMD_MAX (sizeof(sizes)/sizeof(sizes[0])-1)
217 asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
219 struct nfsctl_arg * argp = opaque_argp;
220 union nfsctl_res * resp = opaque_resp;
221 struct nfsctl_arg * arg = NULL;
222 union nfsctl_res * res = NULL;
224 int argsize, respsize;
229 if (!capable(CAP_SYS_ADMIN)) {
233 if (cmd<0 || cmd > CMD_MAX)
236 argsize = sizes[cmd].argsize + (int)&((struct nfsctl_arg *)0)->u;
237 respsize = sizes[cmd].respsize; /* maximum */
238 if (!access_ok(VERIFY_READ, argp, argsize)
239 || (resp && !access_ok(VERIFY_WRITE, resp, respsize))) {
242 err = -ENOMEM; /* ??? */
243 if (!(arg = kmalloc(sizeof(*arg), GFP_USER)) ||
244 (resp && !(res = kmalloc(sizeof(*res), GFP_USER)))) {
249 copy_from_user(arg, argp, argsize);
250 if (arg->ca_version != NFSCTL_VERSION) {
251 printk(KERN_WARNING "nfsd: incompatible version in syscall.\n");
257 err = nfsctl_svc(&arg->ca_svc);
259 case NFSCTL_ADDCLIENT:
260 err = nfsctl_addclient(&arg->ca_client);
262 case NFSCTL_DELCLIENT:
263 err = nfsctl_delclient(&arg->ca_client);
266 err = nfsctl_export(&arg->ca_export);
268 case NFSCTL_UNEXPORT:
269 err = nfsctl_unexport(&arg->ca_export);
272 case NFSCTL_UGIDUPDATE:
273 err = nfsctl_ugidupdate(&arg->ca_umap);
277 err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
280 err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
283 err = nfsctl_getfs(&arg->ca_getfs, &res->cr_getfs);
284 respsize = res->cr_getfs.fh_size+ (int)&((struct knfsd_fh*)0)->fh_base;
290 if (!err && resp && respsize)
291 copy_to_user(resp, res, respsize);
304 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
305 MODULE_LICENSE("GPL");
308 struct nfsd_linkage nfsd_linkage_s = {
309 do_nfsservctl: handle_sys_nfsservctl,
315 * Initialize the module
320 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
322 nfsd_linkage = &nfsd_linkage_s;
324 nfsd_stat_init(); /* Statistics */
325 nfsd_cache_init(); /* RPC reply cache */
326 nfsd_export_init(); /* Exports table */
327 nfsd_lockd_init(); /* lockd->nfsd callbacks */
333 * Clean up the mess before unloading the module
341 nfsd_export_shutdown();
342 nfsd_cache_shutdown();
343 remove_proc_entry("fs/nfs/exports", NULL);
344 remove_proc_entry("fs/nfs", NULL);
345 nfsd_stat_shutdown();
346 nfsd_lockd_shutdown();
349 module_init(nfsd_init);
350 module_exit(nfsd_exit);