[BACK]Return to vfs_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/vfs_subr.c between version 1.253 and 1.254

version 1.253, 2005/09/13 01:45:14 version 1.254, 2005/09/23 12:10:33
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/proc.h>  #include <sys/proc.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
 #include <sys/mount.h>  #include <sys/mount.h>
 #include <sys/time.h>  
 #include <sys/event.h>  
 #include <sys/fcntl.h>  #include <sys/fcntl.h>
 #include <sys/vnode.h>  #include <sys/vnode.h>
 #include <sys/stat.h>  #include <sys/stat.h>
Line 107  __KERNEL_RCSID(0, "$NetBSD$");
Line 105  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/sa.h>  #include <sys/sa.h>
 #include <sys/syscallargs.h>  #include <sys/syscallargs.h>
 #include <sys/device.h>  #include <sys/device.h>
 #include <sys/dirent.h>  
 #include <sys/filedesc.h>  #include <sys/filedesc.h>
   
 #include <miscfs/specfs/specdev.h>  #include <miscfs/specfs/specdev.h>
 #include <miscfs/genfs/genfs.h>  #include <miscfs/genfs/genfs.h>
 #include <miscfs/syncfs/syncfs.h>  #include <miscfs/syncfs/syncfs.h>
   
 #include <netinet/in.h>  
   
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
 #include <uvm/uvm_ddb.h>  #include <uvm/uvm_ddb.h>
   
 #include <netinet/in.h>  
   
 #include <sys/sysctl.h>  #include <sys/sysctl.h>
   
 const enum vtype iftovt_tab[16] = {  const enum vtype iftovt_tab[16] = {
Line 154  struct mntlist mountlist =   /* mounted 
Line 147  struct mntlist mountlist =   /* mounted 
 struct vfs_list_head vfs_list =                 /* vfs list */  struct vfs_list_head vfs_list =                 /* vfs list */
     LIST_HEAD_INITIALIZER(vfs_list);      LIST_HEAD_INITIALIZER(vfs_list);
   
 struct nfs_public nfs_pub;                      /* publicly exported FS */  
   
 struct simplelock mountlist_slock = SIMPLELOCK_INITIALIZER;  struct simplelock mountlist_slock = SIMPLELOCK_INITIALIZER;
 static struct simplelock mntid_slock = SIMPLELOCK_INITIALIZER;  static struct simplelock mntid_slock = SIMPLELOCK_INITIALIZER;
 struct simplelock mntvnode_slock = SIMPLELOCK_INITIALIZER;  struct simplelock mntvnode_slock = SIMPLELOCK_INITIALIZER;
Line 185  int getdevvp(dev_t, struct vnode **, enu
Line 176  int getdevvp(dev_t, struct vnode **, enu
   
 void vclean(struct vnode *, int, struct proc *);  void vclean(struct vnode *, int, struct proc *);
   
 static int vfs_hang_addrlist(struct mount *, struct netexport *,  
                              struct export_args *);  
 static int vfs_free_netcred(struct radix_node *, void *);  
 static void vfs_free_addrlist(struct netexport *);  
 static struct vnode *getcleanvnode(struct proc *);  static struct vnode *getcleanvnode(struct proc *);
   
 #ifdef DEBUG  #ifdef DEBUG
Line 2113  vfs_mountedon(struct vnode *vp)
Line 2100  vfs_mountedon(struct vnode *vp)
         return (error);          return (error);
 }  }
   
 static int  
 sacheck(struct sockaddr *sa)  
 {  
         switch (sa->sa_family) {  
 #ifdef INET  
         case AF_INET: {  
                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;  
                 char *p = (char *)sin->sin_zero;  
                 size_t i;  
   
                 if (sin->sin_len != sizeof(*sin))  
                         return -1;  
                 if (sin->sin_port != 0)  
                         return -1;  
                 for (i = 0; i < sizeof(sin->sin_zero); i++)  
                         if (*p++ != '\0')  
                                 return -1;  
                 return 0;  
         }  
 #endif  
 #ifdef INET6  
         case AF_INET6: {  
                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;  
   
                 if (sin6->sin6_len != sizeof(*sin6))  
                         return -1;  
                 if (sin6->sin6_port != 0)  
                         return -1;  
                 return 0;  
         }  
 #endif  
         default:  
                 return -1;  
         }  
 }  
   
 /*  
  * Build hash lists of net addresses and hang them off the mount point.  
  * Called by ufs_mount() to set up the lists of export addresses.  
  */  
 static int  
 vfs_hang_addrlist(struct mount *mp, struct netexport *nep,  
     struct export_args *argp)  
 {  
         struct netcred *np, *enp;  
         struct radix_node_head *rnh;  
         int i;  
         struct sockaddr *saddr, *smask = 0;  
         struct domain *dom;  
         int error;  
   
         if (argp->ex_addrlen == 0) {  
                 if (mp->mnt_flag & MNT_DEFEXPORTED)  
                         return (EPERM);  
                 np = &nep->ne_defexported;  
                 np->netc_exflags = argp->ex_flags;  
                 crcvt(&np->netc_anon, &argp->ex_anon);  
                 np->netc_anon.cr_ref = 1;  
                 mp->mnt_flag |= MNT_DEFEXPORTED;  
                 return (0);  
         }  
   
         if (argp->ex_addrlen > MLEN || argp->ex_masklen > MLEN)  
                 return (EINVAL);  
   
         i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;  
         np = (struct netcred *)malloc(i, M_NETADDR, M_WAITOK);  
         memset((caddr_t)np, 0, i);  
         saddr = (struct sockaddr *)(np + 1);  
         error = copyin(argp->ex_addr, (caddr_t)saddr, argp->ex_addrlen);  
         if (error)  
                 goto out;  
         if (saddr->sa_len > argp->ex_addrlen)  
                 saddr->sa_len = argp->ex_addrlen;  
         if (sacheck(saddr) == -1)  
                 return EINVAL;  
         if (argp->ex_masklen) {  
                 smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen);  
                 error = copyin(argp->ex_mask, (caddr_t)smask, argp->ex_masklen);  
                 if (error)  
                         goto out;  
                 if (smask->sa_len > argp->ex_masklen)  
                         smask->sa_len = argp->ex_masklen;  
                 if (smask->sa_family != saddr->sa_family)  
                         return EINVAL;  
                 if (sacheck(smask) == -1)  
                         return EINVAL;  
         }  
         i = saddr->sa_family;  
         if ((rnh = nep->ne_rtable[i]) == 0) {  
                 /*  
                  * Seems silly to initialize every AF when most are not  
                  * used, do so on demand here  
                  */  
                 DOMAIN_FOREACH(dom) {  
                         if (dom->dom_family == i && dom->dom_rtattach) {  
                                 dom->dom_rtattach((void **)&nep->ne_rtable[i],  
                                         dom->dom_rtoffset);  
                                 break;  
                         }  
                 }  
                 if ((rnh = nep->ne_rtable[i]) == 0) {  
                         error = ENOBUFS;  
                         goto out;  
                 }  
         }  
   
         enp = (struct netcred *)(*rnh->rnh_addaddr)(saddr, smask, rnh,  
             np->netc_rnodes);  
         if (enp != np) {  
                 if (enp == NULL) {  
                         enp = (struct netcred *)(*rnh->rnh_lookup)(saddr,  
                             smask, rnh);  
                         if (enp == NULL) {  
                                 error = EPERM;  
                                 goto out;  
                         }  
                 } else  
                         enp->netc_refcnt++;  
   
                 goto check;  
         } else  
                 enp->netc_refcnt = 1;  
   
         np->netc_exflags = argp->ex_flags;  
         crcvt(&np->netc_anon, &argp->ex_anon);  
         np->netc_anon.cr_ref = 1;  
         return 0;  
 check:  
         if (enp->netc_exflags != argp->ex_flags ||  
             crcmp(&enp->netc_anon, &argp->ex_anon) != 0)  
                 error = EPERM;  
         else  
                 error = 0;  
 out:  
         free(np, M_NETADDR);  
         return error;  
 }  
   
 /* ARGSUSED */  
 static int  
 vfs_free_netcred(struct radix_node *rn, void *w)  
 {  
         struct radix_node_head *rnh = (struct radix_node_head *)w;  
         struct netcred *np = (struct netcred *)(void *)rn;  
   
         (*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);  
         if (--(np->netc_refcnt) <= 0)  
                 free(np, M_NETADDR);  
         return (0);  
 }  
   
 /*  
  * Free the net address hash lists that are hanging off the mount points.  
  */  
 static void  
 vfs_free_addrlist(struct netexport *nep)  
 {  
         int i;  
         struct radix_node_head *rnh;  
   
         for (i = 0; i <= AF_MAX; i++)  
                 if ((rnh = nep->ne_rtable[i]) != NULL) {  
                         (*rnh->rnh_walktree)(rnh, vfs_free_netcred, rnh);  
                         free((caddr_t)rnh, M_RTABLE);  
                         nep->ne_rtable[i] = 0;  
                 }  
 }  
   
 int  
 vfs_export(struct mount *mp, struct netexport *nep, struct export_args *argp)  
 {  
         int error;  
   
         if (argp->ex_flags & MNT_DELEXPORT) {  
                 if (mp->mnt_flag & MNT_EXPUBLIC) {  
                         vfs_setpublicfs(NULL, NULL, NULL);  
                         mp->mnt_flag &= ~MNT_EXPUBLIC;  
                 }  
                 vfs_free_addrlist(nep);  
                 mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);  
         }  
         if (argp->ex_flags & MNT_EXPORTED) {  
                 if (argp->ex_flags & MNT_EXPUBLIC) {  
                         if ((error = vfs_setpublicfs(mp, nep, argp)) != 0)  
                                 return (error);  
                         mp->mnt_flag |= MNT_EXPUBLIC;  
                 }  
                 if ((error = vfs_hang_addrlist(mp, nep, argp)) != 0)  
                         return (error);  
                 mp->mnt_flag |= MNT_EXPORTED;  
         }  
         return (0);  
 }  
   
 /*  
  * Set the publicly exported filesystem (WebNFS). Currently, only  
  * one public filesystem is possible in the spec (RFC 2054 and 2055)  
  */  
 int  
 vfs_setpublicfs(struct mount *mp, struct netexport *nep,  
     struct export_args *argp)  
 {  
         int error;  
         struct vnode *rvp;  
         char *cp;  
   
         /*  
          * mp == NULL -> invalidate the current info, the FS is  
          * no longer exported. May be called from either vfs_export  
          * or unmount, so check if it hasn't already been done.  
          */  
         if (mp == NULL) {  
                 if (nfs_pub.np_valid) {  
                         nfs_pub.np_valid = 0;  
                         if (nfs_pub.np_index != NULL) {  
                                 FREE(nfs_pub.np_index, M_TEMP);  
                                 nfs_pub.np_index = NULL;  
                         }  
                 }  
                 return (0);  
         }  
   
         /*  
          * Only one allowed at a time.  
          */  
         if (nfs_pub.np_valid != 0 && mp != nfs_pub.np_mount)  
                 return (EBUSY);  
   
         /*  
          * Get real filehandle for root of exported FS.  
          */  
         memset((caddr_t)&nfs_pub.np_handle, 0, sizeof(nfs_pub.np_handle));  
         nfs_pub.np_handle.fh_fsid = mp->mnt_stat.f_fsidx;  
   
         if ((error = VFS_ROOT(mp, &rvp)))  
                 return (error);  
   
         if ((error = VFS_VPTOFH(rvp, &nfs_pub.np_handle.fh_fid)))  
                 return (error);  
   
         vput(rvp);  
   
         /*  
          * If an indexfile was specified, pull it in.  
          */  
         if (argp->ex_indexfile != NULL) {  
                 MALLOC(nfs_pub.np_index, char *, MAXNAMLEN + 1, M_TEMP,  
                     M_WAITOK);  
                 error = copyinstr(argp->ex_indexfile, nfs_pub.np_index,  
                     MAXNAMLEN, (size_t *)0);  
                 if (!error) {  
                         /*  
                          * Check for illegal filenames.  
                          */  
                         for (cp = nfs_pub.np_index; *cp; cp++) {  
                                 if (*cp == '/') {  
                                         error = EINVAL;  
                                         break;  
                                 }  
                         }  
                 }  
                 if (error) {  
                         FREE(nfs_pub.np_index, M_TEMP);  
                         return (error);  
                 }  
         }  
   
         nfs_pub.np_mount = mp;  
         nfs_pub.np_valid = 1;  
         return (0);  
 }  
   
 struct netcred *  
 vfs_export_lookup(struct mount *mp, struct netexport *nep, struct mbuf *nam)  
 {  
         struct netcred *np;  
         struct radix_node_head *rnh;  
         struct sockaddr *saddr;  
   
         np = NULL;  
         if (mp->mnt_flag & MNT_EXPORTED) {  
                 /*  
                  * Lookup in the export list first.  
                  */  
                 if (nam != NULL) {  
                         saddr = mtod(nam, struct sockaddr *);  
                         rnh = nep->ne_rtable[saddr->sa_family];  
                         if (rnh != NULL) {  
                                 np = (struct netcred *)  
                                         (*rnh->rnh_matchaddr)((caddr_t)saddr,  
                                                               rnh);  
                                 if (np && np->netc_rnodes->rn_flags & RNF_ROOT)  
                                         np = NULL;  
                         }  
                 }  
                 /*  
                  * If no address match, use the default if it exists.  
                  */  
                 if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)  
                         np = &nep->ne_defexported;  
         }  
         return (np);  
 }  
   
 /*  /*
  * Do the usual access checking.   * Do the usual access checking.
  * file_mode, uid and gid are from the vnode in question,   * file_mode, uid and gid are from the vnode in question,

Legend:
Removed from v.1.253  
changed lines
  Added in v.1.254

CVSweb <webmaster@jp.NetBSD.org>