xref: /csrg-svn/sys/nfs/nfs_syscalls.c (revision 38884)
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