The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfsd/nfsctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 7a1977bc5a70a68ea3a4fab73ee2b5a2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.