~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/nfsd/nfsctl.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.