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.2 (Berkeley) 08/30/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 "buf.h" 35 #include "mbuf.h" 36 #include "socket.h" 37 #include "socketvar.h" 38 #include "nfsv2.h" 39 #include "nfs.h" 40 41 /* Global defs. */ 42 extern u_long nfs_prog, nfs_vers; 43 extern int (*nfsrv_procs[NFS_NPROCS])(); 44 extern struct buf nfs_bqueue; 45 extern int nfs_iodwant; 46 struct file *getsock(); 47 48 /* 49 * NFS server system calls 50 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 51 */ 52 #define RETURN(value) { u.u_error = (value); return; } 53 54 /* 55 * Get file handle system call 56 */ 57 getfh() 58 { 59 register struct a { 60 char *fname; 61 fhandle_t *fhp; 62 } *uap = (struct a *)u.u_ap; 63 register struct nameidata *ndp = &u.u_nd; 64 register struct vnode *vp; 65 fhandle_t fh; 66 int error; 67 68 /* 69 * Must be super user 70 */ 71 if (error = suser(u.u_cred, &u.u_acflag)) 72 RETURN (error); 73 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 74 ndp->ni_segflg = UIO_USERSPACE; 75 ndp->ni_dirp = uap->fname; 76 if (error = namei(ndp)) 77 RETURN (error); 78 vp = ndp->ni_vp; 79 bzero((caddr_t)&fh, sizeof(fh)); 80 fh.fh_fsid = vp->v_mount->m_fsid; 81 error = VFS_VPTOFH(vp, &fh.fh_fid); 82 vput(vp); 83 if (error) 84 RETURN (error); 85 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); 86 RETURN (error); 87 } 88 89 /* 90 * Mark a mount point in the filesystem exported 91 */ 92 exportfs() 93 { 94 register struct a { 95 char *fname; 96 int rootuid; 97 int exflags; 98 } *uap = (struct a *)u.u_ap; 99 register struct nameidata *ndp = &u.u_nd; 100 register struct vnode *vp; 101 register struct mount *mp; 102 int error; 103 104 /* 105 * Must be super user 106 */ 107 if (error = suser(u.u_cred, &u.u_acflag)) 108 RETURN (error); 109 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; /* Or NOFOLLOW ?? */ 110 ndp->ni_segflg = UIO_USERSPACE; 111 ndp->ni_dirp = uap->fname; 112 if (error = namei(ndp)) 113 RETURN (error); 114 vp = ndp->ni_vp; 115 if (vp->v_type != VDIR) { 116 vput(vp); 117 RETURN (ENOENT); 118 } 119 mp = vp->v_mount; 120 121 /* 122 * If the filesystem has already been exported, just relax 123 * security as required. 124 * Otherwise export it with the given security 125 */ 126 if (mp->m_flag & M_EXPORTED) { 127 if (uap->rootuid == 0) 128 mp->m_exroot = 0; 129 if ((uap->exflags & M_EXRDONLY) == 0) 130 mp->m_flag &= ~M_EXRDONLY; 131 } else { 132 mp->m_exroot = uap->rootuid; 133 if (uap->exflags & M_EXRDONLY) 134 mp->m_flag |= M_EXRDONLY; 135 mp->m_flag |= M_EXPORTED; 136 } 137 vput(vp); 138 RETURN (0); 139 } 140 141 /* 142 * Nfs server psuedo system call for the nfsd's 143 * Never returns unless it fails or gets killed 144 */ 145 nfssvc() 146 { 147 register struct a { 148 int s; 149 } *uap = (struct a *)u.u_ap; 150 register struct mbuf *m; 151 register int siz; 152 register struct ucred *cr; 153 struct file *fp; 154 struct mbuf *mreq, *mrep, *nam, *md; 155 struct socket *so; 156 caddr_t dpos; 157 int proc; 158 u_long retxid; 159 int error; 160 161 /* 162 * Must be super user 163 */ 164 if (error = suser(u.u_cred, &u.u_acflag)) 165 RETURN (error); 166 fp = getsock(uap->s); 167 if (fp == 0) 168 return; 169 so = (struct socket *)fp->f_data; 170 cr = u.u_cred = crcopy(u.u_cred); /* Copy it so others don't see changes */ 171 /* 172 * Just loop arround doin our stuff until SIGKILL 173 */ 174 for (;;) { 175 if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1, 176 &nam, &mrep, &md, &dpos, &retxid, &proc, cr)) { 177 m_freem(nam); 178 continue; 179 } 180 if (error = (*(nfsrv_procs[proc]))(mrep, md, dpos, 181 cr, retxid, &mreq)) { 182 m_freem(nam); 183 nfsstats.srv_errs++; 184 continue; 185 } else 186 nfsstats.srvrpccnt[proc]++; 187 m = mreq; 188 siz = 0; 189 while (m) { 190 siz += m->m_len; 191 m = m->m_next; 192 } 193 if (siz <= 0 || siz > 9216) { 194 printf("mbuf siz=%d\n",siz); 195 panic("Bad nfs svc reply"); 196 } 197 error = nfs_udpsend(so, nam, mreq, 0, siz); 198 m_freem(nam); 199 } 200 } 201 202 #ifndef notyet 203 /* 204 * Nfs pseudo system call for asynchronous i/o daemons. 205 * These babies just pretend to be disk interrupt service routines 206 * for client nfs. They are mainly here for read ahead 207 * Never returns unless it fails or gets killed 208 */ 209 async_daemon() 210 { 211 register struct buf *bp, *dp; 212 int error; 213 214 /* 215 * Must be super user 216 */ 217 if (error = suser(u.u_cred, &u.u_acflag)) 218 RETURN (error); 219 dp = &nfs_bqueue; 220 /* 221 * Just loop arround doin our stuff until SIGKILL 222 */ 223 for (;;) { 224 while (dp->b_actf == NULL) { 225 nfs_iodwant++; 226 sleep((caddr_t)&nfs_iodwant, PZERO+1); 227 } 228 /* Take one off the end of the list */ 229 bp = dp->b_actl; 230 if (bp->b_actl == dp) { 231 dp->b_actf = dp->b_actl = (struct buf *)0; 232 } else { 233 dp->b_actl = bp->b_actl; 234 bp->b_actl->b_actf = dp; 235 } 236 (void) nfs_doio(bp); 237 } 238 } 239 #endif 240