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