1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * @(#)nfs_syscalls.c 7.1 (Berkeley) 07/05/89 21 */ 22 23 #include "param.h" 24 #include "systm.h" 25 #include "user.h" 26 #include "kernel.h" 27 #include "file.h" 28 #include "stat.h" 29 #include "vnode.h" 30 #include "mount.h" 31 #include "proc.h" 32 #include "uio.h" 33 #include "malloc.h" 34 #include "mbuf.h" 35 #include "socket.h" 36 #include "socketvar.h" 37 #include "nfsv2.h" 38 #include "nfs.h" 39 40 /* Global defs. */ 41 extern u_long nfs_prog, nfs_vers; 42 extern int (*nfsrv_procs[NFS_NPROCS])(); 43 struct file *getsock(); 44 45 /* 46 * NFS server system calls 47 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 48 */ 49 #define RETURN(value) { u.u_error = (value); return; } 50 51 /* 52 * Get file handle system call 53 */ 54 getfh() 55 { 56 register struct a { 57 char *fname; 58 fhandle_t *fhp; 59 } *uap = (struct a *)u.u_ap; 60 register struct nameidata *ndp = &u.u_nd; 61 register struct vnode *vp; 62 fhandle_t fh; 63 int error; 64 65 /* 66 * Must be super user 67 */ 68 if (error = suser(u.u_cred, &u.u_acflag)) 69 RETURN (error); 70 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 71 ndp->ni_segflg = UIO_USERSPACE; 72 ndp->ni_dirp = uap->fname; 73 if (error = namei(ndp)) 74 RETURN (error); 75 vp = ndp->ni_vp; 76 bzero((caddr_t)&fh, sizeof(fh)); 77 fh.fh_fsid = vp->v_mount->m_fsid; 78 error = VFS_VPTOFH(vp, &fh.fh_fid); 79 vput(vp); 80 if (error) 81 RETURN (error); 82 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); 83 RETURN (error); 84 } 85 86 /* 87 * Mark a mount point in the filesystem exported 88 */ 89 exportfs() 90 { 91 register struct a { 92 char *fname; 93 int rootuid; 94 int exflags; 95 } *uap = (struct a *)u.u_ap; 96 register struct nameidata *ndp = &u.u_nd; 97 register struct vnode *vp; 98 register struct mount *mp; 99 int error; 100 101 /* 102 * Must be super user 103 */ 104 if (error = suser(u.u_cred, &u.u_acflag)) 105 RETURN (error); 106 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; /* Or NOFOLLOW ?? */ 107 ndp->ni_segflg = UIO_USERSPACE; 108 ndp->ni_dirp = uap->fname; 109 if (error = namei(ndp)) 110 RETURN (error); 111 vp = ndp->ni_vp; 112 if (vp->v_type != VDIR) { 113 vput(vp); 114 RETURN (ENOENT); 115 } 116 mp = vp->v_mount; 117 118 /* 119 * If the filesystem has already been exported, just relax 120 * security as required. 121 * Otherwise export it with the given security 122 */ 123 if (mp->m_flag & M_EXPORTED) { 124 if (uap->rootuid == 0) 125 mp->m_exroot = 0; 126 if ((uap->exflags & M_EXRDONLY) == 0) 127 mp->m_flag &= ~M_EXRDONLY; 128 } else { 129 mp->m_exroot = uap->rootuid; 130 if (uap->exflags & M_EXRDONLY) 131 mp->m_flag |= M_EXRDONLY; 132 mp->m_flag |= M_EXPORTED; 133 } 134 vput(vp); 135 RETURN (0); 136 } 137 138 /* 139 * Nfs server psuedo system call for the nfsd's 140 * Never returns unless it fails or gets killed 141 */ 142 nfssvc() 143 { 144 register struct a { 145 int s; 146 } *uap = (struct a *)u.u_ap; 147 register struct mbuf *m; 148 register int siz; 149 register struct ucred *cr; 150 struct file *fp; 151 struct mbuf *mreq, *mrep, *nam, *md; 152 struct socket *so; 153 caddr_t dpos; 154 int proc; 155 u_long retxid; 156 int error; 157 158 /* 159 * Must be super user 160 */ 161 if (error = suser(u.u_cred, &u.u_acflag)) 162 RETURN (error); 163 fp = getsock(uap->s); 164 if (fp == 0) 165 return; 166 so = (struct socket *)fp->f_data; 167 cr = u.u_cred = crcopy(u.u_cred); /* Copy it so others don't see changes */ 168 /* 169 * Just loop arround doin our stuff until SIGKILL 170 */ 171 for (;;) { 172 if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1, 173 &nam, &mrep, &md, &dpos, &retxid, &proc, cr)) { 174 m_freem(nam); 175 continue; 176 } 177 if (error = (*(nfsrv_procs[proc]))(mrep, md, dpos, 178 cr, retxid, &mreq)) { 179 m_freem(nam); 180 nfsstats.srv_errs++; 181 continue; 182 } else 183 nfsstats.srvrpccnt[proc]++; 184 m = mreq; 185 siz = 0; 186 while (m) { 187 siz += m->m_len; 188 m = m->m_next; 189 } 190 if (siz <= 0 || siz > 9216) { 191 printf("mbuf siz=%d\n",siz); 192 panic("Bad nfs svc reply"); 193 } 194 error = nfs_udpsend(so, nam, mreq, 0, siz); 195 m_freem(nam); 196 } 197 } 198