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