xref: /plan9/sys/src/cmd/unix/9pfreebsd/freebsd-3.2.il-kernel.patch (revision 144145943e440fe30c4e4512a0856f5e3d5ca4be)
1*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9auth.c ./9fs/9auth.c
2*14414594SDavid du Colombier*** /usr/src/sys/9fs/9auth.c	Wed Dec 31 19:00:00 1969
3*14414594SDavid du Colombier--- ./9fs/9auth.c	Mon May 22 17:11:29 2000
4*14414594SDavid du Colombier***************
5*14414594SDavid du Colombier*** 0 ****
6*14414594SDavid du Colombier--- 1,238 ----
7*14414594SDavid du Colombier+ #include <sys/param.h>
8*14414594SDavid du Colombier+ #include <sys/systm.h>
9*14414594SDavid du Colombier+ #include <sys/socket.h>
10*14414594SDavid du Colombier+ #include <sys/socketvar.h>
11*14414594SDavid du Colombier+ #include <sys/protosw.h>
12*14414594SDavid du Colombier+ #include <sys/malloc.h>
13*14414594SDavid du Colombier+ #include <sys/mbuf.h>
14*14414594SDavid du Colombier+ #include <sys/uio.h>
15*14414594SDavid du Colombier+
16*14414594SDavid du Colombier+ #include <9fs/9p.h>
17*14414594SDavid du Colombier+ #include <9fs/9auth.h>
18*14414594SDavid du Colombier+
19*14414594SDavid du Colombier+ #define	N2HCHAR(x)		x = *p++
20*14414594SDavid du Colombier+ #define	N2HSHORT(x)	x = (p[0] | (p[1]<<8)); p += 2
21*14414594SDavid du Colombier+ #define	N2HLONG(x)		x = (p[0] | (p[1]<<8) |\
22*14414594SDavid du Colombier+ 				(p[2]<<16) | (p[3]<<24)); p += 4
23*14414594SDavid du Colombier+ #define	N2HQUAD(x)	x = (u_int64_t)(p[0] | (p[1]<<8) |\
24*14414594SDavid du Colombier+ 					(p[2]<<16) | (p[3]<<24)) |\
25*14414594SDavid du Colombier+ 				((u_int64_t)(p[4] | (p[5]<<8) |\
26*14414594SDavid du Colombier+ 					(p[6]<<16) | (p[7]<<24)) << 32); p += 8
27*14414594SDavid du Colombier+ #define	N2HSTRING(x,n)	bcopy(p, x, n); p += n
28*14414594SDavid du Colombier+
29*14414594SDavid du Colombier+ #define	H2NCHAR(x)	*p++ = x
30*14414594SDavid du Colombier+ #define	H2NSHORT(x)	p[0]=x; p[1]=x>>8; p += 2
31*14414594SDavid du Colombier+ #define	H2NLONG(x)		p[0]=x; p[1]=x>>8; p[2]=x>>16; p[3]=x>>24; p += 4
32*14414594SDavid du Colombier+ #define	H2NQUAD(x)	p[0]=x;	p[1]=x>>8;\
33*14414594SDavid du Colombier+ 			p[2]=x>>16;	p[3]=x>>24;\
34*14414594SDavid du Colombier+ 			p[4]=x>>32;	p[5]=x>>40;\
35*14414594SDavid du Colombier+ 			p[6]=x>>48;	p[7]=x>>56;\
36*14414594SDavid du Colombier+ 			p += 8
37*14414594SDavid du Colombier+ #define	H2NSTRING(x,n)	bcopy(x, p, n); p += n
38*14414594SDavid du Colombier+
39*14414594SDavid du Colombier+ static int u9auth_send __P((struct socket *so, struct mbuf *top, struct proc *p));
40*14414594SDavid du Colombier+ static int u9auth_recv __P((struct socket *so, struct mbuf **mp, struct proc *p));
41*14414594SDavid du Colombier+
42*14414594SDavid du Colombier+ static int u9auth_count = 0;
43*14414594SDavid du Colombier+
44*14414594SDavid du Colombier+ static int u9auth_tr2m(struct u9auth_ticketreq *f, char *ap)
45*14414594SDavid du Colombier+ {
46*14414594SDavid du Colombier+ 	int n;
47*14414594SDavid du Colombier+ 	u_char *p;
48*14414594SDavid du Colombier+
49*14414594SDavid du Colombier+ 	p = (u_char*)ap;
50*14414594SDavid du Colombier+         H2NCHAR(f->type);
51*14414594SDavid du Colombier+ 	H2NSTRING(f->authid, U9FS_NAMELEN);
52*14414594SDavid du Colombier+ 	H2NSTRING(f->authdom, U9FS_DOMLEN);
53*14414594SDavid du Colombier+ 	H2NSTRING(f->chal, U9FS_CHALLEN);
54*14414594SDavid du Colombier+ 	H2NSTRING(f->hostid, U9FS_NAMELEN);
55*14414594SDavid du Colombier+ 	H2NSTRING(f->uid, U9FS_NAMELEN);
56*14414594SDavid du Colombier+ 	n = p - (u_char*)ap;
57*14414594SDavid du Colombier+ 	return n;
58*14414594SDavid du Colombier+ }
59*14414594SDavid du Colombier+
60*14414594SDavid du Colombier+ static struct mbuf * u9auth_m_tr2m(struct u9auth_ticketreq * tktq)
61*14414594SDavid du Colombier+ {
62*14414594SDavid du Colombier+   register struct mbuf *m;
63*14414594SDavid du Colombier+   char * ap;
64*14414594SDavid du Colombier+   int sz = 141;
65*14414594SDavid du Colombier+
66*14414594SDavid du Colombier+   MGETHDR(m, M_WAIT, MT_DATA);
67*14414594SDavid du Colombier+   if( sz > MHLEN )
68*14414594SDavid du Colombier+     MCLGET(m, M_WAIT);
69*14414594SDavid du Colombier+   m->m_len = 0;
70*14414594SDavid du Colombier+
71*14414594SDavid du Colombier+   if ( M_TRAILINGSPACE(m) < sz )
72*14414594SDavid du Colombier+     panic("u9auth_m_tr2m");
73*14414594SDavid du Colombier+
74*14414594SDavid du Colombier+   ap = mtod(m, char *);
75*14414594SDavid du Colombier+   m->m_len = u9auth_tr2m(tktq, ap);
76*14414594SDavid du Colombier+   m->m_pkthdr.len = m->m_len;
77*14414594SDavid du Colombier+
78*14414594SDavid du Colombier+   return (m);
79*14414594SDavid du Colombier+ }
80*14414594SDavid du Colombier+
81*14414594SDavid du Colombier+ static int
82*14414594SDavid du Colombier+ u9auth_send(so, top, p)
83*14414594SDavid du Colombier+ 	register struct socket *so;
84*14414594SDavid du Colombier+ 	register struct mbuf *top;
85*14414594SDavid du Colombier+ 	register struct proc *p;
86*14414594SDavid du Colombier+
87*14414594SDavid du Colombier+ {
88*14414594SDavid du Colombier+   int error, soflags, flags;
89*14414594SDavid du Colombier+
90*14414594SDavid du Colombier+   soflags = so->so_proto->pr_flags;
91*14414594SDavid du Colombier+   if (so->so_type == SOCK_SEQPACKET)
92*14414594SDavid du Colombier+     flags = MSG_EOR;
93*14414594SDavid du Colombier+   else
94*14414594SDavid du Colombier+     flags = 0;
95*14414594SDavid du Colombier+
96*14414594SDavid du Colombier+   error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 0, top, 0, flags, p);
97*14414594SDavid du Colombier+
98*14414594SDavid du Colombier+   return (error);
99*14414594SDavid du Colombier+ }
100*14414594SDavid du Colombier+
101*14414594SDavid du Colombier+ static int
102*14414594SDavid du Colombier+ u9auth_recv(so, mp, p)
103*14414594SDavid du Colombier+      register struct socket * so;
104*14414594SDavid du Colombier+      register struct mbuf **mp;
105*14414594SDavid du Colombier+      struct proc *p;
106*14414594SDavid du Colombier+ {
107*14414594SDavid du Colombier+   struct uio auio;
108*14414594SDavid du Colombier+   u_int32_t len;
109*14414594SDavid du Colombier+   int error = 0, sotype, rcvflg;
110*14414594SDavid du Colombier+
111*14414594SDavid du Colombier+   *mp = 0;
112*14414594SDavid du Colombier+   sotype = so->so_type;
113*14414594SDavid du Colombier+
114*14414594SDavid du Colombier+   /*
115*14414594SDavid du Colombier+    * For reliable protocols, lock against other senders/receivers
116*14414594SDavid du Colombier+    * in case a reconnect is necessary.
117*14414594SDavid du Colombier+    * For SOCK_STREAM, first get the Record Mark to find out how much
118*14414594SDavid du Colombier+    * more there is to get.
119*14414594SDavid du Colombier+    * We must lock the socket against other receivers
120*14414594SDavid du Colombier+    * until we have an entire rpc request/reply.
121*14414594SDavid du Colombier+    */
122*14414594SDavid du Colombier+   if (sotype == SOCK_SEQPACKET ) {
123*14414594SDavid du Colombier+     if( (so->so_state & SS_ISCONNECTED) == 0 )
124*14414594SDavid du Colombier+       return (EACCES);
125*14414594SDavid du Colombier+ 		auio.uio_resid = len = 1000000;
126*14414594SDavid du Colombier+ 		auio.uio_procp = p;
127*14414594SDavid du Colombier+ 		do {
128*14414594SDavid du Colombier+ 			rcvflg = 0;
129*14414594SDavid du Colombier+ 			error =  so->so_proto->pr_usrreqs->pru_soreceive
130*14414594SDavid du Colombier+ 				(so, 0, &auio, mp,
131*14414594SDavid du Colombier+ 				(struct mbuf **)0, &rcvflg);
132*14414594SDavid du Colombier+ 		} while (error == EWOULDBLOCK);
133*14414594SDavid du Colombier+ 		len -= auio.uio_resid;
134*14414594SDavid du Colombier+   }
135*14414594SDavid du Colombier+   if (error) {
136*14414594SDavid du Colombier+     m_freem(*mp);
137*14414594SDavid du Colombier+     *mp = 0;
138*14414594SDavid du Colombier+   }
139*14414594SDavid du Colombier+   return (error);
140*14414594SDavid du Colombier+ }
141*14414594SDavid du Colombier+
142*14414594SDavid du Colombier+ static void
143*14414594SDavid du Colombier+ u9auth_m2t(char *ap, struct u9auth_ticket *f, char *key)
144*14414594SDavid du Colombier+ {
145*14414594SDavid du Colombier+ 	u_char *p;
146*14414594SDavid du Colombier+
147*14414594SDavid du Colombier+ 	if(key)
148*14414594SDavid du Colombier+ 		decrypt9(key, ap, U9AUTH_TICKETLEN);
149*14414594SDavid du Colombier+ 	p = (u_char*)ap;
150*14414594SDavid du Colombier+ 	N2HCHAR(f->num);
151*14414594SDavid du Colombier+ 	N2HSTRING(f->chal, U9FS_CHALLEN);
152*14414594SDavid du Colombier+ 	N2HSTRING(f->cuid, U9FS_NAMELEN);
153*14414594SDavid du Colombier+ 	f->cuid[U9FS_NAMELEN-1] = 0;
154*14414594SDavid du Colombier+ 	N2HSTRING(f->suid, U9FS_NAMELEN);
155*14414594SDavid du Colombier+ 	f->suid[U9FS_NAMELEN-1] = 0;
156*14414594SDavid du Colombier+ 	N2HSTRING(f->key, U9AUTH_DESKEYLEN);
157*14414594SDavid du Colombier+ };
158*14414594SDavid du Colombier+
159*14414594SDavid du Colombier+ static int
160*14414594SDavid du Colombier+ u9auth_a2m(struct u9auth_authenticator *f, char *ap, char *key)
161*14414594SDavid du Colombier+ {
162*14414594SDavid du Colombier+ 	int n;
163*14414594SDavid du Colombier+ 	u_char *p;
164*14414594SDavid du Colombier+
165*14414594SDavid du Colombier+ 	p = (u_char*)ap;
166*14414594SDavid du Colombier+ 	H2NCHAR(f->num);
167*14414594SDavid du Colombier+ 	H2NSTRING(f->chal, U9FS_CHALLEN);
168*14414594SDavid du Colombier+ 	H2NLONG(f->id);
169*14414594SDavid du Colombier+ 	n = p - (u_char*)ap;
170*14414594SDavid du Colombier+ 	if(key)
171*14414594SDavid du Colombier+ 		encrypt9(key, ap, n);
172*14414594SDavid du Colombier+ 	return n;
173*14414594SDavid du Colombier+ }
174*14414594SDavid du Colombier+
175*14414594SDavid du Colombier+ void u9auth_genchal (char * chal)
176*14414594SDavid du Colombier+ {
177*14414594SDavid du Colombier+   u_long * lp = (u_long *)chal;
178*14414594SDavid du Colombier+
179*14414594SDavid du Colombier+   *lp++ = random();
180*14414594SDavid du Colombier+   *lp = random();
181*14414594SDavid du Colombier+ }
182*14414594SDavid du Colombier+
183*14414594SDavid du Colombier+ int u9auth_gettickets (struct socket * so, struct u9fsreq * rep,
184*14414594SDavid du Colombier+ 			   char * user, char * ckey, char * ts, char * authc,
185*14414594SDavid du Colombier+ 		       struct proc *p)
186*14414594SDavid du Colombier+ {
187*14414594SDavid du Colombier+   char * cp;
188*14414594SDavid du Colombier+   struct u9auth_ticketreq tktq;
189*14414594SDavid du Colombier+   struct u9auth_ticket tc;
190*14414594SDavid du Colombier+   struct u9auth_authenticator auth;
191*14414594SDavid du Colombier+   struct mbuf * m;
192*14414594SDavid du Colombier+   int error, len;
193*14414594SDavid du Colombier+
194*14414594SDavid du Colombier+   bzero(&tktq, sizeof(tktq));
195*14414594SDavid du Colombier+   tktq.type = AuthTreq;
196*14414594SDavid du Colombier+   bcopy(rep->r_authid, tktq.authid, U9FS_NAMELEN);
197*14414594SDavid du Colombier+   bcopy(rep->r_authdom, tktq.authdom, U9FS_DOMLEN);
198*14414594SDavid du Colombier+   bcopy(rep->r_chal, tktq.chal, U9FS_CHALLEN);
199*14414594SDavid du Colombier+   strncpy(tktq.hostid, user, U9FS_NAMELEN);
200*14414594SDavid du Colombier+   strncpy(tktq.uid, user, U9FS_NAMELEN);
201*14414594SDavid du Colombier+
202*14414594SDavid du Colombier+   m = u9auth_m_tr2m(&tktq);
203*14414594SDavid du Colombier+   error = u9auth_send(so, m, p);
204*14414594SDavid du Colombier+   if( error )
205*14414594SDavid du Colombier+     goto bad;
206*14414594SDavid du Colombier+   error = u9auth_recv(so, &m, p);
207*14414594SDavid du Colombier+   if( error )
208*14414594SDavid du Colombier+     goto bad;
209*14414594SDavid du Colombier+
210*14414594SDavid du Colombier+   len = U9AUTH_TICKETLEN+1;
211*14414594SDavid du Colombier+   if( m->m_len < len && (m = m_pullup(m, len)) == 0 )
212*14414594SDavid du Colombier+     goto bad;
213*14414594SDavid du Colombier+
214*14414594SDavid du Colombier+   cp = mtod(m, char *);
215*14414594SDavid du Colombier+   switch( cp[0] ) {
216*14414594SDavid du Colombier+   case AuthOK:
217*14414594SDavid du Colombier+     u9auth_m2t(&cp[1], & tc, ckey);
218*14414594SDavid du Colombier+     bzero(&auth, sizeof(auth));
219*14414594SDavid du Colombier+     auth.num = AuthAc;
220*14414594SDavid du Colombier+     bcopy(tc.chal, auth.chal, sizeof(auth.chal));
221*14414594SDavid du Colombier+     auth.id = u9auth_count++;
222*14414594SDavid du Colombier+
223*14414594SDavid du Colombier+     m->m_len -= len;
224*14414594SDavid du Colombier+     m->m_data += len;
225*14414594SDavid du Colombier+
226*14414594SDavid du Colombier+     len = U9AUTH_TICKETLEN;
227*14414594SDavid du Colombier+     if( m->m_len < len && (m = m_pullup(m, len)) == 0 )
228*14414594SDavid du Colombier+       goto bad;
229*14414594SDavid du Colombier+     cp = mtod(m, char *);
230*14414594SDavid du Colombier+     bcopy(cp, ts, len);
231*14414594SDavid du Colombier+     break;
232*14414594SDavid du Colombier+   case AuthErr:
233*14414594SDavid du Colombier+   case AuthOKvar:
234*14414594SDavid du Colombier+     m_freem(m);
235*14414594SDavid du Colombier+     goto bad;
236*14414594SDavid du Colombier+     break;
237*14414594SDavid du Colombier+   }
238*14414594SDavid du Colombier+
239*14414594SDavid du Colombier+   u9auth_a2m(&auth, authc, tc.key);
240*14414594SDavid du Colombier+   return 0;
241*14414594SDavid du Colombier+  bad:
242*14414594SDavid du Colombier+   return error;
243*14414594SDavid du Colombier+ }
244*14414594SDavid du Colombier+
245*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9auth.h ./9fs/9auth.h
246*14414594SDavid du Colombier*** /usr/src/sys/9fs/9auth.h	Wed Dec 31 19:00:00 1969
247*14414594SDavid du Colombier--- ./9fs/9auth.h	Thu Nov 11 15:00:29 1999
248*14414594SDavid du Colombier***************
249*14414594SDavid du Colombier*** 0 ****
250*14414594SDavid du Colombier--- 1,129 ----
251*14414594SDavid du Colombier+ #ifndef P9AUTH_H
252*14414594SDavid du Colombier+ #define P9AUTH_H
253*14414594SDavid du Colombier+
254*14414594SDavid du Colombier+ #define U9AUTH_DOMLEN		48		/* length of an authentication domain name */
255*14414594SDavid du Colombier+ #define U9AUTH_DESKEYLEN	7		/* length of a des key for encrypt/decrypt */
256*14414594SDavid du Colombier+ #define U9AUTH_CHALLEN	8		/* length of a challenge */
257*14414594SDavid du Colombier+ #define U9AUTH_NETCHLEN	16		/* max network challenge length	*/
258*14414594SDavid du Colombier+ #define U9AUTH_CONFIGLEN	14
259*14414594SDavid du Colombier+ #define U9AUTH_SECRETLEN	32		/* max length of a secret */
260*14414594SDavid du Colombier+ #define U9AUTH_APOPCHLEN	256
261*14414594SDavid du Colombier+ #define U9AUTH_MD5LEN		16
262*14414594SDavid du Colombier+ #define U9AUTH_KEYDBOFF	8		/* length of random data at the start of key file */
263*14414594SDavid du Colombier+ #define U9AUTH_OKEYDBLEN	U9FSNAMELEN+U9AUTH_DESKEYLEN+4+2,	/* length of an entry in old key file */
264*14414594SDavid du Colombier+ #define U9AUTH_KEYDBLEN	OKEYDBLENSECRETLEN,	/* length of an entry in key file */
265*14414594SDavid du Colombier+
266*14414594SDavid du Colombier+ /* encryption numberings (anti-replay) */
267*14414594SDavid du Colombier+ enum
268*14414594SDavid du Colombier+ {
269*14414594SDavid du Colombier+ 	AuthTreq=1,	/* ticket request */
270*14414594SDavid du Colombier+ 	AuthChal=2,	/* challenge box request */
271*14414594SDavid du Colombier+ 	AuthPass=3,	/* change password */
272*14414594SDavid du Colombier+ 	AuthOK=4,	/* fixed length reply follows */
273*14414594SDavid du Colombier+ 	AuthErr=5,	/* error follows */
274*14414594SDavid du Colombier+ 	AuthMod=6,	/* modify user */
275*14414594SDavid du Colombier+ 	AuthApop=7,	/* apop authentication for pop3 */
276*14414594SDavid du Colombier+ 	AuthOKvar=9,	/* variable length reply follows */
277*14414594SDavid du Colombier+ 	AuthChap=10,	/* chap authentication for ppp */
278*14414594SDavid du Colombier+ 	AuthMSchap=11,	/* MS chap authentication for ppp */
279*14414594SDavid du Colombier+
280*14414594SDavid du Colombier+
281*14414594SDavid du Colombier+ 	AuthTs=64,	/* ticket encrypted with server's key */
282*14414594SDavid du Colombier+ 	AuthTc,		/* ticket encrypted with client's key */
283*14414594SDavid du Colombier+ 	AuthAs,		/* server generated authenticator */
284*14414594SDavid du Colombier+ 	AuthAc,		/* client generated authenticator */
285*14414594SDavid du Colombier+ 	AuthTp,		/* ticket encrypted with clien's key for password change */
286*14414594SDavid du Colombier+ };
287*14414594SDavid du Colombier+
288*14414594SDavid du Colombier+ struct u9auth_ticketreq
289*14414594SDavid du Colombier+ {
290*14414594SDavid du Colombier+ 	char	type;
291*14414594SDavid du Colombier+ 	char	authid[U9FS_NAMELEN];	/* server's encryption id */
292*14414594SDavid du Colombier+ 	char	authdom[U9AUTH_DOMLEN];	/* server's authentication domain */
293*14414594SDavid du Colombier+ 	char	chal[U9AUTH_CHALLEN];		/* challenge from server */
294*14414594SDavid du Colombier+ 	char	hostid[U9FS_NAMELEN];	/* host's encryption id */
295*14414594SDavid du Colombier+ 	char	uid[U9FS_NAMELEN];		/* uid of requesting user on host */
296*14414594SDavid du Colombier+ };
297*14414594SDavid du Colombier+ #define	U9AUTH_TICKREQLEN	(3*U9FS_NAMELEN+U9AUTH_CHALLEN+U9AUTH_DOMLEN+1)
298*14414594SDavid du Colombier+
299*14414594SDavid du Colombier+ struct u9auth_ticket
300*14414594SDavid du Colombier+ {
301*14414594SDavid du Colombier+ 	char	num;			/* replay protection */
302*14414594SDavid du Colombier+ 	char	chal[U9AUTH_CHALLEN];		/* server challenge */
303*14414594SDavid du Colombier+ 	char	cuid[U9FS_NAMELEN];		/* uid on client */
304*14414594SDavid du Colombier+ 	char	suid[U9FS_NAMELEN];		/* uid on server */
305*14414594SDavid du Colombier+ 	char	key[U9AUTH_DESKEYLEN];		/* nonce DES key */
306*14414594SDavid du Colombier+ };
307*14414594SDavid du Colombier+ #define	U9AUTH_TICKETLEN	(U9AUTH_CHALLEN+2*U9FS_NAMELEN+U9AUTH_DESKEYLEN+1)
308*14414594SDavid du Colombier+
309*14414594SDavid du Colombier+ struct u9auth_authenticator
310*14414594SDavid du Colombier+ {
311*14414594SDavid du Colombier+ 	char	num;			/* replay protection */
312*14414594SDavid du Colombier+ 	char	chal[U9AUTH_CHALLEN];
313*14414594SDavid du Colombier+ 	u_long	id;			/* authenticator id, ++'d with each auth */
314*14414594SDavid du Colombier+ };
315*14414594SDavid du Colombier+ #define	U9AUTH_AUTHENTLEN	(U9AUTH_CHALLEN+4+1)
316*14414594SDavid du Colombier+
317*14414594SDavid du Colombier+ struct u9auth_passwordreq
318*14414594SDavid du Colombier+ {
319*14414594SDavid du Colombier+ 	char	num;
320*14414594SDavid du Colombier+ 	char	old[U9FS_NAMELEN];
321*14414594SDavid du Colombier+ 	char	new[U9FS_NAMELEN];
322*14414594SDavid du Colombier+ 	char	changesecret;
323*14414594SDavid du Colombier+ 	char	secret[U9AUTH_SECRETLEN];	/* new secret */
324*14414594SDavid du Colombier+ };
325*14414594SDavid du Colombier+ #define	U9AUTH_PASSREQLEN	(2*U9FS_NAMELEN+1+1+U9AUTH_SECRETLEN)
326*14414594SDavid du Colombier+
327*14414594SDavid du Colombier+ struct u9auth_nvrsafe
328*14414594SDavid du Colombier+ {
329*14414594SDavid du Colombier+ 	char	machkey[U9AUTH_DESKEYLEN];
330*14414594SDavid du Colombier+ 	u_char	machsum;
331*14414594SDavid du Colombier+ 	char	authkey[U9AUTH_DESKEYLEN];
332*14414594SDavid du Colombier+ 	u_char	authsum;
333*14414594SDavid du Colombier+ 	char	config[U9AUTH_CONFIGLEN];
334*14414594SDavid du Colombier+ 	u_char	configsum;
335*14414594SDavid du Colombier+ 	char	authid[U9FS_NAMELEN];
336*14414594SDavid du Colombier+ 	u_char	authidsum;
337*14414594SDavid du Colombier+ 	char	authdom[U9AUTH_DOMLEN];
338*14414594SDavid du Colombier+ 	u_char	authdomsum;
339*14414594SDavid du Colombier+ };
340*14414594SDavid du Colombier+
341*14414594SDavid du Colombier+ struct u9auth_chalstate
342*14414594SDavid du Colombier+ {
343*14414594SDavid du Colombier+ 	int	afd;			/* /dev/authenticate */
344*14414594SDavid du Colombier+ 	int	asfd;			/* authdial() */
345*14414594SDavid du Colombier+ 	char	chal[U9AUTH_NETCHLEN];		/* challenge/response */
346*14414594SDavid du Colombier+ };
347*14414594SDavid du Colombier+
348*14414594SDavid du Colombier+ struct u9auth_apopchalstate
349*14414594SDavid du Colombier+ {
350*14414594SDavid du Colombier+ 	int	afd;			/* /dev/authenticate */
351*14414594SDavid du Colombier+ 	int	asfd;			/* authdial() */
352*14414594SDavid du Colombier+ 	char	chal[U9AUTH_APOPCHLEN];	/* challenge/response */
353*14414594SDavid du Colombier+ };
354*14414594SDavid du Colombier+
355*14414594SDavid du Colombier+ struct	u9auth_chapreply
356*14414594SDavid du Colombier+ {
357*14414594SDavid du Colombier+ 	u_char	id;
358*14414594SDavid du Colombier+ 	char	uid[U9FS_NAMELEN];
359*14414594SDavid du Colombier+ 	char	resp[U9AUTH_MD5LEN];
360*14414594SDavid du Colombier+ };
361*14414594SDavid du Colombier+
362*14414594SDavid du Colombier+ struct	u9auth_mSchapreply
363*14414594SDavid du Colombier+ {
364*14414594SDavid du Colombier+ 	char	uid[U9FS_NAMELEN];
365*14414594SDavid du Colombier+ 	char	LMresp[24];		/* Lan Manager response */
366*14414594SDavid du Colombier+ 	char	NTresp[24];		/* NT response */
367*14414594SDavid du Colombier+ };
368*14414594SDavid du Colombier+
369*14414594SDavid du Colombier+ #ifdef KERNEL
370*14414594SDavid du Colombier+ void u9auth_genchal __P((char *));
371*14414594SDavid du Colombier+ int  u9auth_gettickets __P((struct socket * so, struct u9fsreq * rep,
372*14414594SDavid du Colombier+ 			   char * user, char * ckey, char * ts, char * authc,
373*14414594SDavid du Colombier+ 			    struct proc * p));
374*14414594SDavid du Colombier+ int encrypt9 __P((void *key, void * vbuf, int n));
375*14414594SDavid du Colombier+ int decrypt9 __P((void *key, void * vbuf, int n));
376*14414594SDavid du Colombier+
377*14414594SDavid du Colombier+ #endif
378*14414594SDavid du Colombier+
379*14414594SDavid du Colombier+ #endif
380*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9crypt.c ./9fs/9crypt.c
381*14414594SDavid du Colombier*** /usr/src/sys/9fs/9crypt.c	Wed Dec 31 19:00:00 1969
382*14414594SDavid du Colombier--- ./9fs/9crypt.c	Thu Nov 11 12:23:02 1999
383*14414594SDavid du Colombier***************
384*14414594SDavid du Colombier*** 0 ****
385*14414594SDavid du Colombier--- 1,416 ----
386*14414594SDavid du Colombier+ /*
387*14414594SDavid du Colombier+  *	Data Encryption Standard
388*14414594SDavid du Colombier+  *	D.P.Mitchell  83/06/08.
389*14414594SDavid du Colombier+  *
390*14414594SDavid du Colombier+  *	block_cipher(key, block, decrypting)
391*14414594SDavid du Colombier+  */
392*14414594SDavid du Colombier+ #include <sys/param.h>
393*14414594SDavid du Colombier+ #include <sys/systm.h>
394*14414594SDavid du Colombier+ #include <sys/socket.h>
395*14414594SDavid du Colombier+ #include <sys/socketvar.h>
396*14414594SDavid du Colombier+
397*14414594SDavid du Colombier+ typedef unsigned char uchar;
398*14414594SDavid du Colombier+ typedef unsigned long ulong;
399*14414594SDavid du Colombier+ #define NAMELEN 28      /* length of path element, including '\0' */
400*14414594SDavid du Colombier+ #include <9fs/9p.h>
401*14414594SDavid du Colombier+ #include <9fs/9auth.h>
402*14414594SDavid du Colombier+
403*14414594SDavid du Colombier+ static	long	ip_low(char [8]);
404*14414594SDavid du Colombier+ static	long	ip_high(char [8]);
405*14414594SDavid du Colombier+ static	void	fp(long, long, char[8]);
406*14414594SDavid du Colombier+ static	void	key_setup(char[U9AUTH_DESKEYLEN], char[128]);
407*14414594SDavid du Colombier+ static	void	block_cipher(char[128], char[8], int);
408*14414594SDavid du Colombier+
409*14414594SDavid du Colombier+ /*
410*14414594SDavid du Colombier+  * destructively encrypt the buffer, which
411*14414594SDavid du Colombier+  * must be at least 8 characters long.
412*14414594SDavid du Colombier+  */
413*14414594SDavid du Colombier+ int
414*14414594SDavid du Colombier+ encrypt9(void *key, void *vbuf, int n)
415*14414594SDavid du Colombier+ {
416*14414594SDavid du Colombier+ 	char ekey[128], *buf;
417*14414594SDavid du Colombier+ 	int i, r;
418*14414594SDavid du Colombier+
419*14414594SDavid du Colombier+ 	if(n < 8)
420*14414594SDavid du Colombier+ 		return 0;
421*14414594SDavid du Colombier+ 	key_setup(key, ekey);
422*14414594SDavid du Colombier+ 	buf = vbuf;
423*14414594SDavid du Colombier+ 	n--;
424*14414594SDavid du Colombier+ 	r = n % 7;
425*14414594SDavid du Colombier+ 	n /= 7;
426*14414594SDavid du Colombier+ 	for(i = 0; i < n; i++){
427*14414594SDavid du Colombier+ 		block_cipher(ekey, buf, 0);
428*14414594SDavid du Colombier+ 		buf += 7;
429*14414594SDavid du Colombier+ 	}
430*14414594SDavid du Colombier+ 	if(r)
431*14414594SDavid du Colombier+ 		block_cipher(ekey, buf - 7 + r, 0);
432*14414594SDavid du Colombier+ 	return 1;
433*14414594SDavid du Colombier+ }
434*14414594SDavid du Colombier+
435*14414594SDavid du Colombier+ /*
436*14414594SDavid du Colombier+  * destructively decrypt the buffer, which
437*14414594SDavid du Colombier+  * must be at least 8 characters long.
438*14414594SDavid du Colombier+  */
439*14414594SDavid du Colombier+ int
440*14414594SDavid du Colombier+ decrypt9(void *key, void *vbuf, int n)
441*14414594SDavid du Colombier+ {
442*14414594SDavid du Colombier+ 	char ekey[128], *buf;
443*14414594SDavid du Colombier+ 	int i, r;
444*14414594SDavid du Colombier+
445*14414594SDavid du Colombier+ 	if(n < 8)
446*14414594SDavid du Colombier+ 		return 0;
447*14414594SDavid du Colombier+ 	key_setup(key, ekey);
448*14414594SDavid du Colombier+ 	buf = vbuf;
449*14414594SDavid du Colombier+ 	n--;
450*14414594SDavid du Colombier+ 	r = n % 7;
451*14414594SDavid du Colombier+ 	n /= 7;
452*14414594SDavid du Colombier+ 	buf += n * 7;
453*14414594SDavid du Colombier+ 	if(r)
454*14414594SDavid du Colombier+ 		block_cipher(ekey, buf - 7 + r, 1);
455*14414594SDavid du Colombier+ 	for(i = 0; i < n; i++){
456*14414594SDavid du Colombier+ 		buf -= 7;
457*14414594SDavid du Colombier+ 		block_cipher(ekey, buf, 1);
458*14414594SDavid du Colombier+ 	}
459*14414594SDavid du Colombier+ 	return 1;
460*14414594SDavid du Colombier+ }
461*14414594SDavid du Colombier+
462*14414594SDavid du Colombier+ /*
463*14414594SDavid du Colombier+  *	Tables for Combined S and P Boxes
464*14414594SDavid du Colombier+  */
465*14414594SDavid du Colombier+
466*14414594SDavid du Colombier+ static long  s0p[] = {
467*14414594SDavid du Colombier+ 0x00410100,0x00010000,0x40400000,0x40410100,0x00400000,0x40010100,0x40010000,0x40400000,
468*14414594SDavid du Colombier+ 0x40010100,0x00410100,0x00410000,0x40000100,0x40400100,0x00400000,0x00000000,0x40010000,
469*14414594SDavid du Colombier+ 0x00010000,0x40000000,0x00400100,0x00010100,0x40410100,0x00410000,0x40000100,0x00400100,
470*14414594SDavid du Colombier+ 0x40000000,0x00000100,0x00010100,0x40410000,0x00000100,0x40400100,0x40410000,0x00000000,
471*14414594SDavid du Colombier+ 0x00000000,0x40410100,0x00400100,0x40010000,0x00410100,0x00010000,0x40000100,0x00400100,
472*14414594SDavid du Colombier+ 0x40410000,0x00000100,0x00010100,0x40400000,0x40010100,0x40000000,0x40400000,0x00410000,
473*14414594SDavid du Colombier+ 0x40410100,0x00010100,0x00410000,0x40400100,0x00400000,0x40000100,0x40010000,0x00000000,
474*14414594SDavid du Colombier+ 0x00010000,0x00400000,0x40400100,0x00410100,0x40000000,0x40410000,0x00000100,0x40010100,
475*14414594SDavid du Colombier+ };
476*14414594SDavid du Colombier+
477*14414594SDavid du Colombier+ static long  s1p[] = {
478*14414594SDavid du Colombier+ 0x08021002,0x00000000,0x00021000,0x08020000,0x08000002,0x00001002,0x08001000,0x00021000,
479*14414594SDavid du Colombier+ 0x00001000,0x08020002,0x00000002,0x08001000,0x00020002,0x08021000,0x08020000,0x00000002,
480*14414594SDavid du Colombier+ 0x00020000,0x08001002,0x08020002,0x00001000,0x00021002,0x08000000,0x00000000,0x00020002,
481*14414594SDavid du Colombier+ 0x08001002,0x00021002,0x08021000,0x08000002,0x08000000,0x00020000,0x00001002,0x08021002,
482*14414594SDavid du Colombier+ 0x00020002,0x08021000,0x08001000,0x00021002,0x08021002,0x00020002,0x08000002,0x00000000,
483*14414594SDavid du Colombier+ 0x08000000,0x00001002,0x00020000,0x08020002,0x00001000,0x08000000,0x00021002,0x08001002,
484*14414594SDavid du Colombier+ 0x08021000,0x00001000,0x00000000,0x08000002,0x00000002,0x08021002,0x00021000,0x08020000,
485*14414594SDavid du Colombier+ 0x08020002,0x00020000,0x00001002,0x08001000,0x08001002,0x00000002,0x08020000,0x00021000,
486*14414594SDavid du Colombier+ };
487*14414594SDavid du Colombier+
488*14414594SDavid du Colombier+ static long  s2p[] = {
489*14414594SDavid du Colombier+ 0x20800000,0x00808020,0x00000020,0x20800020,0x20008000,0x00800000,0x20800020,0x00008020,
490*14414594SDavid du Colombier+ 0x00800020,0x00008000,0x00808000,0x20000000,0x20808020,0x20000020,0x20000000,0x20808000,
491*14414594SDavid du Colombier+ 0x00000000,0x20008000,0x00808020,0x00000020,0x20000020,0x20808020,0x00008000,0x20800000,
492*14414594SDavid du Colombier+ 0x20808000,0x00800020,0x20008020,0x00808000,0x00008020,0x00000000,0x00800000,0x20008020,
493*14414594SDavid du Colombier+ 0x00808020,0x00000020,0x20000000,0x00008000,0x20000020,0x20008000,0x00808000,0x20800020,
494*14414594SDavid du Colombier+ 0x00000000,0x00808020,0x00008020,0x20808000,0x20008000,0x00800000,0x20808020,0x20000000,
495*14414594SDavid du Colombier+ 0x20008020,0x20800000,0x00800000,0x20808020,0x00008000,0x00800020,0x20800020,0x00008020,
496*14414594SDavid du Colombier+ 0x00800020,0x00000000,0x20808000,0x20000020,0x20800000,0x20008020,0x00000020,0x00808000,
497*14414594SDavid du Colombier+ };
498*14414594SDavid du Colombier+
499*14414594SDavid du Colombier+ static long  s3p[] = {
500*14414594SDavid du Colombier+ 0x00080201,0x02000200,0x00000001,0x02080201,0x00000000,0x02080000,0x02000201,0x00080001,
501*14414594SDavid du Colombier+ 0x02080200,0x02000001,0x02000000,0x00000201,0x02000001,0x00080201,0x00080000,0x02000000,
502*14414594SDavid du Colombier+ 0x02080001,0x00080200,0x00000200,0x00000001,0x00080200,0x02000201,0x02080000,0x00000200,
503*14414594SDavid du Colombier+ 0x00000201,0x00000000,0x00080001,0x02080200,0x02000200,0x02080001,0x02080201,0x00080000,
504*14414594SDavid du Colombier+ 0x02080001,0x00000201,0x00080000,0x02000001,0x00080200,0x02000200,0x00000001,0x02080000,
505*14414594SDavid du Colombier+ 0x02000201,0x00000000,0x00000200,0x00080001,0x00000000,0x02080001,0x02080200,0x00000200,
506*14414594SDavid du Colombier+ 0x02000000,0x02080201,0x00080201,0x00080000,0x02080201,0x00000001,0x02000200,0x00080201,
507*14414594SDavid du Colombier+ 0x00080001,0x00080200,0x02080000,0x02000201,0x00000201,0x02000000,0x02000001,0x02080200,
508*14414594SDavid du Colombier+ };
509*14414594SDavid du Colombier+
510*14414594SDavid du Colombier+ static long  s4p[] = {
511*14414594SDavid du Colombier+ 0x01000000,0x00002000,0x00000080,0x01002084,0x01002004,0x01000080,0x00002084,0x01002000,
512*14414594SDavid du Colombier+ 0x00002000,0x00000004,0x01000004,0x00002080,0x01000084,0x01002004,0x01002080,0x00000000,
513*14414594SDavid du Colombier+ 0x00002080,0x01000000,0x00002004,0x00000084,0x01000080,0x00002084,0x00000000,0x01000004,
514*14414594SDavid du Colombier+ 0x00000004,0x01000084,0x01002084,0x00002004,0x01002000,0x00000080,0x00000084,0x01002080,
515*14414594SDavid du Colombier+ 0x01002080,0x01000084,0x00002004,0x01002000,0x00002000,0x00000004,0x01000004,0x01000080,
516*14414594SDavid du Colombier+ 0x01000000,0x00002080,0x01002084,0x00000000,0x00002084,0x01000000,0x00000080,0x00002004,
517*14414594SDavid du Colombier+ 0x01000084,0x00000080,0x00000000,0x01002084,0x01002004,0x01002080,0x00000084,0x00002000,
518*14414594SDavid du Colombier+ 0x00002080,0x01002004,0x01000080,0x00000084,0x00000004,0x00002084,0x01002000,0x01000004,
519*14414594SDavid du Colombier+ };
520*14414594SDavid du Colombier+
521*14414594SDavid du Colombier+ static long  s5p[] = {
522*14414594SDavid du Colombier+ 0x10000008,0x00040008,0x00000000,0x10040400,0x00040008,0x00000400,0x10000408,0x00040000,
523*14414594SDavid du Colombier+ 0x00000408,0x10040408,0x00040400,0x10000000,0x10000400,0x10000008,0x10040000,0x00040408,
524*14414594SDavid du Colombier+ 0x00040000,0x10000408,0x10040008,0x00000000,0x00000400,0x00000008,0x10040400,0x10040008,
525*14414594SDavid du Colombier+ 0x10040408,0x10040000,0x10000000,0x00000408,0x00000008,0x00040400,0x00040408,0x10000400,
526*14414594SDavid du Colombier+ 0x00000408,0x10000000,0x10000400,0x00040408,0x10040400,0x00040008,0x00000000,0x10000400,
527*14414594SDavid du Colombier+ 0x10000000,0x00000400,0x10040008,0x00040000,0x00040008,0x10040408,0x00040400,0x00000008,
528*14414594SDavid du Colombier+ 0x10040408,0x00040400,0x00040000,0x10000408,0x10000008,0x10040000,0x00040408,0x00000000,
529*14414594SDavid du Colombier+ 0x00000400,0x10000008,0x10000408,0x10040400,0x10040000,0x00000408,0x00000008,0x10040008,
530*14414594SDavid du Colombier+ };
531*14414594SDavid du Colombier+
532*14414594SDavid du Colombier+ static long  s6p[] = {
533*14414594SDavid du Colombier+ 0x00000800,0x00000040,0x00200040,0x80200000,0x80200840,0x80000800,0x00000840,0x00000000,
534*14414594SDavid du Colombier+ 0x00200000,0x80200040,0x80000040,0x00200800,0x80000000,0x00200840,0x00200800,0x80000040,
535*14414594SDavid du Colombier+ 0x80200040,0x00000800,0x80000800,0x80200840,0x00000000,0x00200040,0x80200000,0x00000840,
536*14414594SDavid du Colombier+ 0x80200800,0x80000840,0x00200840,0x80000000,0x80000840,0x80200800,0x00000040,0x00200000,
537*14414594SDavid du Colombier+ 0x80000840,0x00200800,0x80200800,0x80000040,0x00000800,0x00000040,0x00200000,0x80200800,
538*14414594SDavid du Colombier+ 0x80200040,0x80000840,0x00000840,0x00000000,0x00000040,0x80200000,0x80000000,0x00200040,
539*14414594SDavid du Colombier+ 0x00000000,0x80200040,0x00200040,0x00000840,0x80000040,0x00000800,0x80200840,0x00200000,
540*14414594SDavid du Colombier+ 0x00200840,0x80000000,0x80000800,0x80200840,0x80200000,0x00200840,0x00200800,0x80000800,
541*14414594SDavid du Colombier+ };
542*14414594SDavid du Colombier+
543*14414594SDavid du Colombier+ static long  s7p[] = {
544*14414594SDavid du Colombier+ 0x04100010,0x04104000,0x00004010,0x00000000,0x04004000,0x00100010,0x04100000,0x04104010,
545*14414594SDavid du Colombier+ 0x00000010,0x04000000,0x00104000,0x00004010,0x00104010,0x04004010,0x04000010,0x04100000,
546*14414594SDavid du Colombier+ 0x00004000,0x00104010,0x00100010,0x04004000,0x04104010,0x04000010,0x00000000,0x00104000,
547*14414594SDavid du Colombier+ 0x04000000,0x00100000,0x04004010,0x04100010,0x00100000,0x00004000,0x04104000,0x00000010,
548*14414594SDavid du Colombier+ 0x00100000,0x00004000,0x04000010,0x04104010,0x00004010,0x04000000,0x00000000,0x00104000,
549*14414594SDavid du Colombier+ 0x04100010,0x04004010,0x04004000,0x00100010,0x04104000,0x00000010,0x00100010,0x04004000,
550*14414594SDavid du Colombier+ 0x04104010,0x00100000,0x04100000,0x04000010,0x00104000,0x00004010,0x04004010,0x04100000,
551*14414594SDavid du Colombier+ 0x00000010,0x04104000,0x00104010,0x00000000,0x04000000,0x04100010,0x00004000,0x00104010,
552*14414594SDavid du Colombier+ };
553*14414594SDavid du Colombier+
554*14414594SDavid du Colombier+ /*
555*14414594SDavid du Colombier+  *	DES electronic codebook encryption of one block
556*14414594SDavid du Colombier+  */
557*14414594SDavid du Colombier+ static void
558*14414594SDavid du Colombier+ block_cipher(char expanded_key[128], char text[8], int decrypting)
559*14414594SDavid du Colombier+ {
560*14414594SDavid du Colombier+ 	char *key;
561*14414594SDavid du Colombier+ 	long crypto, temp, right, left;
562*14414594SDavid du Colombier+ 	int i, key_offset;
563*14414594SDavid du Colombier+
564*14414594SDavid du Colombier+ 	key = expanded_key;
565*14414594SDavid du Colombier+ 	left = ip_low(text);
566*14414594SDavid du Colombier+ 	right = ip_high(text);
567*14414594SDavid du Colombier+ 	if (decrypting) {
568*14414594SDavid du Colombier+ 		key_offset = 16;
569*14414594SDavid du Colombier+ 		key = key + 128 - 8;
570*14414594SDavid du Colombier+ 	} else
571*14414594SDavid du Colombier+ 		key_offset = 0;
572*14414594SDavid du Colombier+ 	for (i = 0; i < 16; i++) {
573*14414594SDavid du Colombier+ 		temp = (right << 1) | ((right >> 31) & 1);
574*14414594SDavid du Colombier+ 		crypto  = s0p[(temp         & 0x3f) ^ *key++];
575*14414594SDavid du Colombier+ 		crypto |= s1p[((temp >>  4) & 0x3f) ^ *key++];
576*14414594SDavid du Colombier+ 		crypto |= s2p[((temp >>  8) & 0x3f) ^ *key++];
577*14414594SDavid du Colombier+ 		crypto |= s3p[((temp >> 12) & 0x3f) ^ *key++];
578*14414594SDavid du Colombier+ 		crypto |= s4p[((temp >> 16) & 0x3f) ^ *key++];
579*14414594SDavid du Colombier+ 		crypto |= s5p[((temp >> 20) & 0x3f) ^ *key++];
580*14414594SDavid du Colombier+ 		crypto |= s6p[((temp >> 24) & 0x3f) ^ *key++];
581*14414594SDavid du Colombier+ 		temp = ((right & 1) << 5) | ((right >> 27) & 0x1f);
582*14414594SDavid du Colombier+ 		crypto |= s7p[temp ^ *key++];
583*14414594SDavid du Colombier+ 		temp = left;
584*14414594SDavid du Colombier+ 		left = right;
585*14414594SDavid du Colombier+ 		right = temp ^ crypto;
586*14414594SDavid du Colombier+ 		key -= key_offset;
587*14414594SDavid du Colombier+ 	}
588*14414594SDavid du Colombier+ 	/*
589*14414594SDavid du Colombier+ 	 *	standard final permutation (IPI)
590*14414594SDavid du Colombier+ 	 *	left and right are reversed here
591*14414594SDavid du Colombier+ 	 */
592*14414594SDavid du Colombier+ 	fp(right, left, text);
593*14414594SDavid du Colombier+ }
594*14414594SDavid du Colombier+
595*14414594SDavid du Colombier+ /*
596*14414594SDavid du Colombier+  *	Initial Permutation
597*14414594SDavid du Colombier+  */
598*14414594SDavid du Colombier+ static long iptab[] = {
599*14414594SDavid du Colombier+ 	0x00000000, 0x00008000, 0x00000000, 0x00008000,
600*14414594SDavid du Colombier+ 	0x00000080, 0x00008080, 0x00000080, 0x00008080
601*14414594SDavid du Colombier+ };
602*14414594SDavid du Colombier+
603*14414594SDavid du Colombier+ static long
604*14414594SDavid du Colombier+ ip_low(char block[8])
605*14414594SDavid du Colombier+ {
606*14414594SDavid du Colombier+ 	int i;
607*14414594SDavid du Colombier+ 	long l;
608*14414594SDavid du Colombier+
609*14414594SDavid du Colombier+ 	l = 0;
610*14414594SDavid du Colombier+ 	for(i = 0; i < 8; i++){
611*14414594SDavid du Colombier+ 		l |= iptab[(block[i] >> 4) & 7] >> i;
612*14414594SDavid du Colombier+ 		l |= iptab[block[i] & 7] << (16 - i);
613*14414594SDavid du Colombier+ 	}
614*14414594SDavid du Colombier+ 	return l;
615*14414594SDavid du Colombier+ }
616*14414594SDavid du Colombier+
617*14414594SDavid du Colombier+ static long
618*14414594SDavid du Colombier+ ip_high(char block[8])
619*14414594SDavid du Colombier+ {
620*14414594SDavid du Colombier+ 	int i;
621*14414594SDavid du Colombier+ 	long l;
622*14414594SDavid du Colombier+
623*14414594SDavid du Colombier+ 	l = 0;
624*14414594SDavid du Colombier+ 	for(i = 0; i < 8; i++){
625*14414594SDavid du Colombier+ 		l |= iptab[(block[i] >> 5) & 7] >> i;
626*14414594SDavid du Colombier+ 		l |= iptab[(block[i] >> 1) & 7] << (16 - i);
627*14414594SDavid du Colombier+ 	}
628*14414594SDavid du Colombier+ 	return l;
629*14414594SDavid du Colombier+ }
630*14414594SDavid du Colombier+
631*14414594SDavid du Colombier+ /*
632*14414594SDavid du Colombier+  *	Final Permutation
633*14414594SDavid du Colombier+  */
634*14414594SDavid du Colombier+ static unsigned long	fptab[] = {
635*14414594SDavid du Colombier+ 0x00000000,0x80000000,0x00800000,0x80800000,0x00008000,0x80008000,0x00808000,0x80808000,
636*14414594SDavid du Colombier+ 0x00000080,0x80000080,0x00800080,0x80800080,0x00008080,0x80008080,0x00808080,0x80808080,
637*14414594SDavid du Colombier+ };
638*14414594SDavid du Colombier+
639*14414594SDavid du Colombier+ static void
640*14414594SDavid du Colombier+ fp(long left, long right, char text[8])
641*14414594SDavid du Colombier+ {
642*14414594SDavid du Colombier+ 	unsigned long ta[2], t, v[2];
643*14414594SDavid du Colombier+ 	int i, j, sh;
644*14414594SDavid du Colombier+
645*14414594SDavid du Colombier+ 	ta[0] = right;
646*14414594SDavid du Colombier+ 	ta[1] = left;
647*14414594SDavid du Colombier+ 	v[0] = v[1] = 0;
648*14414594SDavid du Colombier+ 	for(i = 0; i < 2; i++){
649*14414594SDavid du Colombier+ 		t = ta[i];
650*14414594SDavid du Colombier+ 		sh = i;
651*14414594SDavid du Colombier+ 		for(j = 0; j < 4; j++){
652*14414594SDavid du Colombier+ 			v[1] |= fptab[t & 0xf] >> sh;
653*14414594SDavid du Colombier+ 			t >>= 4;
654*14414594SDavid du Colombier+ 			v[0] |= fptab[t & 0xf] >> sh;
655*14414594SDavid du Colombier+ 			t >>= 4;
656*14414594SDavid du Colombier+ 			sh += 2;
657*14414594SDavid du Colombier+ 		}
658*14414594SDavid du Colombier+ 	}
659*14414594SDavid du Colombier+ 	for(i = 0; i < 2; i++)
660*14414594SDavid du Colombier+ 		for(j = 0; j < 4; j++){
661*14414594SDavid du Colombier+ 			*text++ = v[i];
662*14414594SDavid du Colombier+ 			v[i] >>= 8;
663*14414594SDavid du Colombier+ 		}
664*14414594SDavid du Colombier+ }
665*14414594SDavid du Colombier+
666*14414594SDavid du Colombier+ /*
667*14414594SDavid du Colombier+  *	Key set-up
668*14414594SDavid du Colombier+  */
669*14414594SDavid du Colombier+ static uchar keyexpand[][15][2] = {
670*14414594SDavid du Colombier+ 	{   3,  2,   9,  8,  18,  8,  27, 32,  33,  2,  42, 16,  48,  8,  65, 16,
671*14414594SDavid du Colombier+ 	   74,  2,  80,  2,  89,  4,  99, 16, 104,  4, 122, 32,   0,  0, },
672*14414594SDavid du Colombier+ 	{   1,  4,   8,  1,  18,  4,  25, 32,  34, 32,  41,  8,  50,  8,  59, 32,
673*14414594SDavid du Colombier+ 	   64, 16,  75,  4,  90,  1,  97, 16, 106,  2, 112,  2, 123,  1, },
674*14414594SDavid du Colombier+ 	{   2,  1,  19,  8,  35,  1,  40,  1,  50,  4,  57, 32,  75,  2,  80, 32,
675*14414594SDavid du Colombier+ 	   89,  1,  96, 16, 107,  4, 120,  8,   0,  0,   0,  0,   0,  0, },
676*14414594SDavid du Colombier+ 	{   4, 32,  20,  2,  31,  4,  37, 32,  47,  1,  54,  1,  63,  2,  68,  1,
677*14414594SDavid du Colombier+ 	   78,  4,  84,  8, 101, 16, 108,  4, 119, 16, 126,  8,   0,  0, },
678*14414594SDavid du Colombier+ 	{   5,  4,  15,  4,  21, 32,  31,  1,  38,  1,  47,  2,  53,  2,  68,  8,
679*14414594SDavid du Colombier+ 	   85, 16,  92,  4, 103, 16, 108, 32, 118, 32, 124,  2,   0,  0, },
680*14414594SDavid du Colombier+ 	{  15,  2,  21,  2,  39,  8,  46, 16,  55, 32,  61,  1,  71, 16,  76, 32,
681*14414594SDavid du Colombier+ 	   86, 32,  93,  4, 102,  2, 108, 16, 117,  8, 126,  1,   0,  0, },
682*14414594SDavid du Colombier+ 	{  14, 16,  23, 32,  29,  1,  38,  8,  52,  2,  63,  4,  70,  2,  76, 16,
683*14414594SDavid du Colombier+ 	   85,  8, 100,  1, 110,  4, 116,  8, 127,  8,   0,  0,   0,  0, },
684*14414594SDavid du Colombier+ 	{   1,  8,   8, 32,  17,  1,  24, 16,  35,  4,  50,  1,  57, 16,  67,  8,
685*14414594SDavid du Colombier+ 	   83,  1,  88,  1,  98,  4, 105, 32, 114, 32, 123,  2,   0,  0, },
686*14414594SDavid du Colombier+ 	{   0,  1,  11, 16,  16,  4,  35,  2,  40, 32,  49,  1,  56, 16,  65,  2,
687*14414594SDavid du Colombier+ 	   74, 16,  80,  8,  99,  8, 115,  1, 121,  4,   0,  0,   0,  0, },
688*14414594SDavid du Colombier+ 	{   9, 16,  18,  2,  24,  2,  33,  4,  43, 16,  48,  4,  66, 32,  73,  8,
689*14414594SDavid du Colombier+ 	   82,  8,  91, 32,  97,  2, 106, 16, 112,  8, 122,  1,   0,  0, },
690*14414594SDavid du Colombier+ 	{  14, 32,  21,  4,  30,  2,  36, 16,  45,  8,  60,  1,  69,  2,  87,  8,
691*14414594SDavid du Colombier+ 	   94, 16, 103, 32, 109,  1, 118,  8, 124, 32,   0,  0,   0,  0, },
692*14414594SDavid du Colombier+ 	{   7,  4,  14,  2,  20, 16,  29,  8,  44,  1,  54,  4,  60,  8,  71,  8,
693*14414594SDavid du Colombier+ 	   78, 16,  87, 32,  93,  1, 102,  8, 116,  2, 125,  4,   0,  0, },
694*14414594SDavid du Colombier+ 	{   7,  2,  12,  1,  22,  4,  28,  8,  45, 16,  52,  4,  63, 16,  70,  8,
695*14414594SDavid du Colombier+ 	   84,  2,  95,  4, 101, 32, 111,  1, 118,  1,   0,  0,   0,  0, },
696*14414594SDavid du Colombier+ 	{   6, 16,  13, 16,  20,  4,  31, 16,  36, 32,  46, 32,  53,  4,  62,  2,
697*14414594SDavid du Colombier+ 	   69, 32,  79,  1,  86,  1,  95,  2, 101,  2, 119,  8,   0,  0, },
698*14414594SDavid du Colombier+ 	{   0, 32,  10,  8,  19, 32,  25,  2,  34, 16,  40,  8,  59,  8,  66,  2,
699*14414594SDavid du Colombier+ 	   72,  2,  81,  4,  91, 16,  96,  4, 115,  2, 121,  8,   0,  0, },
700*14414594SDavid du Colombier+ 	{   3, 16,  10,  4,  17, 32,  26, 32,  33,  8,  42,  8,  51, 32,  57,  2,
701*14414594SDavid du Colombier+ 	   67,  4,  82,  1,  89, 16,  98,  2, 104,  2, 113,  4, 120,  1, },
702*14414594SDavid du Colombier+ 	{   1, 16,  11,  8,  27,  1,  32,  1,  42,  4,  49, 32,  58, 32,  67,  2,
703*14414594SDavid du Colombier+ 	   72, 32,  81,  1,  88, 16,  99,  4, 114,  1,   0,  0,   0,  0, },
704*14414594SDavid du Colombier+ 	{   6, 32,  12,  2,  23,  4,  29, 32,  39,  1,  46,  1,  55,  2,  61,  2,
705*14414594SDavid du Colombier+ 	   70,  4,  76,  8,  93, 16, 100,  4, 111, 16, 116, 32,   0,  0, },
706*14414594SDavid du Colombier+ 	{   6,  2,  13, 32,  23,  1,  30,  1,  39,  2,  45,  2,  63,  8,  77, 16,
707*14414594SDavid du Colombier+ 	   84,  4,  95, 16, 100, 32, 110, 32, 117,  4, 127,  4,   0,  0, },
708*14414594SDavid du Colombier+ 	{   4,  1,  13,  2,  31,  8,  38, 16,  47, 32,  53,  1,  62,  8,  68, 32,
709*14414594SDavid du Colombier+ 	   78, 32,  85,  4,  94,  2, 100, 16, 109,  8, 127,  2,   0,  0, },
710*14414594SDavid du Colombier+ 	{   5, 16,  15, 32,  21,  1,  30,  8,  44,  2,  55,  4,  61, 32,  68, 16,
711*14414594SDavid du Colombier+ 	   77,  8,  92,  1, 102,  4, 108,  8, 126, 16,   0,  0,   0,  0, },
712*14414594SDavid du Colombier+ 	{   2,  8,   9,  1,  16, 16,  27,  4,  42,  1,  49, 16,  58,  2,  75,  1,
713*14414594SDavid du Colombier+ 	   80,  1,  90,  4,  97, 32, 106, 32, 113,  8, 120, 32,   0,  0, },
714*14414594SDavid du Colombier+ 	{   2,  4,   8,  4,  27,  2,  32, 32,  41,  1,  48, 16,  59,  4,  66, 16,
715*14414594SDavid du Colombier+ 	   72,  8,  91,  8, 107,  1, 112,  1, 123, 16,   0,  0,   0,  0, },
716*14414594SDavid du Colombier+ 	{   3,  8,  10,  2,  16,  2,  25,  4,  35, 16,  40,  4,  59,  2,  65,  8,
717*14414594SDavid du Colombier+ 	   74,  8,  83, 32,  89,  2,  98, 16, 104,  8, 121, 16,   0,  0, },
718*14414594SDavid du Colombier+ 	{   4,  2,  13,  4,  22,  2,  28, 16,  37,  8,  52,  1,  62,  4,  79,  8,
719*14414594SDavid du Colombier+ 	   86, 16,  95, 32, 101,  1, 110,  8, 126, 32,   0,  0,   0,  0, },
720*14414594SDavid du Colombier+ 	{   5, 32,  12, 16,  21,  8,  36,  1,  46,  4,  52,  8,  70, 16,  79, 32,
721*14414594SDavid du Colombier+ 	   85,  1,  94,  8, 108,  2, 119,  4, 126,  2,   0,  0,   0,  0, },
722*14414594SDavid du Colombier+ 	{   5,  2,  14,  4,  20,  8,  37, 16,  44,  4,  55, 16,  60, 32,  76,  2,
723*14414594SDavid du Colombier+ 	   87,  4,  93, 32, 103,  1, 110,  1, 119,  2, 124,  1,   0,  0, },
724*14414594SDavid du Colombier+ 	{   7, 32,  12,  4,  23, 16,  28, 32,  38, 32,  45,  4,  54,  2,  60, 16,
725*14414594SDavid du Colombier+ 	   71,  1,  78,  1,  87,  2,  93,  2, 111,  8, 118, 16, 125, 16, },
726*14414594SDavid du Colombier+ 	{   1,  1,  11, 32,  17,  2,  26, 16,  32,  8,  51,  8,  64,  2,  73,  4,
727*14414594SDavid du Colombier+ 	   83, 16,  88,  4, 107,  2, 112, 32, 122,  8,   0,  0,   0,  0, },
728*14414594SDavid du Colombier+ 	{   0,  4,   9, 32,  18, 32,  25,  8,  34,  8,  43, 32,  49,  2,  58, 16,
729*14414594SDavid du Colombier+ 	   74,  1,  81, 16,  90,  2,  96,  2, 105,  4, 115, 16, 122,  4, },
730*14414594SDavid du Colombier+ 	{   2,  2,  19,  1,  24,  1,  34,  4,  41, 32,  50, 32,  57,  8,  64, 32,
731*14414594SDavid du Colombier+ 	   73,  1,  80, 16,  91,  4, 106,  1, 113, 16, 123,  8,   0,  0, },
732*14414594SDavid du Colombier+ 	{   3,  4,  10, 16,  16,  8,  35,  8,  51,  1,  56,  1,  67, 16,  72,  4,
733*14414594SDavid du Colombier+ 	   91,  2,  96, 32, 105,  1, 112, 16, 121,  2,   0,  0,   0,  0, },
734*14414594SDavid du Colombier+ 	{   4, 16,  15,  1,  22,  1,  31,  2,  37,  2,  55,  8,  62, 16,  69, 16,
735*14414594SDavid du Colombier+ 	   76,  4,  87, 16,  92, 32, 102, 32, 109,  4, 118,  2, 125, 32, },
736*14414594SDavid du Colombier+ 	{   6,  4,  23,  8,  30, 16,  39, 32,  45,  1,  54,  8,  70, 32,  77,  4,
737*14414594SDavid du Colombier+ 	   86,  2,  92, 16, 101,  8, 116,  1, 125,  2,   0,  0,   0,  0, },
738*14414594SDavid du Colombier+ 	{   4,  4,  13,  1,  22,  8,  36,  2,  47,  4,  53, 32,  63,  1,  69,  8,
739*14414594SDavid du Colombier+ 	   84,  1,  94,  4, 100,  8, 117, 16, 127, 32,   0,  0,   0,  0, },
740*14414594SDavid du Colombier+ 	{   3, 32,   8, 16,  19,  4,  34,  1,  41, 16,  50,  2,  56,  2,  67,  1,
741*14414594SDavid du Colombier+ 	   72,  1,  82,  4,  89, 32,  98, 32, 105,  8, 114,  8, 121,  1, },
742*14414594SDavid du Colombier+ 	{   1, 32,  19,  2,  24, 32,  33,  1,  40, 16,  51,  4,  64,  8,  83,  8,
743*14414594SDavid du Colombier+ 	   99,  1, 104,  1, 114,  4, 120,  4,   0,  0,   0,  0,   0,  0, },
744*14414594SDavid du Colombier+ 	{   8,  2,  17,  4,  27, 16,  32,  4,  51,  2,  56, 32,  66,  8,  75, 32,
745*14414594SDavid du Colombier+ 	   81,  2,  90, 16,  96,  8, 115,  8, 122,  2,   0,  0,   0,  0, },
746*14414594SDavid du Colombier+ 	{   2, 16,  18,  1,  25, 16,  34,  2,  40,  2,  49,  4,  59, 16,  66,  4,
747*14414594SDavid du Colombier+ 	   73, 32,  82, 32,  89,  8,  98,  8, 107, 32, 113,  2, 123,  4, },
748*14414594SDavid du Colombier+ 	{   7,  1,  13,  8,  28,  1,  38,  4,  44,  8,  61, 16,  71, 32,  77,  1,
749*14414594SDavid du Colombier+ 	   86,  8, 100,  2, 111,  4, 117, 32, 124, 16,   0,  0,   0,  0, },
750*14414594SDavid du Colombier+ 	{  12,  8,  29, 16,  36,  4,  47, 16,  52, 32,  62, 32,  68,  2,  79,  4,
751*14414594SDavid du Colombier+ 	   85, 32,  95,  1, 102,  1, 111,  2, 117,  2, 126,  4,   0,  0, },
752*14414594SDavid du Colombier+ 	{   5,  1,  15, 16,  20, 32,  30, 32,  37,  4,  46,  2,  52, 16,  61,  8,
753*14414594SDavid du Colombier+ 	   70,  1,  79,  2,  85,  2, 103,  8, 110, 16, 119, 32, 124,  4, },
754*14414594SDavid du Colombier+ 	{   0, 16,   9,  2,  18, 16,  24,  8,  43,  8,  59,  1,  65,  4,  75, 16,
755*14414594SDavid du Colombier+ 	   80,  4,  99,  2, 104, 32, 113,  1, 123, 32,   0,  0,   0,  0, },
756*14414594SDavid du Colombier+ 	{  10, 32,  17,  8,  26,  8,  35, 32,  41,  2,  50, 16,  56,  8,  66,  1,
757*14414594SDavid du Colombier+ 	   73, 16,  82,  2,  88,  2,  97,  4, 107, 16, 112,  4, 121, 32, },
758*14414594SDavid du Colombier+ 	{   0,  2,  11,  1,  16,  1,  26,  4,  33, 32,  42, 32,  49,  8,  58,  8,
759*14414594SDavid du Colombier+ 	   65,  1,  72, 16,  83,  4,  98,  1, 105, 16, 114,  2,   0,  0, },
760*14414594SDavid du Colombier+ 	{   8,  8,  27,  8,  43,  1,  48,  1,  58,  4,  64,  4,  83,  2,  88, 32,
761*14414594SDavid du Colombier+ 	   97,  1, 104, 16, 115,  4, 122, 16,   0,  0,   0,  0,   0,  0, },
762*14414594SDavid du Colombier+ 	{   5,  8,  14,  1,  23,  2,  29,  2,  47,  8,  54, 16,  63, 32,  68,  4,
763*14414594SDavid du Colombier+ 	   79, 16,  84, 32,  94, 32, 101,  4, 110,  2, 116, 16, 127,  1, },
764*14414594SDavid du Colombier+ 	{   4,  8,  15,  8,  22, 16,  31, 32,  37,  1,  46,  8,  60,  2,  69,  4,
765*14414594SDavid du Colombier+ 	   78,  2,  84, 16,  93,  8, 108,  1, 118,  4,   0,  0,   0,  0, },
766*14414594SDavid du Colombier+ 	{   7, 16,  14,  8,  28,  2,  39,  4,  45, 32,  55,  1,  62,  1,  76,  1,
767*14414594SDavid du Colombier+ 	   86,  4,  92,  8, 109, 16, 116,  4, 125,  1,   0,  0,   0,  0, },
768*14414594SDavid du Colombier+ 	{   1,  2,  11,  4,  26,  1,  33, 16,  42,  2,  48,  2,  57,  4,  64,  1,
769*14414594SDavid du Colombier+ 	   74,  4,  81, 32,  90, 32,  97,  8, 106,  8, 115, 32, 120, 16, },
770*14414594SDavid du Colombier+ 	{   2, 32,  11,  2,  16, 32,  25,  1,  32, 16,  43,  4,  58,  1,  75,  8,
771*14414594SDavid du Colombier+ 	   91,  1,  96,  1, 106,  4, 113, 32,   0,  0,   0,  0,   0,  0, },
772*14414594SDavid du Colombier+ 	{   3,  1,   9,  4,  19, 16,  24,  4,  43,  2,  48, 32,  57,  1,  67, 32,
773*14414594SDavid du Colombier+ 	   73,  2,  82, 16,  88,  8, 107,  8, 120,  2,   0,  0,   0,  0, },
774*14414594SDavid du Colombier+ 	{   0,  8,  10,  1,  17, 16,  26,  2,  32,  2,  41,  4,  51, 16,  56,  4,
775*14414594SDavid du Colombier+ 	   65, 32,  74, 32,  81,  8,  90,  8,  99, 32, 105,  2, 114, 16, },
776*14414594SDavid du Colombier+ 	{   6,  1,  20,  1,  30,  4,  36,  8,  53, 16,  60,  4,  69,  1,  78,  8,
777*14414594SDavid du Colombier+ 	   92,  2, 103,  4, 109, 32, 119,  1, 125,  8,   0,  0,   0,  0, },
778*14414594SDavid du Colombier+ 	{   7,  8,  21, 16,  28,  4,  39, 16,  44, 32,  54, 32,  61,  4,  71,  4,
779*14414594SDavid du Colombier+ 	   77, 32,  87,  1,  94,  1, 103,  2, 109,  2, 124,  8,   0,  0, },
780*14414594SDavid du Colombier+ 	{   6,  8,  12, 32,  22, 32,  29,  4,  38,  2,  44, 16,  53,  8,  71,  2,
781*14414594SDavid du Colombier+ 	   77,  2,  95,  8, 102, 16, 111, 32, 117,  1, 127, 16,   0,  0, }
782*14414594SDavid du Colombier+ };
783*14414594SDavid du Colombier+
784*14414594SDavid du Colombier+ static void
785*14414594SDavid du Colombier+ key_setup(char key[U9AUTH_DESKEYLEN], char *ek)
786*14414594SDavid du Colombier+ {
787*14414594SDavid du Colombier+ 	int i, j, k, mask;
788*14414594SDavid du Colombier+ 	uchar (*x)[2];
789*14414594SDavid du Colombier+
790*14414594SDavid du Colombier+ 	bzero(ek, 128);
791*14414594SDavid du Colombier+ 	x = keyexpand[0];
792*14414594SDavid du Colombier+ 	for(i = 0; i < 7; i++){
793*14414594SDavid du Colombier+ 		k = key[i];
794*14414594SDavid du Colombier+ 		for(mask = 0x80; mask; mask >>= 1){
795*14414594SDavid du Colombier+ 			if(k & mask)
796*14414594SDavid du Colombier+ 				for(j = 0; j < 15; j++)
797*14414594SDavid du Colombier+ 					ek[x[j][0]] |= x[j][1];
798*14414594SDavid du Colombier+ 			x += 15;
799*14414594SDavid du Colombier+ 		}
800*14414594SDavid du Colombier+ 	}
801*14414594SDavid du Colombier+ }
802*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs.h ./9fs/9fs.h
803*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs.h	Wed Dec 31 19:00:00 1969
804*14414594SDavid du Colombier--- ./9fs/9fs.h	Mon May 22 11:31:29 2000
805*14414594SDavid du Colombier***************
806*14414594SDavid du Colombier*** 0 ****
807*14414594SDavid du Colombier--- 1,294 ----
808*14414594SDavid du Colombier+ /*
809*14414594SDavid du Colombier+  * Copyright (c) 1989, 1993, 1995
810*14414594SDavid du Colombier+  *	The Regents of the University of California.  All rights reserved.
811*14414594SDavid du Colombier+  *
812*14414594SDavid du Colombier+  * This code is derived from software contributed to Berkeley by
813*14414594SDavid du Colombier+  * Rick Macklem at The University of Guelph.
814*14414594SDavid du Colombier+  *
815*14414594SDavid du Colombier+  * Redistribution and use in source and binary forms, with or without
816*14414594SDavid du Colombier+  * modification, are permitted provided that the following conditions
817*14414594SDavid du Colombier+  * are met:
818*14414594SDavid du Colombier+  * 1. Redistributions of source code must retain the above copyright
819*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer.
820*14414594SDavid du Colombier+  * 2. Redistributions in binary form must reproduce the above copyright
821*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer in the
822*14414594SDavid du Colombier+  *    documentation and/or other materials provided with the distribution.
823*14414594SDavid du Colombier+  * 3. All advertising materials mentioning features or use of this software
824*14414594SDavid du Colombier+  *    must display the following acknowledgement:
825*14414594SDavid du Colombier+  *	This product includes software developed by the University of
826*14414594SDavid du Colombier+  *	California, Berkeley and its contributors.
827*14414594SDavid du Colombier+  * 4. Neither the name of the University nor the names of its contributors
828*14414594SDavid du Colombier+  *    may be used to endorse or promote products derived from this software
829*14414594SDavid du Colombier+  *    without specific prior written permission.
830*14414594SDavid du Colombier+  *
831*14414594SDavid du Colombier+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
832*14414594SDavid du Colombier+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
833*14414594SDavid du Colombier+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
834*14414594SDavid du Colombier+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
835*14414594SDavid du Colombier+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
836*14414594SDavid du Colombier+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
837*14414594SDavid du Colombier+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
838*14414594SDavid du Colombier+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
839*14414594SDavid du Colombier+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
840*14414594SDavid du Colombier+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
841*14414594SDavid du Colombier+  * SUCH DAMAGE.
842*14414594SDavid du Colombier+  *
843*14414594SDavid du Colombier+  *	@(#)nfs.h	8.4 (Berkeley) 5/1/95
844*14414594SDavid du Colombier+  * $Id: nfs.h,v 1.44 1998/09/07 05:42:15 bde Exp $
845*14414594SDavid du Colombier+  */
846*14414594SDavid du Colombier+
847*14414594SDavid du Colombier+ #ifndef _9FS_H_
848*14414594SDavid du Colombier+ #define _9FS_H_
849*14414594SDavid du Colombier+
850*14414594SDavid du Colombier+ #ifdef KERNEL
851*14414594SDavid du Colombier+ #include "opt_u9fs.h"
852*14414594SDavid du Colombier+ #endif
853*14414594SDavid du Colombier+
854*14414594SDavid du Colombier+ #define U9FS_FABLKSIZE   512
855*14414594SDavid du Colombier+ #define U9FS_PORT        17008
856*14414594SDavid du Colombier+
857*14414594SDavid du Colombier+ /*
858*14414594SDavid du Colombier+  * The set of signals the interrupt an I/O in progress for U9FSMNT_INT mounts.
859*14414594SDavid du Colombier+  * What should be in this set is open to debate, but I believe that since
860*14414594SDavid du Colombier+  * I/O system calls on ufs are never interrupted by signals the set should
861*14414594SDavid du Colombier+  * be minimal. My reasoning is that many current programs that use signals
862*14414594SDavid du Colombier+  * such as SIGALRM will not expect file I/O system calls to be interrupted
863*14414594SDavid du Colombier+  * by them and break.
864*14414594SDavid du Colombier+  */
865*14414594SDavid du Colombier+ #define	U9FSINT_SIGMASK	(sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \
866*14414594SDavid du Colombier+ 			 sigmask(SIGHUP)|sigmask(SIGQUIT))
867*14414594SDavid du Colombier+
868*14414594SDavid du Colombier+ /*
869*14414594SDavid du Colombier+  * U9FS mount option flags
870*14414594SDavid du Colombier+  */
871*14414594SDavid du Colombier+ #define	U9FSMNT_SOFT		0x00000001  /* soft mount (hard is default) */
872*14414594SDavid du Colombier+ #define	U9FSMNT_MAXGRPS		0x00000020  /* set maximum grouplist size */
873*14414594SDavid du Colombier+ #define	U9FSMNT_INT		0x00000040  /* allow interrupts on hard mount */
874*14414594SDavid du Colombier+ #define	U9FSMNT_KERB		0x00000400  /* Use Kerberos authentication */
875*14414594SDavid du Colombier+ #define	U9FSMNT_READAHEAD	0x00002000  /* set read ahead */
876*14414594SDavid du Colombier+
877*14414594SDavid du Colombier+ #define U9FSSTA_HASWRITEVERF	0x00040000  /* Has write verifier for V3 */
878*14414594SDavid du Colombier+ #define U9FSSTA_GOTPATHCONF	0x00080000  /* Got the V3 pathconf info */
879*14414594SDavid du Colombier+ #define U9FSSTA_GOTFSINFO	0x00100000  /* Got the V3 fsinfo */
880*14414594SDavid du Colombier+ #define	U9FSSTA_MNTD		0x00200000  /* Mnt server for mnt point */
881*14414594SDavid du Colombier+ #define	U9FSSTA_DISMINPROG	0x00400000  /* Dismount in progress */
882*14414594SDavid du Colombier+ #define	U9FSSTA_DISMNT		0x00800000  /* Dismounted */
883*14414594SDavid du Colombier+ #define	U9FSSTA_SNDLOCK		0x01000000  /* Send socket lock */
884*14414594SDavid du Colombier+ #define	U9FSSTA_WANTSND		0x02000000  /* Want above */
885*14414594SDavid du Colombier+ #define	U9FSSTA_RCVLOCK		0x04000000  /* Rcv socket lock */
886*14414594SDavid du Colombier+ #define	U9FSSTA_WANTRCV		0x08000000  /* Want above */
887*14414594SDavid du Colombier+ #define	U9FSSTA_WAITAUTH		0x10000000  /* Wait for authentication */
888*14414594SDavid du Colombier+ #define	U9FSSTA_HASAUTH		0x20000000  /* Has authenticator */
889*14414594SDavid du Colombier+ #define	U9FSSTA_WANTAUTH		0x40000000  /* Wants an authenticator */
890*14414594SDavid du Colombier+ #define	U9FSSTA_AUTHERR		0x80000000  /* Authentication error */
891*14414594SDavid du Colombier+
892*14414594SDavid du Colombier+ #define	U9FSNOHASH(fhsum) (&u9fsnodehashtbl[(fhsum) % u9fsnodehash])
893*14414594SDavid du Colombier+
894*14414594SDavid du Colombier+ /*
895*14414594SDavid du Colombier+  * Arguments to mount 9FS
896*14414594SDavid du Colombier+  */
897*14414594SDavid du Colombier+ #define U9FS_ARGSVERSION	1	/* change when nfs_args changes */
898*14414594SDavid du Colombier+ struct u9fs_args {
899*14414594SDavid du Colombier+ 	int		version;	/* args structure version number */
900*14414594SDavid du Colombier+ 	struct sockaddr	*addr;		/* file server address */
901*14414594SDavid du Colombier+ 	int		addrlen;	/* length of address */
902*14414594SDavid du Colombier+ 	int		sotype;		/* Socket type */
903*14414594SDavid du Colombier+ 	int		proto;		/* and Protocol */
904*14414594SDavid du Colombier+ 	int		fhsize;		/* Size, in bytes, of fh */
905*14414594SDavid du Colombier+ 	int		flags;		/* flags */
906*14414594SDavid du Colombier+ 	int		wsize;		/* write size in bytes */
907*14414594SDavid du Colombier+ 	int		rsize;		/* read size in bytes */
908*14414594SDavid du Colombier+ 	int		readdirsize;	/* readdir size in bytes */
909*14414594SDavid du Colombier+ 	char		*hostname;	/* server's name */
910*14414594SDavid du Colombier+
911*14414594SDavid du Colombier+         struct sockaddr * authaddr;
912*14414594SDavid du Colombier+         int             authaddrlen;
913*14414594SDavid du Colombier+         int             authsotype;
914*14414594SDavid du Colombier+         int             authsoproto;
915*14414594SDavid du Colombier+
916*14414594SDavid du Colombier+         int             nusers;
917*14414594SDavid du Colombier+         char            user[U9FS_NAMELEN];
918*14414594SDavid du Colombier+         char            key[U9AUTH_DESKEYLEN];
919*14414594SDavid du Colombier+         struct p9user {
920*14414594SDavid du Colombier+ 	  uid_t p9_uid;
921*14414594SDavid du Colombier+ 	  char p9_name[U9FS_NAMELEN];
922*14414594SDavid du Colombier+ 	} * users;
923*14414594SDavid du Colombier+ };
924*14414594SDavid du Colombier+
925*14414594SDavid du Colombier+ #define U9FS_USER_HASHSIZE 512
926*14414594SDavid du Colombier+
927*14414594SDavid du Colombier+ struct u9fsuser {
928*14414594SDavid du Colombier+   LIST_ENTRY(u9fsuser) u_hash;
929*14414594SDavid du Colombier+   uid_t                u_uid;
930*14414594SDavid du Colombier+   char                 u_name[U9FS_NAMELEN];
931*14414594SDavid du Colombier+   char                 u_ckey[U9AUTH_DESKEYLEN];  /* user key */
932*14414594SDavid du Colombier+   char                 u_skey[U9AUTH_DESKEYLEN];  /* session key */
933*14414594SDavid du Colombier+ };
934*14414594SDavid du Colombier+
935*14414594SDavid du Colombier+ /*
936*14414594SDavid du Colombier+  * The u9fsnode is the u9fs equivalent to ufs's inode. Any similarity
937*14414594SDavid du Colombier+  * is purely coincidental.
938*14414594SDavid du Colombier+  * There is a unique u9fsnode allocated for each active file,
939*14414594SDavid du Colombier+  * each current directory, each mounted-on file, text file, and the root.
940*14414594SDavid du Colombier+  * An u9fsnode is 'named' by its file handle. (nget/u9fs_node.c)
941*14414594SDavid du Colombier+  * If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
942*14414594SDavid du Colombier+  * type definitions), file handles of > 32 bytes should probably be split out
943*14414594SDavid du Colombier+  * into a separate MALLOC()'d data structure. (Reduce the size of u9fsfh_t by
944*14414594SDavid du Colombier+  * changing the definition in u9fsproto.h of U9FS_SMALLFH.)
945*14414594SDavid du Colombier+  * NB: Hopefully the current order of the fields is such that everything will
946*14414594SDavid du Colombier+  *     be well aligned and, therefore, tightly packed.
947*14414594SDavid du Colombier+  */
948*14414594SDavid du Colombier+ struct u9fsnode {
949*14414594SDavid du Colombier+ 	LIST_ENTRY(u9fsnode)	n_hash;		/* Hash chain */
950*14414594SDavid du Colombier+ 	u_quad_t		n_size;		/* Current size of file */
951*14414594SDavid du Colombier+ 	struct vattr		n_vattr;	/* Vnode attribute cache */
952*14414594SDavid du Colombier+ 	time_t			n_attrstamp;	/* Attr. cache timestamp */
953*14414594SDavid du Colombier+ 	u_int32_t		n_mode;		/* ACCESS mode cache */
954*14414594SDavid du Colombier+ 	uid_t			n_modeuid;	/* credentials having mode */
955*14414594SDavid du Colombier+ 	time_t			n_modestamp;	/* mode cache timestamp */
956*14414594SDavid du Colombier+ 	time_t			n_mtime;	/* Prev modify time. */
957*14414594SDavid du Colombier+ 	time_t			n_ctime;	/* Prev create time. */
958*14414594SDavid du Colombier+         struct u9fs_qid         n_qid;
959*14414594SDavid du Colombier+ 	u_short			n_fid;		/* U9FS FID */
960*14414594SDavid du Colombier+         u_short                 n_rdfid;
961*14414594SDavid du Colombier+         u_short                 n_wrfid;
962*14414594SDavid du Colombier+ 	struct vnode		*n_vnode;	/* associated vnode */
963*14414594SDavid du Colombier+ 	struct lockf		*n_lockf;	/* Locking record of file */
964*14414594SDavid du Colombier+ 	int			n_error;	/* Save write error value */
965*14414594SDavid du Colombier+         struct u9fsdir          n_dir;
966*14414594SDavid du Colombier+ 	short			n_flag;		/* Flag for locking.. */
967*14414594SDavid du Colombier+         int                     n_opens;        /* number of opens */
968*14414594SDavid du Colombier+ };
969*14414594SDavid du Colombier+
970*14414594SDavid du Colombier+ #define n_atim		n_un1.nf_atim
971*14414594SDavid du Colombier+ #define n_mtim		n_un2.nf_mtim
972*14414594SDavid du Colombier+ #define n_sillyrename	n_un3.nf_silly
973*14414594SDavid du Colombier+ #define n_cookieverf	n_un1.nd_cookieverf
974*14414594SDavid du Colombier+ #define n_direofoffset	n_un2.nd_direof
975*14414594SDavid du Colombier+ #define n_cookies	n_un3.nd_cook
976*14414594SDavid du Colombier+
977*14414594SDavid du Colombier+ /*
978*14414594SDavid du Colombier+  * Flags for n_flag
979*14414594SDavid du Colombier+  */
980*14414594SDavid du Colombier+ #define	NFLUSHWANT	0x0001	/* Want wakeup from a flush in prog. */
981*14414594SDavid du Colombier+ #define	NFLUSHINPROG	0x0002	/* Avoid multiple calls to vinvalbuf() */
982*14414594SDavid du Colombier+ #define	NMODIFIED	0x0004	/* Might have a modified buffer in bio */
983*14414594SDavid du Colombier+ #define	NWRITEERR	0x0008	/* Flag write errors so close will know */
984*14414594SDavid du Colombier+ #define	NQU9FSNONCACHE	0x0020	/* Non-cachable lease */
985*14414594SDavid du Colombier+ #define	NQU9FSWRITE	0x0040	/* Write lease */
986*14414594SDavid du Colombier+ #define	NQU9FSEVICTED	0x0080	/* Has been evicted */
987*14414594SDavid du Colombier+ #define	NACC		0x0100	/* Special file accessed */
988*14414594SDavid du Colombier+ #define	NUPD		0x0200	/* Special file updated */
989*14414594SDavid du Colombier+ #define	NCHG		0x0400	/* Special file times changed */
990*14414594SDavid du Colombier+ #define NLOCKED		0x0800  /* node is locked */
991*14414594SDavid du Colombier+ #define NWANTED		0x0100  /* someone wants to lock */
992*14414594SDavid du Colombier+
993*14414594SDavid du Colombier+ /*
994*14414594SDavid du Colombier+  * Convert between u9fsnode pointers and vnode pointers
995*14414594SDavid du Colombier+  */
996*14414594SDavid du Colombier+ #define VTOU9FS(vp)	((struct u9fsnode *)(vp)->v_data)
997*14414594SDavid du Colombier+ #define U9FSTOV(np)	((struct vnode *)(np)->n_vnode)
998*14414594SDavid du Colombier+
999*14414594SDavid du Colombier+ /*
1000*14414594SDavid du Colombier+  * Mount structure.
1001*14414594SDavid du Colombier+  * One allocated on every U9FS mount.
1002*14414594SDavid du Colombier+  * Holds U9FS specific information for mount.
1003*14414594SDavid du Colombier+  */
1004*14414594SDavid du Colombier+ struct	u9fsmount {
1005*14414594SDavid du Colombier+ 	int	nm_flag;		/* Flags for soft/hard... */
1006*14414594SDavid du Colombier+ 	int	nm_state;		/* Internal state flags */
1007*14414594SDavid du Colombier+ 	struct	mount *nm_mountp;	/* Vfs structure for this filesystem */
1008*14414594SDavid du Colombier+ 	int	nm_numgrps;		/* Max. size of groupslist */
1009*14414594SDavid du Colombier+         u9fsfh_t nm_fh;                /* qid.path */
1010*14414594SDavid du Colombier+ 	u_short	nm_fid;	                /* fid of root dir */
1011*14414594SDavid du Colombier+ 	struct	socket *nm_so;		/* Rpc socket */
1012*14414594SDavid du Colombier+ 	int	nm_sotype;		/* Type of socket */
1013*14414594SDavid du Colombier+ 	int	nm_soproto;		/* and protocol */
1014*14414594SDavid du Colombier+ 	int	nm_soflags;		/* pr_flags for socket protocol */
1015*14414594SDavid du Colombier+ 	struct	sockaddr *nm_nam;	/* Addr of server */
1016*14414594SDavid du Colombier+ 	int	nm_sent;		/* Request send count */
1017*14414594SDavid du Colombier+ 	int	nm_cwnd;		/* Request send window */
1018*14414594SDavid du Colombier+ 	int	nm_rsize;		/* Max size of read rpc */
1019*14414594SDavid du Colombier+ 	int	nm_wsize;		/* Max size of write rpc */
1020*14414594SDavid du Colombier+ 	int	nm_readdirsize;		/* Size of a readdir rpc */
1021*14414594SDavid du Colombier+
1022*14414594SDavid du Colombier+   struct lock   nm_lock;                /* lock for tag/fid freelist */
1023*14414594SDavid du Colombier+   bitstr_t * nm_tags;
1024*14414594SDavid du Colombier+   bitstr_t * nm_fids;
1025*14414594SDavid du Colombier+   TAILQ_HEAD(u9fs_reqq, u9fsreq) nm_reqq;
1026*14414594SDavid du Colombier+
1027*14414594SDavid du Colombier+         uid_t   nm_authuid;             /* Uid for authenticator */
1028*14414594SDavid du Colombier+ #if 0
1029*14414594SDavid du Colombier+ 	struct vnode *nm_inprog;	/* Vnode in prog by nqu9fs_clientd() */
1030*14414594SDavid du Colombier+ 	uid_t	nm_authuid;		/* Uid for authenticator */
1031*14414594SDavid du Colombier+ 	int	nm_authtype;		/* Authenticator type */
1032*14414594SDavid du Colombier+ 	int	nm_authlen;		/* and length */
1033*14414594SDavid du Colombier+ 	char	*nm_authstr;		/* Authenticator string */
1034*14414594SDavid du Colombier+ 	char	*nm_verfstr;		/* and the verifier */
1035*14414594SDavid du Colombier+ 	int	nm_verflen;
1036*14414594SDavid du Colombier+ 	u_char	nm_verf[U9FSX_V3WRITEVERF]; /* V3 write verifier */
1037*14414594SDavid du Colombier+ 	U9FSKERBKEY_T nm_key;		/* and the session key */
1038*14414594SDavid du Colombier+ 	int	nm_numuids;		/* Number of u9fsuid mappings */
1039*14414594SDavid du Colombier+ 	TAILQ_HEAD(, u9fsuid) nm_uidlruhead; /* Lists of u9fsuid mappings */
1040*14414594SDavid du Colombier+ 	LIST_HEAD(, u9fsuid) nm_uidhashtbl[U9FS_MUIDHASHSIZ];
1041*14414594SDavid du Colombier+ 	TAILQ_HEAD(, buf) nm_bufq;	/* async io buffer queue */
1042*14414594SDavid du Colombier+ 	short	nm_bufqlen;		/* number of buffers in queue */
1043*14414594SDavid du Colombier+ 	short	nm_bufqwant;		/* process wants to add to the queue */
1044*14414594SDavid du Colombier+ 	int	nm_bufqiods;		/* number of iods processing queue */
1045*14414594SDavid du Colombier+ #endif
1046*14414594SDavid du Colombier+ 	u_int64_t nm_maxfilesize;	/* maximum file size */
1047*14414594SDavid du Colombier+ };
1048*14414594SDavid du Colombier+
1049*14414594SDavid du Colombier+ #ifdef KERNEL
1050*14414594SDavid du Colombier+
1051*14414594SDavid du Colombier+ #ifdef MALLOC_DECLARE
1052*14414594SDavid du Colombier+ MALLOC_DECLARE(M_U9FSHASH);
1053*14414594SDavid du Colombier+ MALLOC_DECLARE(M_U9FSBITS);
1054*14414594SDavid du Colombier+
1055*14414594SDavid du Colombier+ extern        vop_t   **u9fs_vnodeop_p;
1056*14414594SDavid du Colombier+
1057*14414594SDavid du Colombier+ /* u9fs_node.c */
1058*14414594SDavid du Colombier+ void     u9fs_nhinit __P((void));
1059*14414594SDavid du Colombier+ int u9fs_nget __P((struct mount *mntp, u9fsfh_t fh, struct u9fsnode **npp, struct proc * p));
1060*14414594SDavid du Colombier+
1061*14414594SDavid du Colombier+ /* u9fs_subr.c */
1062*14414594SDavid du Colombier+ void u9fs_id_init __P((bitstr_t ** bits));
1063*14414594SDavid du Colombier+ u_short u9fs_id_new __P((bitstr_t * bits));
1064*14414594SDavid du Colombier+ void u9fs_id_free __P((bitstr_t * bits, u_short v));
1065*14414594SDavid du Colombier+ void u9fs_uhinit __P((void));
1066*14414594SDavid du Colombier+ uid_t u9fs_name2uid __P((char * name));
1067*14414594SDavid du Colombier+ struct u9fsuser *  u9fs_finduser __P((uid_t uid));
1068*14414594SDavid du Colombier+ void  u9fs_hashuser __P((uid_t uid, char *name));
1069*14414594SDavid du Colombier+ int u9fs_mbuftouio __P((struct mbuf *m, struct uio *uiop, int siz));
1070*14414594SDavid du Colombier+ int u9fs_uiotombuf __P((struct uio *uiop, struct mbuf **mq, int siz));
1071*14414594SDavid du Colombier+
1072*14414594SDavid du Colombier+ /* u9fs_vnopes.c */
1073*14414594SDavid du Colombier+ int u9fs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
1074*14414594SDavid du Colombier+ int u9fs_readrpc __P((struct vnode *vp, struct uio *uiop, struct ucred *cred));
1075*14414594SDavid du Colombier+ int u9fs_writerpc __P((struct vnode *vp, struct uio *uiop, struct ucred *cred));
1076*14414594SDavid du Colombier+
1077*14414594SDavid du Colombier+ /* u9fs_bio.c */
1078*14414594SDavid du Colombier+ int u9fs_bioread __P((struct vnode *, struct uio *, int, struct ucred *,int));
1079*14414594SDavid du Colombier+ int u9fs_biowrite __P((struct vnode *, struct uio *, int ioflag, struct ucred *));
1080*14414594SDavid du Colombier+ int u9fs_doio __P((struct buf *, struct ucred *, struct proc *));
1081*14414594SDavid du Colombier+ int	u9fs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct proc *, int));
1082*14414594SDavid du Colombier+
1083*14414594SDavid du Colombier+
1084*14414594SDavid du Colombier+ /* u9fs_socket.c */
1085*14414594SDavid du Colombier+ int u9fs_sigintr __P((struct u9fsmount *nmp, struct proc *p));
1086*14414594SDavid du Colombier+ void     u9fs_disconnect __P((struct socket *));
1087*14414594SDavid du Colombier+ int      u9fs_connect __P((struct socket ** sop, struct sockaddr * saddr, int sotype, int soproto, struct proc * p));
1088*14414594SDavid du Colombier+ int      u9fs_connect_9fs __P((struct u9fsmount *));
1089*14414594SDavid du Colombier+ int      u9fs_connect_9auth __P((struct u9fsmount *, struct u9fs_args *, struct socket **));
1090*14414594SDavid du Colombier+ int u9fs_request __P((struct u9fsreq * req, struct u9fsreq * rep, int relm));
1091*14414594SDavid du Colombier+
1092*14414594SDavid du Colombier+ #endif
1093*14414594SDavid du Colombier+
1094*14414594SDavid du Colombier+ /*
1095*14414594SDavid du Colombier+  * Convert mount ptr to u9fsmount ptr.
1096*14414594SDavid du Colombier+  */
1097*14414594SDavid du Colombier+ #define VFSTOU9FS(mp)	((struct u9fsmount *)((mp)->mnt_data))
1098*14414594SDavid du Colombier+
1099*14414594SDavid du Colombier+ #endif	/* KERNEL */
1100*14414594SDavid du Colombier+
1101*14414594SDavid du Colombier+ #endif
1102*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_bio.c ./9fs/9fs_bio.c
1103*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_bio.c	Wed Dec 31 19:00:00 1969
1104*14414594SDavid du Colombier--- ./9fs/9fs_bio.c	Fri Nov 26 12:28:50 1999
1105*14414594SDavid du Colombier***************
1106*14414594SDavid du Colombier*** 0 ****
1107*14414594SDavid du Colombier--- 1,550 ----
1108*14414594SDavid du Colombier+ #include <sys/param.h>
1109*14414594SDavid du Colombier+ #include <sys/sockio.h>
1110*14414594SDavid du Colombier+ #include <sys/proc.h>
1111*14414594SDavid du Colombier+ #include <sys/vnode.h>
1112*14414594SDavid du Colombier+ #include <sys/kernel.h>
1113*14414594SDavid du Colombier+ #include <sys/sysctl.h>
1114*14414594SDavid du Colombier+ #include <sys/malloc.h>
1115*14414594SDavid du Colombier+ #include <sys/mount.h>
1116*14414594SDavid du Colombier+ #include <sys/mbuf.h>
1117*14414594SDavid du Colombier+ #include <sys/socket.h>
1118*14414594SDavid du Colombier+ #include <sys/socketvar.h>
1119*14414594SDavid du Colombier+ #include <sys/systm.h>
1120*14414594SDavid du Colombier+ #include <sys/protosw.h>
1121*14414594SDavid du Colombier+ #include <sys/syslog.h>
1122*14414594SDavid du Colombier+
1123*14414594SDavid du Colombier+ #include <netinet/in.h>
1124*14414594SDavid du Colombier+ #include <netinet/tcp.h>
1125*14414594SDavid du Colombier+
1126*14414594SDavid du Colombier+ #include <vm/vm.h>
1127*14414594SDavid du Colombier+ #include <vm/vm_extern.h>
1128*14414594SDavid du Colombier+ #include <vm/vm_zone.h>
1129*14414594SDavid du Colombier+ #include <vm/vm_prot.h>
1130*14414594SDavid du Colombier+ #include <vm/vm_page.h>
1131*14414594SDavid du Colombier+ #include <vm/vm_object.h>
1132*14414594SDavid du Colombier+ #include <vm/vm_pager.h>
1133*14414594SDavid du Colombier+ #include <vm/vnode_pager.h>
1134*14414594SDavid du Colombier+
1135*14414594SDavid du Colombier+ #include <net/if.h>
1136*14414594SDavid du Colombier+ #include <net/route.h>
1137*14414594SDavid du Colombier+ #include <netinet/in.h>
1138*14414594SDavid du Colombier+
1139*14414594SDavid du Colombier+ #include <9fs/bitstring.h>
1140*14414594SDavid du Colombier+ #include <9fs/9p.h>
1141*14414594SDavid du Colombier+ #include <9fs/9auth.h>
1142*14414594SDavid du Colombier+ #include <9fs/9fs.h>
1143*14414594SDavid du Colombier+
1144*14414594SDavid du Colombier+ static struct buf *u9fs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size, struct proc *p));
1145*14414594SDavid du Colombier+ static void u9fs_prot_buf __P((struct buf *bp, int off, int n));
1146*14414594SDavid du Colombier+
1147*14414594SDavid du Colombier+ /*
1148*14414594SDavid du Colombier+  * Vnode op for read using bio
1149*14414594SDavid du Colombier+  */
1150*14414594SDavid du Colombier+ int
1151*14414594SDavid du Colombier+ u9fs_bioread(vp, uio, ioflag, cred, getpages)
1152*14414594SDavid du Colombier+ 	register struct vnode *vp;
1153*14414594SDavid du Colombier+ 	register struct uio *uio;
1154*14414594SDavid du Colombier+ 	int ioflag;
1155*14414594SDavid du Colombier+ 	struct ucred *cred;
1156*14414594SDavid du Colombier+ 	int getpages;
1157*14414594SDavid du Colombier+ {
1158*14414594SDavid du Colombier+ 	register struct u9fsnode *np = VTOU9FS(vp);
1159*14414594SDavid du Colombier+ 	register int biosize;
1160*14414594SDavid du Colombier+ 	off_t diff;
1161*14414594SDavid du Colombier+ 	struct buf *bp = 0;
1162*14414594SDavid du Colombier+ 	struct proc *p;
1163*14414594SDavid du Colombier+ 	struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
1164*14414594SDavid du Colombier+ 	daddr_t lbn;
1165*14414594SDavid du Colombier+ 	int error = 0, n = 0, on = 0, bufsize, not_readin;
1166*14414594SDavid du Colombier+
1167*14414594SDavid du Colombier+ 	if (uio->uio_resid == 0)
1168*14414594SDavid du Colombier+ 		return (0);
1169*14414594SDavid du Colombier+ 	if (uio->uio_offset < 0)
1170*14414594SDavid du Colombier+ 		return (EINVAL);
1171*14414594SDavid du Colombier+ 	p = uio->uio_procp;
1172*14414594SDavid du Colombier+ 	if (vp->v_type != VDIR &&
1173*14414594SDavid du Colombier+ 	    (uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
1174*14414594SDavid du Colombier+ 		return (EFBIG);
1175*14414594SDavid du Colombier+ 	biosize = vp->v_mount->mnt_stat.f_iosize;
1176*14414594SDavid du Colombier+ #if 0
1177*14414594SDavid du Colombier+ 	if( np->n_qid.vers ) { /* in cache, check revision */
1178*14414594SDavid du Colombier+ 	  error = VOP_GETATTR(vp, &vattr, cred, p);
1179*14414594SDavid du Colombier+ 	  if( error )
1180*14414594SDavid du Colombier+ 	    return error;
1181*14414594SDavid du Colombier+ 	  if( np->n_qid.vers != np->n_dir.dir_qid.vers ) {
1182*14414594SDavid du Colombier+ 	    /* content changed */
1183*14414594SDavid du Colombier+ 	    u9fs_vinvalbuf(vp, V_SAVE, cred, p, 1);
1184*14414594SDavid du Colombier+ 	  }
1185*14414594SDavid du Colombier+ 	}
1186*14414594SDavid du Colombier+ #endif
1187*14414594SDavid du Colombier+ 	do {
1188*14414594SDavid du Colombier+ 	    switch (vp->v_type) {
1189*14414594SDavid du Colombier+ 	    case VREG:
1190*14414594SDavid du Colombier+ 		lbn = uio->uio_offset / biosize;
1191*14414594SDavid du Colombier+ 		on = uio->uio_offset & (biosize - 1);
1192*14414594SDavid du Colombier+ 		not_readin = 1;
1193*14414594SDavid du Colombier+
1194*14414594SDavid du Colombier+ #if 0
1195*14414594SDavid du Colombier+ 		/*
1196*14414594SDavid du Colombier+ 		 * Start the read ahead(s), as required.
1197*14414594SDavid du Colombier+ 		 */
1198*14414594SDavid du Colombier+ 		if (u9fs_numasync > 0 && nmp->nm_readahead > 0) {
1199*14414594SDavid du Colombier+ 		    for (nra = 0; nra < nmp->nm_readahead &&
1200*14414594SDavid du Colombier+ 			(off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) {
1201*14414594SDavid du Colombier+ 			rabn = lbn + 1 + nra;
1202*14414594SDavid du Colombier+ 			if (!incore(vp, rabn)) {
1203*14414594SDavid du Colombier+ 			    rabp = u9fs_getcacheblk(vp, rabn, biosize, p);
1204*14414594SDavid du Colombier+ 			    if (!rabp)
1205*14414594SDavid du Colombier+ 				return (EINTR);
1206*14414594SDavid du Colombier+ 			    if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
1207*14414594SDavid du Colombier+ 				rabp->b_flags |= (B_READ | B_ASYNC);
1208*14414594SDavid du Colombier+ 				vfs_busy_pages(rabp, 0);
1209*14414594SDavid du Colombier+ 				if (u9fs_asyncio(rabp, cred)) {
1210*14414594SDavid du Colombier+ 				    rabp->b_flags |= B_INVAL|B_ERROR;
1211*14414594SDavid du Colombier+ 				    vfs_unbusy_pages(rabp);
1212*14414594SDavid du Colombier+ 				    brelse(rabp);
1213*14414594SDavid du Colombier+ 				}
1214*14414594SDavid du Colombier+ 			    } else
1215*14414594SDavid du Colombier+ 				brelse(rabp);
1216*14414594SDavid du Colombier+ 			}
1217*14414594SDavid du Colombier+ 		    }
1218*14414594SDavid du Colombier+ 		}
1219*14414594SDavid du Colombier+ #endif
1220*14414594SDavid du Colombier+
1221*14414594SDavid du Colombier+ 		/*
1222*14414594SDavid du Colombier+ 		 * If the block is in the cache and has the required data
1223*14414594SDavid du Colombier+ 		 * in a valid region, just copy it out.
1224*14414594SDavid du Colombier+ 		 * Otherwise, get the block and write back/read in,
1225*14414594SDavid du Colombier+ 		 * as required.
1226*14414594SDavid du Colombier+ 		 */
1227*14414594SDavid du Colombier+ again:
1228*14414594SDavid du Colombier+ 		bufsize = biosize;
1229*14414594SDavid du Colombier+ 		if ((off_t)(lbn + 1) * biosize > np->n_size &&
1230*14414594SDavid du Colombier+ 		    (off_t)(lbn + 1) * biosize - np->n_size < biosize) {
1231*14414594SDavid du Colombier+ 			bufsize = np->n_size - (off_t)lbn * biosize;
1232*14414594SDavid du Colombier+ 			bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1233*14414594SDavid du Colombier+ 		}
1234*14414594SDavid du Colombier+ 		bp = u9fs_getcacheblk(vp, lbn, bufsize, p);
1235*14414594SDavid du Colombier+ 		if (!bp)
1236*14414594SDavid du Colombier+ 			return (EINTR);
1237*14414594SDavid du Colombier+ 		/*
1238*14414594SDavid du Colombier+ 		 * If we are being called from u9fs_getpages, we must
1239*14414594SDavid du Colombier+ 		 * make sure the buffer is a vmio buffer.  The vp will
1240*14414594SDavid du Colombier+ 		 * already be setup for vmio but there may be some old
1241*14414594SDavid du Colombier+ 		 * non-vmio buffers attached to it.
1242*14414594SDavid du Colombier+ 		 */
1243*14414594SDavid du Colombier+ 		if (getpages && !(bp->b_flags & B_VMIO)) {
1244*14414594SDavid du Colombier+ #ifdef DIAGNOSTIC
1245*14414594SDavid du Colombier+ 			printf("u9fs_bioread: non vmio buf found, discarding\n");
1246*14414594SDavid du Colombier+ #endif
1247*14414594SDavid du Colombier+ 			bp->b_flags |= B_NOCACHE;
1248*14414594SDavid du Colombier+ 			if (bp->b_dirtyend > 0) {
1249*14414594SDavid du Colombier+ 				if ((bp->b_flags & B_DELWRI) == 0)
1250*14414594SDavid du Colombier+ 					panic("u9fsbioread");
1251*14414594SDavid du Colombier+ 				if (VOP_BWRITE(bp) == EINTR)
1252*14414594SDavid du Colombier+ 					return (EINTR);
1253*14414594SDavid du Colombier+ 			} else
1254*14414594SDavid du Colombier+ 				brelse(bp);
1255*14414594SDavid du Colombier+ 			goto again;
1256*14414594SDavid du Colombier+ 		}
1257*14414594SDavid du Colombier+ 		if ((bp->b_flags & B_CACHE) == 0) {
1258*14414594SDavid du Colombier+ 		    bp->b_flags |= B_READ;
1259*14414594SDavid du Colombier+ 		    bp->b_flags &= ~(B_DONE | B_ERROR | B_INVAL);
1260*14414594SDavid du Colombier+ 		    not_readin = 0;
1261*14414594SDavid du Colombier+ 		    vfs_busy_pages(bp, 0);
1262*14414594SDavid du Colombier+ 		    error = u9fs_doio(bp, cred, p);
1263*14414594SDavid du Colombier+ 		    if (error) {
1264*14414594SDavid du Colombier+ 			brelse(bp);
1265*14414594SDavid du Colombier+ 			return (error);
1266*14414594SDavid du Colombier+ 		    }
1267*14414594SDavid du Colombier+ 		    np->n_qid.vers = np->n_dir.dir_qid.vers;
1268*14414594SDavid du Colombier+ 		}
1269*14414594SDavid du Colombier+ 		if (bufsize > on) {
1270*14414594SDavid du Colombier+ 			n = min((unsigned)(bufsize - on), uio->uio_resid);
1271*14414594SDavid du Colombier+ 		} else {
1272*14414594SDavid du Colombier+ 			n = 0;
1273*14414594SDavid du Colombier+ 		}
1274*14414594SDavid du Colombier+ 		diff = np->n_size - uio->uio_offset;
1275*14414594SDavid du Colombier+ 		if (diff < n)
1276*14414594SDavid du Colombier+ 			n = diff;
1277*14414594SDavid du Colombier+ 		if (not_readin && n > 0) {
1278*14414594SDavid du Colombier+ 			if (on < bp->b_validoff || (on + n) > bp->b_validend) {
1279*14414594SDavid du Colombier+ 				bp->b_flags |= B_NOCACHE;
1280*14414594SDavid du Colombier+ 				if (bp->b_dirtyend > 0) {
1281*14414594SDavid du Colombier+ 				    if ((bp->b_flags & B_DELWRI) == 0)
1282*14414594SDavid du Colombier+ 					panic("u9fsbioread");
1283*14414594SDavid du Colombier+ 				    if (VOP_BWRITE(bp) == EINTR)
1284*14414594SDavid du Colombier+ 					return (EINTR);
1285*14414594SDavid du Colombier+ 				} else
1286*14414594SDavid du Colombier+ 				    brelse(bp);
1287*14414594SDavid du Colombier+ 				goto again;
1288*14414594SDavid du Colombier+ 			}
1289*14414594SDavid du Colombier+ 		}
1290*14414594SDavid du Colombier+ 		vp->v_lastr = lbn;
1291*14414594SDavid du Colombier+ 		diff = (on >= bp->b_validend) ? 0 : (bp->b_validend - on);
1292*14414594SDavid du Colombier+ 		if (diff < n)
1293*14414594SDavid du Colombier+ 			n = diff;
1294*14414594SDavid du Colombier+ 		break;
1295*14414594SDavid du Colombier+ 	    case VDIR:
1296*14414594SDavid du Colombier+ 	        biosize = nmp->nm_readdirsize;
1297*14414594SDavid du Colombier+ 		lbn = (uoff_t)uio->uio_offset / biosize;
1298*14414594SDavid du Colombier+ 		on = uio->uio_offset % biosize;
1299*14414594SDavid du Colombier+ 		bp = u9fs_getcacheblk(vp, lbn, biosize, p);
1300*14414594SDavid du Colombier+ 		if (!bp)
1301*14414594SDavid du Colombier+ 		    return (EINTR);
1302*14414594SDavid du Colombier+ 		if ((bp->b_flags & B_CACHE) == 0) {
1303*14414594SDavid du Colombier+ 		    bp->b_flags |= B_READ;
1304*14414594SDavid du Colombier+ 		    vfs_busy_pages(bp, 0);
1305*14414594SDavid du Colombier+ 		    error = u9fs_doio(bp, cred, p);
1306*14414594SDavid du Colombier+ 		    if (error) {
1307*14414594SDavid du Colombier+ 			    brelse(bp);
1308*14414594SDavid du Colombier+ 		    }
1309*14414594SDavid du Colombier+ 		    if (error)
1310*14414594SDavid du Colombier+ 			    return (error);
1311*14414594SDavid du Colombier+ 		    np->n_qid.vers = np->n_dir.dir_qid.vers;
1312*14414594SDavid du Colombier+ 		}
1313*14414594SDavid du Colombier+
1314*14414594SDavid du Colombier+ 		/*
1315*14414594SDavid du Colombier+ 		 * Make sure we use a signed variant of min() since
1316*14414594SDavid du Colombier+ 		 * the second term may be negative.
1317*14414594SDavid du Colombier+ 		 */
1318*14414594SDavid du Colombier+ 		n = lmin(uio->uio_resid, biosize - bp->b_resid - on);
1319*14414594SDavid du Colombier+ 		break;
1320*14414594SDavid du Colombier+ 	    default:
1321*14414594SDavid du Colombier+ 		printf(" u9fs_bioread: type %x unexpected\n",vp->v_type);
1322*14414594SDavid du Colombier+ 		break;
1323*14414594SDavid du Colombier+ 	    };
1324*14414594SDavid du Colombier+
1325*14414594SDavid du Colombier+ 	    if (n > 0) {
1326*14414594SDavid du Colombier+ 		    error = uiomove(bp->b_data + on, (int)n, uio);
1327*14414594SDavid du Colombier+ 	    }
1328*14414594SDavid du Colombier+ 	    brelse(bp);
1329*14414594SDavid du Colombier+ 	} while (error == 0 && uio->uio_resid > 0 && n > 0);
1330*14414594SDavid du Colombier+ 	return (error);
1331*14414594SDavid du Colombier+ }
1332*14414594SDavid du Colombier+
1333*14414594SDavid du Colombier+ /*
1334*14414594SDavid du Colombier+  * Vnode op for write using bio
1335*14414594SDavid du Colombier+  */
1336*14414594SDavid du Colombier+ int
1337*14414594SDavid du Colombier+ u9fs_biowrite(vp, uio, ioflag, cred)
1338*14414594SDavid du Colombier+      register struct vnode *vp;
1339*14414594SDavid du Colombier+      register struct uio *uio;
1340*14414594SDavid du Colombier+      register int  ioflag;
1341*14414594SDavid du Colombier+      register struct ucred *cred;
1342*14414594SDavid du Colombier+ {
1343*14414594SDavid du Colombier+   register int biosize;
1344*14414594SDavid du Colombier+   struct proc *p = uio->uio_procp;
1345*14414594SDavid du Colombier+   struct u9fsnode *np = VTOU9FS(vp);
1346*14414594SDavid du Colombier+   struct buf *bp;
1347*14414594SDavid du Colombier+   struct vattr vattr;
1348*14414594SDavid du Colombier+   struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
1349*14414594SDavid du Colombier+   daddr_t lbn;
1350*14414594SDavid du Colombier+   int bufsize;
1351*14414594SDavid du Colombier+   int n, on, error = 0;
1352*14414594SDavid du Colombier+
1353*14414594SDavid du Colombier+   if (ioflag & (IO_APPEND | IO_SYNC)) {
1354*14414594SDavid du Colombier+     if (ioflag & IO_APPEND) {
1355*14414594SDavid du Colombier+       error = VOP_GETATTR(vp, &vattr, cred, p);
1356*14414594SDavid du Colombier+       if (error)
1357*14414594SDavid du Colombier+ 	return (error);
1358*14414594SDavid du Colombier+       uio->uio_offset = np->n_size;
1359*14414594SDavid du Colombier+     }
1360*14414594SDavid du Colombier+   }
1361*14414594SDavid du Colombier+   if (uio->uio_offset < 0)
1362*14414594SDavid du Colombier+     return (EINVAL);
1363*14414594SDavid du Colombier+   if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
1364*14414594SDavid du Colombier+     return (EFBIG);
1365*14414594SDavid du Colombier+   if (uio->uio_resid == 0)
1366*14414594SDavid du Colombier+     return (0);
1367*14414594SDavid du Colombier+
1368*14414594SDavid du Colombier+ 	/*
1369*14414594SDavid du Colombier+ 	 * I use nm_rsize, not nm_wsize so that all buffer cache blocks
1370*14414594SDavid du Colombier+ 	 * will be the same size within a filesystem. nfs_writerpc will
1371*14414594SDavid du Colombier+ 	 * still use nm_wsize when sizing the rpc's.
1372*14414594SDavid du Colombier+ 	 */
1373*14414594SDavid du Colombier+ 	biosize = vp->v_mount->mnt_stat.f_iosize;
1374*14414594SDavid du Colombier+ 	do {
1375*14414594SDavid du Colombier+ 		lbn = uio->uio_offset / biosize;
1376*14414594SDavid du Colombier+ 		on = uio->uio_offset & (biosize-1);
1377*14414594SDavid du Colombier+ 		n = min((unsigned)(biosize - on), uio->uio_resid);
1378*14414594SDavid du Colombier+ 		if (uio->uio_offset + n > np->n_size) {
1379*14414594SDavid du Colombier+ 			np->n_size = uio->uio_offset + n;
1380*14414594SDavid du Colombier+ 			vnode_pager_setsize(vp, np->n_size);
1381*14414594SDavid du Colombier+ 		}
1382*14414594SDavid du Colombier+ 		bufsize = biosize;
1383*14414594SDavid du Colombier+ 		if ((off_t)(lbn + 1) * biosize > np->n_size) {
1384*14414594SDavid du Colombier+ 			bufsize = np->n_size - (off_t)lbn * biosize;
1385*14414594SDavid du Colombier+ 			bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1386*14414594SDavid du Colombier+ 		}
1387*14414594SDavid du Colombier+ 		bp = u9fs_getcacheblk(vp, lbn, bufsize, p);
1388*14414594SDavid du Colombier+ 		if (!bp)
1389*14414594SDavid du Colombier+ 			return (EINTR);
1390*14414594SDavid du Colombier+ 		if (bp->b_wcred == NOCRED) {
1391*14414594SDavid du Colombier+ 			crhold(cred);
1392*14414594SDavid du Colombier+ 			bp->b_wcred = cred;
1393*14414594SDavid du Colombier+ 		}
1394*14414594SDavid du Colombier+
1395*14414594SDavid du Colombier+ 		error = uiomove((char *)bp->b_data + on, n, uio);
1396*14414594SDavid du Colombier+ 		if (error) {
1397*14414594SDavid du Colombier+ 			bp->b_flags |= B_ERROR;
1398*14414594SDavid du Colombier+ 			brelse(bp);
1399*14414594SDavid du Colombier+ 			return (error);
1400*14414594SDavid du Colombier+ 		}
1401*14414594SDavid du Colombier+
1402*14414594SDavid du Colombier+ 		/*
1403*14414594SDavid du Colombier+ 		 * This will keep the buffer and mmaped regions more coherent.
1404*14414594SDavid du Colombier+ 		 */
1405*14414594SDavid du Colombier+ 		u9fs_prot_buf(bp, on, n);
1406*14414594SDavid du Colombier+ 		bp->b_dirtyoff = on;
1407*14414594SDavid du Colombier+ 		bp->b_dirtyend = on + n;
1408*14414594SDavid du Colombier+
1409*14414594SDavid du Colombier+ 		if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
1410*14414594SDavid du Colombier+ 		    bp->b_validoff > bp->b_dirtyend) {
1411*14414594SDavid du Colombier+ 		  /* XXX: destroys our read cache if not overlapping */
1412*14414594SDavid du Colombier+ 		  /* two choice: none implemented
1413*14414594SDavid du Colombier+ 		     1> keep the bigger(smaller) piece
1414*14414594SDavid du Colombier+ 		     2> read the missing segment
1415*14414594SDavid du Colombier+ 		  */
1416*14414594SDavid du Colombier+ 			bp->b_validoff = bp->b_dirtyoff;
1417*14414594SDavid du Colombier+ 			bp->b_validend = bp->b_dirtyend;
1418*14414594SDavid du Colombier+ 		} else {
1419*14414594SDavid du Colombier+ 			bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
1420*14414594SDavid du Colombier+ 			bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
1421*14414594SDavid du Colombier+ 		}
1422*14414594SDavid du Colombier+
1423*14414594SDavid du Colombier+ 		error = bwrite(bp);
1424*14414594SDavid du Colombier+ 		if( error ) {
1425*14414594SDavid du Colombier+ 		  bp->b_flags |= B_ERROR;
1426*14414594SDavid du Colombier+ 		  /* brelse(bp); */
1427*14414594SDavid du Colombier+ 		  return error;
1428*14414594SDavid du Colombier+ 		}
1429*14414594SDavid du Colombier+ 	} while (uio->uio_resid > 0 && n > 0);
1430*14414594SDavid du Colombier+ 	return 0;
1431*14414594SDavid du Colombier+ }
1432*14414594SDavid du Colombier+
1433*14414594SDavid du Colombier+ /*
1434*14414594SDavid du Colombier+  * Do an I/O operation to/from a cache block. This may be called
1435*14414594SDavid du Colombier+  * synchronously or from an u9fsiod.
1436*14414594SDavid du Colombier+  */
1437*14414594SDavid du Colombier+ int
1438*14414594SDavid du Colombier+ u9fs_doio(bp, cr, p)
1439*14414594SDavid du Colombier+ 	register struct buf *bp;
1440*14414594SDavid du Colombier+ 	struct ucred *cr;
1441*14414594SDavid du Colombier+ 	struct proc *p;
1442*14414594SDavid du Colombier+ {
1443*14414594SDavid du Colombier+ 	register struct uio *uiop;
1444*14414594SDavid du Colombier+ 	register struct vnode *vp;
1445*14414594SDavid du Colombier+ 	struct u9fsnode *np;
1446*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
1447*14414594SDavid du Colombier+ 	int error = 0, diff, len;
1448*14414594SDavid du Colombier+ 	struct uio uio;
1449*14414594SDavid du Colombier+ 	struct iovec io;
1450*14414594SDavid du Colombier+
1451*14414594SDavid du Colombier+ 	vp = bp->b_vp;
1452*14414594SDavid du Colombier+ 	np = VTOU9FS(vp);
1453*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(vp->v_mount);
1454*14414594SDavid du Colombier+ 	uiop = &uio;
1455*14414594SDavid du Colombier+ 	uiop->uio_iov = &io;
1456*14414594SDavid du Colombier+ 	uiop->uio_iovcnt = 1;
1457*14414594SDavid du Colombier+ 	uiop->uio_segflg = UIO_SYSSPACE;
1458*14414594SDavid du Colombier+ 	uiop->uio_procp = p;
1459*14414594SDavid du Colombier+
1460*14414594SDavid du Colombier+ 	if (bp->b_flags & B_READ ) {
1461*14414594SDavid du Colombier+ 	    io.iov_len = uiop->uio_resid = bp->b_bcount;
1462*14414594SDavid du Colombier+ 	    io.iov_base = bp->b_data;
1463*14414594SDavid du Colombier+ 	    uiop->uio_rw = UIO_READ;
1464*14414594SDavid du Colombier+ 	    switch (vp->v_type) {
1465*14414594SDavid du Colombier+ 	    case VREG:
1466*14414594SDavid du Colombier+ 		uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
1467*14414594SDavid du Colombier+ 		error = u9fs_readrpc(vp, uiop, cr);
1468*14414594SDavid du Colombier+ 		if (!error) {
1469*14414594SDavid du Colombier+ 		    bp->b_validoff = 0;
1470*14414594SDavid du Colombier+ 		    if (uiop->uio_resid) {
1471*14414594SDavid du Colombier+ 			/*
1472*14414594SDavid du Colombier+ 			 * If len > 0, there is a hole in the file and
1473*14414594SDavid du Colombier+ 			 * no writes after the hole have been pushed to
1474*14414594SDavid du Colombier+ 			 * the server yet.
1475*14414594SDavid du Colombier+ 			 * Just zero fill the rest of the valid area.
1476*14414594SDavid du Colombier+ 			 */
1477*14414594SDavid du Colombier+ 			diff = bp->b_bcount - uiop->uio_resid;
1478*14414594SDavid du Colombier+ 			len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE
1479*14414594SDavid du Colombier+ 				+ diff);
1480*14414594SDavid du Colombier+ 			if (len > 0) {
1481*14414594SDavid du Colombier+ 			    len = min(len, uiop->uio_resid);
1482*14414594SDavid du Colombier+ 			    bzero((char *)bp->b_data + diff, len);
1483*14414594SDavid du Colombier+ 			    bp->b_validend = diff + len;
1484*14414594SDavid du Colombier+ 			} else
1485*14414594SDavid du Colombier+ 			    bp->b_validend = diff;
1486*14414594SDavid du Colombier+ 		    } else
1487*14414594SDavid du Colombier+ 			bp->b_validend = bp->b_bcount;
1488*14414594SDavid du Colombier+ 		}
1489*14414594SDavid du Colombier+ 		break;
1490*14414594SDavid du Colombier+ 	    case VDIR:
1491*14414594SDavid du Colombier+ 		uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * nmp->nm_readdirsize;
1492*14414594SDavid du Colombier+ 		error = u9fs_readdirrpc(vp, uiop, cr);
1493*14414594SDavid du Colombier+ 		if (error == 0 && uiop->uio_resid == bp->b_bcount)
1494*14414594SDavid du Colombier+ 		  bp->b_flags |= B_INVAL;
1495*14414594SDavid du Colombier+ 		break;
1496*14414594SDavid du Colombier+ 	    default:
1497*14414594SDavid du Colombier+ 		printf("u9fs_doio:  type %x unexpected\n",vp->v_type);
1498*14414594SDavid du Colombier+ 		break;
1499*14414594SDavid du Colombier+ 	    };
1500*14414594SDavid du Colombier+ 	    if (error) {
1501*14414594SDavid du Colombier+ 		bp->b_flags |= B_ERROR;
1502*14414594SDavid du Colombier+ 		bp->b_error = error;
1503*14414594SDavid du Colombier+ 	    }
1504*14414594SDavid du Colombier+ 	} else {
1505*14414594SDavid du Colombier+ 	    if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)
1506*14414594SDavid du Colombier+ 		bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;
1507*14414594SDavid du Colombier+
1508*14414594SDavid du Colombier+ 	    if (bp->b_dirtyend > bp->b_dirtyoff) {
1509*14414594SDavid du Colombier+ 		io.iov_len = uiop->uio_resid = bp->b_dirtyend
1510*14414594SDavid du Colombier+ 		    - bp->b_dirtyoff;
1511*14414594SDavid du Colombier+ 		uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE
1512*14414594SDavid du Colombier+ 		    + bp->b_dirtyoff;
1513*14414594SDavid du Colombier+ 		io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
1514*14414594SDavid du Colombier+ 		uiop->uio_rw = UIO_WRITE;
1515*14414594SDavid du Colombier+ 		bp->b_flags |= B_WRITEINPROG;
1516*14414594SDavid du Colombier+ 		error = u9fs_writerpc(vp, uiop, cr);
1517*14414594SDavid du Colombier+ 		bp->b_flags &= ~B_WRITEINPROG;
1518*14414594SDavid du Colombier+
1519*14414594SDavid du Colombier+ 		if (error) {
1520*14414594SDavid du Colombier+ 		  bp->b_flags |= B_ERROR;
1521*14414594SDavid du Colombier+ 		  bp->b_error = np->n_error = error;
1522*14414594SDavid du Colombier+ 		  np->n_flag |= NWRITEERR;
1523*14414594SDavid du Colombier+ 		}
1524*14414594SDavid du Colombier+ 		bp->b_dirtyoff = bp->b_dirtyend = 0;
1525*14414594SDavid du Colombier+ 	    } else {
1526*14414594SDavid du Colombier+ 		bp->b_resid = 0;
1527*14414594SDavid du Colombier+ 		biodone(bp);
1528*14414594SDavid du Colombier+ 		return (0);
1529*14414594SDavid du Colombier+ 	    }
1530*14414594SDavid du Colombier+ 	}
1531*14414594SDavid du Colombier+ 	bp->b_resid = uiop->uio_resid;
1532*14414594SDavid du Colombier+ 	biodone(bp);
1533*14414594SDavid du Colombier+ 	return error;
1534*14414594SDavid du Colombier+ }
1535*14414594SDavid du Colombier+
1536*14414594SDavid du Colombier+ /*
1537*14414594SDavid du Colombier+  * Get an u9fs cache block.
1538*14414594SDavid du Colombier+  * Allocate a new one if the block isn't currently in the cache
1539*14414594SDavid du Colombier+  * and return the block marked busy. If the calling process is
1540*14414594SDavid du Colombier+  * interrupted by a signal for an interruptible mount point, return
1541*14414594SDavid du Colombier+  * NULL.
1542*14414594SDavid du Colombier+  */
1543*14414594SDavid du Colombier+ static struct buf *
1544*14414594SDavid du Colombier+ u9fs_getcacheblk(vp, bn, size, p)
1545*14414594SDavid du Colombier+ 	struct vnode *vp;
1546*14414594SDavid du Colombier+ 	daddr_t bn;
1547*14414594SDavid du Colombier+ 	int size;
1548*14414594SDavid du Colombier+ 	struct proc *p;
1549*14414594SDavid du Colombier+ {
1550*14414594SDavid du Colombier+ 	register struct buf *bp;
1551*14414594SDavid du Colombier+ 	struct mount *mp;
1552*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
1553*14414594SDavid du Colombier+
1554*14414594SDavid du Colombier+ 	mp = vp->v_mount;
1555*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(mp);
1556*14414594SDavid du Colombier+
1557*14414594SDavid du Colombier+ 	if (nmp->nm_flag & U9FSMNT_INT) {
1558*14414594SDavid du Colombier+ 		bp = getblk(vp, bn, size, PCATCH, 0);
1559*14414594SDavid du Colombier+ 		while (bp == (struct buf *)0) {
1560*14414594SDavid du Colombier+ 			if (u9fs_sigintr(nmp, p))
1561*14414594SDavid du Colombier+ 				return ((struct buf *)0);
1562*14414594SDavid du Colombier+ 			bp = getblk(vp, bn, size, 0, 2 * hz);
1563*14414594SDavid du Colombier+ 		}
1564*14414594SDavid du Colombier+ 	} else
1565*14414594SDavid du Colombier+ 		bp = getblk(vp, bn, size, 0, 0);
1566*14414594SDavid du Colombier+
1567*14414594SDavid du Colombier+ 	if (vp->v_type == VREG) {
1568*14414594SDavid du Colombier+ 		int biosize;
1569*14414594SDavid du Colombier+ 		biosize = mp->mnt_stat.f_iosize;
1570*14414594SDavid du Colombier+ 		bp->b_blkno = bn * (biosize / DEV_BSIZE);
1571*14414594SDavid du Colombier+ 	}
1572*14414594SDavid du Colombier+
1573*14414594SDavid du Colombier+ 	return (bp);
1574*14414594SDavid du Colombier+ }
1575*14414594SDavid du Colombier+
1576*14414594SDavid du Colombier+ static void
1577*14414594SDavid du Colombier+ u9fs_prot_buf(bp, off, n)
1578*14414594SDavid du Colombier+ 	struct buf *bp;
1579*14414594SDavid du Colombier+ 	int off;
1580*14414594SDavid du Colombier+ 	int n;
1581*14414594SDavid du Colombier+ {
1582*14414594SDavid du Colombier+ 	int pindex, boff, end;
1583*14414594SDavid du Colombier+
1584*14414594SDavid du Colombier+ 	if ((bp->b_flags & B_VMIO) == 0)
1585*14414594SDavid du Colombier+ 		return;
1586*14414594SDavid du Colombier+
1587*14414594SDavid du Colombier+ 	end = round_page(off + n);
1588*14414594SDavid du Colombier+ 	for (boff = trunc_page(off); boff < end; boff += PAGE_SIZE) {
1589*14414594SDavid du Colombier+ 		pindex = boff >> PAGE_SHIFT;
1590*14414594SDavid du Colombier+ 		vm_page_protect(bp->b_pages[pindex], VM_PROT_NONE);
1591*14414594SDavid du Colombier+ 	}
1592*14414594SDavid du Colombier+ }
1593*14414594SDavid du Colombier+
1594*14414594SDavid du Colombier+ /*
1595*14414594SDavid du Colombier+  * Flush and invalidate all dirty buffers. If another process is already
1596*14414594SDavid du Colombier+  * doing the flush, just wait for completion.
1597*14414594SDavid du Colombier+  */
1598*14414594SDavid du Colombier+ int
1599*14414594SDavid du Colombier+ u9fs_vinvalbuf(vp, flags, cred, p, intrflg)
1600*14414594SDavid du Colombier+ 	struct vnode *vp;
1601*14414594SDavid du Colombier+ 	int flags;
1602*14414594SDavid du Colombier+ 	struct ucred *cred;
1603*14414594SDavid du Colombier+ 	struct proc *p;
1604*14414594SDavid du Colombier+ 	int intrflg;
1605*14414594SDavid du Colombier+ {
1606*14414594SDavid du Colombier+ 	register struct u9fsnode *np = VTOU9FS(vp);
1607*14414594SDavid du Colombier+ 	struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
1608*14414594SDavid du Colombier+ 	int error = 0, slpflag, slptimeo;
1609*14414594SDavid du Colombier+
1610*14414594SDavid du Colombier+ 	if (vp->v_flag & VXLOCK) {
1611*14414594SDavid du Colombier+ 		return (0);
1612*14414594SDavid du Colombier+ 	}
1613*14414594SDavid du Colombier+
1614*14414594SDavid du Colombier+ 	if ((nmp->nm_flag & U9FSMNT_INT) == 0)
1615*14414594SDavid du Colombier+ 		intrflg = 0;
1616*14414594SDavid du Colombier+ 	if (intrflg) {
1617*14414594SDavid du Colombier+ 		slpflag = PCATCH;
1618*14414594SDavid du Colombier+ 		slptimeo = 2 * hz;
1619*14414594SDavid du Colombier+ 	} else {
1620*14414594SDavid du Colombier+ 		slpflag = 0;
1621*14414594SDavid du Colombier+ 		slptimeo = 0;
1622*14414594SDavid du Colombier+ 	}
1623*14414594SDavid du Colombier+ 	/*
1624*14414594SDavid du Colombier+ 	 * First wait for any other process doing a flush to complete.
1625*14414594SDavid du Colombier+ 	 */
1626*14414594SDavid du Colombier+ 	while (np->n_flag & NFLUSHINPROG) {
1627*14414594SDavid du Colombier+ 		np->n_flag |= NFLUSHWANT;
1628*14414594SDavid du Colombier+ 		error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "u9fsvinval",
1629*14414594SDavid du Colombier+ 			slptimeo);
1630*14414594SDavid du Colombier+ 		if (error && intrflg && u9fs_sigintr(nmp, p))
1631*14414594SDavid du Colombier+ 			return (EINTR);
1632*14414594SDavid du Colombier+ 	}
1633*14414594SDavid du Colombier+
1634*14414594SDavid du Colombier+ 	/*
1635*14414594SDavid du Colombier+ 	 * Now, flush as required.
1636*14414594SDavid du Colombier+ 	 */
1637*14414594SDavid du Colombier+ 	np->n_flag |= NFLUSHINPROG;
1638*14414594SDavid du Colombier+ 	error = vinvalbuf(vp, flags, cred, p, slpflag, 0);
1639*14414594SDavid du Colombier+ 	while (error) {
1640*14414594SDavid du Colombier+ 		if (intrflg && u9fs_sigintr(nmp, p)) {
1641*14414594SDavid du Colombier+ 			np->n_flag &= ~NFLUSHINPROG;
1642*14414594SDavid du Colombier+ 			if (np->n_flag & NFLUSHWANT) {
1643*14414594SDavid du Colombier+ 				np->n_flag &= ~NFLUSHWANT;
1644*14414594SDavid du Colombier+ 				wakeup((caddr_t)&np->n_flag);
1645*14414594SDavid du Colombier+ 			}
1646*14414594SDavid du Colombier+ 			return (EINTR);
1647*14414594SDavid du Colombier+ 		}
1648*14414594SDavid du Colombier+ 		error = vinvalbuf(vp, flags, cred, p, 0, slptimeo);
1649*14414594SDavid du Colombier+ 	}
1650*14414594SDavid du Colombier+ 	np->n_flag &= ~(NMODIFIED | NFLUSHINPROG);
1651*14414594SDavid du Colombier+ 	if (np->n_flag & NFLUSHWANT) {
1652*14414594SDavid du Colombier+ 		np->n_flag &= ~NFLUSHWANT;
1653*14414594SDavid du Colombier+ 		wakeup((caddr_t)&np->n_flag);
1654*14414594SDavid du Colombier+ 	}
1655*14414594SDavid du Colombier+ 	return (0);
1656*14414594SDavid du Colombier+ }
1657*14414594SDavid du Colombier+
1658*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_node.c ./9fs/9fs_node.c
1659*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_node.c	Wed Dec 31 19:00:00 1969
1660*14414594SDavid du Colombier--- ./9fs/9fs_node.c	Thu Nov 25 15:36:49 1999
1661*14414594SDavid du Colombier***************
1662*14414594SDavid du Colombier*** 0 ****
1663*14414594SDavid du Colombier--- 1,132 ----
1664*14414594SDavid du Colombier+ #include <sys/param.h>
1665*14414594SDavid du Colombier+ #include <sys/sockio.h>
1666*14414594SDavid du Colombier+ #include <sys/proc.h>
1667*14414594SDavid du Colombier+ #include <sys/vnode.h>
1668*14414594SDavid du Colombier+ #include <sys/kernel.h>
1669*14414594SDavid du Colombier+ #include <sys/sysctl.h>
1670*14414594SDavid du Colombier+ #include <sys/malloc.h>
1671*14414594SDavid du Colombier+ #include <sys/mount.h>
1672*14414594SDavid du Colombier+ #include <sys/mbuf.h>
1673*14414594SDavid du Colombier+ #include <sys/socket.h>
1674*14414594SDavid du Colombier+ #include <sys/socketvar.h>
1675*14414594SDavid du Colombier+ #include <sys/systm.h>
1676*14414594SDavid du Colombier+ #include <sys/protosw.h>
1677*14414594SDavid du Colombier+ #include <sys/syslog.h>
1678*14414594SDavid du Colombier+
1679*14414594SDavid du Colombier+ #include <netinet/in.h>
1680*14414594SDavid du Colombier+ #include <netinet/tcp.h>
1681*14414594SDavid du Colombier+
1682*14414594SDavid du Colombier+ #include <vm/vm.h>
1683*14414594SDavid du Colombier+ #include <vm/vm_extern.h>
1684*14414594SDavid du Colombier+ #include <vm/vm_zone.h>
1685*14414594SDavid du Colombier+
1686*14414594SDavid du Colombier+ #include <net/if.h>
1687*14414594SDavid du Colombier+ #include <net/route.h>
1688*14414594SDavid du Colombier+ #include <netinet/in.h>
1689*14414594SDavid du Colombier+
1690*14414594SDavid du Colombier+ #include <9fs/bitstring.h>
1691*14414594SDavid du Colombier+ #include <9fs/9p.h>
1692*14414594SDavid du Colombier+ #include <9fs/9auth.h>
1693*14414594SDavid du Colombier+ #include <9fs/9fs.h>
1694*14414594SDavid du Colombier+
1695*14414594SDavid du Colombier+ vm_zone_t u9fsnode_zone;
1696*14414594SDavid du Colombier+ static LIST_HEAD(u9fsnodehashhead, u9fsnode) *u9fsnodehashtbl;
1697*14414594SDavid du Colombier+ static u_long u9fsnodehash;
1698*14414594SDavid du Colombier+ MALLOC_DEFINE(M_U9FSHASH, "U9FS hash", "U9FS hash tables");
1699*14414594SDavid du Colombier+
1700*14414594SDavid du Colombier+ /*
1701*14414594SDavid du Colombier+  * Initialize hash links for u9fsnodes
1702*14414594SDavid du Colombier+  * and build u9fsnode free list.
1703*14414594SDavid du Colombier+  */
1704*14414594SDavid du Colombier+ void
1705*14414594SDavid du Colombier+ u9fs_nhinit()
1706*14414594SDavid du Colombier+ {
1707*14414594SDavid du Colombier+   u9fsnode_zone = zinit("U9FSNODE", sizeof(struct u9fsnode), 0, 0, 1);
1708*14414594SDavid du Colombier+   u9fsnodehashtbl = phashinit(desiredvnodes, M_U9FSHASH, &u9fsnodehash);
1709*14414594SDavid du Colombier+ }
1710*14414594SDavid du Colombier+
1711*14414594SDavid du Colombier+ /*
1712*14414594SDavid du Colombier+  * Look up a vnode/u9fsnode by file handle.
1713*14414594SDavid du Colombier+  * Callers must check for mount points!!
1714*14414594SDavid du Colombier+  * In all cases, a pointer to a
1715*14414594SDavid du Colombier+  * u9fsnode structure is returned.
1716*14414594SDavid du Colombier+  */
1717*14414594SDavid du Colombier+ static int u9fs_node_hash_lock;
1718*14414594SDavid du Colombier+
1719*14414594SDavid du Colombier+ int
1720*14414594SDavid du Colombier+ u9fs_nget(mntp, fh, npp, p)
1721*14414594SDavid du Colombier+      struct mount *mntp;
1722*14414594SDavid du Colombier+      register u9fsfh_t fh;
1723*14414594SDavid du Colombier+      struct u9fsnode **npp;
1724*14414594SDavid du Colombier+      struct proc * p;
1725*14414594SDavid du Colombier+ {
1726*14414594SDavid du Colombier+   struct u9fsnode *np;
1727*14414594SDavid du Colombier+   struct u9fsnodehashhead *nhpp;
1728*14414594SDavid du Colombier+   register struct vnode *vp;
1729*14414594SDavid du Colombier+   struct vnode *nvp;
1730*14414594SDavid du Colombier+   int error;
1731*14414594SDavid du Colombier+
1732*14414594SDavid du Colombier+   nhpp = U9FSNOHASH(fh);
1733*14414594SDavid du Colombier+ loop:
1734*14414594SDavid du Colombier+   for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
1735*14414594SDavid du Colombier+     if (mntp != U9FSTOV(np)->v_mount || fh != np->n_qid.path )
1736*14414594SDavid du Colombier+       continue;
1737*14414594SDavid du Colombier+     vp = U9FSTOV(np);
1738*14414594SDavid du Colombier+     if (vget(vp, LK_EXCLUSIVE, p))
1739*14414594SDavid du Colombier+       goto loop;
1740*14414594SDavid du Colombier+     *npp = np;
1741*14414594SDavid du Colombier+     return(0);
1742*14414594SDavid du Colombier+   }
1743*14414594SDavid du Colombier+   /*
1744*14414594SDavid du Colombier+    * Obtain a lock to prevent a race condition if the getnewvnode()
1745*14414594SDavid du Colombier+    * or MALLOC() below happens to block.
1746*14414594SDavid du Colombier+    */
1747*14414594SDavid du Colombier+   if (u9fs_node_hash_lock) {
1748*14414594SDavid du Colombier+     while (u9fs_node_hash_lock) {
1749*14414594SDavid du Colombier+       u9fs_node_hash_lock = -1;
1750*14414594SDavid du Colombier+       tsleep(&u9fs_node_hash_lock, PVM, "u9fsngt", 0);
1751*14414594SDavid du Colombier+     }
1752*14414594SDavid du Colombier+     goto loop;
1753*14414594SDavid du Colombier+   }
1754*14414594SDavid du Colombier+   u9fs_node_hash_lock = 1;
1755*14414594SDavid du Colombier+
1756*14414594SDavid du Colombier+   /*
1757*14414594SDavid du Colombier+    * allocate before getnewvnode since doing so afterward
1758*14414594SDavid du Colombier+    * might cause a bogus v_data pointer to get dereferenced
1759*14414594SDavid du Colombier+    * elsewhere if zalloc should block.
1760*14414594SDavid du Colombier+    */
1761*14414594SDavid du Colombier+   np = zalloc(u9fsnode_zone);
1762*14414594SDavid du Colombier+
1763*14414594SDavid du Colombier+   error = getnewvnode(VT_U9FS, mntp, u9fs_vnodeop_p, &nvp);
1764*14414594SDavid du Colombier+   if (error) {
1765*14414594SDavid du Colombier+     if (u9fs_node_hash_lock < 0)
1766*14414594SDavid du Colombier+       wakeup(&u9fs_node_hash_lock);
1767*14414594SDavid du Colombier+     u9fs_node_hash_lock = 0;
1768*14414594SDavid du Colombier+     *npp = 0;
1769*14414594SDavid du Colombier+     zfree(u9fsnode_zone, np);
1770*14414594SDavid du Colombier+     return (error);
1771*14414594SDavid du Colombier+   }
1772*14414594SDavid du Colombier+   vp = nvp;
1773*14414594SDavid du Colombier+   bzero((caddr_t)np, sizeof *np);
1774*14414594SDavid du Colombier+   vp->v_data = np;
1775*14414594SDavid du Colombier+   np->n_vnode = vp;
1776*14414594SDavid du Colombier+   /*
1777*14414594SDavid du Colombier+    * Insert the u9fsnode in the hash queue for its new file handle
1778*14414594SDavid du Colombier+    */
1779*14414594SDavid du Colombier+   LIST_INSERT_HEAD(nhpp, np, n_hash);
1780*14414594SDavid du Colombier+   np->n_qid.path = fh;
1781*14414594SDavid du Colombier+   np->n_qid.vers = 0; /* not in cache yet */
1782*14414594SDavid du Colombier+   np->n_fid = 0; /* should be set by the caller */
1783*14414594SDavid du Colombier+   *npp = np;
1784*14414594SDavid du Colombier+
1785*14414594SDavid du Colombier+   if (u9fs_node_hash_lock < 0)
1786*14414594SDavid du Colombier+     wakeup(&u9fs_node_hash_lock);
1787*14414594SDavid du Colombier+   u9fs_node_hash_lock = 0;
1788*14414594SDavid du Colombier+
1789*14414594SDavid du Colombier+   /*
1790*14414594SDavid du Colombier+    * Lock the new u9fsnode.
1791*14414594SDavid du Colombier+    */
1792*14414594SDavid du Colombier+   vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1793*14414594SDavid du Colombier+
1794*14414594SDavid du Colombier+   return (0);
1795*14414594SDavid du Colombier+ }
1796*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_socket.c ./9fs/9fs_socket.c
1797*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_socket.c	Wed Dec 31 19:00:00 1969
1798*14414594SDavid du Colombier--- ./9fs/9fs_socket.c	Thu Nov 25 15:48:46 1999
1799*14414594SDavid du Colombier***************
1800*14414594SDavid du Colombier*** 0 ****
1801*14414594SDavid du Colombier--- 1,503 ----
1802*14414594SDavid du Colombier+ #include <sys/param.h>
1803*14414594SDavid du Colombier+ #include <sys/sockio.h>
1804*14414594SDavid du Colombier+ #include <sys/proc.h>
1805*14414594SDavid du Colombier+ #include <sys/vnode.h>
1806*14414594SDavid du Colombier+ #include <sys/kernel.h>
1807*14414594SDavid du Colombier+ #include <sys/sysctl.h>
1808*14414594SDavid du Colombier+ #include <sys/malloc.h>
1809*14414594SDavid du Colombier+ #include <sys/mount.h>
1810*14414594SDavid du Colombier+ #include <sys/mbuf.h>
1811*14414594SDavid du Colombier+ #include <sys/socket.h>
1812*14414594SDavid du Colombier+ #include <sys/socketvar.h>
1813*14414594SDavid du Colombier+ #include <sys/systm.h>
1814*14414594SDavid du Colombier+ #include <sys/protosw.h>
1815*14414594SDavid du Colombier+ #include <sys/syslog.h>
1816*14414594SDavid du Colombier+
1817*14414594SDavid du Colombier+ #include <netinet/in.h>
1818*14414594SDavid du Colombier+ #include <netinet/tcp.h>
1819*14414594SDavid du Colombier+
1820*14414594SDavid du Colombier+ #include <vm/vm.h>
1821*14414594SDavid du Colombier+ #include <vm/vm_extern.h>
1822*14414594SDavid du Colombier+ #include <vm/vm_zone.h>
1823*14414594SDavid du Colombier+
1824*14414594SDavid du Colombier+ #include <net/if.h>
1825*14414594SDavid du Colombier+ #include <net/route.h>
1826*14414594SDavid du Colombier+ #include <netinet/in.h>
1827*14414594SDavid du Colombier+
1828*14414594SDavid du Colombier+ #include <9fs/bitstring.h>
1829*14414594SDavid du Colombier+ #include <9fs/9p.h>
1830*14414594SDavid du Colombier+ #include <9fs/9auth.h>
1831*14414594SDavid du Colombier+ #include <9fs/9fs.h>
1832*14414594SDavid du Colombier+
1833*14414594SDavid du Colombier+ static int u9fs_reply __P((struct u9fsreq * req));
1834*14414594SDavid du Colombier+ static int u9fs_send __P((struct socket * so, struct mbuf * mreq, struct u9fsreq * req));
1835*14414594SDavid du Colombier+ static int u9fs_receive __P((struct socket * so, struct mbuf **mrep, struct u9fsreq * req));
1836*14414594SDavid du Colombier+
1837*14414594SDavid du Colombier+ static int u9fs_sndlock __P((int *flagp, int *statep, struct u9fsreq *rep));
1838*14414594SDavid du Colombier+ static void u9fs_sndunlock __P((int *flagp, int *statep));
1839*14414594SDavid du Colombier+ static int u9fs_rcvlock __P((struct u9fsreq *req));
1840*14414594SDavid du Colombier+ static void u9fs_rcvunlock __P((int *flagp, int *statep));
1841*14414594SDavid du Colombier+
1842*14414594SDavid du Colombier+ int
1843*14414594SDavid du Colombier+ u9fs_connect(struct socket ** sop, struct sockaddr * saddr, int sotype, int soproto, struct proc * p)
1844*14414594SDavid du Colombier+ {
1845*14414594SDavid du Colombier+   register struct socket * so;
1846*14414594SDavid du Colombier+   int error, s;
1847*14414594SDavid du Colombier+
1848*14414594SDavid du Colombier+   *sop = 0;
1849*14414594SDavid du Colombier+   error = socreate(saddr->sa_family, sop, sotype, soproto, p);
1850*14414594SDavid du Colombier+   if( error )
1851*14414594SDavid du Colombier+     return error;
1852*14414594SDavid du Colombier+   so = *sop;
1853*14414594SDavid du Colombier+   error = soconnect(so, saddr, p);
1854*14414594SDavid du Colombier+   if( error )
1855*14414594SDavid du Colombier+     return error;
1856*14414594SDavid du Colombier+
1857*14414594SDavid du Colombier+   /*
1858*14414594SDavid du Colombier+    * Wait for the connection to complete. Cribbed from the
1859*14414594SDavid du Colombier+    * connect system call but with the wait timing out so
1860*14414594SDavid du Colombier+    * that interruptible mounts don't hang here for a long time.
1861*14414594SDavid du Colombier+    */
1862*14414594SDavid du Colombier+   s = splnet();
1863*14414594SDavid du Colombier+   while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
1864*14414594SDavid du Colombier+     (void) tsleep((caddr_t)&so->so_timeo, PSOCK,
1865*14414594SDavid du Colombier+ 		  "u9fscon", 2 * hz);
1866*14414594SDavid du Colombier+
1867*14414594SDavid du Colombier+   if (so->so_error) {
1868*14414594SDavid du Colombier+     error = so->so_error;
1869*14414594SDavid du Colombier+     so->so_error = 0;
1870*14414594SDavid du Colombier+     splx(s);
1871*14414594SDavid du Colombier+     return error;
1872*14414594SDavid du Colombier+   }
1873*14414594SDavid du Colombier+   splx(s);
1874*14414594SDavid du Colombier+
1875*14414594SDavid du Colombier+   return (0);
1876*14414594SDavid du Colombier+ }
1877*14414594SDavid du Colombier+
1878*14414594SDavid du Colombier+ int u9fs_connect_9auth(struct u9fsmount * nmp, struct u9fs_args * argp, struct socket ** sop)
1879*14414594SDavid du Colombier+ {
1880*14414594SDavid du Colombier+   int error;
1881*14414594SDavid du Colombier+   struct proc * p = & proc0;
1882*14414594SDavid du Colombier+   struct sockaddr *nam;
1883*14414594SDavid du Colombier+
1884*14414594SDavid du Colombier+   error = getsockaddr(&nam, (caddr_t)argp->authaddr, argp->authaddrlen);
1885*14414594SDavid du Colombier+   if( error )
1886*14414594SDavid du Colombier+     return error;
1887*14414594SDavid du Colombier+   error = u9fs_connect(sop, nam, argp->authsotype,
1888*14414594SDavid du Colombier+ 		       argp->authsoproto, p);
1889*14414594SDavid du Colombier+   if( error == 0 )
1890*14414594SDavid du Colombier+     return 0;
1891*14414594SDavid du Colombier+
1892*14414594SDavid du Colombier+   u9fs_disconnect(*sop);
1893*14414594SDavid du Colombier+   *sop = 0;
1894*14414594SDavid du Colombier+   return error;
1895*14414594SDavid du Colombier+ }
1896*14414594SDavid du Colombier+
1897*14414594SDavid du Colombier+ /*
1898*14414594SDavid du Colombier+  * Initialize sockets and congestion for a new U9FS connection.
1899*14414594SDavid du Colombier+  * We do not free the sockaddr if error.
1900*14414594SDavid du Colombier+  */
1901*14414594SDavid du Colombier+ int
1902*14414594SDavid du Colombier+ u9fs_connect_9fs(nmp)
1903*14414594SDavid du Colombier+      register struct u9fsmount *nmp;
1904*14414594SDavid du Colombier+ {
1905*14414594SDavid du Colombier+   register struct socket *so;
1906*14414594SDavid du Colombier+   int error, rcvreserve, sndreserve;
1907*14414594SDavid du Colombier+   struct proc *p = &proc0; /* only used for socreate and sobind */
1908*14414594SDavid du Colombier+
1909*14414594SDavid du Colombier+   error = u9fs_connect(&nmp->nm_so, nmp->nm_nam, nmp->nm_sotype,
1910*14414594SDavid du Colombier+ 		       nmp->nm_soproto, p);
1911*14414594SDavid du Colombier+   if (error)
1912*14414594SDavid du Colombier+     goto bad;
1913*14414594SDavid du Colombier+   so = nmp->nm_so;
1914*14414594SDavid du Colombier+   nmp->nm_soflags = so->so_proto->pr_flags;
1915*14414594SDavid du Colombier+
1916*14414594SDavid du Colombier+   if (nmp->nm_flag & (U9FSMNT_SOFT | U9FSMNT_INT)) {
1917*14414594SDavid du Colombier+     so->so_rcv.sb_timeo = (5 * hz);
1918*14414594SDavid du Colombier+     so->so_snd.sb_timeo = (5 * hz);
1919*14414594SDavid du Colombier+   } else {
1920*14414594SDavid du Colombier+     so->so_rcv.sb_timeo = 0;
1921*14414594SDavid du Colombier+     so->so_snd.sb_timeo = 0;
1922*14414594SDavid du Colombier+   }
1923*14414594SDavid du Colombier+
1924*14414594SDavid du Colombier+   /* XXX: i dont understand this, only one outstanding request? */
1925*14414594SDavid du Colombier+   if (nmp->nm_sotype == SOCK_SEQPACKET) {
1926*14414594SDavid du Colombier+     sndreserve = (nmp->nm_wsize) * 2;
1927*14414594SDavid du Colombier+     rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize)) * 2;
1928*14414594SDavid du Colombier+   } else {
1929*14414594SDavid du Colombier+     if (nmp->nm_sotype != SOCK_STREAM)
1930*14414594SDavid du Colombier+       panic("u9fscon sotype");
1931*14414594SDavid du Colombier+     if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
1932*14414594SDavid du Colombier+       struct sockopt sopt;
1933*14414594SDavid du Colombier+       int val;
1934*14414594SDavid du Colombier+
1935*14414594SDavid du Colombier+       bzero(&sopt, sizeof sopt);
1936*14414594SDavid du Colombier+       sopt.sopt_level = SOL_SOCKET;
1937*14414594SDavid du Colombier+       sopt.sopt_name = SO_KEEPALIVE;
1938*14414594SDavid du Colombier+       sopt.sopt_val = &val;
1939*14414594SDavid du Colombier+       sopt.sopt_valsize = sizeof val;
1940*14414594SDavid du Colombier+       val = 1;
1941*14414594SDavid du Colombier+       sosetopt(so, &sopt);
1942*14414594SDavid du Colombier+     }
1943*14414594SDavid du Colombier+     if (so->so_proto->pr_protocol == IPPROTO_TCP) {
1944*14414594SDavid du Colombier+       struct sockopt sopt;
1945*14414594SDavid du Colombier+       int val;
1946*14414594SDavid du Colombier+
1947*14414594SDavid du Colombier+       bzero(&sopt, sizeof sopt);
1948*14414594SDavid du Colombier+       sopt.sopt_level = IPPROTO_TCP;
1949*14414594SDavid du Colombier+       sopt.sopt_name = TCP_NODELAY;
1950*14414594SDavid du Colombier+       sopt.sopt_val = &val;
1951*14414594SDavid du Colombier+       sopt.sopt_valsize = sizeof val;
1952*14414594SDavid du Colombier+       val = 1;
1953*14414594SDavid du Colombier+       sosetopt(so, &sopt);
1954*14414594SDavid du Colombier+     }
1955*14414594SDavid du Colombier+     sndreserve = (nmp->nm_wsize) * 2;
1956*14414594SDavid du Colombier+     rcvreserve = (nmp->nm_rsize) * 2;
1957*14414594SDavid du Colombier+   }
1958*14414594SDavid du Colombier+   error = soreserve(so, sndreserve, rcvreserve);
1959*14414594SDavid du Colombier+   if (error)
1960*14414594SDavid du Colombier+     goto bad;
1961*14414594SDavid du Colombier+   so->so_rcv.sb_flags |= SB_NOINTR;
1962*14414594SDavid du Colombier+   so->so_snd.sb_flags |= SB_NOINTR;
1963*14414594SDavid du Colombier+
1964*14414594SDavid du Colombier+   /* Initialize other non-zero congestion variables */
1965*14414594SDavid du Colombier+   nmp->nm_sent = 0;
1966*14414594SDavid du Colombier+   return (0);
1967*14414594SDavid du Colombier+
1968*14414594SDavid du Colombier+ bad:
1969*14414594SDavid du Colombier+   u9fs_disconnect(nmp->nm_so);
1970*14414594SDavid du Colombier+   nmp->nm_so = 0;
1971*14414594SDavid du Colombier+   return (error);
1972*14414594SDavid du Colombier+ }
1973*14414594SDavid du Colombier+
1974*14414594SDavid du Colombier+ /*
1975*14414594SDavid du Colombier+  * U9FS disconnect. Clean up and unlink.
1976*14414594SDavid du Colombier+  */
1977*14414594SDavid du Colombier+ void
1978*14414594SDavid du Colombier+ u9fs_disconnect(struct socket * so)
1979*14414594SDavid du Colombier+ {
1980*14414594SDavid du Colombier+     soshutdown(so, 2);
1981*14414594SDavid du Colombier+     soclose(so);
1982*14414594SDavid du Colombier+ }
1983*14414594SDavid du Colombier+
1984*14414594SDavid du Colombier+ /*
1985*14414594SDavid du Colombier+  * Lock a socket against others.
1986*14414594SDavid du Colombier+  * Necessary for STREAM sockets to ensure you get an entire rpc request/reply
1987*14414594SDavid du Colombier+  * and also to avoid race conditions between the processes with u9fs requests
1988*14414594SDavid du Colombier+  * in progress when a reconnect is necessary.
1989*14414594SDavid du Colombier+  */
1990*14414594SDavid du Colombier+ static int
1991*14414594SDavid du Colombier+ u9fs_sndlock(flagp, statep, rep)
1992*14414594SDavid du Colombier+ 	register int *flagp;
1993*14414594SDavid du Colombier+ 	register int *statep;
1994*14414594SDavid du Colombier+ 	struct u9fsreq *rep;
1995*14414594SDavid du Colombier+ {
1996*14414594SDavid du Colombier+ 	struct proc *p;
1997*14414594SDavid du Colombier+ 	int slpflag = 0, slptimeo = 0;
1998*14414594SDavid du Colombier+
1999*14414594SDavid du Colombier+ 	if (rep) {
2000*14414594SDavid du Colombier+ 		p = rep->r_procp;
2001*14414594SDavid du Colombier+ 		if (rep->r_nmp->nm_flag & U9FSMNT_INT)
2002*14414594SDavid du Colombier+ 			slpflag = PCATCH;
2003*14414594SDavid du Colombier+ 	} else
2004*14414594SDavid du Colombier+ 		p = (struct proc *)0;
2005*14414594SDavid du Colombier+ 	while (*statep & U9FSSTA_SNDLOCK) {
2006*14414594SDavid du Colombier+ 		if (u9fs_sigintr(rep->r_nmp, p))
2007*14414594SDavid du Colombier+ 			return (EINTR);
2008*14414594SDavid du Colombier+ 		*statep |= U9FSSTA_WANTSND;
2009*14414594SDavid du Colombier+ 		(void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1),
2010*14414594SDavid du Colombier+ 			"u9fsndlck", slptimeo);
2011*14414594SDavid du Colombier+ 		if (slpflag == PCATCH) {
2012*14414594SDavid du Colombier+ 			slpflag = 0;
2013*14414594SDavid du Colombier+ 			slptimeo = 2 * hz;
2014*14414594SDavid du Colombier+ 		}
2015*14414594SDavid du Colombier+ 	}
2016*14414594SDavid du Colombier+ 	*statep |= U9FSSTA_SNDLOCK;
2017*14414594SDavid du Colombier+ 	return (0);
2018*14414594SDavid du Colombier+ }
2019*14414594SDavid du Colombier+
2020*14414594SDavid du Colombier+
2021*14414594SDavid du Colombier+ /*
2022*14414594SDavid du Colombier+  * Unlock the stream socket for others.
2023*14414594SDavid du Colombier+  */
2024*14414594SDavid du Colombier+ static void
2025*14414594SDavid du Colombier+ u9fs_sndunlock(flagp, statep)
2026*14414594SDavid du Colombier+ 	register int *flagp;
2027*14414594SDavid du Colombier+ 	register int *statep;
2028*14414594SDavid du Colombier+ {
2029*14414594SDavid du Colombier+
2030*14414594SDavid du Colombier+ 	if ((*statep & U9FSSTA_SNDLOCK) == 0)
2031*14414594SDavid du Colombier+ 		panic("u9fs sndunlock");
2032*14414594SDavid du Colombier+ 	*statep &= ~U9FSSTA_SNDLOCK;
2033*14414594SDavid du Colombier+ 	if (*statep & U9FSSTA_WANTSND) {
2034*14414594SDavid du Colombier+ 		*statep &= ~U9FSSTA_WANTSND;
2035*14414594SDavid du Colombier+ 		wakeup((caddr_t)flagp);
2036*14414594SDavid du Colombier+ 	}
2037*14414594SDavid du Colombier+ }
2038*14414594SDavid du Colombier+
2039*14414594SDavid du Colombier+ /*
2040*14414594SDavid du Colombier+  * Test for a termination condition pending on the process.
2041*14414594SDavid du Colombier+  * This is used for U9FSMNT_INT mounts.
2042*14414594SDavid du Colombier+  */
2043*14414594SDavid du Colombier+ int
2044*14414594SDavid du Colombier+ u9fs_sigintr(nmp, p)
2045*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
2046*14414594SDavid du Colombier+ 	struct proc * p;
2047*14414594SDavid du Colombier+ {
2048*14414594SDavid du Colombier+ 	if (!(nmp->nm_flag & U9FSMNT_INT))
2049*14414594SDavid du Colombier+ 		return (0);
2050*14414594SDavid du Colombier+ 	if (p && p->p_siglist &&
2051*14414594SDavid du Colombier+ 	    (((p->p_siglist & ~p->p_sigmask) & ~p->p_sigignore) &
2052*14414594SDavid du Colombier+ 	    U9FSINT_SIGMASK))
2053*14414594SDavid du Colombier+ 		return (EINTR);
2054*14414594SDavid du Colombier+ 	return (0);
2055*14414594SDavid du Colombier+ }
2056*14414594SDavid du Colombier+
2057*14414594SDavid du Colombier+ /*
2058*14414594SDavid du Colombier+  * This is the u9fs send routine. For connection based socket types, it
2059*14414594SDavid du Colombier+  * must be called with an u9fs_sndlock() on the socket.
2060*14414594SDavid du Colombier+  * "rep == NULL" indicates that it has been called from a server.
2061*14414594SDavid du Colombier+  * For the client side:
2062*14414594SDavid du Colombier+  * - return EINTR if the RPC is terminated, 0 otherwise
2063*14414594SDavid du Colombier+  * - set R_MUSTRESEND if the send fails for any reason
2064*14414594SDavid du Colombier+  * - do any cleanup required by recoverable socket errors (?)
2065*14414594SDavid du Colombier+  * For the server side:
2066*14414594SDavid du Colombier+  * - return EINTR or ERESTART if interrupted by a signal
2067*14414594SDavid du Colombier+  * - return EPIPE if a connection is lost for connection based sockets (TCP...)
2068*14414594SDavid du Colombier+  * - do any cleanup required by recoverable socket errors (?)
2069*14414594SDavid du Colombier+  */
2070*14414594SDavid du Colombier+ static int
2071*14414594SDavid du Colombier+ u9fs_send(so, top, req)
2072*14414594SDavid du Colombier+ 	register struct socket *so;
2073*14414594SDavid du Colombier+ 	register struct mbuf *top;
2074*14414594SDavid du Colombier+ 	struct u9fsreq *req;
2075*14414594SDavid du Colombier+ {
2076*14414594SDavid du Colombier+   int error, soflags, flags;
2077*14414594SDavid du Colombier+
2078*14414594SDavid du Colombier+   soflags = so->so_proto->pr_flags;
2079*14414594SDavid du Colombier+   if (so->so_type == SOCK_SEQPACKET)
2080*14414594SDavid du Colombier+     flags = MSG_EOR;
2081*14414594SDavid du Colombier+   else
2082*14414594SDavid du Colombier+     flags = 0;
2083*14414594SDavid du Colombier+
2084*14414594SDavid du Colombier+   error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 0, top, 0,
2085*14414594SDavid du Colombier+ 					       flags, req->r_procp);
2086*14414594SDavid du Colombier+   if (error)
2087*14414594SDavid du Colombier+     log(LOG_INFO, "u9fs send error %d for server %s\n",error,
2088*14414594SDavid du Colombier+ 	  req->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
2089*14414594SDavid du Colombier+
2090*14414594SDavid du Colombier+   return (error);
2091*14414594SDavid du Colombier+ }
2092*14414594SDavid du Colombier+
2093*14414594SDavid du Colombier+ static int
2094*14414594SDavid du Colombier+ u9fs_receive(so, mrep, req)
2095*14414594SDavid du Colombier+      register struct socket * so;
2096*14414594SDavid du Colombier+      struct mbuf **mrep;
2097*14414594SDavid du Colombier+      struct u9fsreq * req;
2098*14414594SDavid du Colombier+ {
2099*14414594SDavid du Colombier+   struct uio auio;
2100*14414594SDavid du Colombier+   u_int32_t len;
2101*14414594SDavid du Colombier+   int error = 0, sotype, rcvflg;
2102*14414594SDavid du Colombier+
2103*14414594SDavid du Colombier+   /*
2104*14414594SDavid du Colombier+    * Set up arguments for soreceive()
2105*14414594SDavid du Colombier+    */
2106*14414594SDavid du Colombier+   *mrep = (struct mbuf *)0;
2107*14414594SDavid du Colombier+   sotype = req->r_nmp->nm_sotype;
2108*14414594SDavid du Colombier+
2109*14414594SDavid du Colombier+   /*
2110*14414594SDavid du Colombier+    * For reliable protocols, lock against other senders/receivers
2111*14414594SDavid du Colombier+    * in case a reconnect is necessary.
2112*14414594SDavid du Colombier+    * For SOCK_STREAM, first get the Record Mark to find out how much
2113*14414594SDavid du Colombier+    * more there is to get.
2114*14414594SDavid du Colombier+    * We must lock the socket against other receivers
2115*14414594SDavid du Colombier+    * until we have an entire rpc request/reply.
2116*14414594SDavid du Colombier+    */
2117*14414594SDavid du Colombier+   if (sotype == SOCK_SEQPACKET ) {
2118*14414594SDavid du Colombier+     if( (so->so_state & SS_ISCONNECTED) == 0 )
2119*14414594SDavid du Colombier+       return (EACCES);
2120*14414594SDavid du Colombier+ 		auio.uio_resid = len = 1000000;
2121*14414594SDavid du Colombier+ 		auio.uio_procp = req->r_procp;
2122*14414594SDavid du Colombier+ 		do {
2123*14414594SDavid du Colombier+ 			rcvflg = 0;
2124*14414594SDavid du Colombier+ 			error =  so->so_proto->pr_usrreqs->pru_soreceive
2125*14414594SDavid du Colombier+ 				(so, 0, &auio, mrep,
2126*14414594SDavid du Colombier+ 				(struct mbuf **)0, &rcvflg);
2127*14414594SDavid du Colombier+ 		} while (error == EWOULDBLOCK);
2128*14414594SDavid du Colombier+ 		len -= auio.uio_resid;
2129*14414594SDavid du Colombier+   }
2130*14414594SDavid du Colombier+   if (error) {
2131*14414594SDavid du Colombier+     m_freem(*mrep);
2132*14414594SDavid du Colombier+     *mrep = (struct mbuf *)0;
2133*14414594SDavid du Colombier+   }
2134*14414594SDavid du Colombier+   return (error);
2135*14414594SDavid du Colombier+ }
2136*14414594SDavid du Colombier+
2137*14414594SDavid du Colombier+ static int
2138*14414594SDavid du Colombier+ u9fs_rcvlock(req)
2139*14414594SDavid du Colombier+ 	register struct u9fsreq *req;
2140*14414594SDavid du Colombier+ {
2141*14414594SDavid du Colombier+ 	register int *flagp = &req->r_nmp->nm_flag;
2142*14414594SDavid du Colombier+ 	register int *statep = &req->r_nmp->nm_state;
2143*14414594SDavid du Colombier+ 	int slpflag, slptimeo = 0;
2144*14414594SDavid du Colombier+
2145*14414594SDavid du Colombier+ 	if (*flagp & U9FSMNT_INT)
2146*14414594SDavid du Colombier+ 		slpflag = PCATCH;
2147*14414594SDavid du Colombier+ 	else
2148*14414594SDavid du Colombier+ 		slpflag = 0;
2149*14414594SDavid du Colombier+ 	while (*statep & U9FSSTA_RCVLOCK) {
2150*14414594SDavid du Colombier+ 		if (u9fs_sigintr(req->r_nmp, req->r_procp))
2151*14414594SDavid du Colombier+ 			return (EINTR);
2152*14414594SDavid du Colombier+ 		*statep |= U9FSSTA_WANTRCV;
2153*14414594SDavid du Colombier+ 		(void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), "u9fsrcvlk",
2154*14414594SDavid du Colombier+ 			slptimeo);
2155*14414594SDavid du Colombier+ 		/*
2156*14414594SDavid du Colombier+ 		 * If our reply was recieved while we were sleeping,
2157*14414594SDavid du Colombier+ 		 * then just return without taking the lock to avoid a
2158*14414594SDavid du Colombier+ 		 * situation where a single iod could 'capture' the
2159*14414594SDavid du Colombier+ 		 * recieve lock.
2160*14414594SDavid du Colombier+ 		 */
2161*14414594SDavid du Colombier+ 		if (req->r_mrep != NULL)
2162*14414594SDavid du Colombier+ 			return (EALREADY);
2163*14414594SDavid du Colombier+ 		if (slpflag == PCATCH) {
2164*14414594SDavid du Colombier+ 			slpflag = 0;
2165*14414594SDavid du Colombier+ 			slptimeo = 2 * hz;
2166*14414594SDavid du Colombier+ 		}
2167*14414594SDavid du Colombier+ 	}
2168*14414594SDavid du Colombier+ 	*statep |= U9FSSTA_RCVLOCK;
2169*14414594SDavid du Colombier+ 	return (0);
2170*14414594SDavid du Colombier+ }
2171*14414594SDavid du Colombier+
2172*14414594SDavid du Colombier+ /*
2173*14414594SDavid du Colombier+  * Unlock the stream socket for others.
2174*14414594SDavid du Colombier+  */
2175*14414594SDavid du Colombier+ static void
2176*14414594SDavid du Colombier+ u9fs_rcvunlock(flagp, statep)
2177*14414594SDavid du Colombier+ 	register int *flagp;
2178*14414594SDavid du Colombier+ 	register int *statep;
2179*14414594SDavid du Colombier+ {
2180*14414594SDavid du Colombier+
2181*14414594SDavid du Colombier+ 	if ((*statep & U9FSSTA_RCVLOCK) == 0)
2182*14414594SDavid du Colombier+ 		panic("u9fs rcvunlock");
2183*14414594SDavid du Colombier+ 	*statep &= ~U9FSSTA_RCVLOCK;
2184*14414594SDavid du Colombier+ 	if (*statep & U9FSSTA_WANTRCV) {
2185*14414594SDavid du Colombier+ 		*statep &= ~U9FSSTA_WANTRCV;
2186*14414594SDavid du Colombier+ 		wakeup((caddr_t)flagp);
2187*14414594SDavid du Colombier+ 	}
2188*14414594SDavid du Colombier+ }
2189*14414594SDavid du Colombier+
2190*14414594SDavid du Colombier+ /*
2191*14414594SDavid du Colombier+  * Implement receipt of reply on a socket.
2192*14414594SDavid du Colombier+  * We must search through the list of received datagrams matching them
2193*14414594SDavid du Colombier+  * with outstanding requests using the xid, until ours is found.
2194*14414594SDavid du Colombier+  */
2195*14414594SDavid du Colombier+ /* ARGSUSED */
2196*14414594SDavid du Colombier+ static
2197*14414594SDavid du Colombier+ int u9fs_reply(struct u9fsreq * req)
2198*14414594SDavid du Colombier+ {
2199*14414594SDavid du Colombier+   int error;
2200*14414594SDavid du Colombier+   struct mbuf * mrep;
2201*14414594SDavid du Colombier+   register struct u9fsmount *nmp = req->r_nmp;
2202*14414594SDavid du Colombier+   u_short tag;
2203*14414594SDavid du Colombier+   struct u9fsreq * qp;
2204*14414594SDavid du Colombier+
2205*14414594SDavid du Colombier+   /*
2206*14414594SDavid du Colombier+    * Loop around until we get our own reply
2207*14414594SDavid du Colombier+    */
2208*14414594SDavid du Colombier+   for (;;) {
2209*14414594SDavid du Colombier+     /*
2210*14414594SDavid du Colombier+      * Lock against other receivers so that I don't get stuck in
2211*14414594SDavid du Colombier+      * sbwait() after someone else has received my reply for me.
2212*14414594SDavid du Colombier+      * Also necessary for connection based protocols to avoid
2213*14414594SDavid du Colombier+      * race conditions during a reconnect.
2214*14414594SDavid du Colombier+      * If u9fs_rcvlock() returns EALREADY, that means that
2215*14414594SDavid du Colombier+      * the reply has already been recieved by another
2216*14414594SDavid du Colombier+      * process and we can return immediately.  In this
2217*14414594SDavid du Colombier+      * case, the lock is not taken to avoid races with
2218*14414594SDavid du Colombier+      * other processes.
2219*14414594SDavid du Colombier+      */
2220*14414594SDavid du Colombier+     error = u9fs_rcvlock(req);
2221*14414594SDavid du Colombier+     if (error == EALREADY)
2222*14414594SDavid du Colombier+       return (0);
2223*14414594SDavid du Colombier+     if (error)
2224*14414594SDavid du Colombier+       return (error);
2225*14414594SDavid du Colombier+     /*
2226*14414594SDavid du Colombier+      * Get the next Rpc reply off the socket
2227*14414594SDavid du Colombier+      */
2228*14414594SDavid du Colombier+     error = u9fs_receive(nmp->nm_so, &mrep, req);
2229*14414594SDavid du Colombier+     u9fs_rcvunlock(&nmp->nm_flag, &nmp->nm_state);
2230*14414594SDavid du Colombier+     if (error)
2231*14414594SDavid du Colombier+       return (error);
2232*14414594SDavid du Colombier+
2233*14414594SDavid du Colombier+     /* extract the tag */
2234*14414594SDavid du Colombier+     tag = u9p_m_tag(&mrep);
2235*14414594SDavid du Colombier+
2236*14414594SDavid du Colombier+     /*
2237*14414594SDavid du Colombier+      * Loop through the request list to match up the reply
2238*14414594SDavid du Colombier+      * Iff no match, just drop the datagram
2239*14414594SDavid du Colombier+      */
2240*14414594SDavid du Colombier+     for (qp = nmp->nm_reqq.tqh_first; qp != 0; qp = qp->r_chain.tqe_next) {
2241*14414594SDavid du Colombier+       if ( qp->r_mrep == 0 && qp->r_tag == tag )
2242*14414594SDavid du Colombier+ 	break;
2243*14414594SDavid du Colombier+     }
2244*14414594SDavid du Colombier+     if( qp == 0 ) {
2245*14414594SDavid du Colombier+       m_freem(mrep);
2246*14414594SDavid du Colombier+       continue;
2247*14414594SDavid du Colombier+     }
2248*14414594SDavid du Colombier+
2249*14414594SDavid du Colombier+     if( u9p_m_m2s(&mrep, qp->r_rep) ) { /* freed by m2s */
2250*14414594SDavid du Colombier+       continue;
2251*14414594SDavid du Colombier+     }
2252*14414594SDavid du Colombier+
2253*14414594SDavid du Colombier+     qp->r_mrep = mrep;  /* should not be freed until the reply is read */
2254*14414594SDavid du Colombier+
2255*14414594SDavid du Colombier+     if( qp == req )
2256*14414594SDavid du Colombier+       return 0;
2257*14414594SDavid du Colombier+   }
2258*14414594SDavid du Colombier+ }
2259*14414594SDavid du Colombier+
2260*14414594SDavid du Colombier+ int u9fs_request(struct u9fsreq * req, struct u9fsreq * rep, int relm)
2261*14414594SDavid du Colombier+ {
2262*14414594SDavid du Colombier+   struct mbuf * mreq;
2263*14414594SDavid du Colombier+   int error,s;
2264*14414594SDavid du Colombier+   struct u9fsmount * nmp;
2265*14414594SDavid du Colombier+
2266*14414594SDavid du Colombier+   req->r_rep = rep;
2267*14414594SDavid du Colombier+   req->r_mrep = 0;
2268*14414594SDavid du Colombier+   nmp = req->r_nmp;
2269*14414594SDavid du Colombier+   req->r_tag = u9fs_id_new(nmp->nm_tags);
2270*14414594SDavid du Colombier+
2271*14414594SDavid du Colombier+   mreq = u9p_m_s2m(req);
2272*14414594SDavid du Colombier+
2273*14414594SDavid du Colombier+   /*
2274*14414594SDavid du Colombier+    * Chain request into list of outstanding requests. Be sure
2275*14414594SDavid du Colombier+    * to put it LAST so timer finds oldest requests first.
2276*14414594SDavid du Colombier+    */
2277*14414594SDavid du Colombier+   s = splsoftclock();
2278*14414594SDavid du Colombier+   TAILQ_INSERT_TAIL(&nmp->nm_reqq, req, r_chain);
2279*14414594SDavid du Colombier+   splx(s);
2280*14414594SDavid du Colombier+
2281*14414594SDavid du Colombier+   error = u9fs_send(nmp->nm_so, mreq, req);
2282*14414594SDavid du Colombier+
2283*14414594SDavid du Colombier+   if( !error )
2284*14414594SDavid du Colombier+     error = u9fs_reply(req);
2285*14414594SDavid du Colombier+
2286*14414594SDavid du Colombier+   /*
2287*14414594SDavid du Colombier+    * RPC done, unlink the request.
2288*14414594SDavid du Colombier+    */
2289*14414594SDavid du Colombier+   s = splsoftclock();
2290*14414594SDavid du Colombier+   TAILQ_REMOVE(&nmp->nm_reqq, req, r_chain);
2291*14414594SDavid du Colombier+   splx(s);
2292*14414594SDavid du Colombier+
2293*14414594SDavid du Colombier+   u9fs_id_free(nmp->nm_tags, req->r_tag);
2294*14414594SDavid du Colombier+
2295*14414594SDavid du Colombier+   if( !error && relm ) {
2296*14414594SDavid du Colombier+ 	m_freem(req->r_mrep);
2297*14414594SDavid du Colombier+ 	req->r_mrep = 0;
2298*14414594SDavid du Colombier+   }
2299*14414594SDavid du Colombier+   if( rep->r_type == Rerror )
2300*14414594SDavid du Colombier+       error = EACCES;
2301*14414594SDavid du Colombier+
2302*14414594SDavid du Colombier+   return error;
2303*14414594SDavid du Colombier+ }
2304*14414594SDavid du Colombier+
2305*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_subr.c ./9fs/9fs_subr.c
2306*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_subr.c	Wed Dec 31 19:00:00 1969
2307*14414594SDavid du Colombier--- ./9fs/9fs_subr.c	Fri Nov 26 12:28:17 1999
2308*14414594SDavid du Colombier***************
2309*14414594SDavid du Colombier*** 0 ****
2310*14414594SDavid du Colombier--- 1,240 ----
2311*14414594SDavid du Colombier+ #include <sys/param.h>
2312*14414594SDavid du Colombier+ #include <sys/sockio.h>
2313*14414594SDavid du Colombier+ #include <sys/proc.h>
2314*14414594SDavid du Colombier+ #include <sys/vnode.h>
2315*14414594SDavid du Colombier+ #include <sys/kernel.h>
2316*14414594SDavid du Colombier+ #include <sys/sysctl.h>
2317*14414594SDavid du Colombier+ #include <sys/malloc.h>
2318*14414594SDavid du Colombier+ #include <sys/mount.h>
2319*14414594SDavid du Colombier+ #include <sys/mbuf.h>
2320*14414594SDavid du Colombier+ #include <sys/socket.h>
2321*14414594SDavid du Colombier+ #include <sys/socketvar.h>
2322*14414594SDavid du Colombier+ #include <sys/systm.h>
2323*14414594SDavid du Colombier+ #include <sys/protosw.h>
2324*14414594SDavid du Colombier+ #include <sys/syslog.h>
2325*14414594SDavid du Colombier+
2326*14414594SDavid du Colombier+ #include <netinet/in.h>
2327*14414594SDavid du Colombier+ #include <netinet/tcp.h>
2328*14414594SDavid du Colombier+
2329*14414594SDavid du Colombier+ #include <vm/vm.h>
2330*14414594SDavid du Colombier+ #include <vm/vm_extern.h>
2331*14414594SDavid du Colombier+ #include <vm/vm_zone.h>
2332*14414594SDavid du Colombier+
2333*14414594SDavid du Colombier+ #include <net/if.h>
2334*14414594SDavid du Colombier+ #include <net/route.h>
2335*14414594SDavid du Colombier+ #include <netinet/in.h>
2336*14414594SDavid du Colombier+
2337*14414594SDavid du Colombier+ #include <9fs/bitstring.h>
2338*14414594SDavid du Colombier+ #include <9fs/9p.h>
2339*14414594SDavid du Colombier+ #include <9fs/9auth.h>
2340*14414594SDavid du Colombier+ #include <9fs/9fs.h>
2341*14414594SDavid du Colombier+
2342*14414594SDavid du Colombier+ vm_zone_t u9fsuser_zone;
2343*14414594SDavid du Colombier+ LIST_HEAD(u9fsuserhashhead, u9fsuser) * u9fsuidhashtbl, * u9fsunamehashtbl;
2344*14414594SDavid du Colombier+ u_long u9fsuidhash;
2345*14414594SDavid du Colombier+ u_long u9fsunamehash;
2346*14414594SDavid du Colombier+ MALLOC_DEFINE(M_U9FSBITS, "U9FS bits", "U9FS tag/fid maps");
2347*14414594SDavid du Colombier+
2348*14414594SDavid du Colombier+ static int   u9fs_hashname __P((char * name));
2349*14414594SDavid du Colombier+
2350*14414594SDavid du Colombier+ void u9fs_uhinit()
2351*14414594SDavid du Colombier+ {
2352*14414594SDavid du Colombier+   u9fsuser_zone = zinit("U9FSUSER", sizeof(struct u9fsuser), 0, 0, 1);
2353*14414594SDavid du Colombier+   u9fsuidhashtbl   = phashinit(U9FS_USER_HASHSIZE, M_U9FSHASH, &u9fsuidhash);
2354*14414594SDavid du Colombier+   u9fsunamehashtbl = phashinit(U9FS_USER_HASHSIZE, M_U9FSHASH, &u9fsunamehash);
2355*14414594SDavid du Colombier+ }
2356*14414594SDavid du Colombier+
2357*14414594SDavid du Colombier+ void
2358*14414594SDavid du Colombier+ u9fs_id_init(bits)
2359*14414594SDavid du Colombier+      bitstr_t ** bits;
2360*14414594SDavid du Colombier+ {
2361*14414594SDavid du Colombier+   bit_alloc(*bits, 0x10000, M_U9FSBITS, M_WAITOK);
2362*14414594SDavid du Colombier+   bit_nset(*bits, 1, 0xffff);  /* we dont use zero */
2363*14414594SDavid du Colombier+ }
2364*14414594SDavid du Colombier+
2365*14414594SDavid du Colombier+ u_short
2366*14414594SDavid du Colombier+ u9fs_id_new(bits)
2367*14414594SDavid du Colombier+      bitstr_t * bits;
2368*14414594SDavid du Colombier+ {
2369*14414594SDavid du Colombier+   int v;
2370*14414594SDavid du Colombier+
2371*14414594SDavid du Colombier+   bit_ffs(bits, 0x10000, &v);
2372*14414594SDavid du Colombier+   if( v < 0 )
2373*14414594SDavid du Colombier+     panic("no more u9fs bits!");
2374*14414594SDavid du Colombier+
2375*14414594SDavid du Colombier+   bit_clear(bits, v);
2376*14414594SDavid du Colombier+   return ((u_short)v);
2377*14414594SDavid du Colombier+ }
2378*14414594SDavid du Colombier+
2379*14414594SDavid du Colombier+ void
2380*14414594SDavid du Colombier+ u9fs_id_free(bits, v)
2381*14414594SDavid du Colombier+      bitstr_t * bits;
2382*14414594SDavid du Colombier+      u_short v;
2383*14414594SDavid du Colombier+ {
2384*14414594SDavid du Colombier+   bit_set(bits, v);
2385*14414594SDavid du Colombier+ }
2386*14414594SDavid du Colombier+
2387*14414594SDavid du Colombier+
2388*14414594SDavid du Colombier+ static int u9fs_hashname(char * cp)
2389*14414594SDavid du Colombier+ {
2390*14414594SDavid du Colombier+   int h = 0;
2391*14414594SDavid du Colombier+
2392*14414594SDavid du Colombier+   cp[U9FS_NAMELEN-1] = 0;
2393*14414594SDavid du Colombier+   do
2394*14414594SDavid du Colombier+     h += *cp;
2395*14414594SDavid du Colombier+   while ( *cp++ );
2396*14414594SDavid du Colombier+
2397*14414594SDavid du Colombier+   return h;
2398*14414594SDavid du Colombier+ }
2399*14414594SDavid du Colombier+
2400*14414594SDavid du Colombier+ void u9fs_hashuser(uid_t uid, char * name)
2401*14414594SDavid du Colombier+ {
2402*14414594SDavid du Colombier+   int h;
2403*14414594SDavid du Colombier+   struct u9fsuser * u9p, *u9p2;
2404*14414594SDavid du Colombier+   struct u9fsuserhashhead * u9hp;
2405*14414594SDavid du Colombier+
2406*14414594SDavid du Colombier+   if( u9fs_name2uid(name) != 65534 ) /* already hashed by previous mount */
2407*14414594SDavid du Colombier+     return;
2408*14414594SDavid du Colombier+
2409*14414594SDavid du Colombier+   u9p = zalloc(u9fsuser_zone);
2410*14414594SDavid du Colombier+   bzero(u9p, sizeof(*u9p));
2411*14414594SDavid du Colombier+   u9p->u_uid = uid;
2412*14414594SDavid du Colombier+   strncpy(u9p->u_name, name, U9FS_NAMELEN);
2413*14414594SDavid du Colombier+   u9hp = & u9fsuidhashtbl[uid % u9fsuidhash];
2414*14414594SDavid du Colombier+   LIST_INSERT_HEAD(u9hp, u9p, u_hash);
2415*14414594SDavid du Colombier+
2416*14414594SDavid du Colombier+   u9p2 = zalloc(u9fsuser_zone);
2417*14414594SDavid du Colombier+   bcopy(u9p, u9p2, sizeof(*u9p));
2418*14414594SDavid du Colombier+   h = u9fs_hashname(name);
2419*14414594SDavid du Colombier+   u9hp = & u9fsunamehashtbl[h%u9fsunamehash];
2420*14414594SDavid du Colombier+   LIST_INSERT_HEAD(u9hp, u9p2, u_hash);
2421*14414594SDavid du Colombier+ }
2422*14414594SDavid du Colombier+
2423*14414594SDavid du Colombier+ /* name must be at least U9FS_NAMELEN long! */
2424*14414594SDavid du Colombier+ struct u9fsuser * u9fs_finduser(uid_t uid)
2425*14414594SDavid du Colombier+ {
2426*14414594SDavid du Colombier+   struct u9fsuser * u9p;
2427*14414594SDavid du Colombier+   struct u9fsuserhashhead * u9hp;
2428*14414594SDavid du Colombier+
2429*14414594SDavid du Colombier+   u9hp = & u9fsuidhashtbl[uid % u9fsuidhash];
2430*14414594SDavid du Colombier+   LIST_FOREACH(u9p, u9hp, u_hash)
2431*14414594SDavid du Colombier+     if( u9p->u_uid == uid )
2432*14414594SDavid du Colombier+       break;
2433*14414594SDavid du Colombier+
2434*14414594SDavid du Colombier+   return u9p;
2435*14414594SDavid du Colombier+ }
2436*14414594SDavid du Colombier+
2437*14414594SDavid du Colombier+ uid_t u9fs_name2uid(char *name)
2438*14414594SDavid du Colombier+ {
2439*14414594SDavid du Colombier+   struct u9fsuser * u9p;
2440*14414594SDavid du Colombier+   struct u9fsuserhashhead * u9hp;
2441*14414594SDavid du Colombier+   int h;
2442*14414594SDavid du Colombier+
2443*14414594SDavid du Colombier+   h = u9fs_hashname(name);
2444*14414594SDavid du Colombier+   u9hp = & u9fsunamehashtbl[h%u9fsunamehash];
2445*14414594SDavid du Colombier+   LIST_FOREACH(u9p, u9hp, u_hash)
2446*14414594SDavid du Colombier+     if( strcmp(u9p->u_name, name) == 0 )
2447*14414594SDavid du Colombier+       break;
2448*14414594SDavid du Colombier+
2449*14414594SDavid du Colombier+   if( u9p )
2450*14414594SDavid du Colombier+     return u9p->u_uid;
2451*14414594SDavid du Colombier+   else
2452*14414594SDavid du Colombier+     return 65534; /* nobody */
2453*14414594SDavid du Colombier+ }
2454*14414594SDavid du Colombier+
2455*14414594SDavid du Colombier+ /*
2456*14414594SDavid du Colombier+  * copies a uio scatter/gather list to an mbuf chain.
2457*14414594SDavid du Colombier+  */
2458*14414594SDavid du Colombier+ int
2459*14414594SDavid du Colombier+ u9fs_uiotombuf(uiop, mq, siz)
2460*14414594SDavid du Colombier+ 	register struct uio *uiop;
2461*14414594SDavid du Colombier+ 	struct mbuf **mq;
2462*14414594SDavid du Colombier+ 	int siz;
2463*14414594SDavid du Colombier+ {
2464*14414594SDavid du Colombier+   register struct mbuf *m;
2465*14414594SDavid du Colombier+   struct mbuf * top, **mp;
2466*14414594SDavid du Colombier+   int mlen, len, error = 0;
2467*14414594SDavid du Colombier+
2468*14414594SDavid du Colombier+   mp = & top;
2469*14414594SDavid du Colombier+   while(siz) {
2470*14414594SDavid du Colombier+     MGET(m, M_WAIT, MT_DATA);
2471*14414594SDavid du Colombier+     mlen = MLEN;
2472*14414594SDavid du Colombier+     if (siz >= MINCLSIZE) {
2473*14414594SDavid du Colombier+       MCLGET(m, M_WAIT);
2474*14414594SDavid du Colombier+       if ((m->m_flags & M_EXT))
2475*14414594SDavid du Colombier+ 	mlen = MCLBYTES;
2476*14414594SDavid du Colombier+     }
2477*14414594SDavid du Colombier+     len = min(mlen, siz);
2478*14414594SDavid du Colombier+     error = uiomove(mtod(m, caddr_t), (int)len, uiop);
2479*14414594SDavid du Colombier+     siz -= len;
2480*14414594SDavid du Colombier+     m->m_len = len;
2481*14414594SDavid du Colombier+     *mp = m;
2482*14414594SDavid du Colombier+     if (error)
2483*14414594SDavid du Colombier+       goto release;
2484*14414594SDavid du Colombier+     mp = &m->m_next;
2485*14414594SDavid du Colombier+   }
2486*14414594SDavid du Colombier+   *mq = top;
2487*14414594SDavid du Colombier+   return 0;
2488*14414594SDavid du Colombier+
2489*14414594SDavid du Colombier+  release:
2490*14414594SDavid du Colombier+   if( top )
2491*14414594SDavid du Colombier+     m_freem(top);
2492*14414594SDavid du Colombier+
2493*14414594SDavid du Colombier+   return error;
2494*14414594SDavid du Colombier+ }
2495*14414594SDavid du Colombier+
2496*14414594SDavid du Colombier+ /*
2497*14414594SDavid du Colombier+  * copies mbuf chain to the uio scatter/gather list
2498*14414594SDavid du Colombier+  */
2499*14414594SDavid du Colombier+ int
2500*14414594SDavid du Colombier+ u9fs_mbuftouio(m, uiop, siz)
2501*14414594SDavid du Colombier+      struct mbuf *m;
2502*14414594SDavid du Colombier+      register struct uio *uiop;
2503*14414594SDavid du Colombier+      int siz;
2504*14414594SDavid du Colombier+ {
2505*14414594SDavid du Colombier+   register char *mbufcp, *uiocp;
2506*14414594SDavid du Colombier+   register int xfer, left, len;
2507*14414594SDavid du Colombier+   long uiosiz;
2508*14414594SDavid du Colombier+
2509*14414594SDavid du Colombier+   mbufcp = mtod(m, char *);
2510*14414594SDavid du Colombier+   len = m->m_len;
2511*14414594SDavid du Colombier+   while (siz > 0) {
2512*14414594SDavid du Colombier+     if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
2513*14414594SDavid du Colombier+       return (EFBIG);
2514*14414594SDavid du Colombier+     left = uiop->uio_iov->iov_len;
2515*14414594SDavid du Colombier+     uiocp = uiop->uio_iov->iov_base;
2516*14414594SDavid du Colombier+     if (left > siz)
2517*14414594SDavid du Colombier+       left = siz;
2518*14414594SDavid du Colombier+     uiosiz = left;
2519*14414594SDavid du Colombier+     while (left > 0) {
2520*14414594SDavid du Colombier+       while (len == 0) {
2521*14414594SDavid du Colombier+ 	m = m->m_next;
2522*14414594SDavid du Colombier+ 	if (m == NULL)
2523*14414594SDavid du Colombier+ 	  return (EBADRPC);
2524*14414594SDavid du Colombier+ 	mbufcp = mtod(m, caddr_t);
2525*14414594SDavid du Colombier+ 	len = m->m_len;
2526*14414594SDavid du Colombier+       }
2527*14414594SDavid du Colombier+       xfer = (left > len) ? len : left;
2528*14414594SDavid du Colombier+       if (uiop->uio_segflg == UIO_SYSSPACE)
2529*14414594SDavid du Colombier+ 	bcopy(mbufcp, uiocp, xfer);
2530*14414594SDavid du Colombier+       else
2531*14414594SDavid du Colombier+ 	copyout(mbufcp, uiocp, xfer);
2532*14414594SDavid du Colombier+       left -= xfer;
2533*14414594SDavid du Colombier+       len -= xfer;
2534*14414594SDavid du Colombier+       mbufcp += xfer;
2535*14414594SDavid du Colombier+       uiocp += xfer;
2536*14414594SDavid du Colombier+       uiop->uio_offset += xfer;
2537*14414594SDavid du Colombier+       uiop->uio_resid -= xfer;
2538*14414594SDavid du Colombier+     }
2539*14414594SDavid du Colombier+     if (uiop->uio_iov->iov_len <= siz) {
2540*14414594SDavid du Colombier+       uiop->uio_iovcnt--;
2541*14414594SDavid du Colombier+       uiop->uio_iov++;
2542*14414594SDavid du Colombier+     } else {
2543*14414594SDavid du Colombier+       uiop->uio_iov->iov_base += uiosiz;
2544*14414594SDavid du Colombier+       uiop->uio_iov->iov_len -= uiosiz;
2545*14414594SDavid du Colombier+     }
2546*14414594SDavid du Colombier+     siz -= uiosiz;
2547*14414594SDavid du Colombier+   }
2548*14414594SDavid du Colombier+   return (0);
2549*14414594SDavid du Colombier+ }
2550*14414594SDavid du Colombier+
2551*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_vfsops.c ./9fs/9fs_vfsops.c
2552*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_vfsops.c	Wed Dec 31 19:00:00 1969
2553*14414594SDavid du Colombier--- ./9fs/9fs_vfsops.c	Mon May 22 16:33:47 2000
2554*14414594SDavid du Colombier***************
2555*14414594SDavid du Colombier*** 0 ****
2556*14414594SDavid du Colombier--- 1,639 ----
2557*14414594SDavid du Colombier+ /*
2558*14414594SDavid du Colombier+  * Copyright (c) 1989, 1993, 1995
2559*14414594SDavid du Colombier+  *	The Regents of the University of California.  All rights reserved.
2560*14414594SDavid du Colombier+  *
2561*14414594SDavid du Colombier+  * This code is derived from software contributed to Berkeley by
2562*14414594SDavid du Colombier+  * Rick Macklem at The University of Guelph.
2563*14414594SDavid du Colombier+  *
2564*14414594SDavid du Colombier+  * Redistribution and use in source and binary forms, with or without
2565*14414594SDavid du Colombier+  * modification, are permitted provided that the following conditions
2566*14414594SDavid du Colombier+  * are met:
2567*14414594SDavid du Colombier+  * 1. Redistributions of source code must retain the above copyright
2568*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer.
2569*14414594SDavid du Colombier+  * 2. Redistributions in binary form must reproduce the above copyright
2570*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer in the
2571*14414594SDavid du Colombier+  *    documentation and/or other materials provided with the distribution.
2572*14414594SDavid du Colombier+  * 3. All advertising materials mentioning features or use of this software
2573*14414594SDavid du Colombier+  *    must display the following acknowledgement:
2574*14414594SDavid du Colombier+  *	This product includes software developed by the University of
2575*14414594SDavid du Colombier+  *	California, Berkeley and its contributors.
2576*14414594SDavid du Colombier+  * 4. Neither the name of the University nor the names of its contributors
2577*14414594SDavid du Colombier+  *    may be used to endorse or promote products derived from this software
2578*14414594SDavid du Colombier+  *    without specific prior written permission.
2579*14414594SDavid du Colombier+  *
2580*14414594SDavid du Colombier+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2581*14414594SDavid du Colombier+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2582*14414594SDavid du Colombier+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2583*14414594SDavid du Colombier+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2584*14414594SDavid du Colombier+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2585*14414594SDavid du Colombier+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2586*14414594SDavid du Colombier+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2587*14414594SDavid du Colombier+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2588*14414594SDavid du Colombier+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2589*14414594SDavid du Colombier+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2590*14414594SDavid du Colombier+  * SUCH DAMAGE.
2591*14414594SDavid du Colombier+  *
2592*14414594SDavid du Colombier+  *	@(#)u9fs_vfsops.c	8.12 (Berkeley) 5/20/95
2593*14414594SDavid du Colombier+  * $Id: u9fs_vfsops.c,v 1.79 1998/12/04 22:54:54 archie Exp $
2594*14414594SDavid du Colombier+  */
2595*14414594SDavid du Colombier+
2596*14414594SDavid du Colombier+ #include <sys/param.h>
2597*14414594SDavid du Colombier+ #include <sys/sockio.h>
2598*14414594SDavid du Colombier+ #include <sys/proc.h>
2599*14414594SDavid du Colombier+ #include <sys/vnode.h>
2600*14414594SDavid du Colombier+ #include <sys/kernel.h>
2601*14414594SDavid du Colombier+ #include <sys/sysctl.h>
2602*14414594SDavid du Colombier+ #include <sys/malloc.h>
2603*14414594SDavid du Colombier+ #include <sys/mount.h>
2604*14414594SDavid du Colombier+ #include <sys/mbuf.h>
2605*14414594SDavid du Colombier+ #include <sys/socket.h>
2606*14414594SDavid du Colombier+ #include <sys/socketvar.h>
2607*14414594SDavid du Colombier+ #include <sys/systm.h>
2608*14414594SDavid du Colombier+ #include <sys/protosw.h>
2609*14414594SDavid du Colombier+ #include <sys/syslog.h>
2610*14414594SDavid du Colombier+
2611*14414594SDavid du Colombier+ #include <netinet/in.h>
2612*14414594SDavid du Colombier+ #include <netinet/tcp.h>
2613*14414594SDavid du Colombier+
2614*14414594SDavid du Colombier+ #include <vm/vm.h>
2615*14414594SDavid du Colombier+ #include <vm/vm_extern.h>
2616*14414594SDavid du Colombier+ #include <vm/vm_zone.h>
2617*14414594SDavid du Colombier+
2618*14414594SDavid du Colombier+ #include <net/if.h>
2619*14414594SDavid du Colombier+ #include <net/route.h>
2620*14414594SDavid du Colombier+ #include <netinet/in.h>
2621*14414594SDavid du Colombier+
2622*14414594SDavid du Colombier+ #include <9fs/bitstring.h>
2623*14414594SDavid du Colombier+ #include <9fs/9p.h>
2624*14414594SDavid du Colombier+ #include <9fs/9auth.h>
2625*14414594SDavid du Colombier+ #include <9fs/9fs.h>
2626*14414594SDavid du Colombier+
2627*14414594SDavid du Colombier+ vm_zone_t u9fsmount_zone;
2628*14414594SDavid du Colombier+
2629*14414594SDavid du Colombier+ static int	u9fs_mount __P(( struct mount *mp, char *path, caddr_t data,
2630*14414594SDavid du Colombier+ 			struct nameidata *ndp, struct proc *p));
2631*14414594SDavid du Colombier+ static int	u9fs_start __P(( struct mount *mp, int flags,
2632*14414594SDavid du Colombier+ 			struct proc *p));
2633*14414594SDavid du Colombier+ static int	u9fs_unmount __P(( struct mount *mp, int mntflags,
2634*14414594SDavid du Colombier+ 			struct proc *p));
2635*14414594SDavid du Colombier+ static int	u9fs_root __P(( struct mount *mp, struct vnode **vpp));
2636*14414594SDavid du Colombier+ static int	u9fs_quotactl __P(( struct mount *mp, int cmds, uid_t uid,
2637*14414594SDavid du Colombier+ 			caddr_t arg, struct proc *p));
2638*14414594SDavid du Colombier+ static int	u9fs_statfs __P(( struct mount *mp, struct statfs *sbp,
2639*14414594SDavid du Colombier+ 			struct proc *p));
2640*14414594SDavid du Colombier+ static int	u9fs_sync __P(( struct mount *mp, int waitfor,
2641*14414594SDavid du Colombier+ 			struct ucred *cred, struct proc *p));
2642*14414594SDavid du Colombier+ static int	u9fs_vptofh __P(( struct vnode *vp, struct fid *fhp));
2643*14414594SDavid du Colombier+ static int	u9fs_fhtovp __P((struct mount *mp, struct fid *fhp,
2644*14414594SDavid du Colombier+ 			struct sockaddr *nam, struct vnode **vpp,
2645*14414594SDavid du Colombier+ 			int *exflagsp, struct ucred **credanonp));
2646*14414594SDavid du Colombier+ static int	u9fs_vget __P((struct mount *, ino_t, struct vnode **));
2647*14414594SDavid du Colombier+ static int      u9fs_init __P((struct vfsconf *vfsp));
2648*14414594SDavid du Colombier+ int             u9fs_uninit __P((struct vfsconf *vfsp));
2649*14414594SDavid du Colombier+
2650*14414594SDavid du Colombier+ /* */
2651*14414594SDavid du Colombier+ static int	mountu9fs __P((struct u9fs_args *,struct mount *,
2652*14414594SDavid du Colombier+ 			struct sockaddr *,char *,char *,struct vnode **, struct proc *p));
2653*14414594SDavid du Colombier+ static int	u9fs_iosize __P((struct u9fsmount *nmp));
2654*14414594SDavid du Colombier+ static void	u9fs_decode_args __P((struct u9fsmount *nmp, struct u9fs_args *argp, struct proc *p));
2655*14414594SDavid du Colombier+
2656*14414594SDavid du Colombier+ /*
2657*14414594SDavid du Colombier+  * u9fs vfs operations.
2658*14414594SDavid du Colombier+  */
2659*14414594SDavid du Colombier+ static struct vfsops u9fs_vfsops = {
2660*14414594SDavid du Colombier+ 	u9fs_mount,
2661*14414594SDavid du Colombier+ 	u9fs_start,
2662*14414594SDavid du Colombier+ 	u9fs_unmount,
2663*14414594SDavid du Colombier+ 	u9fs_root,
2664*14414594SDavid du Colombier+ 	u9fs_quotactl,
2665*14414594SDavid du Colombier+ 	u9fs_statfs,
2666*14414594SDavid du Colombier+ 	u9fs_sync,
2667*14414594SDavid du Colombier+ 	u9fs_vget,
2668*14414594SDavid du Colombier+ 	u9fs_fhtovp,
2669*14414594SDavid du Colombier+ 	u9fs_vptofh,
2670*14414594SDavid du Colombier+ 	u9fs_init,
2671*14414594SDavid du Colombier+ 	u9fs_uninit,
2672*14414594SDavid du Colombier+ 	0
2673*14414594SDavid du Colombier+ };
2674*14414594SDavid du Colombier+ VFS_SET(u9fs_vfsops, u9fs, VFCF_NETWORK);
2675*14414594SDavid du Colombier+
2676*14414594SDavid du Colombier+ /*
2677*14414594SDavid du Colombier+  * u9fs statfs call
2678*14414594SDavid du Colombier+  */
2679*14414594SDavid du Colombier+ static int
2680*14414594SDavid du Colombier+ u9fs_statfs(mp, sbp, p)
2681*14414594SDavid du Colombier+ 	struct mount *mp;
2682*14414594SDavid du Colombier+ 	register struct statfs *sbp;
2683*14414594SDavid du Colombier+ 	struct proc *p;
2684*14414594SDavid du Colombier+ {
2685*14414594SDavid du Colombier+   /* we have a worm with infinite storage,
2686*14414594SDavid du Colombier+      stat not supported by 9fs */
2687*14414594SDavid du Colombier+   return 0;
2688*14414594SDavid du Colombier+ }
2689*14414594SDavid du Colombier+
2690*14414594SDavid du Colombier+ /*
2691*14414594SDavid du Colombier+  * Common code for mount and mountroot
2692*14414594SDavid du Colombier+  */
2693*14414594SDavid du Colombier+ static int
2694*14414594SDavid du Colombier+ mountu9fs(argp, mp, nam, pth, hst, vpp, p)
2695*14414594SDavid du Colombier+ 	register struct u9fs_args *argp;
2696*14414594SDavid du Colombier+ 	register struct mount *mp;
2697*14414594SDavid du Colombier+ 	struct sockaddr *nam;
2698*14414594SDavid du Colombier+ 	char *pth, *hst;
2699*14414594SDavid du Colombier+ 	struct vnode **vpp;
2700*14414594SDavid du Colombier+ 	struct proc *p;
2701*14414594SDavid du Colombier+ {
2702*14414594SDavid du Colombier+   register struct u9fsmount *nmp;
2703*14414594SDavid du Colombier+   struct u9fsnode *np;
2704*14414594SDavid du Colombier+   int error;
2705*14414594SDavid du Colombier+   struct vattr attrs;
2706*14414594SDavid du Colombier+   struct u9fsreq req, rep;
2707*14414594SDavid du Colombier+   char * mntpoint;
2708*14414594SDavid du Colombier+   struct u9fsuser * u9p;
2709*14414594SDavid du Colombier+   struct socket * so;
2710*14414594SDavid du Colombier+
2711*14414594SDavid du Colombier+   if (mp->mnt_flag & MNT_UPDATE) {
2712*14414594SDavid du Colombier+ #if 0
2713*14414594SDavid du Colombier+     nmp = VFSTONFS(mp);
2714*14414594SDavid du Colombier+ <    /* update paths, file handles, etc, here	XXX */
2715*14414594SDavid du Colombier+     FREE(nam, M_SONAME);
2716*14414594SDavid du Colombier+ #endif
2717*14414594SDavid du Colombier+     return (0);
2718*14414594SDavid du Colombier+   } else {
2719*14414594SDavid du Colombier+     nmp = zalloc(u9fsmount_zone);
2720*14414594SDavid du Colombier+     bzero((caddr_t)nmp, sizeof (struct u9fsmount));
2721*14414594SDavid du Colombier+ #if 0
2722*14414594SDavid du Colombier+     TAILQ_INIT(&nmp->nm_uidlruhead);
2723*14414594SDavid du Colombier+     TAILQ_INIT(&nmp->nm_bufq);
2724*14414594SDavid du Colombier+ #endif
2725*14414594SDavid du Colombier+     mp->mnt_data = (qaddr_t)nmp;
2726*14414594SDavid du Colombier+   }
2727*14414594SDavid du Colombier+   vfs_getnewfsid(mp);
2728*14414594SDavid du Colombier+   nmp->nm_mountp = mp;
2729*14414594SDavid du Colombier+
2730*14414594SDavid du Colombier+   nmp->nm_maxfilesize = (u_int64_t)0xffffffffffffffffLL;
2731*14414594SDavid du Colombier+
2732*14414594SDavid du Colombier+   nmp->nm_wsize = U9FS_MAXFDATA;
2733*14414594SDavid du Colombier+   nmp->nm_rsize = U9FS_MAXFDATA;
2734*14414594SDavid du Colombier+   nmp->nm_readdirsize = U9FS_MAXDDATA;
2735*14414594SDavid du Colombier+   bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
2736*14414594SDavid du Colombier+   bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
2737*14414594SDavid du Colombier+   nmp->nm_nam = nam;
2738*14414594SDavid du Colombier+
2739*14414594SDavid du Colombier+   mntpoint = index(hst, '/');
2740*14414594SDavid du Colombier+   if( mntpoint )
2741*14414594SDavid du Colombier+     mntpoint++;
2742*14414594SDavid du Colombier+
2743*14414594SDavid du Colombier+   /* Set up the sockets and per-host congestion */
2744*14414594SDavid du Colombier+   nmp->nm_sotype = argp->sotype;
2745*14414594SDavid du Colombier+   nmp->nm_soproto = argp->proto;
2746*14414594SDavid du Colombier+
2747*14414594SDavid du Colombier+   u9fs_decode_args(nmp, argp, p);
2748*14414594SDavid du Colombier+
2749*14414594SDavid du Colombier+   lockinit(& nmp->nm_lock, PVFS, "u9fsmount", 0, 0);
2750*14414594SDavid du Colombier+   u9fs_id_init(&nmp->nm_tags);
2751*14414594SDavid du Colombier+   u9fs_id_init(&nmp->nm_fids);
2752*14414594SDavid du Colombier+   TAILQ_INIT(&nmp->nm_reqq);
2753*14414594SDavid du Colombier+
2754*14414594SDavid du Colombier+   if ((error = u9fs_connect_9fs(nmp)))
2755*14414594SDavid du Colombier+     goto bad;
2756*14414594SDavid du Colombier+
2757*14414594SDavid du Colombier+   /* "Tnop 1", "Tsession 1 0", "Tattach 1 1 none main 0 0", */
2758*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
2759*14414594SDavid du Colombier+   req.r_nmp = nmp;
2760*14414594SDavid du Colombier+   req.r_procp = p;
2761*14414594SDavid du Colombier+
2762*14414594SDavid du Colombier+   req.r_type = Tnop;
2763*14414594SDavid du Colombier+   error = u9fs_request(& req, & rep, 1);
2764*14414594SDavid du Colombier+   if( error )
2765*14414594SDavid du Colombier+     return error;
2766*14414594SDavid du Colombier+
2767*14414594SDavid du Colombier+   req.r_type = Tsession;
2768*14414594SDavid du Colombier+   /* bzero(req.r_chal, sizeof(req.r_chal)); */
2769*14414594SDavid du Colombier+   u9auth_genchal(req.r_chal);
2770*14414594SDavid du Colombier+   error = u9fs_request(& req, & rep, 1);
2771*14414594SDavid du Colombier+   if( error )
2772*14414594SDavid du Colombier+     return error;
2773*14414594SDavid du Colombier+
2774*14414594SDavid du Colombier+   if( argp->authaddr ) {
2775*14414594SDavid du Colombier+     /* get tickets from the auth server */
2776*14414594SDavid du Colombier+     error = u9fs_connect_9auth(nmp, argp, & so);
2777*14414594SDavid du Colombier+     if( error )
2778*14414594SDavid du Colombier+       goto bad;
2779*14414594SDavid du Colombier+     u9p = u9fs_finduser(u9fs_name2uid(argp->user));
2780*14414594SDavid du Colombier+     error = u9auth_gettickets(so, & rep, argp->user, u9p->u_ckey,
2781*14414594SDavid du Colombier+ 			      req.r_ticket, req.r_auth, p);
2782*14414594SDavid du Colombier+     u9fs_disconnect(so);
2783*14414594SDavid du Colombier+     if( error )
2784*14414594SDavid du Colombier+       goto bad;
2785*14414594SDavid du Colombier+   }
2786*14414594SDavid du Colombier+
2787*14414594SDavid du Colombier+   req.r_type = Tattach;
2788*14414594SDavid du Colombier+   req.r_fid = u9fs_id_new(nmp->nm_fids);
2789*14414594SDavid du Colombier+   strcpy(req.r_uname, argp->user);
2790*14414594SDavid du Colombier+   strcpy(req.r_aname, mntpoint);
2791*14414594SDavid du Colombier+   error = u9fs_request(& req, & rep, 1);
2792*14414594SDavid du Colombier+   if( error )
2793*14414594SDavid du Colombier+     return error;
2794*14414594SDavid du Colombier+   nmp->nm_fh = rep.r_qid.path;
2795*14414594SDavid du Colombier+   nmp->nm_fid = req.r_fid;
2796*14414594SDavid du Colombier+   /* XXX: we should have checked our challenge to the server! */
2797*14414594SDavid du Colombier+
2798*14414594SDavid du Colombier+   /*
2799*14414594SDavid du Colombier+    * This is silly, but it has to be set so that vinifod() works.
2800*14414594SDavid du Colombier+    * We do not want to do an u9fs_statfs() here since we can get
2801*14414594SDavid du Colombier+    * stuck on a dead server and we are holding a lock on the mount
2802*14414594SDavid du Colombier+    * point.
2803*14414594SDavid du Colombier+    */
2804*14414594SDavid du Colombier+   mp->mnt_stat.f_iosize = u9fs_iosize(nmp);
2805*14414594SDavid du Colombier+
2806*14414594SDavid du Colombier+   /*
2807*14414594SDavid du Colombier+    * A reference count is needed on the u9fsnode representing the
2808*14414594SDavid du Colombier+    * remote root.  If this object is not persistent, then backward
2809*14414594SDavid du Colombier+    * traversals of the mount point (i.e. "..") will not work if
2810*14414594SDavid du Colombier+    * the u9fsnode gets flushed out of the cache. Ufs does not have
2811*14414594SDavid du Colombier+    * this problem, because one can identify root inodes by their
2812*14414594SDavid du Colombier+    * number == ROOTINO (2).
2813*14414594SDavid du Colombier+    */
2814*14414594SDavid du Colombier+   error = u9fs_nget(mp, nmp->nm_fh, &np, p);
2815*14414594SDavid du Colombier+   np->n_fid = nmp->nm_fid;
2816*14414594SDavid du Colombier+
2817*14414594SDavid du Colombier+   nmp->nm_authuid = p->p_ucred->cr_uid;
2818*14414594SDavid du Colombier+
2819*14414594SDavid du Colombier+   if (error)
2820*14414594SDavid du Colombier+     goto bad;
2821*14414594SDavid du Colombier+   *vpp = U9FSTOV(np);
2822*14414594SDavid du Colombier+
2823*14414594SDavid du Colombier+   /*
2824*14414594SDavid du Colombier+    * Get file attributes for the mountpoint.  This has the side
2825*14414594SDavid du Colombier+    * effect of filling in (*vpp)->v_type with the correct value.
2826*14414594SDavid du Colombier+    */
2827*14414594SDavid du Colombier+   VOP_GETATTR(*vpp, &attrs, p->p_ucred, p);
2828*14414594SDavid du Colombier+
2829*14414594SDavid du Colombier+   /*
2830*14414594SDavid du Colombier+    * Lose the lock but keep the ref.
2831*14414594SDavid du Colombier+    */
2832*14414594SDavid du Colombier+   VOP_UNLOCK(*vpp, 0, p);
2833*14414594SDavid du Colombier+
2834*14414594SDavid du Colombier+   return (0);
2835*14414594SDavid du Colombier+ bad:
2836*14414594SDavid du Colombier+   u9fs_disconnect(nmp->nm_so);
2837*14414594SDavid du Colombier+   zfree(u9fsmount_zone, nmp);
2838*14414594SDavid du Colombier+   FREE(nam, M_SONAME);
2839*14414594SDavid du Colombier+   return (error);
2840*14414594SDavid du Colombier+ }
2841*14414594SDavid du Colombier+
2842*14414594SDavid du Colombier+ /*
2843*14414594SDavid du Colombier+  * VFS Operations.
2844*14414594SDavid du Colombier+  *
2845*14414594SDavid du Colombier+  * mount system call
2846*14414594SDavid du Colombier+  * It seems a bit dumb to copyinstr() the host and path here and then
2847*14414594SDavid du Colombier+  * bcopy() them in mountu9fs(), but I wanted to detect errors before
2848*14414594SDavid du Colombier+  * doing the sockargs() call because sockargs() allocates an mbuf and
2849*14414594SDavid du Colombier+  * an error after that means that I have to release the mbuf.
2850*14414594SDavid du Colombier+  */
2851*14414594SDavid du Colombier+ /* ARGSUSED */
2852*14414594SDavid du Colombier+ static int
2853*14414594SDavid du Colombier+ u9fs_mount(mp, path, data, ndp, p)
2854*14414594SDavid du Colombier+ 	struct mount *mp;
2855*14414594SDavid du Colombier+ 	char *path;
2856*14414594SDavid du Colombier+ 	caddr_t data;
2857*14414594SDavid du Colombier+ 	struct nameidata *ndp;
2858*14414594SDavid du Colombier+ 	struct proc *p;
2859*14414594SDavid du Colombier+ {
2860*14414594SDavid du Colombier+   int error;
2861*14414594SDavid du Colombier+   struct u9fs_args args;
2862*14414594SDavid du Colombier+   struct sockaddr *nam;
2863*14414594SDavid du Colombier+   struct vnode *vp;
2864*14414594SDavid du Colombier+   char pth[MNAMELEN], hst[MNAMELEN];
2865*14414594SDavid du Colombier+   size_t len;
2866*14414594SDavid du Colombier+
2867*14414594SDavid du Colombier+   if( path == NULL )
2868*14414594SDavid du Colombier+     return (EOPNOTSUPP);
2869*14414594SDavid du Colombier+
2870*14414594SDavid du Colombier+   error = copyin(data, (caddr_t)&args, sizeof (struct u9fs_args));
2871*14414594SDavid du Colombier+   if (error)
2872*14414594SDavid du Colombier+     return (error);
2873*14414594SDavid du Colombier+
2874*14414594SDavid du Colombier+   if (args.version != U9FS_ARGSVERSION)
2875*14414594SDavid du Colombier+     return (EPROGMISMATCH);
2876*14414594SDavid du Colombier+
2877*14414594SDavid du Colombier+   if (mp->mnt_flag & MNT_UPDATE) {
2878*14414594SDavid du Colombier+ #if 0
2879*14414594SDavid du Colombier+     register struct u9fsmount *nmp = VFSTONFS(mp);
2880*14414594SDavid du Colombier+
2881*14414594SDavid du Colombier+     if (nmp == NULL)
2882*14414594SDavid du Colombier+       return (EIO);
2883*14414594SDavid du Colombier+     /*
2884*14414594SDavid du Colombier+      * When doing an update, we can't change from or to
2885*14414594SDavid du Colombier+      * v3 and/or nqu9fs, or change cookie translation
2886*14414594SDavid du Colombier+      */
2887*14414594SDavid du Colombier+     args.flags = (args.flags &
2888*14414594SDavid du Colombier+ 		  ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) |
2889*14414594SDavid du Colombier+       (nmp->nm_flag &
2890*14414594SDavid du Colombier+        (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/));
2891*14414594SDavid du Colombier+     u9fs_decode_args(nmp, &args, p);
2892*14414594SDavid du Colombier+ #endif
2893*14414594SDavid du Colombier+     return (0);
2894*14414594SDavid du Colombier+   }
2895*14414594SDavid du Colombier+
2896*14414594SDavid du Colombier+   error = copyinstr(path, pth, MNAMELEN-1, &len);
2897*14414594SDavid du Colombier+   if (error)
2898*14414594SDavid du Colombier+     return (error);
2899*14414594SDavid du Colombier+   bzero(&pth[len], MNAMELEN - len);
2900*14414594SDavid du Colombier+   error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
2901*14414594SDavid du Colombier+   if (error)
2902*14414594SDavid du Colombier+     return (error);
2903*14414594SDavid du Colombier+   bzero(&hst[len], MNAMELEN - len);
2904*14414594SDavid du Colombier+   /* sockargs() call must be after above copyin() calls */
2905*14414594SDavid du Colombier+   error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
2906*14414594SDavid du Colombier+   if (error)
2907*14414594SDavid du Colombier+     return (error);
2908*14414594SDavid du Colombier+   error = mountu9fs(&args, mp, nam, pth, hst, &vp, p);
2909*14414594SDavid du Colombier+   return (error);
2910*14414594SDavid du Colombier+ }
2911*14414594SDavid du Colombier+
2912*14414594SDavid du Colombier+ /*
2913*14414594SDavid du Colombier+  * unmount system call
2914*14414594SDavid du Colombier+  */
2915*14414594SDavid du Colombier+ static int
2916*14414594SDavid du Colombier+ u9fs_unmount(mp, mntflags, p)
2917*14414594SDavid du Colombier+      struct mount *mp;
2918*14414594SDavid du Colombier+      int mntflags;
2919*14414594SDavid du Colombier+      struct proc *p;
2920*14414594SDavid du Colombier+ {
2921*14414594SDavid du Colombier+   register struct u9fsmount *nmp;
2922*14414594SDavid du Colombier+   struct u9fsnode *np;
2923*14414594SDavid du Colombier+   struct vnode *vp;
2924*14414594SDavid du Colombier+   int error, flags = 0;
2925*14414594SDavid du Colombier+
2926*14414594SDavid du Colombier+   if (mntflags & MNT_FORCE)
2927*14414594SDavid du Colombier+     flags |= FORCECLOSE;
2928*14414594SDavid du Colombier+   nmp = VFSTOU9FS(mp);
2929*14414594SDavid du Colombier+
2930*14414594SDavid du Colombier+   if( p->p_ucred->cr_uid != nmp->nm_authuid )
2931*14414594SDavid du Colombier+     return (EPERM);
2932*14414594SDavid du Colombier+
2933*14414594SDavid du Colombier+   /*
2934*14414594SDavid du Colombier+    * Goes something like this..
2935*14414594SDavid du Colombier+    * - Check for activity on the root vnode (other than ourselves).
2936*14414594SDavid du Colombier+    * - Call vflush() to clear out vnodes for this file system,
2937*14414594SDavid du Colombier+    *   except for the root vnode.
2938*14414594SDavid du Colombier+    * - Decrement reference on the vnode representing remote root.
2939*14414594SDavid du Colombier+    * - Close the socket
2940*14414594SDavid du Colombier+    * - Free up the data structures
2941*14414594SDavid du Colombier+    */
2942*14414594SDavid du Colombier+   /*
2943*14414594SDavid du Colombier+    * We need to decrement the ref. count on the u9fsnode representing
2944*14414594SDavid du Colombier+    * the remote root.  See comment in mountu9fs().  The VFS unmount()
2945*14414594SDavid du Colombier+    * has done vput on this vnode, otherwise we would get deadlock!
2946*14414594SDavid du Colombier+    */
2947*14414594SDavid du Colombier+   error = u9fs_nget(mp, nmp->nm_fh, &np, p);
2948*14414594SDavid du Colombier+   if (error)
2949*14414594SDavid du Colombier+     return(error);
2950*14414594SDavid du Colombier+   vp = U9FSTOV(np);
2951*14414594SDavid du Colombier+   if (vp->v_usecount > 2) {
2952*14414594SDavid du Colombier+     vput(vp);
2953*14414594SDavid du Colombier+     return (EBUSY);
2954*14414594SDavid du Colombier+   }
2955*14414594SDavid du Colombier+
2956*14414594SDavid du Colombier+   error = vflush(mp, vp, flags);
2957*14414594SDavid du Colombier+   if (error) {
2958*14414594SDavid du Colombier+     vput(vp);
2959*14414594SDavid du Colombier+     return (error);
2960*14414594SDavid du Colombier+   }
2961*14414594SDavid du Colombier+
2962*14414594SDavid du Colombier+   /*
2963*14414594SDavid du Colombier+    * We are now committed to the unmount.
2964*14414594SDavid du Colombier+    */
2965*14414594SDavid du Colombier+   /*
2966*14414594SDavid du Colombier+    * There are two reference counts and one lock to get rid of here.
2967*14414594SDavid du Colombier+    */
2968*14414594SDavid du Colombier+   vput(vp);
2969*14414594SDavid du Colombier+   vrele(vp);
2970*14414594SDavid du Colombier+   vgone(vp);
2971*14414594SDavid du Colombier+   u9fs_disconnect(nmp->nm_so);
2972*14414594SDavid du Colombier+   FREE(nmp->nm_nam, M_SONAME);
2973*14414594SDavid du Colombier+
2974*14414594SDavid du Colombier+   zfree(u9fsmount_zone, nmp);
2975*14414594SDavid du Colombier+   return (0);
2976*14414594SDavid du Colombier+ }
2977*14414594SDavid du Colombier+
2978*14414594SDavid du Colombier+ /*
2979*14414594SDavid du Colombier+  * Return root of a filesystem
2980*14414594SDavid du Colombier+  */
2981*14414594SDavid du Colombier+ static int
2982*14414594SDavid du Colombier+ u9fs_root(mp, vpp)
2983*14414594SDavid du Colombier+ 	struct mount *mp;
2984*14414594SDavid du Colombier+ 	struct vnode **vpp;
2985*14414594SDavid du Colombier+ {
2986*14414594SDavid du Colombier+         register struct vnode *vp;
2987*14414594SDavid du Colombier+         struct u9fsmount *nmp;
2988*14414594SDavid du Colombier+         struct u9fsnode *np;
2989*14414594SDavid du Colombier+         int error;
2990*14414594SDavid du Colombier+
2991*14414594SDavid du Colombier+         nmp = VFSTOU9FS(mp);
2992*14414594SDavid du Colombier+         error = u9fs_nget(mp, nmp->nm_fh, &np, curproc); /* XXX */
2993*14414594SDavid du Colombier+         if (error)
2994*14414594SDavid du Colombier+                 return (error);
2995*14414594SDavid du Colombier+         vp = U9FSTOV(np);
2996*14414594SDavid du Colombier+         if (vp->v_type == VNON)
2997*14414594SDavid du Colombier+             vp->v_type = VDIR;
2998*14414594SDavid du Colombier+         vp->v_flag = VROOT;
2999*14414594SDavid du Colombier+         *vpp = vp;
3000*14414594SDavid du Colombier+         return (0);
3001*14414594SDavid du Colombier+ }
3002*14414594SDavid du Colombier+
3003*14414594SDavid du Colombier+ extern int syncprt;
3004*14414594SDavid du Colombier+
3005*14414594SDavid du Colombier+ /*
3006*14414594SDavid du Colombier+  * Flush out the buffer cache
3007*14414594SDavid du Colombier+  */
3008*14414594SDavid du Colombier+ /* ARGSUSED */
3009*14414594SDavid du Colombier+ static int
3010*14414594SDavid du Colombier+ u9fs_sync(mp, waitfor, cred, p)
3011*14414594SDavid du Colombier+ 	struct mount *mp;
3012*14414594SDavid du Colombier+ 	int waitfor;
3013*14414594SDavid du Colombier+ 	struct ucred *cred;
3014*14414594SDavid du Colombier+ 	struct proc *p;
3015*14414594SDavid du Colombier+ {
3016*14414594SDavid du Colombier+   /* no cache yet */
3017*14414594SDavid du Colombier+   return 0;
3018*14414594SDavid du Colombier+ }
3019*14414594SDavid du Colombier+
3020*14414594SDavid du Colombier+ /*
3021*14414594SDavid du Colombier+  * U9FS flat namespace lookup.
3022*14414594SDavid du Colombier+  * Currently unsupported.
3023*14414594SDavid du Colombier+  */
3024*14414594SDavid du Colombier+ /* ARGSUSED */
3025*14414594SDavid du Colombier+ static int
3026*14414594SDavid du Colombier+ u9fs_vget(mp, ino, vpp)
3027*14414594SDavid du Colombier+ 	struct mount *mp;
3028*14414594SDavid du Colombier+ 	ino_t ino;
3029*14414594SDavid du Colombier+ 	struct vnode **vpp;
3030*14414594SDavid du Colombier+ {
3031*14414594SDavid du Colombier+
3032*14414594SDavid du Colombier+ 	return (EOPNOTSUPP);
3033*14414594SDavid du Colombier+ }
3034*14414594SDavid du Colombier+
3035*14414594SDavid du Colombier+ /*
3036*14414594SDavid du Colombier+  * At this point, this should never happen
3037*14414594SDavid du Colombier+  */
3038*14414594SDavid du Colombier+ /* ARGSUSED */
3039*14414594SDavid du Colombier+ static int
3040*14414594SDavid du Colombier+ u9fs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
3041*14414594SDavid du Colombier+ 	register struct mount *mp;
3042*14414594SDavid du Colombier+ 	struct fid *fhp;
3043*14414594SDavid du Colombier+ 	struct sockaddr *nam;
3044*14414594SDavid du Colombier+ 	struct vnode **vpp;
3045*14414594SDavid du Colombier+ 	int *exflagsp;
3046*14414594SDavid du Colombier+ 	struct ucred **credanonp;
3047*14414594SDavid du Colombier+ {
3048*14414594SDavid du Colombier+
3049*14414594SDavid du Colombier+ 	return (EINVAL);
3050*14414594SDavid du Colombier+ }
3051*14414594SDavid du Colombier+
3052*14414594SDavid du Colombier+ /*
3053*14414594SDavid du Colombier+  * Vnode pointer to File handle, should never happen either
3054*14414594SDavid du Colombier+  */
3055*14414594SDavid du Colombier+ /* ARGSUSED */
3056*14414594SDavid du Colombier+ static int
3057*14414594SDavid du Colombier+ u9fs_vptofh(vp, fhp)
3058*14414594SDavid du Colombier+ 	struct vnode *vp;
3059*14414594SDavid du Colombier+ 	struct fid *fhp;
3060*14414594SDavid du Colombier+ {
3061*14414594SDavid du Colombier+
3062*14414594SDavid du Colombier+ 	return (EINVAL);
3063*14414594SDavid du Colombier+ }
3064*14414594SDavid du Colombier+
3065*14414594SDavid du Colombier+ /*
3066*14414594SDavid du Colombier+  * Vfs start routine, a no-op.
3067*14414594SDavid du Colombier+  */
3068*14414594SDavid du Colombier+ /* ARGSUSED */
3069*14414594SDavid du Colombier+ static int
3070*14414594SDavid du Colombier+ u9fs_start(mp, flags, p)
3071*14414594SDavid du Colombier+ 	struct mount *mp;
3072*14414594SDavid du Colombier+ 	int flags;
3073*14414594SDavid du Colombier+ 	struct proc *p;
3074*14414594SDavid du Colombier+ {
3075*14414594SDavid du Colombier+
3076*14414594SDavid du Colombier+ 	return (0);
3077*14414594SDavid du Colombier+ }
3078*14414594SDavid du Colombier+
3079*14414594SDavid du Colombier+ /*
3080*14414594SDavid du Colombier+  * Do operations associated with quotas, not supported
3081*14414594SDavid du Colombier+  */
3082*14414594SDavid du Colombier+ /* ARGSUSED */
3083*14414594SDavid du Colombier+ static int
3084*14414594SDavid du Colombier+ u9fs_quotactl(mp, cmd, uid, arg, p)
3085*14414594SDavid du Colombier+ 	struct mount *mp;
3086*14414594SDavid du Colombier+ 	int cmd;
3087*14414594SDavid du Colombier+ 	uid_t uid;
3088*14414594SDavid du Colombier+ 	caddr_t arg;
3089*14414594SDavid du Colombier+ 	struct proc *p;
3090*14414594SDavid du Colombier+ {
3091*14414594SDavid du Colombier+
3092*14414594SDavid du Colombier+ 	return (EOPNOTSUPP);
3093*14414594SDavid du Colombier+ }
3094*14414594SDavid du Colombier+
3095*14414594SDavid du Colombier+ /*
3096*14414594SDavid du Colombier+  * Called once to initialize data structures...
3097*14414594SDavid du Colombier+  */
3098*14414594SDavid du Colombier+ int
3099*14414594SDavid du Colombier+ u9fs_init(vfsp)
3100*14414594SDavid du Colombier+ 	struct vfsconf *vfsp;
3101*14414594SDavid du Colombier+ {
3102*14414594SDavid du Colombier+   u9fsmount_zone = zinit("U9FSMOUNT", sizeof(struct u9fsmount), 0, 0, 1);
3103*14414594SDavid du Colombier+   u9fs_nhinit();			/* Init the u9fsnode table */
3104*14414594SDavid du Colombier+   u9fs_uhinit();
3105*14414594SDavid du Colombier+   return 0;
3106*14414594SDavid du Colombier+ }
3107*14414594SDavid du Colombier+
3108*14414594SDavid du Colombier+ int
3109*14414594SDavid du Colombier+ u9fs_uninit(vfsp)
3110*14414594SDavid du Colombier+ 	struct vfsconf *vfsp;
3111*14414594SDavid du Colombier+ {
3112*14414594SDavid du Colombier+   return 0;
3113*14414594SDavid du Colombier+ }
3114*14414594SDavid du Colombier+
3115*14414594SDavid du Colombier+ static int
3116*14414594SDavid du Colombier+ u9fs_iosize(nmp)
3117*14414594SDavid du Colombier+      struct u9fsmount* nmp;
3118*14414594SDavid du Colombier+ {
3119*14414594SDavid du Colombier+   int iosize;
3120*14414594SDavid du Colombier+
3121*14414594SDavid du Colombier+   /*
3122*14414594SDavid du Colombier+    * Calculate the size used for io buffers.  Use the larger
3123*14414594SDavid du Colombier+    * of the two sizes to minimise u9fs requests but make sure
3124*14414594SDavid du Colombier+    * that it is at least one VM page to avoid wasting buffer
3125*14414594SDavid du Colombier+    * space.
3126*14414594SDavid du Colombier+    */
3127*14414594SDavid du Colombier+   iosize = max(nmp->nm_rsize, nmp->nm_wsize);
3128*14414594SDavid du Colombier+   if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
3129*14414594SDavid du Colombier+   return iosize;
3130*14414594SDavid du Colombier+ }
3131*14414594SDavid du Colombier+
3132*14414594SDavid du Colombier+ static void
3133*14414594SDavid du Colombier+ u9fs_decode_args(nmp, argp, p)
3134*14414594SDavid du Colombier+      struct u9fsmount *nmp;
3135*14414594SDavid du Colombier+      struct u9fs_args *argp;
3136*14414594SDavid du Colombier+      struct proc * p;
3137*14414594SDavid du Colombier+ {
3138*14414594SDavid du Colombier+   int s, i;
3139*14414594SDavid du Colombier+   int maxio;
3140*14414594SDavid du Colombier+   struct p9user * p9p, p9u;
3141*14414594SDavid du Colombier+   struct u9fsuser * u9p;
3142*14414594SDavid du Colombier+
3143*14414594SDavid du Colombier+   s = splnet();
3144*14414594SDavid du Colombier+   /* Update flags atomically.  Don't change the lock bits. */
3145*14414594SDavid du Colombier+   nmp->nm_flag = argp->flags | nmp->nm_flag;
3146*14414594SDavid du Colombier+   splx(s);
3147*14414594SDavid du Colombier+
3148*14414594SDavid du Colombier+   maxio = U9FS_MAXFDATA;
3149*14414594SDavid du Colombier+
3150*14414594SDavid du Colombier+   if (argp->wsize > 0) {
3151*14414594SDavid du Colombier+     nmp->nm_wsize = argp->wsize;
3152*14414594SDavid du Colombier+     /* Round down to multiple of blocksize */
3153*14414594SDavid du Colombier+     nmp->nm_wsize &= ~(U9FS_FABLKSIZE - 1);
3154*14414594SDavid du Colombier+     if (nmp->nm_wsize <= 0)
3155*14414594SDavid du Colombier+       nmp->nm_wsize = U9FS_FABLKSIZE;
3156*14414594SDavid du Colombier+   }
3157*14414594SDavid du Colombier+   if (nmp->nm_wsize > maxio)
3158*14414594SDavid du Colombier+     nmp->nm_wsize = maxio;
3159*14414594SDavid du Colombier+   if (nmp->nm_wsize > MAXBSIZE)
3160*14414594SDavid du Colombier+     nmp->nm_wsize = MAXBSIZE;
3161*14414594SDavid du Colombier+
3162*14414594SDavid du Colombier+   if (argp->rsize > 0) {
3163*14414594SDavid du Colombier+     nmp->nm_rsize = argp->rsize;
3164*14414594SDavid du Colombier+     /* Round down to multiple of blocksize */
3165*14414594SDavid du Colombier+     nmp->nm_rsize &= ~(U9FS_FABLKSIZE - 1);
3166*14414594SDavid du Colombier+     if (nmp->nm_rsize <= 0)
3167*14414594SDavid du Colombier+       nmp->nm_rsize = U9FS_FABLKSIZE;
3168*14414594SDavid du Colombier+   }
3169*14414594SDavid du Colombier+   if (nmp->nm_rsize > maxio)
3170*14414594SDavid du Colombier+     nmp->nm_rsize = maxio;
3171*14414594SDavid du Colombier+   if (nmp->nm_rsize > MAXBSIZE)
3172*14414594SDavid du Colombier+     nmp->nm_rsize = MAXBSIZE;
3173*14414594SDavid du Colombier+
3174*14414594SDavid du Colombier+   if (argp->readdirsize > 0) {
3175*14414594SDavid du Colombier+     nmp->nm_readdirsize = argp->readdirsize;
3176*14414594SDavid du Colombier+   }
3177*14414594SDavid du Colombier+   if (nmp->nm_readdirsize > maxio)
3178*14414594SDavid du Colombier+     nmp->nm_readdirsize = maxio;
3179*14414594SDavid du Colombier+   if (nmp->nm_readdirsize > nmp->nm_rsize)
3180*14414594SDavid du Colombier+     nmp->nm_readdirsize = nmp->nm_rsize;
3181*14414594SDavid du Colombier+
3182*14414594SDavid du Colombier+   if( argp->nusers ) {
3183*14414594SDavid du Colombier+     p9p = argp->users;
3184*14414594SDavid du Colombier+     for(i = 0; i < argp->nusers; i++) {
3185*14414594SDavid du Colombier+       copyin(p9p, &p9u, sizeof(p9u));
3186*14414594SDavid du Colombier+       u9fs_hashuser(p9u.p9_uid, p9u.p9_name);
3187*14414594SDavid du Colombier+       p9p ++;
3188*14414594SDavid du Colombier+     }
3189*14414594SDavid du Colombier+     printf("%d p9users loaded\n", argp->nusers);
3190*14414594SDavid du Colombier+   }
3191*14414594SDavid du Colombier+
3192*14414594SDavid du Colombier+   if( (u9p = u9fs_finduser(u9fs_name2uid(argp->user))) ) {
3193*14414594SDavid du Colombier+     bcopy(argp->key, u9p->u_ckey, U9AUTH_DESKEYLEN);
3194*14414594SDavid du Colombier+   }
3195*14414594SDavid du Colombier+ }
3196*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_vnops.c ./9fs/9fs_vnops.c
3197*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_vnops.c	Wed Dec 31 19:00:00 1969
3198*14414594SDavid du Colombier--- ./9fs/9fs_vnops.c	Mon May 22 11:40:00 2000
3199*14414594SDavid du Colombier***************
3200*14414594SDavid du Colombier*** 0 ****
3201*14414594SDavid du Colombier--- 1,1794 ----
3202*14414594SDavid du Colombier+ /*
3203*14414594SDavid du Colombier+  * Copyright (c) 1989, 1993
3204*14414594SDavid du Colombier+  *	The Regents of the University of California.  All rights reserved.
3205*14414594SDavid du Colombier+  *
3206*14414594SDavid du Colombier+  * This code is derived from software contributed to Berkeley by
3207*14414594SDavid du Colombier+  * Rick Macklem at The University of Guelph.
3208*14414594SDavid du Colombier+  *
3209*14414594SDavid du Colombier+  * Redistribution and use in source and binary forms, with or without
3210*14414594SDavid du Colombier+  * modification, are permitted provided that the following conditions
3211*14414594SDavid du Colombier+  * are met:
3212*14414594SDavid du Colombier+  * 1. Redistributions of source code must retain the above copyright
3213*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer.
3214*14414594SDavid du Colombier+  * 2. Redistributions in binary form must reproduce the above copyright
3215*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer in the
3216*14414594SDavid du Colombier+  *    documentation and/or other materials provided with the distribution.
3217*14414594SDavid du Colombier+  * 3. All advertising materials mentioning features or use of this software
3218*14414594SDavid du Colombier+  *    must display the following acknowledgement:
3219*14414594SDavid du Colombier+  *	This product includes software developed by the University of
3220*14414594SDavid du Colombier+  *	California, Berkeley and its contributors.
3221*14414594SDavid du Colombier+  * 4. Neither the name of the University nor the names of its contributors
3222*14414594SDavid du Colombier+  *    may be used to endorse or promote products derived from this software
3223*14414594SDavid du Colombier+  *    without specific prior written permission.
3224*14414594SDavid du Colombier+  *
3225*14414594SDavid du Colombier+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3226*14414594SDavid du Colombier+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3227*14414594SDavid du Colombier+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3228*14414594SDavid du Colombier+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3229*14414594SDavid du Colombier+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3230*14414594SDavid du Colombier+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3231*14414594SDavid du Colombier+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3232*14414594SDavid du Colombier+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3233*14414594SDavid du Colombier+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3234*14414594SDavid du Colombier+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3235*14414594SDavid du Colombier+  * SUCH DAMAGE.
3236*14414594SDavid du Colombier+  *
3237*14414594SDavid du Colombier+  *	@(#)u9fs_vnops.c	8.16 (Berkeley) 5/27/95
3238*14414594SDavid du Colombier+  * $Id: u9fs_vnops.c,v 1.116.2.3 1999/02/13 08:03:47 dillon Exp $
3239*14414594SDavid du Colombier+  */
3240*14414594SDavid du Colombier+
3241*14414594SDavid du Colombier+
3242*14414594SDavid du Colombier+ /*
3243*14414594SDavid du Colombier+  * vnode op calls for 9FS
3244*14414594SDavid du Colombier+  */
3245*14414594SDavid du Colombier+
3246*14414594SDavid du Colombier+ #include "opt_inet.h"
3247*14414594SDavid du Colombier+
3248*14414594SDavid du Colombier+ #include <sys/param.h>
3249*14414594SDavid du Colombier+ #include <sys/kernel.h>
3250*14414594SDavid du Colombier+ #include <sys/systm.h>
3251*14414594SDavid du Colombier+ #include <sys/resourcevar.h>
3252*14414594SDavid du Colombier+ #include <sys/proc.h>
3253*14414594SDavid du Colombier+ #include <sys/mount.h>
3254*14414594SDavid du Colombier+ #include <sys/buf.h>
3255*14414594SDavid du Colombier+ #include <sys/malloc.h>
3256*14414594SDavid du Colombier+ #include <sys/mbuf.h>
3257*14414594SDavid du Colombier+ #include <sys/namei.h>
3258*14414594SDavid du Colombier+ #include <sys/socket.h>
3259*14414594SDavid du Colombier+ #include <sys/vnode.h>
3260*14414594SDavid du Colombier+ #include <sys/dirent.h>
3261*14414594SDavid du Colombier+ #include <sys/fcntl.h>
3262*14414594SDavid du Colombier+ #include <sys/lockf.h>
3263*14414594SDavid du Colombier+ #include <sys/stat.h>
3264*14414594SDavid du Colombier+ #include <sys/sysctl.h>
3265*14414594SDavid du Colombier+
3266*14414594SDavid du Colombier+ #include <vm/vm.h>
3267*14414594SDavid du Colombier+ #include <vm/vm_extern.h>
3268*14414594SDavid du Colombier+ #include <vm/vm_zone.h>
3269*14414594SDavid du Colombier+ #include <vm/vm_prot.h>
3270*14414594SDavid du Colombier+ #include <vm/vm_page.h>
3271*14414594SDavid du Colombier+ #include <vm/vm_object.h>
3272*14414594SDavid du Colombier+ #include <vm/vm_pager.h>
3273*14414594SDavid du Colombier+ #include <vm/vnode_pager.h>
3274*14414594SDavid du Colombier+
3275*14414594SDavid du Colombier+ #include <net/if.h>
3276*14414594SDavid du Colombier+ #include <netinet/in.h>
3277*14414594SDavid du Colombier+ #include <netinet/in_var.h>
3278*14414594SDavid du Colombier+
3279*14414594SDavid du Colombier+ #include <9fs/bitstring.h>
3280*14414594SDavid du Colombier+ #include <9fs/9p.h>
3281*14414594SDavid du Colombier+ #include <9fs/9auth.h>
3282*14414594SDavid du Colombier+ #include <9fs/9fs.h>
3283*14414594SDavid du Colombier+
3284*14414594SDavid du Colombier+ #define u9fs_poll vop_nopoll
3285*14414594SDavid du Colombier+ static	int	u9fs_lookup __P((struct vop_lookup_args *));
3286*14414594SDavid du Colombier+ static	int	u9fs_create __P((struct vop_create_args *));
3287*14414594SDavid du Colombier+ static	int	u9fs_mknod __P((struct vop_mknod_args *));
3288*14414594SDavid du Colombier+ static	int	u9fs_open __P((struct vop_open_args *));
3289*14414594SDavid du Colombier+ static	int	u9fs_close __P((struct vop_close_args *));
3290*14414594SDavid du Colombier+ static	int	u9fs_access __P((struct vop_access_args *));
3291*14414594SDavid du Colombier+ static	int	u9fs_getattr __P((struct vop_getattr_args *));
3292*14414594SDavid du Colombier+ static	int	u9fs_setattr __P((struct vop_setattr_args *));
3293*14414594SDavid du Colombier+ static	int	u9fs_read __P((struct vop_read_args *));
3294*14414594SDavid du Colombier+ static	int	u9fs_mmap __P((struct vop_mmap_args *));
3295*14414594SDavid du Colombier+ static	int	u9fs_fsync __P((struct vop_fsync_args *));
3296*14414594SDavid du Colombier+ static	int	u9fs_remove __P((struct vop_remove_args *));
3297*14414594SDavid du Colombier+ static	int	u9fs_link __P((struct vop_link_args *));
3298*14414594SDavid du Colombier+ static	int	u9fs_rename __P((struct vop_rename_args *));
3299*14414594SDavid du Colombier+ static	int	u9fs_mkdir __P((struct vop_mkdir_args *));
3300*14414594SDavid du Colombier+ static	int	u9fs_rmdir __P((struct vop_rmdir_args *));
3301*14414594SDavid du Colombier+ static	int	u9fs_symlink __P((struct vop_symlink_args *));
3302*14414594SDavid du Colombier+ static	int	u9fs_readdir __P((struct vop_readdir_args *));
3303*14414594SDavid du Colombier+ static	int	u9fs_bmap __P((struct vop_bmap_args *));
3304*14414594SDavid du Colombier+ static	int	u9fs_strategy __P((struct vop_strategy_args *));
3305*14414594SDavid du Colombier+ static int	u9fs_readlink __P((struct vop_readlink_args *));
3306*14414594SDavid du Colombier+ static int	u9fs_print __P((struct vop_print_args *));
3307*14414594SDavid du Colombier+ static int	u9fs_advlock __P((struct vop_advlock_args *));
3308*14414594SDavid du Colombier+ static int	u9fs_bwrite __P((struct vop_bwrite_args *));
3309*14414594SDavid du Colombier+ static int   u9fs_abortop __P((struct vop_abortop_args *));
3310*14414594SDavid du Colombier+ static int   u9fs_getpages __P((struct vop_getpages_args *));
3311*14414594SDavid du Colombier+ static int   u9fs_putpages __P((struct vop_putpages_args *));
3312*14414594SDavid du Colombier+ static int   u9fs_inactive __P((struct vop_inactive_args *));
3313*14414594SDavid du Colombier+ static int   u9fs_reclaim __P((struct vop_reclaim_args *));
3314*14414594SDavid du Colombier+ static int   u9fs_write __P((struct vop_write_args *));
3315*14414594SDavid du Colombier+
3316*14414594SDavid du Colombier+ /*
3317*14414594SDavid du Colombier+  * Global vfs data structures for u9fs
3318*14414594SDavid du Colombier+  */
3319*14414594SDavid du Colombier+ vop_t **u9fs_vnodeop_p;
3320*14414594SDavid du Colombier+ static struct vnodeopv_entry_desc u9fs_vnodeop_entries[] = {
3321*14414594SDavid du Colombier+ 	{ &vop_default_desc,		(vop_t *) vop_defaultop },
3322*14414594SDavid du Colombier+ 	{ &vop_abortop_desc,		(vop_t *) u9fs_abortop },
3323*14414594SDavid du Colombier+ 	{ &vop_access_desc,		(vop_t *) u9fs_access },
3324*14414594SDavid du Colombier+ 	{ &vop_advlock_desc,		(vop_t *) u9fs_advlock },
3325*14414594SDavid du Colombier+ 	{ &vop_bmap_desc,		(vop_t *) u9fs_bmap },
3326*14414594SDavid du Colombier+ 	{ &vop_bwrite_desc,		(vop_t *) u9fs_bwrite },
3327*14414594SDavid du Colombier+ 	{ &vop_close_desc,		(vop_t *) u9fs_close },
3328*14414594SDavid du Colombier+ 	{ &vop_create_desc,		(vop_t *) u9fs_create },
3329*14414594SDavid du Colombier+ 	{ &vop_fsync_desc,		(vop_t *) u9fs_fsync },
3330*14414594SDavid du Colombier+ 	{ &vop_getattr_desc,		(vop_t *) u9fs_getattr },
3331*14414594SDavid du Colombier+ 	{ &vop_getpages_desc,		(vop_t *) u9fs_getpages },
3332*14414594SDavid du Colombier+ 	{ &vop_putpages_desc,		(vop_t *) u9fs_putpages },
3333*14414594SDavid du Colombier+ 	{ &vop_inactive_desc,		(vop_t *) u9fs_inactive },
3334*14414594SDavid du Colombier+ 	{ &vop_lease_desc,		(vop_t *) vop_null },
3335*14414594SDavid du Colombier+ 	{ &vop_link_desc,		(vop_t *) u9fs_link },
3336*14414594SDavid du Colombier+ 	{ &vop_lock_desc,		(vop_t *) vop_sharedlock },
3337*14414594SDavid du Colombier+ 	{ &vop_lookup_desc,		(vop_t *) u9fs_lookup },
3338*14414594SDavid du Colombier+ 	{ &vop_mkdir_desc,		(vop_t *) u9fs_mkdir },
3339*14414594SDavid du Colombier+ 	{ &vop_mknod_desc,		(vop_t *) u9fs_mknod },
3340*14414594SDavid du Colombier+ 	{ &vop_mmap_desc,		(vop_t *) u9fs_mmap },
3341*14414594SDavid du Colombier+ 	{ &vop_open_desc,		(vop_t *) u9fs_open },
3342*14414594SDavid du Colombier+ 	{ &vop_poll_desc,		(vop_t *) vop_nopoll },
3343*14414594SDavid du Colombier+ 	{ &vop_print_desc,		(vop_t *) u9fs_print },
3344*14414594SDavid du Colombier+ 	{ &vop_read_desc,		(vop_t *) u9fs_read },
3345*14414594SDavid du Colombier+ 	{ &vop_readdir_desc,		(vop_t *) u9fs_readdir },
3346*14414594SDavid du Colombier+ 	{ &vop_readlink_desc,		(vop_t *) u9fs_readlink },
3347*14414594SDavid du Colombier+ 	{ &vop_reclaim_desc,		(vop_t *) u9fs_reclaim },
3348*14414594SDavid du Colombier+ 	{ &vop_remove_desc,		(vop_t *) u9fs_remove },
3349*14414594SDavid du Colombier+ 	{ &vop_rename_desc,		(vop_t *) u9fs_rename },
3350*14414594SDavid du Colombier+ 	{ &vop_rmdir_desc,		(vop_t *) u9fs_rmdir },
3351*14414594SDavid du Colombier+ 	{ &vop_setattr_desc,		(vop_t *) u9fs_setattr },
3352*14414594SDavid du Colombier+ 	{ &vop_strategy_desc,		(vop_t *) u9fs_strategy },
3353*14414594SDavid du Colombier+ 	{ &vop_symlink_desc,		(vop_t *) u9fs_symlink },
3354*14414594SDavid du Colombier+ 	{ &vop_write_desc,		(vop_t *) u9fs_write },
3355*14414594SDavid du Colombier+ 	{ NULL, NULL }
3356*14414594SDavid du Colombier+ };
3357*14414594SDavid du Colombier+ static struct vnodeopv_desc u9fs_vnodeop_opv_desc =
3358*14414594SDavid du Colombier+ 	{ &u9fs_vnodeop_p, u9fs_vnodeop_entries };
3359*14414594SDavid du Colombier+ VNODEOP_SET(u9fs_vnodeop_opv_desc);
3360*14414594SDavid du Colombier+
3361*14414594SDavid du Colombier+ extern vm_zone_t u9fsnode_zone;
3362*14414594SDavid du Colombier+
3363*14414594SDavid du Colombier+ static int u9fs_trunc(struct vnode * vp, struct ucred * cred, struct proc * p);
3364*14414594SDavid du Colombier+ static void u9fs_free_fid __P((u_short fid, struct u9fsmount * nmp, struct proc * p));
3365*14414594SDavid du Colombier+ static void u9fs_updtcache __P((struct u9fsnode *, struct u9fsreq *));
3366*14414594SDavid du Colombier+
3367*14414594SDavid du Colombier+ #define     DIRHDSIZ        (sizeof (struct dirent) - (MAXNAMLEN + 1))
3368*14414594SDavid du Colombier+
3369*14414594SDavid du Colombier+ /* open returns a qid for cache consistent check */
3370*14414594SDavid du Colombier+ static void
3371*14414594SDavid du Colombier+ u9fs_updtcache(struct u9fsnode * np, struct u9fsreq * rep)
3372*14414594SDavid du Colombier+ {
3373*14414594SDavid du Colombier+   if( rep->r_type != Rerror )
3374*14414594SDavid du Colombier+     np->n_dir.dir_qid = rep->r_qid;
3375*14414594SDavid du Colombier+ }
3376*14414594SDavid du Colombier+
3377*14414594SDavid du Colombier+ static int
3378*14414594SDavid du Colombier+ u9fs_trunc(vp, cred, p)
3379*14414594SDavid du Colombier+      register struct vnode * vp;
3380*14414594SDavid du Colombier+      struct ucred * cred;
3381*14414594SDavid du Colombier+      struct proc * p;
3382*14414594SDavid du Colombier+ {
3383*14414594SDavid du Colombier+   struct u9fsnode *np = VTOU9FS(vp);
3384*14414594SDavid du Colombier+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3385*14414594SDavid du Colombier+   int error;
3386*14414594SDavid du Colombier+   u_short newfid;
3387*14414594SDavid du Colombier+   struct u9fsreq req, rep;
3388*14414594SDavid du Colombier+   u_char mode;
3389*14414594SDavid du Colombier+
3390*14414594SDavid du Colombier+   /*
3391*14414594SDavid du Colombier+    * Disallow write attempts on filesystems mounted read-only;
3392*14414594SDavid du Colombier+    * unless the file is a socket, fifo, or a block or character
3393*14414594SDavid du Colombier+    * device resident on the filesystem.
3394*14414594SDavid du Colombier+    */
3395*14414594SDavid du Colombier+   if ( (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3396*14414594SDavid du Colombier+     switch (vp->v_type) {
3397*14414594SDavid du Colombier+     case VREG:
3398*14414594SDavid du Colombier+     case VDIR:
3399*14414594SDavid du Colombier+     case VLNK:
3400*14414594SDavid du Colombier+       return (EROFS);
3401*14414594SDavid du Colombier+     default:
3402*14414594SDavid du Colombier+       break;
3403*14414594SDavid du Colombier+     }
3404*14414594SDavid du Colombier+   }
3405*14414594SDavid du Colombier+   mode = U9P_MODE_WR | U9P_MODE_TRUNC;
3406*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
3407*14414594SDavid du Colombier+   req.r_nmp = nmp;
3408*14414594SDavid du Colombier+   req.r_procp = p;
3409*14414594SDavid du Colombier+   newfid = u9fs_id_new(nmp->nm_fids);
3410*14414594SDavid du Colombier+   req.r_type = Tclone;
3411*14414594SDavid du Colombier+   req.r_fid  = np->n_fid;
3412*14414594SDavid du Colombier+   req.r_newfid = newfid;
3413*14414594SDavid du Colombier+   error = u9fs_request(&req, &rep, 1);
3414*14414594SDavid du Colombier+   if( error )
3415*14414594SDavid du Colombier+     return error;
3416*14414594SDavid du Colombier+   req.r_type = Topen;
3417*14414594SDavid du Colombier+   req.r_fid = newfid;
3418*14414594SDavid du Colombier+   req.r_mode = mode;
3419*14414594SDavid du Colombier+   error = u9fs_request(&req, &rep, 1);
3420*14414594SDavid du Colombier+   if( !error )
3421*14414594SDavid du Colombier+     u9fs_vinvalbuf(vp, 0, cred, p, 0);
3422*14414594SDavid du Colombier+   if( error || np->n_wrfid ) {
3423*14414594SDavid du Colombier+     u9fs_free_fid(newfid, nmp, p);
3424*14414594SDavid du Colombier+     return error;
3425*14414594SDavid du Colombier+   }
3426*14414594SDavid du Colombier+
3427*14414594SDavid du Colombier+   if( !U9P_PERM_EXCL(np->n_dir.dir_mode))
3428*14414594SDavid du Colombier+     np->n_wrfid = newfid;
3429*14414594SDavid du Colombier+   else
3430*14414594SDavid du Colombier+     u9fs_free_fid(newfid, nmp, p);
3431*14414594SDavid du Colombier+
3432*14414594SDavid du Colombier+   return (0);
3433*14414594SDavid du Colombier+ }
3434*14414594SDavid du Colombier+
3435*14414594SDavid du Colombier+ /*
3436*14414594SDavid du Colombier+  * u9fs access vnode op.
3437*14414594SDavid du Colombier+  */
3438*14414594SDavid du Colombier+ static int
3439*14414594SDavid du Colombier+ u9fs_access(ap)
3440*14414594SDavid du Colombier+ 	struct vop_access_args /* {
3441*14414594SDavid du Colombier+ 		struct vnode *a_vp;
3442*14414594SDavid du Colombier+ 		int  a_mode;
3443*14414594SDavid du Colombier+ 		struct ucred *a_cred;
3444*14414594SDavid du Colombier+ 		struct proc *a_p;
3445*14414594SDavid du Colombier+ 	} */ *ap;
3446*14414594SDavid du Colombier+ {
3447*14414594SDavid du Colombier+   register struct vnode *vp = ap->a_vp;
3448*14414594SDavid du Colombier+   struct u9fsnode *np = VTOU9FS(vp);
3449*14414594SDavid du Colombier+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3450*14414594SDavid du Colombier+   struct proc * p = ap->a_p;
3451*14414594SDavid du Colombier+   int error, a_mode = ap->a_mode;
3452*14414594SDavid du Colombier+   u_short * fidp = 0, *fidp2 = 0, newfid;
3453*14414594SDavid du Colombier+   struct u9fsreq req, rep;
3454*14414594SDavid du Colombier+   u_char mode;
3455*14414594SDavid du Colombier+   struct ucred * cred = ap->a_cred;
3456*14414594SDavid du Colombier+
3457*14414594SDavid du Colombier+   /* XXX: for the moment, only the authenticator has access */
3458*14414594SDavid du Colombier+   if( cred->cr_uid != nmp->nm_authuid )
3459*14414594SDavid du Colombier+     return (EPERM);
3460*14414594SDavid du Colombier+
3461*14414594SDavid du Colombier+   /*
3462*14414594SDavid du Colombier+    * Disallow write attempts on filesystems mounted read-only;
3463*14414594SDavid du Colombier+    * unless the file is a socket, fifo, or a block or character
3464*14414594SDavid du Colombier+    * device resident on the filesystem.
3465*14414594SDavid du Colombier+    */
3466*14414594SDavid du Colombier+   if ((a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3467*14414594SDavid du Colombier+     switch (vp->v_type) {
3468*14414594SDavid du Colombier+     case VREG:
3469*14414594SDavid du Colombier+     case VDIR:
3470*14414594SDavid du Colombier+     case VLNK:
3471*14414594SDavid du Colombier+       return (EROFS);
3472*14414594SDavid du Colombier+     default:
3473*14414594SDavid du Colombier+       break;
3474*14414594SDavid du Colombier+     }
3475*14414594SDavid du Colombier+   }
3476*14414594SDavid du Colombier+
3477*14414594SDavid du Colombier+   /* we cant open an exclusive open file here */
3478*14414594SDavid du Colombier+   if( U9P_PERM_EXCL(np->n_dir.dir_mode) )
3479*14414594SDavid du Colombier+     return 0;
3480*14414594SDavid du Colombier+
3481*14414594SDavid du Colombier+   /* check permission by actually opening it */
3482*14414594SDavid du Colombier+   /* translate mode */
3483*14414594SDavid du Colombier+   mode = 0;
3484*14414594SDavid du Colombier+   if( a_mode & VREAD ) {
3485*14414594SDavid du Colombier+     fidp = &np->n_rdfid;
3486*14414594SDavid du Colombier+     mode = U9P_MODE_RD;
3487*14414594SDavid du Colombier+   }
3488*14414594SDavid du Colombier+   if( a_mode & VWRITE ) {
3489*14414594SDavid du Colombier+     fidp = &np->n_wrfid;
3490*14414594SDavid du Colombier+     mode = U9P_MODE_WR;
3491*14414594SDavid du Colombier+   }
3492*14414594SDavid du Colombier+   if( (a_mode & (VREAD|VWRITE)) == (VREAD|VWRITE) ) {
3493*14414594SDavid du Colombier+     fidp2 = &np->n_rdfid;
3494*14414594SDavid du Colombier+     mode = U9P_MODE_RDWR;
3495*14414594SDavid du Colombier+   }
3496*14414594SDavid du Colombier+
3497*14414594SDavid du Colombier+   if( a_mode & VEXEC ) {
3498*14414594SDavid du Colombier+     fidp = &np->n_rdfid;
3499*14414594SDavid du Colombier+     if( vp->v_type == VREG )
3500*14414594SDavid du Colombier+       mode = U9P_MODE_EX;
3501*14414594SDavid du Colombier+   }
3502*14414594SDavid du Colombier+
3503*14414594SDavid du Colombier+   if( fidp2 == 0 )
3504*14414594SDavid du Colombier+     fidp2 = fidp;
3505*14414594SDavid du Colombier+
3506*14414594SDavid du Colombier+   /* open fid mode */
3507*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
3508*14414594SDavid du Colombier+   req.r_nmp = nmp;
3509*14414594SDavid du Colombier+   req.r_procp = p;
3510*14414594SDavid du Colombier+   newfid = u9fs_id_new(nmp->nm_fids);
3511*14414594SDavid du Colombier+   req.r_type = Tclone;
3512*14414594SDavid du Colombier+   req.r_fid  = np->n_fid;
3513*14414594SDavid du Colombier+   req.r_newfid = newfid;
3514*14414594SDavid du Colombier+   error = u9fs_request(&req, &rep, 1);
3515*14414594SDavid du Colombier+   if( error )
3516*14414594SDavid du Colombier+     return error;
3517*14414594SDavid du Colombier+   req.r_type = Topen;
3518*14414594SDavid du Colombier+   req.r_fid = newfid;
3519*14414594SDavid du Colombier+   req.r_mode = mode;
3520*14414594SDavid du Colombier+   error = u9fs_request(&req, &rep, 1);
3521*14414594SDavid du Colombier+   u9fs_updtcache(np, &rep);
3522*14414594SDavid du Colombier+   if( error || (*fidp && *fidp2 ) ) {
3523*14414594SDavid du Colombier+     u9fs_free_fid(newfid, nmp, p);
3524*14414594SDavid du Colombier+     return error;
3525*14414594SDavid du Colombier+   }
3526*14414594SDavid du Colombier+
3527*14414594SDavid du Colombier+   *fidp = *fidp2 = newfid;
3528*14414594SDavid du Colombier+
3529*14414594SDavid du Colombier+   return (0);
3530*14414594SDavid du Colombier+ }
3531*14414594SDavid du Colombier+
3532*14414594SDavid du Colombier+ /*
3533*14414594SDavid du Colombier+  * u9fs open vnode op
3534*14414594SDavid du Colombier+  * Check to see if the type is ok
3535*14414594SDavid du Colombier+  * and that deletion is not in progress.
3536*14414594SDavid du Colombier+  * For paged in text files, you will need to flush the page cache
3537*14414594SDavid du Colombier+  * if consistency is lost.
3538*14414594SDavid du Colombier+  */
3539*14414594SDavid du Colombier+ /* ARGSUSED */
3540*14414594SDavid du Colombier+ static int
3541*14414594SDavid du Colombier+ u9fs_open(ap)
3542*14414594SDavid du Colombier+ 	struct vop_open_args /* {
3543*14414594SDavid du Colombier+ 		struct vnode *a_vp;
3544*14414594SDavid du Colombier+ 		int  a_mode;
3545*14414594SDavid du Colombier+ 		struct ucred *a_cred;
3546*14414594SDavid du Colombier+ 		struct proc *a_p;
3547*14414594SDavid du Colombier+ 	} */ *ap;
3548*14414594SDavid du Colombier+ {
3549*14414594SDavid du Colombier+   register struct vnode *vp = ap->a_vp;
3550*14414594SDavid du Colombier+   struct u9fsnode *np = VTOU9FS(vp);
3551*14414594SDavid du Colombier+   int error=0, a_mode = ap->a_mode;
3552*14414594SDavid du Colombier+   u_short * fidp = 0, *fidp2 = 0, newfid;
3553*14414594SDavid du Colombier+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3554*14414594SDavid du Colombier+   struct proc * p = ap->a_p;
3555*14414594SDavid du Colombier+   struct u9fsreq req, rep;
3556*14414594SDavid du Colombier+   u_char mode;
3557*14414594SDavid du Colombier+   struct ucred * cred = ap->a_cred;
3558*14414594SDavid du Colombier+
3559*14414594SDavid du Colombier+   /* assume access permissions have been checked via VOP_ACCESS */
3560*14414594SDavid du Colombier+   /* the file is actually opened except the rdwr case */
3561*14414594SDavid du Colombier+
3562*14414594SDavid du Colombier+   if( a_mode & (O_EXCL|O_SHLOCK|O_EXLOCK) ) {
3563*14414594SDavid du Colombier+ #if 0  /* XXX: what can we do here? */
3564*14414594SDavid du Colombier+     return (EOPNOTSUPP);
3565*14414594SDavid du Colombier+ #endif
3566*14414594SDavid du Colombier+   }
3567*14414594SDavid du Colombier+
3568*14414594SDavid du Colombier+   /* translate mode */
3569*14414594SDavid du Colombier+   mode = 0;
3570*14414594SDavid du Colombier+   if( a_mode & FREAD ) {
3571*14414594SDavid du Colombier+     fidp = &np->n_rdfid;
3572*14414594SDavid du Colombier+     mode = U9P_MODE_RD;
3573*14414594SDavid du Colombier+   }
3574*14414594SDavid du Colombier+   if( a_mode & FWRITE ) {
3575*14414594SDavid du Colombier+     fidp = &np->n_wrfid;
3576*14414594SDavid du Colombier+     mode = U9P_MODE_WR;
3577*14414594SDavid du Colombier+   }
3578*14414594SDavid du Colombier+   if( (a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE) ) {
3579*14414594SDavid du Colombier+     fidp2 = & np->n_rdfid;
3580*14414594SDavid du Colombier+     mode = U9P_MODE_RDWR;
3581*14414594SDavid du Colombier+   }
3582*14414594SDavid du Colombier+   if( fidp2 == 0)
3583*14414594SDavid du Colombier+     fidp2 = fidp;
3584*14414594SDavid du Colombier+
3585*14414594SDavid du Colombier+   if( U9P_PERM_EXCL(np->n_dir.dir_mode) ) {
3586*14414594SDavid du Colombier+     if( *fidp || *fidp2 )
3587*14414594SDavid du Colombier+       return ENOLCK;
3588*14414594SDavid du Colombier+
3589*14414594SDavid du Colombier+     /* open fid mode */
3590*14414594SDavid du Colombier+     bzero(&req, sizeof(req));
3591*14414594SDavid du Colombier+     req.r_nmp = nmp;
3592*14414594SDavid du Colombier+     req.r_procp = p;
3593*14414594SDavid du Colombier+     newfid = u9fs_id_new(nmp->nm_fids);
3594*14414594SDavid du Colombier+     req.r_type = Tclone;
3595*14414594SDavid du Colombier+     req.r_fid  = np->n_fid;
3596*14414594SDavid du Colombier+     req.r_newfid = newfid;
3597*14414594SDavid du Colombier+     error = u9fs_request(&req, &rep, 1);
3598*14414594SDavid du Colombier+     if( error )
3599*14414594SDavid du Colombier+       return error;
3600*14414594SDavid du Colombier+     req.r_type = Topen;
3601*14414594SDavid du Colombier+     req.r_fid = newfid;
3602*14414594SDavid du Colombier+     req.r_mode = mode;
3603*14414594SDavid du Colombier+     error = u9fs_request(&req, &rep, 1);
3604*14414594SDavid du Colombier+     if( error ) {
3605*14414594SDavid du Colombier+       u9fs_free_fid(newfid, nmp, p);
3606*14414594SDavid du Colombier+       return error;
3607*14414594SDavid du Colombier+     }
3608*14414594SDavid du Colombier+     u9fs_updtcache(np, &rep);
3609*14414594SDavid du Colombier+
3610*14414594SDavid du Colombier+     *fidp = *fidp2 = newfid;
3611*14414594SDavid du Colombier+   }
3612*14414594SDavid du Colombier+
3613*14414594SDavid du Colombier+   if( *fidp == 0 )
3614*14414594SDavid du Colombier+     panic("open");
3615*14414594SDavid du Colombier+
3616*14414594SDavid du Colombier+   if( *fidp2 == 0 ) {
3617*14414594SDavid du Colombier+     /* open fid mode */
3618*14414594SDavid du Colombier+     bzero(&req, sizeof(req));
3619*14414594SDavid du Colombier+     req.r_nmp = nmp;
3620*14414594SDavid du Colombier+     req.r_procp = p;
3621*14414594SDavid du Colombier+     newfid = u9fs_id_new(nmp->nm_fids);
3622*14414594SDavid du Colombier+     req.r_type = Tclone;
3623*14414594SDavid du Colombier+     req.r_fid  = np->n_fid;
3624*14414594SDavid du Colombier+     req.r_newfid = newfid;
3625*14414594SDavid du Colombier+     error = u9fs_request(&req, &rep, 1);
3626*14414594SDavid du Colombier+     if( error )
3627*14414594SDavid du Colombier+       return error;
3628*14414594SDavid du Colombier+     req.r_type = Topen;
3629*14414594SDavid du Colombier+     req.r_fid = newfid;
3630*14414594SDavid du Colombier+     req.r_mode = mode;
3631*14414594SDavid du Colombier+     error = u9fs_request(&req, &rep, 1);
3632*14414594SDavid du Colombier+     if( error ) {
3633*14414594SDavid du Colombier+       u9fs_free_fid(newfid, nmp, p);
3634*14414594SDavid du Colombier+       return error;
3635*14414594SDavid du Colombier+     }
3636*14414594SDavid du Colombier+     u9fs_updtcache(np, &rep);
3637*14414594SDavid du Colombier+     *fidp2 = newfid;
3638*14414594SDavid du Colombier+   }
3639*14414594SDavid du Colombier+
3640*14414594SDavid du Colombier+   if( np->n_qid.vers != np->n_dir.dir_qid.vers ) /* content changed */
3641*14414594SDavid du Colombier+     u9fs_vinvalbuf(vp, 0, cred, p, 0);
3642*14414594SDavid du Colombier+
3643*14414594SDavid du Colombier+   return 0;
3644*14414594SDavid du Colombier+ }
3645*14414594SDavid du Colombier+
3646*14414594SDavid du Colombier+ /*
3647*14414594SDavid du Colombier+  * u9fs close vnode op
3648*14414594SDavid du Colombier+  * What an U9FS client should do upon close after writing is a debatable issue.
3649*14414594SDavid du Colombier+  * Most U9FS clients push delayed writes to the server upon close, basically for
3650*14414594SDavid du Colombier+  * two reasons:
3651*14414594SDavid du Colombier+  * 1 - So that any write errors may be reported back to the client process
3652*14414594SDavid du Colombier+  *     doing the close system call. By far the two most likely errors are
3653*14414594SDavid du Colombier+  *     U9FSERR_NOSPC and U9FSERR_DQUOT to indicate space allocation failure.
3654*14414594SDavid du Colombier+  * 2 - To put a worst case upper bound on cache inconsistency between
3655*14414594SDavid du Colombier+  *     multiple clients for the file.
3656*14414594SDavid du Colombier+  * There is also a consistency problem for Version 2 of the protocol w.r.t.
3657*14414594SDavid du Colombier+  * not being able to tell if other clients are writing a file concurrently,
3658*14414594SDavid du Colombier+  * since there is no way of knowing if the changed modify time in the reply
3659*14414594SDavid du Colombier+  * is only due to the write for this client.
3660*14414594SDavid du Colombier+  * (U9FS Version 3 provides weak cache consistency data in the reply that
3661*14414594SDavid du Colombier+  *  should be sufficient to detect and handle this case.)
3662*14414594SDavid du Colombier+  *
3663*14414594SDavid du Colombier+  * The current code does the following:
3664*14414594SDavid du Colombier+  * for U9FS Version 2 - play it safe and flush/invalidate all dirty buffers
3665*14414594SDavid du Colombier+  * for U9FS Version 3 - flush dirty buffers to the server but don't invalidate
3666*14414594SDavid du Colombier+  *                     or commit them (this satisfies 1 and 2 except for the
3667*14414594SDavid du Colombier+  *                     case where the server crashes after this close but
3668*14414594SDavid du Colombier+  *                     before the commit RPC, which is felt to be "good
3669*14414594SDavid du Colombier+  *                     enough". Changing the last argument to u9fs_flush() to
3670*14414594SDavid du Colombier+  *                     a 1 would force a commit operation, if it is felt a
3671*14414594SDavid du Colombier+  *                     commit is necessary now.
3672*14414594SDavid du Colombier+  * for NQU9FS         - do nothing now, since 2 is dealt with via leases and
3673*14414594SDavid du Colombier+  *                     1 should be dealt with via an fsync() system call for
3674*14414594SDavid du Colombier+  *                     cases where write errors are important.
3675*14414594SDavid du Colombier+  */
3676*14414594SDavid du Colombier+ /* ARGSUSED */
3677*14414594SDavid du Colombier+ static int
3678*14414594SDavid du Colombier+ u9fs_close(ap)
3679*14414594SDavid du Colombier+ 	struct vop_close_args /* {
3680*14414594SDavid du Colombier+ 		struct vnodeop_desc *a_desc;
3681*14414594SDavid du Colombier+ 		struct vnode *a_vp;
3682*14414594SDavid du Colombier+ 		int  a_fflag;
3683*14414594SDavid du Colombier+ 		struct ucred *a_cred;
3684*14414594SDavid du Colombier+ 		struct proc *a_p;
3685*14414594SDavid du Colombier+ 	} */ *ap;
3686*14414594SDavid du Colombier+ {
3687*14414594SDavid du Colombier+   int fflag = ap->a_fflag;
3688*14414594SDavid du Colombier+   struct vnode * vp = ap->a_vp;
3689*14414594SDavid du Colombier+   struct u9fsnode * np = VTOU9FS(vp);
3690*14414594SDavid du Colombier+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3691*14414594SDavid du Colombier+   struct proc * p = ap->a_p;
3692*14414594SDavid du Colombier+
3693*14414594SDavid du Colombier+   if( U9P_PERM_EXCL(np->n_dir.dir_mode) ) {
3694*14414594SDavid du Colombier+     if( (fflag & FREAD) ) {
3695*14414594SDavid du Colombier+       u9fs_free_fid(np->n_rdfid, nmp, p);
3696*14414594SDavid du Colombier+       np->n_rdfid = 0;
3697*14414594SDavid du Colombier+     }
3698*14414594SDavid du Colombier+
3699*14414594SDavid du Colombier+     if( (fflag & FWRITE) == FWRITE ) {
3700*14414594SDavid du Colombier+       u9fs_free_fid(np->n_wrfid, nmp, p);
3701*14414594SDavid du Colombier+       np->n_wrfid = 0;
3702*14414594SDavid du Colombier+     }
3703*14414594SDavid du Colombier+
3704*14414594SDavid du Colombier+     if( (fflag & (FREAD|FWRITE)) == (FREAD|FWRITE) )
3705*14414594SDavid du Colombier+       np->n_wrfid = 0;
3706*14414594SDavid du Colombier+   }
3707*14414594SDavid du Colombier+
3708*14414594SDavid du Colombier+   return 0;
3709*14414594SDavid du Colombier+ }
3710*14414594SDavid du Colombier+
3711*14414594SDavid du Colombier+ /*
3712*14414594SDavid du Colombier+  * u9fs getattr call from vfs.
3713*14414594SDavid du Colombier+  */
3714*14414594SDavid du Colombier+ static int
3715*14414594SDavid du Colombier+ u9fs_getattr(ap)
3716*14414594SDavid du Colombier+ 	struct vop_getattr_args /* {
3717*14414594SDavid du Colombier+ 		struct vnode *a_vp;
3718*14414594SDavid du Colombier+ 		struct vattr *a_vap;
3719*14414594SDavid du Colombier+ 		struct ucred *a_cred;
3720*14414594SDavid du Colombier+ 		struct proc *a_p;
3721*14414594SDavid du Colombier+ 	} */ *ap;
3722*14414594SDavid du Colombier+ {
3723*14414594SDavid du Colombier+   register struct vnode *vp = ap->a_vp;
3724*14414594SDavid du Colombier+   register struct u9fsnode *np = VTOU9FS(vp);
3725*14414594SDavid du Colombier+   int error = 0;
3726*14414594SDavid du Colombier+   struct u9fsreq req, rep;
3727*14414594SDavid du Colombier+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3728*14414594SDavid du Colombier+   struct u9fsdir * dir;
3729*14414594SDavid du Colombier+   struct vattr * vap = ap->a_vap;
3730*14414594SDavid du Colombier+
3731*14414594SDavid du Colombier+   /*
3732*14414594SDavid du Colombier+    * Update local times for special files.
3733*14414594SDavid du Colombier+    */
3734*14414594SDavid du Colombier+   if (np->n_flag & (NACC | NUPD))
3735*14414594SDavid du Colombier+     np->n_flag |= NCHG;
3736*14414594SDavid du Colombier+ #if 0
3737*14414594SDavid du Colombier+   /*
3738*14414594SDavid du Colombier+    * First look in the cache.
3739*14414594SDavid du Colombier+    */
3740*14414594SDavid du Colombier+   if (u9fs_getattrcache(vp, ap->a_vap) == 0)
3741*14414594SDavid du Colombier+     return (0);
3742*14414594SDavid du Colombier+ #endif
3743*14414594SDavid du Colombier+   if( np->n_fid == 0 )
3744*14414594SDavid du Colombier+     panic("u9fs_getattr");
3745*14414594SDavid du Colombier+
3746*14414594SDavid du Colombier+   /* stat fid */
3747*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
3748*14414594SDavid du Colombier+   req.r_nmp = nmp;
3749*14414594SDavid du Colombier+   req.r_procp = ap->a_p;
3750*14414594SDavid du Colombier+   req.r_type = Tstat;
3751*14414594SDavid du Colombier+   req.r_fid = np->n_fid;
3752*14414594SDavid du Colombier+   error = u9fs_request(& req, & rep, 1);
3753*14414594SDavid du Colombier+   if( error )
3754*14414594SDavid du Colombier+     return error;
3755*14414594SDavid du Colombier+
3756*14414594SDavid du Colombier+   /* fill in vattr */
3757*14414594SDavid du Colombier+   dir = & np->n_dir;
3758*14414594SDavid du Colombier+   u9p_m2d(rep.r_stat, dir);
3759*14414594SDavid du Colombier+
3760*14414594SDavid du Colombier+   bzero(vap, sizeof(*vap));
3761*14414594SDavid du Colombier+   /* the plan9 file system has no other types. */
3762*14414594SDavid du Colombier+   /* XXX: we have not delt with devices yet */
3763*14414594SDavid du Colombier+   if( U9P_PERM_CHDIR(dir->dir_mode) )
3764*14414594SDavid du Colombier+     vap->va_type = VDIR;
3765*14414594SDavid du Colombier+   else
3766*14414594SDavid du Colombier+     vap->va_type = VREG;
3767*14414594SDavid du Colombier+
3768*14414594SDavid du Colombier+   vap->va_mode  = U9P_PERM_ALL(dir->dir_mode);
3769*14414594SDavid du Colombier+   vap->va_nlink = 1;
3770*14414594SDavid du Colombier+   vap->va_uid = u9fs_name2uid(dir->dir_uid);
3771*14414594SDavid du Colombier+   vap->va_gid = u9fs_name2uid(dir->dir_gid);
3772*14414594SDavid du Colombier+   vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
3773*14414594SDavid du Colombier+   vap->va_fileid = dir->dir_qid.path;
3774*14414594SDavid du Colombier+   vap->va_size = np->n_size = dir->dir_length;
3775*14414594SDavid du Colombier+   vap->va_blocksize = PAGE_SIZE;
3776*14414594SDavid du Colombier+   vap->va_atime.tv_sec = dir->dir_atime;
3777*14414594SDavid du Colombier+   vap->va_atime.tv_nsec = 0;
3778*14414594SDavid du Colombier+   vap->va_mtime.tv_sec = dir->dir_mtime;
3779*14414594SDavid du Colombier+   vap->va_mtime.tv_nsec = 0;
3780*14414594SDavid du Colombier+   vap->va_ctime.tv_sec = dir->dir_mtime;
3781*14414594SDavid du Colombier+   vap->va_ctime.tv_nsec = dir->dir_mtime;
3782*14414594SDavid du Colombier+   vap->va_gen = VNOVAL;
3783*14414594SDavid du Colombier+   vap->va_flags = 0;
3784*14414594SDavid du Colombier+   vap->va_bytes = vap->va_size;
3785*14414594SDavid du Colombier+   vap->va_filerev = dir->dir_qid.vers;
3786*14414594SDavid du Colombier+
3787*14414594SDavid du Colombier+   vp->v_type = vap->va_type;
3788*14414594SDavid du Colombier+   vp->v_tag = VT_U9FS;
3789*14414594SDavid du Colombier+
3790*14414594SDavid du Colombier+   return (error);
3791*14414594SDavid du Colombier+ }
3792*14414594SDavid du Colombier+
3793*14414594SDavid du Colombier+ /*
3794*14414594SDavid du Colombier+  * u9fs setattr call.
3795*14414594SDavid du Colombier+  */
3796*14414594SDavid du Colombier+ static int
3797*14414594SDavid du Colombier+ u9fs_setattr(ap)
3798*14414594SDavid du Colombier+ 	struct vop_setattr_args /* {
3799*14414594SDavid du Colombier+ 		struct vnodeop_desc *a_desc;
3800*14414594SDavid du Colombier+ 		struct vnode *a_vp;
3801*14414594SDavid du Colombier+ 		struct vattr *a_vap;
3802*14414594SDavid du Colombier+ 		struct ucred *a_cred;
3803*14414594SDavid du Colombier+ 		struct proc *a_p;
3804*14414594SDavid du Colombier+ 	} */ *ap;
3805*14414594SDavid du Colombier+ {
3806*14414594SDavid du Colombier+   register struct vnode *vp = ap->a_vp;
3807*14414594SDavid du Colombier+   register struct u9fsnode *np = VTOU9FS(vp);
3808*14414594SDavid du Colombier+   register struct vattr *vap = ap->a_vap;
3809*14414594SDavid du Colombier+   int error = 0;
3810*14414594SDavid du Colombier+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3811*14414594SDavid du Colombier+   struct u9fsdir dir;
3812*14414594SDavid du Colombier+   struct u9fsuser * u9p;
3813*14414594SDavid du Colombier+   struct vattr attr;
3814*14414594SDavid du Colombier+   struct u9fsreq req, rep;
3815*14414594SDavid du Colombier+
3816*14414594SDavid du Colombier+   if( vp->v_mount->mnt_flag & MNT_RDONLY )
3817*14414594SDavid du Colombier+     return (EROFS);
3818*14414594SDavid du Colombier+
3819*14414594SDavid du Colombier+   if( vap->va_nlink != VNOVAL || vap->va_uid != VNOVAL ||
3820*14414594SDavid du Colombier+       vap->va_fsid != VNOVAL || vap->va_fileid != VNOVAL ||
3821*14414594SDavid du Colombier+ #if 0
3822*14414594SDavid du Colombier+       vap->va_size != VNOVAL || vap->va_blocksize != VNOVAL ||
3823*14414594SDavid du Colombier+ #endif
3824*14414594SDavid du Colombier+       vap->va_atime.tv_sec != VNOVAL || vap->va_ctime.tv_sec != VNOVAL ||
3825*14414594SDavid du Colombier+       vap->va_gen != VNOVAL ||
3826*14414594SDavid du Colombier+       vap->va_flags != VNOVAL || vap->va_bytes != VNOVAL ) {
3827*14414594SDavid du Colombier+ #if 0
3828*14414594SDavid du Colombier+     printf("%d %d %d %d %d %d %d %d %d %d %d\n", vap->va_nlink, vap->va_uid, vap->va_fsid,
3829*14414594SDavid du Colombier+ 	       vap->va_fileid, vap->va_size, vap->va_blocksize,
3830*14414594SDavid du Colombier+ 	       vap->va_atime.tv_sec, vap->va_ctime.tv_sec, vap->va_gen,
3831*14414594SDavid du Colombier+ 	       vap->va_flags, vap->va_bytes);
3832*14414594SDavid du Colombier+     printf("unsupported setattr\n");
3833*14414594SDavid du Colombier+     /* touch tries to change ctime first.
3834*14414594SDavid du Colombier+      * if fails, it touches the first byte
3835*14414594SDavid du Colombier+     */
3836*14414594SDavid du Colombier+ #endif
3837*14414594SDavid du Colombier+     return (EOPNOTSUPP);
3838*14414594SDavid du Colombier+   }
3839*14414594SDavid du Colombier+
3840*14414594SDavid du Colombier+   if( vap->va_size == 0 )
3841*14414594SDavid du Colombier+     u9fs_trunc(vp, ap->a_cred, ap->a_p);
3842*14414594SDavid du Colombier+
3843*14414594SDavid du Colombier+   bcopy(&np->n_dir, &dir, sizeof(dir));
3844*14414594SDavid du Colombier+   if( vap->va_mode  != (mode_t)VNOVAL ) {
3845*14414594SDavid du Colombier+     dir.dir_mode = U9P_PERM_NONPERM(dir.dir_mode)|U9P_PERM_ALL(vap->va_mode);
3846*14414594SDavid du Colombier+   }
3847*14414594SDavid du Colombier+   if( vap->va_gid != VNOVAL ) {
3848*14414594SDavid du Colombier+     if( (u9p = u9fs_finduser(vap->va_gid)) == 0 )
3849*14414594SDavid du Colombier+       return (EINVAL);
3850*14414594SDavid du Colombier+     strncpy(u9p->u_name, dir.dir_gid, U9FS_NAMELEN);
3851*14414594SDavid du Colombier+   }
3852*14414594SDavid du Colombier+   if( vap->va_mtime.tv_sec != VNOVAL ) {
3853*14414594SDavid du Colombier+     dir.dir_mtime = vap->va_mtime.tv_sec;
3854*14414594SDavid du Colombier+   }
3855*14414594SDavid du Colombier+
3856*14414594SDavid du Colombier+   /* stat fid */
3857*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
3858*14414594SDavid du Colombier+   req.r_nmp = nmp;
3859*14414594SDavid du Colombier+   req.r_procp = ap->a_p;
3860*14414594SDavid du Colombier+   req.r_type = Twstat;
3861*14414594SDavid du Colombier+   req.r_fid = np->n_fid;
3862*14414594SDavid du Colombier+   u9p_d2m(&dir, req.r_stat);
3863*14414594SDavid du Colombier+   error = u9fs_request(& req, & rep, 1);
3864*14414594SDavid du Colombier+   if( error )
3865*14414594SDavid du Colombier+     return error;
3866*14414594SDavid du Colombier+   VOP_GETATTR(vp, &attr, ap->a_cred, ap->a_p);
3867*14414594SDavid du Colombier+
3868*14414594SDavid du Colombier+   return 0;
3869*14414594SDavid du Colombier+ }
3870*14414594SDavid du Colombier+
3871*14414594SDavid du Colombier+ /*
3872*14414594SDavid du Colombier+  * u9fs lookup call, one step at a time...
3873*14414594SDavid du Colombier+  * First look in cache
3874*14414594SDavid du Colombier+  * If not found, unlock the directory u9fsnode and do the rpc
3875*14414594SDavid du Colombier+  */
3876*14414594SDavid du Colombier+ static int
3877*14414594SDavid du Colombier+ u9fs_lookup(ap)
3878*14414594SDavid du Colombier+ 	struct vop_lookup_args /* {
3879*14414594SDavid du Colombier+ 		struct vnodeop_desc *a_desc;
3880*14414594SDavid du Colombier+ 		struct vnode *a_dvp;
3881*14414594SDavid du Colombier+ 		struct vnode **a_vpp;
3882*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
3883*14414594SDavid du Colombier+ 	} */ *ap;
3884*14414594SDavid du Colombier+ {
3885*14414594SDavid du Colombier+ 	struct componentname *cnp = ap->a_cnp;
3886*14414594SDavid du Colombier+ 	struct vnode *dvp = ap->a_dvp;
3887*14414594SDavid du Colombier+ 	struct vnode **vpp = ap->a_vpp;
3888*14414594SDavid du Colombier+ 	int flags = cnp->cn_flags;
3889*14414594SDavid du Colombier+ 	struct vnode *newvp;
3890*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
3891*14414594SDavid du Colombier+ 	long len;
3892*14414594SDavid du Colombier+ 	u9fsfh_t fh;
3893*14414594SDavid du Colombier+ 	struct u9fsnode *np;
3894*14414594SDavid du Colombier+ 	int lockparent, wantparent, error = 0;
3895*14414594SDavid du Colombier+ 	struct proc *p = cnp->cn_proc;
3896*14414594SDavid du Colombier+ 	struct u9fsreq req, rep;
3897*14414594SDavid du Colombier+ 	u_short newfid;
3898*14414594SDavid du Colombier+ 	struct vattr attrs;
3899*14414594SDavid du Colombier+
3900*14414594SDavid du Colombier+ 	*vpp = NULLVP;
3901*14414594SDavid du Colombier+ 	if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
3902*14414594SDavid du Colombier+ 	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
3903*14414594SDavid du Colombier+ 		return (EROFS);
3904*14414594SDavid du Colombier+ 	if (dvp->v_type != VDIR)
3905*14414594SDavid du Colombier+ 		return (ENOTDIR);
3906*14414594SDavid du Colombier+ 	lockparent = flags & LOCKPARENT;
3907*14414594SDavid du Colombier+ 	wantparent = flags & (LOCKPARENT|WANTPARENT);
3908*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(dvp->v_mount);
3909*14414594SDavid du Colombier+ 	np = VTOU9FS(dvp);
3910*14414594SDavid du Colombier+ #if 0
3911*14414594SDavid du Colombier+ 	if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
3912*14414594SDavid du Colombier+ 		struct vattr vattr;
3913*14414594SDavid du Colombier+ 		int vpid;
3914*14414594SDavid du Colombier+
3915*14414594SDavid du Colombier+ 		if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) {
3916*14414594SDavid du Colombier+ 			*vpp = NULLVP;
3917*14414594SDavid du Colombier+ 			return (error);
3918*14414594SDavid du Colombier+ 		}
3919*14414594SDavid du Colombier+
3920*14414594SDavid du Colombier+ 		newvp = *vpp;
3921*14414594SDavid du Colombier+ 		vpid = newvp->v_id;
3922*14414594SDavid du Colombier+ 		/*
3923*14414594SDavid du Colombier+ 		 * See the comment starting `Step through' in ufs/ufs_lookup.c
3924*14414594SDavid du Colombier+ 		 * for an explanation of the locking protocol
3925*14414594SDavid du Colombier+ 		 */
3926*14414594SDavid du Colombier+ 		if (dvp == newvp) {
3927*14414594SDavid du Colombier+ 			VREF(newvp);
3928*14414594SDavid du Colombier+ 			error = 0;
3929*14414594SDavid du Colombier+ 		} else if (flags & ISDOTDOT) {
3930*14414594SDavid du Colombier+ 			VOP_UNLOCK(dvp, 0, p);
3931*14414594SDavid du Colombier+ 			error = vget(newvp, LK_EXCLUSIVE, p);
3932*14414594SDavid du Colombier+ 			if (!error && lockparent && (flags & ISLASTCN))
3933*14414594SDavid du Colombier+ 				error = vn_lock(dvp, LK_EXCLUSIVE, p);
3934*14414594SDavid du Colombier+ 		} else {
3935*14414594SDavid du Colombier+ 			error = vget(newvp, LK_EXCLUSIVE, p);
3936*14414594SDavid du Colombier+ 			if (!lockparent || error || !(flags & ISLASTCN))
3937*14414594SDavid du Colombier+ 				VOP_UNLOCK(dvp, 0, p);
3938*14414594SDavid du Colombier+ 		}
3939*14414594SDavid du Colombier+ 		if (!error) {
3940*14414594SDavid du Colombier+ 			if (vpid == newvp->v_id) {
3941*14414594SDavid du Colombier+ 			   if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p)
3942*14414594SDavid du Colombier+ 			    && vattr.va_ctime.tv_sec == VTOU9FS(newvp)->n_ctime) {
3943*14414594SDavid du Colombier+ 				u9fsstats.lookupcache_hits++;
3944*14414594SDavid du Colombier+ 				if (cnp->cn_nameiop != LOOKUP &&
3945*14414594SDavid du Colombier+ 				    (flags & ISLASTCN))
3946*14414594SDavid du Colombier+ 					cnp->cn_flags |= SAVENAME;
3947*14414594SDavid du Colombier+ 				return (0);
3948*14414594SDavid du Colombier+ 			   }
3949*14414594SDavid du Colombier+ 			   cache_purge(newvp);
3950*14414594SDavid du Colombier+ 			}
3951*14414594SDavid du Colombier+ 			vput(newvp);
3952*14414594SDavid du Colombier+ 			if (lockparent && dvp != newvp && (flags & ISLASTCN))
3953*14414594SDavid du Colombier+ 				VOP_UNLOCK(dvp, 0, p);
3954*14414594SDavid du Colombier+ 		}
3955*14414594SDavid du Colombier+ 		error = vn_lock(dvp, LK_EXCLUSIVE, p);
3956*14414594SDavid du Colombier+ 		*vpp = NULLVP;
3957*14414594SDavid du Colombier+ 		if (error)
3958*14414594SDavid du Colombier+ 			return (error);
3959*14414594SDavid du Colombier+ 	}
3960*14414594SDavid du Colombier+ #endif
3961*14414594SDavid du Colombier+ 	error = 0;
3962*14414594SDavid du Colombier+ 	newvp = NULLVP;
3963*14414594SDavid du Colombier+ 	len = cnp->cn_namelen;
3964*14414594SDavid du Colombier+
3965*14414594SDavid du Colombier+ 	/* Tclwalk tag fid newfid name */
3966*14414594SDavid du Colombier+ 	bzero(&req, sizeof(req));
3967*14414594SDavid du Colombier+ 	req.r_procp = p;
3968*14414594SDavid du Colombier+ 	req.r_nmp = nmp;
3969*14414594SDavid du Colombier+ 	req.r_type = Tclwalk;
3970*14414594SDavid du Colombier+ 	req.r_fid = np->n_fid;
3971*14414594SDavid du Colombier+ 	newfid = req.r_newfid = u9fs_id_new(nmp->nm_fids);
3972*14414594SDavid du Colombier+ 	bcopy(cnp->cn_nameptr, req.r_name, len);
3973*14414594SDavid du Colombier+ 	if( (error = u9fs_request(&req, &rep, 1)) ) {
3974*14414594SDavid du Colombier+ 	  u9fs_id_free(nmp->nm_fids, newfid);
3975*14414594SDavid du Colombier+ 	  return error;
3976*14414594SDavid du Colombier+ 	}
3977*14414594SDavid du Colombier+
3978*14414594SDavid du Colombier+ 	fh = rep.r_qid.path;
3979*14414594SDavid du Colombier+ 	if( fh == 0 ) {
3980*14414594SDavid du Colombier+ 	  u9fs_id_free(nmp->nm_fids, newfid);
3981*14414594SDavid du Colombier+ 	  error = ENOENT;
3982*14414594SDavid du Colombier+ 	  goto lastcheck;
3983*14414594SDavid du Colombier+ 	}
3984*14414594SDavid du Colombier+
3985*14414594SDavid du Colombier+ 	/*
3986*14414594SDavid du Colombier+ 	 * Handle RENAME case...
3987*14414594SDavid du Colombier+ 	 */
3988*14414594SDavid du Colombier+ 	if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
3989*14414594SDavid du Colombier+ #if 0
3990*14414594SDavid du Colombier+ 	  /* XXX: I dont understand this. rename foo foo? */
3991*14414594SDavid du Colombier+ 		if (U9FS_CMPFH(np, fhp, fhsize)) {
3992*14414594SDavid du Colombier+ 			m_freem(mrep);
3993*14414594SDavid du Colombier+ 			return (EISDIR);
3994*14414594SDavid du Colombier+ 		}
3995*14414594SDavid du Colombier+ #endif
3996*14414594SDavid du Colombier+ 		error = u9fs_nget(dvp->v_mount, fh, &np, p);
3997*14414594SDavid du Colombier+ 		if (error)
3998*14414594SDavid du Colombier+ 		  goto fail;
3999*14414594SDavid du Colombier+
4000*14414594SDavid du Colombier+ 		if ( np->n_fid )
4001*14414594SDavid du Colombier+ 		  u9fs_free_fid(newfid, nmp, p);
4002*14414594SDavid du Colombier+ 		else
4003*14414594SDavid du Colombier+ 		  np->n_fid = newfid;
4004*14414594SDavid du Colombier+
4005*14414594SDavid du Colombier+ 		newvp = U9FSTOV(np);
4006*14414594SDavid du Colombier+ 		*vpp = newvp;
4007*14414594SDavid du Colombier+ 		cnp->cn_flags |= SAVENAME;
4008*14414594SDavid du Colombier+ 		if (!lockparent)
4009*14414594SDavid du Colombier+ 			VOP_UNLOCK(dvp, 0, p);
4010*14414594SDavid du Colombier+ 		return (0);
4011*14414594SDavid du Colombier+ 	}
4012*14414594SDavid du Colombier+
4013*14414594SDavid du Colombier+ 	if (flags & ISDOTDOT) {
4014*14414594SDavid du Colombier+ 		VOP_UNLOCK(dvp, 0, p);
4015*14414594SDavid du Colombier+ 		error = u9fs_nget(dvp->v_mount, fh, &np, p);
4016*14414594SDavid du Colombier+ 		if (error) {
4017*14414594SDavid du Colombier+ 			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
4018*14414594SDavid du Colombier+ 			goto fail;
4019*14414594SDavid du Colombier+ 		}
4020*14414594SDavid du Colombier+ 		if( np->n_fid )
4021*14414594SDavid du Colombier+ 		  u9fs_free_fid(newfid, nmp, p);
4022*14414594SDavid du Colombier+ 		else
4023*14414594SDavid du Colombier+ 		  np->n_fid = req.r_newfid;
4024*14414594SDavid du Colombier+
4025*14414594SDavid du Colombier+ 		newvp = U9FSTOV(np);
4026*14414594SDavid du Colombier+ 		if (lockparent && (flags & ISLASTCN) &&
4027*14414594SDavid du Colombier+ 		    (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
4028*14414594SDavid du Colombier+ 		    	vput(newvp);
4029*14414594SDavid du Colombier+ 			return (error);
4030*14414594SDavid du Colombier+ 		}
4031*14414594SDavid du Colombier+ 	} else if (np->n_qid.path == fh) {
4032*14414594SDavid du Colombier+ 	        u9fs_free_fid(newfid, nmp, p);
4033*14414594SDavid du Colombier+ 		VREF(dvp);
4034*14414594SDavid du Colombier+ 		newvp = dvp;
4035*14414594SDavid du Colombier+ 	} else {
4036*14414594SDavid du Colombier+ 		error = u9fs_nget(dvp->v_mount, fh, &np, p);
4037*14414594SDavid du Colombier+ 		if (error)
4038*14414594SDavid du Colombier+ 		  goto fail;
4039*14414594SDavid du Colombier+
4040*14414594SDavid du Colombier+ 		if( np->n_fid )
4041*14414594SDavid du Colombier+ 		  u9fs_free_fid(newfid, nmp, p);
4042*14414594SDavid du Colombier+ 		else
4043*14414594SDavid du Colombier+ 		  np->n_fid = req.r_newfid;
4044*14414594SDavid du Colombier+
4045*14414594SDavid du Colombier+ 		if (!lockparent || !(flags & ISLASTCN))
4046*14414594SDavid du Colombier+ 			VOP_UNLOCK(dvp, 0, p);
4047*14414594SDavid du Colombier+ 		newvp = U9FSTOV(np);
4048*14414594SDavid du Colombier+
4049*14414594SDavid du Colombier+ 		VOP_GETATTR(newvp, & attrs, p->p_ucred, p);
4050*14414594SDavid du Colombier+ 	}
4051*14414594SDavid du Colombier+
4052*14414594SDavid du Colombier+ 	if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
4053*14414594SDavid du Colombier+ 		cnp->cn_flags |= SAVENAME;
4054*14414594SDavid du Colombier+ #if 0
4055*14414594SDavid du Colombier+ 	if ((cnp->cn_flags & MAKEENTRY) &&
4056*14414594SDavid du Colombier+ 	    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
4057*14414594SDavid du Colombier+ 		np->n_ctime = np->n_vattr.va_ctime.tv_sec;
4058*14414594SDavid du Colombier+ 		cache_enter(dvp, newvp, cnp);
4059*14414594SDavid du Colombier+ 	}
4060*14414594SDavid du Colombier+ #endif
4061*14414594SDavid du Colombier+ 	*vpp = newvp;
4062*14414594SDavid du Colombier+  lastcheck:
4063*14414594SDavid du Colombier+ 	if (error) {
4064*14414594SDavid du Colombier+ 		if (newvp != NULLVP) {
4065*14414594SDavid du Colombier+ 			vrele(newvp);
4066*14414594SDavid du Colombier+ 			*vpp = NULLVP;
4067*14414594SDavid du Colombier+ 		}
4068*14414594SDavid du Colombier+ 		if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
4069*14414594SDavid du Colombier+ 		    (flags & ISLASTCN) && error == ENOENT) {
4070*14414594SDavid du Colombier+ 			if (!lockparent)
4071*14414594SDavid du Colombier+ 				VOP_UNLOCK(dvp, 0, p);
4072*14414594SDavid du Colombier+ 			if (dvp->v_mount->mnt_flag & MNT_RDONLY)
4073*14414594SDavid du Colombier+ 				error = EROFS;
4074*14414594SDavid du Colombier+ 			else
4075*14414594SDavid du Colombier+ 				error = EJUSTRETURN;
4076*14414594SDavid du Colombier+ 		}
4077*14414594SDavid du Colombier+ 		if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
4078*14414594SDavid du Colombier+ 			cnp->cn_flags |= SAVENAME;
4079*14414594SDavid du Colombier+ 	}
4080*14414594SDavid du Colombier+ 	return (error);
4081*14414594SDavid du Colombier+
4082*14414594SDavid du Colombier+  fail:
4083*14414594SDavid du Colombier+ 	u9fs_free_fid(newfid, nmp, p);
4084*14414594SDavid du Colombier+ 	return (error);
4085*14414594SDavid du Colombier+ }
4086*14414594SDavid du Colombier+
4087*14414594SDavid du Colombier+ /*
4088*14414594SDavid du Colombier+  * u9fs read call.
4089*14414594SDavid du Colombier+  * Just call u9fs_bioread() to do the work.
4090*14414594SDavid du Colombier+  */
4091*14414594SDavid du Colombier+ static int
4092*14414594SDavid du Colombier+ u9fs_read(ap)
4093*14414594SDavid du Colombier+ 	struct vop_read_args /* {
4094*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4095*14414594SDavid du Colombier+ 		struct uio *a_uio;
4096*14414594SDavid du Colombier+ 		int  a_ioflag;
4097*14414594SDavid du Colombier+ 		struct ucred *a_cred;
4098*14414594SDavid du Colombier+ 	} */ *ap;
4099*14414594SDavid du Colombier+ {
4100*14414594SDavid du Colombier+   register struct vnode *vp = ap->a_vp;
4101*14414594SDavid du Colombier+
4102*14414594SDavid du Colombier+   if (vp->v_type != VREG)
4103*14414594SDavid du Colombier+     return (EPERM);
4104*14414594SDavid du Colombier+   return (u9fs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
4105*14414594SDavid du Colombier+ }
4106*14414594SDavid du Colombier+
4107*14414594SDavid du Colombier+ /*
4108*14414594SDavid du Colombier+  * u9fs readlink call
4109*14414594SDavid du Colombier+  */
4110*14414594SDavid du Colombier+ static int
4111*14414594SDavid du Colombier+ u9fs_readlink(ap)
4112*14414594SDavid du Colombier+ 	struct vop_readlink_args /* {
4113*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4114*14414594SDavid du Colombier+ 		struct uio *a_uio;
4115*14414594SDavid du Colombier+ 		struct ucred *a_cred;
4116*14414594SDavid du Colombier+ 	} */ *ap;
4117*14414594SDavid du Colombier+ {
4118*14414594SDavid du Colombier+   return (EOPNOTSUPP);
4119*14414594SDavid du Colombier+ }
4120*14414594SDavid du Colombier+
4121*14414594SDavid du Colombier+ /*
4122*14414594SDavid du Colombier+  * u9fs mknod vop
4123*14414594SDavid du Colombier+  * just call u9fs_mknodrpc() to do the work.
4124*14414594SDavid du Colombier+  */
4125*14414594SDavid du Colombier+ /* ARGSUSED */
4126*14414594SDavid du Colombier+ static int
4127*14414594SDavid du Colombier+ u9fs_mknod(ap)
4128*14414594SDavid du Colombier+ 	struct vop_mknod_args /* {
4129*14414594SDavid du Colombier+ 		struct vnode *a_dvp;
4130*14414594SDavid du Colombier+ 		struct vnode **a_vpp;
4131*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
4132*14414594SDavid du Colombier+ 		struct vattr *a_vap;
4133*14414594SDavid du Colombier+ 	} */ *ap;
4134*14414594SDavid du Colombier+ {
4135*14414594SDavid du Colombier+   return (EOPNOTSUPP);
4136*14414594SDavid du Colombier+ }
4137*14414594SDavid du Colombier+
4138*14414594SDavid du Colombier+ /*
4139*14414594SDavid du Colombier+  * u9fs file create call
4140*14414594SDavid du Colombier+  */
4141*14414594SDavid du Colombier+ static int
4142*14414594SDavid du Colombier+ u9fs_create(ap)
4143*14414594SDavid du Colombier+ 	struct vop_create_args /* {
4144*14414594SDavid du Colombier+ 		struct vnode *a_dvp;
4145*14414594SDavid du Colombier+ 		struct vnode **a_vpp;
4146*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
4147*14414594SDavid du Colombier+ 		struct vattr *a_vap;
4148*14414594SDavid du Colombier+ 	} */ *ap;
4149*14414594SDavid du Colombier+ {
4150*14414594SDavid du Colombier+ 	register struct vnode *dvp = ap->a_dvp;
4151*14414594SDavid du Colombier+ 	register struct vattr *vap = ap->a_vap;
4152*14414594SDavid du Colombier+ 	register struct componentname *cnp = ap->a_cnp;
4153*14414594SDavid du Colombier+ 	struct u9fsnode *np = (struct u9fsnode *)0;
4154*14414594SDavid du Colombier+ 	struct vnode *newvp = (struct vnode *)0;
4155*14414594SDavid du Colombier+ 	int error = 0, len;
4156*14414594SDavid du Colombier+ 	struct vattr vattr;
4157*14414594SDavid du Colombier+ 	struct u9fsreq req, rep;
4158*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
4159*14414594SDavid du Colombier+ 	u9fsfh_t fh;
4160*14414594SDavid du Colombier+ 	struct proc * p;
4161*14414594SDavid du Colombier+ 	int pfid;
4162*14414594SDavid du Colombier+
4163*14414594SDavid du Colombier+ #if 0
4164*14414594SDavid du Colombier+ 	/*
4165*14414594SDavid du Colombier+ 	 * Oops, not for me..
4166*14414594SDavid du Colombier+ 	 */
4167*14414594SDavid du Colombier+ 	if (vap->va_type == VSOCK)
4168*14414594SDavid du Colombier+ 		return (u9fs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
4169*14414594SDavid du Colombier+ #endif
4170*14414594SDavid du Colombier+
4171*14414594SDavid du Colombier+ 	if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
4172*14414594SDavid du Colombier+ 		VOP_ABORTOP(dvp, cnp);
4173*14414594SDavid du Colombier+ 		return (error);
4174*14414594SDavid du Colombier+ 	}
4175*14414594SDavid du Colombier+
4176*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(dvp->v_mount);
4177*14414594SDavid du Colombier+ 	np = VTOU9FS(dvp);
4178*14414594SDavid du Colombier+ 	p = cnp->cn_proc;
4179*14414594SDavid du Colombier+
4180*14414594SDavid du Colombier+ 	bzero(&req, sizeof(req));
4181*14414594SDavid du Colombier+ 	req.r_nmp = nmp;
4182*14414594SDavid du Colombier+ 	req.r_procp = p;
4183*14414594SDavid du Colombier+
4184*14414594SDavid du Colombier+ 	req.r_type = Tclone;
4185*14414594SDavid du Colombier+ 	pfid = req.r_fid  = np->n_fid;
4186*14414594SDavid du Colombier+ 	req.r_newfid = u9fs_id_new(nmp->nm_fids);
4187*14414594SDavid du Colombier+ 	error = u9fs_request(&req, &rep, 1);
4188*14414594SDavid du Colombier+ 	if( error )
4189*14414594SDavid du Colombier+ 	  return error;
4190*14414594SDavid du Colombier+
4191*14414594SDavid du Colombier+ 	req.r_type = Tcreate;
4192*14414594SDavid du Colombier+ 	req.r_fid = req.r_newfid;
4193*14414594SDavid du Colombier+ 	len = cnp->cn_namelen;
4194*14414594SDavid du Colombier+ 	if( len > U9FS_NAMELEN )
4195*14414594SDavid du Colombier+ 	  len = U9FS_NAMELEN;
4196*14414594SDavid du Colombier+ 	strncpy(req.r_name, cnp->cn_nameptr, len);
4197*14414594SDavid du Colombier+ 	req.r_name[U9FS_NAMELEN] = 0;
4198*14414594SDavid du Colombier+ 	req.r_perm = U9P_PERM_ALL(vap->va_mode);
4199*14414594SDavid du Colombier+ 	if( vap->va_type == VDIR ) {
4200*14414594SDavid du Colombier+ 	  req.r_perm |= 0x80000000;
4201*14414594SDavid du Colombier+ 	  req.r_mode = U9P_MODE_RD;
4202*14414594SDavid du Colombier+ 	} else
4203*14414594SDavid du Colombier+ 	  req.r_mode = U9P_MODE_WR | U9P_MODE_TRUNC;
4204*14414594SDavid du Colombier+ 	if(vap->va_vaflags & VA_EXCLUSIVE)
4205*14414594SDavid du Colombier+ 	  req.r_mode = U9P_MODE_EX;
4206*14414594SDavid du Colombier+
4207*14414594SDavid du Colombier+ 	error = u9fs_request(&req, &rep, 1);
4208*14414594SDavid du Colombier+ 	if( error )
4209*14414594SDavid du Colombier+ 	  return error;
4210*14414594SDavid du Colombier+
4211*14414594SDavid du Colombier+ 	fh = rep.r_qid.path;
4212*14414594SDavid du Colombier+ 	u9fs_nget(dvp->v_mount, fh, &np, p);
4213*14414594SDavid du Colombier+ 	newvp = U9FSTOV(np);
4214*14414594SDavid du Colombier+ 	if( vap->va_type == VDIR )
4215*14414594SDavid du Colombier+ 	  np->n_rdfid = req.r_fid;
4216*14414594SDavid du Colombier+ 	else
4217*14414594SDavid du Colombier+ 	  np->n_wrfid = req.r_fid;
4218*14414594SDavid du Colombier+
4219*14414594SDavid du Colombier+ 	req.r_type = Tclwalk;
4220*14414594SDavid du Colombier+ 	req.r_fid  = pfid;
4221*14414594SDavid du Colombier+ 	req.r_newfid = u9fs_id_new(nmp->nm_fids);
4222*14414594SDavid du Colombier+ 	/* r_name is already filled */
4223*14414594SDavid du Colombier+ 	error = u9fs_request(&req, &rep, 1);
4224*14414594SDavid du Colombier+ 	if( error )
4225*14414594SDavid du Colombier+ 	  return error;
4226*14414594SDavid du Colombier+ 	np->n_fid = req.r_newfid;
4227*14414594SDavid du Colombier+ 	VOP_GETATTR(newvp, & vattr, p->p_ucred, p);
4228*14414594SDavid du Colombier+
4229*14414594SDavid du Colombier+ 	*ap->a_vpp = newvp;
4230*14414594SDavid du Colombier+ 	zfree(namei_zone, cnp->cn_pnbuf);
4231*14414594SDavid du Colombier+
4232*14414594SDavid du Colombier+ 	return 0;
4233*14414594SDavid du Colombier+ }
4234*14414594SDavid du Colombier+
4235*14414594SDavid du Colombier+ /*
4236*14414594SDavid du Colombier+  * u9fs file remove call
4237*14414594SDavid du Colombier+  * To try and make u9fs semantics closer to ufs semantics, a file that has
4238*14414594SDavid du Colombier+  * other processes using the vnode is renamed instead of removed and then
4239*14414594SDavid du Colombier+  * removed later on the last close.
4240*14414594SDavid du Colombier+  * - If v_usecount > 1
4241*14414594SDavid du Colombier+  *	  If a rename is not already in the works
4242*14414594SDavid du Colombier+  *	     call u9fs_sillyrename() to set it up
4243*14414594SDavid du Colombier+  *     else
4244*14414594SDavid du Colombier+  *	  do the remove rpc
4245*14414594SDavid du Colombier+  */
4246*14414594SDavid du Colombier+ static int
4247*14414594SDavid du Colombier+ u9fs_remove(ap)
4248*14414594SDavid du Colombier+ 	struct vop_remove_args /* {
4249*14414594SDavid du Colombier+ 		struct vnodeop_desc *a_desc;
4250*14414594SDavid du Colombier+ 		struct vnode * a_dvp;
4251*14414594SDavid du Colombier+ 		struct vnode * a_vp;
4252*14414594SDavid du Colombier+ 		struct componentname * a_cnp;
4253*14414594SDavid du Colombier+ 	} */ *ap;
4254*14414594SDavid du Colombier+ {
4255*14414594SDavid du Colombier+ 	register struct vnode *vp = ap->a_vp;
4256*14414594SDavid du Colombier+ 	register struct componentname *cnp = ap->a_cnp;
4257*14414594SDavid du Colombier+ 	struct u9fsnode *np;
4258*14414594SDavid du Colombier+ 	struct u9fsreq req, rep;
4259*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
4260*14414594SDavid du Colombier+ 	struct proc * p;
4261*14414594SDavid du Colombier+ 	int error;
4262*14414594SDavid du Colombier+
4263*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(vp->v_mount);
4264*14414594SDavid du Colombier+ 	np = VTOU9FS(vp);
4265*14414594SDavid du Colombier+ 	p = cnp->cn_proc;
4266*14414594SDavid du Colombier+ 	bzero(&req, sizeof(req));
4267*14414594SDavid du Colombier+ 	req.r_nmp = nmp;
4268*14414594SDavid du Colombier+ 	req.r_procp = p;
4269*14414594SDavid du Colombier+ 	req.r_type = Tremove;
4270*14414594SDavid du Colombier+ 	req.r_fid = np->n_fid;
4271*14414594SDavid du Colombier+ 	error = u9fs_request(&req, &rep, 1);
4272*14414594SDavid du Colombier+ 	if( error )
4273*14414594SDavid du Colombier+ 	  return error;
4274*14414594SDavid du Colombier+ 	zfree(namei_zone, cnp->cn_pnbuf);
4275*14414594SDavid du Colombier+ 	return 0;
4276*14414594SDavid du Colombier+ }
4277*14414594SDavid du Colombier+
4278*14414594SDavid du Colombier+ /*
4279*14414594SDavid du Colombier+  * u9fs file rename call
4280*14414594SDavid du Colombier+  */
4281*14414594SDavid du Colombier+ static int
4282*14414594SDavid du Colombier+ u9fs_rename(ap)
4283*14414594SDavid du Colombier+ 	struct vop_rename_args  /* {
4284*14414594SDavid du Colombier+ 		struct vnode *a_fdvp;
4285*14414594SDavid du Colombier+ 		struct vnode *a_fvp;
4286*14414594SDavid du Colombier+ 		struct componentname *a_fcnp;
4287*14414594SDavid du Colombier+ 		struct vnode *a_tdvp;
4288*14414594SDavid du Colombier+ 		struct vnode *a_tvp;
4289*14414594SDavid du Colombier+ 		struct componentname *a_tcnp;
4290*14414594SDavid du Colombier+ 	} */ *ap;
4291*14414594SDavid du Colombier+ {
4292*14414594SDavid du Colombier+ 	register struct vnode *fvp = ap->a_fvp;
4293*14414594SDavid du Colombier+ 	register struct vnode *tvp = ap->a_tvp;
4294*14414594SDavid du Colombier+ 	register struct vnode *fdvp = ap->a_fdvp;
4295*14414594SDavid du Colombier+ 	register struct vnode *tdvp = ap->a_tdvp;
4296*14414594SDavid du Colombier+ 	register struct componentname *tcnp = ap->a_tcnp;
4297*14414594SDavid du Colombier+ 	register struct componentname *fcnp = ap->a_fcnp;
4298*14414594SDavid du Colombier+ 	int error, len;
4299*14414594SDavid du Colombier+ 	struct u9fsmount * nmp;
4300*14414594SDavid du Colombier+ 	struct u9fsreq req, rep;
4301*14414594SDavid du Colombier+ 	struct u9fsdir dir;
4302*14414594SDavid du Colombier+ 	struct u9fsnode * np;
4303*14414594SDavid du Colombier+
4304*14414594SDavid du Colombier+ 	/* we cant do cross-directory renaming or move to an existing file */
4305*14414594SDavid du Colombier+ 	if( fdvp != tdvp || tvp != 0 || fvp->v_mount->mnt_flag & MNT_RDONLY ){
4306*14414594SDavid du Colombier+ 	  printf("rename to existing file not supported\n");
4307*14414594SDavid du Colombier+ 	  error = EOPNOTSUPP;
4308*14414594SDavid du Colombier+ 	  goto out;
4309*14414594SDavid du Colombier+ 	}
4310*14414594SDavid du Colombier+
4311*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(fvp->v_mount);
4312*14414594SDavid du Colombier+ 	np = VTOU9FS(fvp);
4313*14414594SDavid du Colombier+
4314*14414594SDavid du Colombier+ 	bcopy(&np->n_dir, &dir, sizeof(dir));
4315*14414594SDavid du Colombier+ 	len = tcnp->cn_namelen;
4316*14414594SDavid du Colombier+ 	if( len > U9FS_NAMELEN )
4317*14414594SDavid du Colombier+ 	  len = U9FS_NAMELEN;
4318*14414594SDavid du Colombier+ 	strncpy(dir.dir_name, tcnp->cn_nameptr, len);
4319*14414594SDavid du Colombier+ 	dir.dir_name[U9FS_NAMELEN-1] = 0;
4320*14414594SDavid du Colombier+
4321*14414594SDavid du Colombier+ 	/* stat fid */
4322*14414594SDavid du Colombier+ 	bzero(&req, sizeof(req));
4323*14414594SDavid du Colombier+ 	req.r_nmp = nmp;
4324*14414594SDavid du Colombier+ 	req.r_procp = fcnp->cn_proc;
4325*14414594SDavid du Colombier+ 	req.r_type = Twstat;
4326*14414594SDavid du Colombier+ 	req.r_fid = np->n_fid;
4327*14414594SDavid du Colombier+ 	u9p_d2m(&dir, req.r_stat);
4328*14414594SDavid du Colombier+ 	error = u9fs_request(& req, & rep, 1);
4329*14414594SDavid du Colombier+
4330*14414594SDavid du Colombier+  out:
4331*14414594SDavid du Colombier+ 	if (tdvp == tvp)
4332*14414594SDavid du Colombier+ 		vrele(tdvp);
4333*14414594SDavid du Colombier+ 	else
4334*14414594SDavid du Colombier+ 		vput(tdvp);
4335*14414594SDavid du Colombier+ 	if (tvp)
4336*14414594SDavid du Colombier+ 		vput(tvp);
4337*14414594SDavid du Colombier+ 	vrele(fdvp);
4338*14414594SDavid du Colombier+ 	vrele(fvp);
4339*14414594SDavid du Colombier+
4340*14414594SDavid du Colombier+ 	return error;
4341*14414594SDavid du Colombier+ }
4342*14414594SDavid du Colombier+
4343*14414594SDavid du Colombier+ /*
4344*14414594SDavid du Colombier+  * u9fs hard link create call
4345*14414594SDavid du Colombier+  */
4346*14414594SDavid du Colombier+ static int
4347*14414594SDavid du Colombier+ u9fs_link(ap)
4348*14414594SDavid du Colombier+ 	struct vop_link_args /* {
4349*14414594SDavid du Colombier+ 		struct vnode *a_tdvp;
4350*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4351*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
4352*14414594SDavid du Colombier+ 	} */ *ap;
4353*14414594SDavid du Colombier+ {
4354*14414594SDavid du Colombier+   return (EOPNOTSUPP);
4355*14414594SDavid du Colombier+ }
4356*14414594SDavid du Colombier+
4357*14414594SDavid du Colombier+ /*
4358*14414594SDavid du Colombier+  * u9fs symbolic link create call
4359*14414594SDavid du Colombier+  */
4360*14414594SDavid du Colombier+ static int
4361*14414594SDavid du Colombier+ u9fs_symlink(ap)
4362*14414594SDavid du Colombier+ 	struct vop_symlink_args /* {
4363*14414594SDavid du Colombier+ 		struct vnode *a_dvp;
4364*14414594SDavid du Colombier+ 		struct vnode **a_vpp;
4365*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
4366*14414594SDavid du Colombier+ 		struct vattr *a_vap;
4367*14414594SDavid du Colombier+ 		char *a_target;
4368*14414594SDavid du Colombier+ 	} */ *ap;
4369*14414594SDavid du Colombier+ {
4370*14414594SDavid du Colombier+   return (EOPNOTSUPP);
4371*14414594SDavid du Colombier+ }
4372*14414594SDavid du Colombier+
4373*14414594SDavid du Colombier+ /*
4374*14414594SDavid du Colombier+  * u9fs make dir call
4375*14414594SDavid du Colombier+  */
4376*14414594SDavid du Colombier+ static int
4377*14414594SDavid du Colombier+ u9fs_mkdir(ap)
4378*14414594SDavid du Colombier+ 	struct vop_mkdir_args /* {
4379*14414594SDavid du Colombier+ 		struct vnode *a_dvp;
4380*14414594SDavid du Colombier+ 		struct vnode **a_vpp;
4381*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
4382*14414594SDavid du Colombier+ 		struct vattr *a_vap;
4383*14414594SDavid du Colombier+ 	} */ *ap;
4384*14414594SDavid du Colombier+ {
4385*14414594SDavid du Colombier+   struct vop_create_args cap;
4386*14414594SDavid du Colombier+
4387*14414594SDavid du Colombier+   cap.a_dvp = ap->a_dvp;
4388*14414594SDavid du Colombier+   cap.a_vpp = ap->a_vpp;
4389*14414594SDavid du Colombier+   cap.a_cnp = ap->a_cnp;
4390*14414594SDavid du Colombier+   cap.a_vap = ap->a_vap;
4391*14414594SDavid du Colombier+   return u9fs_create(&cap);
4392*14414594SDavid du Colombier+ }
4393*14414594SDavid du Colombier+
4394*14414594SDavid du Colombier+ /*
4395*14414594SDavid du Colombier+  * u9fs remove directory call
4396*14414594SDavid du Colombier+  */
4397*14414594SDavid du Colombier+ static int
4398*14414594SDavid du Colombier+ u9fs_rmdir(ap)
4399*14414594SDavid du Colombier+ 	struct vop_rmdir_args /* {
4400*14414594SDavid du Colombier+ 		struct vnode *a_dvp;
4401*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4402*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
4403*14414594SDavid du Colombier+ 	} */ *ap;
4404*14414594SDavid du Colombier+ {
4405*14414594SDavid du Colombier+ 	register struct vnode *vp = ap->a_vp;
4406*14414594SDavid du Colombier+ 	register struct componentname *cnp = ap->a_cnp;
4407*14414594SDavid du Colombier+ 	struct u9fsnode *np;
4408*14414594SDavid du Colombier+ 	struct u9fsreq req, rep;
4409*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
4410*14414594SDavid du Colombier+ 	struct proc * p;
4411*14414594SDavid du Colombier+ 	int error;
4412*14414594SDavid du Colombier+
4413*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(vp->v_mount);
4414*14414594SDavid du Colombier+ 	np = VTOU9FS(vp);
4415*14414594SDavid du Colombier+ 	p = cnp->cn_proc;
4416*14414594SDavid du Colombier+ 	bzero(&req, sizeof(req));
4417*14414594SDavid du Colombier+ 	req.r_nmp = nmp;
4418*14414594SDavid du Colombier+ 	req.r_procp = p;
4419*14414594SDavid du Colombier+ 	req.r_type = Tremove;
4420*14414594SDavid du Colombier+ 	req.r_fid = np->n_fid;
4421*14414594SDavid du Colombier+ 	error = u9fs_request(&req, &rep, 1);
4422*14414594SDavid du Colombier+ 	if( error )
4423*14414594SDavid du Colombier+ 	  return error;
4424*14414594SDavid du Colombier+ 	u9fs_id_free(nmp->nm_fids, np->n_fid);
4425*14414594SDavid du Colombier+ 	np->n_fid = 0;
4426*14414594SDavid du Colombier+ 	zfree(namei_zone, cnp->cn_pnbuf);
4427*14414594SDavid du Colombier+ 	return 0;
4428*14414594SDavid du Colombier+ }
4429*14414594SDavid du Colombier+
4430*14414594SDavid du Colombier+ /*
4431*14414594SDavid du Colombier+  * u9fs readdir call
4432*14414594SDavid du Colombier+  */
4433*14414594SDavid du Colombier+ static int
4434*14414594SDavid du Colombier+ u9fs_readdir(ap)
4435*14414594SDavid du Colombier+ 	struct vop_readdir_args /* {
4436*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4437*14414594SDavid du Colombier+ 		struct uio *a_uio;
4438*14414594SDavid du Colombier+ 		struct ucred *a_cred;
4439*14414594SDavid du Colombier+ 	} */ *ap;
4440*14414594SDavid du Colombier+ {
4441*14414594SDavid du Colombier+   register struct vnode *vp = ap->a_vp;
4442*14414594SDavid du Colombier+   register struct uio *uio = ap->a_uio;
4443*14414594SDavid du Colombier+   int error;
4444*14414594SDavid du Colombier+
4445*14414594SDavid du Colombier+   if (vp->v_type != VDIR)
4446*14414594SDavid du Colombier+     return (EPERM);
4447*14414594SDavid du Colombier+
4448*14414594SDavid du Colombier+   /*
4449*14414594SDavid du Colombier+    * Call u9fs_bioread() to do the real work.
4450*14414594SDavid du Colombier+    */
4451*14414594SDavid du Colombier+   error = u9fs_bioread(vp, uio, 0, ap->a_cred, 0);
4452*14414594SDavid du Colombier+
4453*14414594SDavid du Colombier+   return (error);
4454*14414594SDavid du Colombier+ }
4455*14414594SDavid du Colombier+
4456*14414594SDavid du Colombier+ /*
4457*14414594SDavid du Colombier+  * Kludge City..
4458*14414594SDavid du Colombier+  * - make u9fs_bmap() essentially a no-op that does no translation
4459*14414594SDavid du Colombier+  * - do u9fs_strategy() by doing I/O with u9fs_readrpc/u9fs_writerpc
4460*14414594SDavid du Colombier+  *   (Maybe I could use the process's page mapping, but I was concerned that
4461*14414594SDavid du Colombier+  *    Kernel Write might not be enabled and also figured copyout() would do
4462*14414594SDavid du Colombier+  *    a lot more work than bcopy() and also it currently happens in the
4463*14414594SDavid du Colombier+  *    context of the swapper process (2).
4464*14414594SDavid du Colombier+  */
4465*14414594SDavid du Colombier+ static int
4466*14414594SDavid du Colombier+ u9fs_bmap(ap)
4467*14414594SDavid du Colombier+ 	struct vop_bmap_args /* {
4468*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4469*14414594SDavid du Colombier+ 		daddr_t  a_bn;
4470*14414594SDavid du Colombier+ 		struct vnode **a_vpp;
4471*14414594SDavid du Colombier+ 		daddr_t *a_bnp;
4472*14414594SDavid du Colombier+ 		int *a_runp;
4473*14414594SDavid du Colombier+ 		int *a_runb;
4474*14414594SDavid du Colombier+ 	} */ *ap;
4475*14414594SDavid du Colombier+ {
4476*14414594SDavid du Colombier+   register struct vnode *vp = ap->a_vp;
4477*14414594SDavid du Colombier+
4478*14414594SDavid du Colombier+   if (ap->a_vpp != NULL)
4479*14414594SDavid du Colombier+     *ap->a_vpp = vp;
4480*14414594SDavid du Colombier+   if (ap->a_bnp != NULL)
4481*14414594SDavid du Colombier+     *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
4482*14414594SDavid du Colombier+   if (ap->a_runp != NULL)
4483*14414594SDavid du Colombier+     *ap->a_runp = 0;
4484*14414594SDavid du Colombier+   if (ap->a_runb != NULL)
4485*14414594SDavid du Colombier+     *ap->a_runb = 0;
4486*14414594SDavid du Colombier+   return (0);
4487*14414594SDavid du Colombier+
4488*14414594SDavid du Colombier+   return 0;
4489*14414594SDavid du Colombier+ }
4490*14414594SDavid du Colombier+
4491*14414594SDavid du Colombier+ /*
4492*14414594SDavid du Colombier+  * Strategy routine.
4493*14414594SDavid du Colombier+  * For async requests when u9fsiod(s) are running, queue the request by
4494*14414594SDavid du Colombier+  * calling u9fs_asyncio(), otherwise just all u9fs_doio() to do the
4495*14414594SDavid du Colombier+  * request.
4496*14414594SDavid du Colombier+  */
4497*14414594SDavid du Colombier+ static int
4498*14414594SDavid du Colombier+ u9fs_strategy(ap)
4499*14414594SDavid du Colombier+ 	struct vop_strategy_args *ap;
4500*14414594SDavid du Colombier+ {
4501*14414594SDavid du Colombier+ 	register struct buf *bp = ap->a_bp;
4502*14414594SDavid du Colombier+ 	struct ucred *cr;
4503*14414594SDavid du Colombier+ 	struct proc *p;
4504*14414594SDavid du Colombier+ 	int error = 0;
4505*14414594SDavid du Colombier+
4506*14414594SDavid du Colombier+ 	if (bp->b_flags & B_PHYS)
4507*14414594SDavid du Colombier+ 		panic("nfs physio");
4508*14414594SDavid du Colombier+ 	if (bp->b_flags & B_ASYNC)
4509*14414594SDavid du Colombier+ 	        panic("u9fs async");
4510*14414594SDavid du Colombier+
4511*14414594SDavid du Colombier+ 	p = curproc;	/* XXX */
4512*14414594SDavid du Colombier+ 	if (bp->b_flags & B_READ)
4513*14414594SDavid du Colombier+ 		cr = bp->b_rcred;
4514*14414594SDavid du Colombier+ 	else
4515*14414594SDavid du Colombier+ 		cr = bp->b_wcred;
4516*14414594SDavid du Colombier+ 	error = u9fs_doio(bp, cr, p);
4517*14414594SDavid du Colombier+ 	return (error);
4518*14414594SDavid du Colombier+ }
4519*14414594SDavid du Colombier+
4520*14414594SDavid du Colombier+ /*
4521*14414594SDavid du Colombier+  * Mmap a file
4522*14414594SDavid du Colombier+  *
4523*14414594SDavid du Colombier+  * NB Currently unsupported.
4524*14414594SDavid du Colombier+  */
4525*14414594SDavid du Colombier+ /* ARGSUSED */
4526*14414594SDavid du Colombier+ static int
4527*14414594SDavid du Colombier+ u9fs_mmap(ap)
4528*14414594SDavid du Colombier+ 	struct vop_mmap_args /* {
4529*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4530*14414594SDavid du Colombier+ 		int  a_fflags;
4531*14414594SDavid du Colombier+ 		struct ucred *a_cred;
4532*14414594SDavid du Colombier+ 		struct proc *a_p;
4533*14414594SDavid du Colombier+ 	} */ *ap;
4534*14414594SDavid du Colombier+ {
4535*14414594SDavid du Colombier+ 	return (EINVAL);
4536*14414594SDavid du Colombier+ }
4537*14414594SDavid du Colombier+
4538*14414594SDavid du Colombier+ /*
4539*14414594SDavid du Colombier+  * fsync vnode op. Just call u9fs_flush() with commit == 1.
4540*14414594SDavid du Colombier+  */
4541*14414594SDavid du Colombier+ /* ARGSUSED */
4542*14414594SDavid du Colombier+ static int
4543*14414594SDavid du Colombier+ u9fs_fsync(ap)
4544*14414594SDavid du Colombier+ 	struct vop_fsync_args /* {
4545*14414594SDavid du Colombier+ 		struct vnodeop_desc *a_desc;
4546*14414594SDavid du Colombier+ 		struct vnode * a_vp;
4547*14414594SDavid du Colombier+ 		struct ucred * a_cred;
4548*14414594SDavid du Colombier+ 		int  a_waitfor;
4549*14414594SDavid du Colombier+ 		struct proc * a_p;
4550*14414594SDavid du Colombier+ 	} */ *ap;
4551*14414594SDavid du Colombier+ {
4552*14414594SDavid du Colombier+   /* we have a blocking writeback cache */
4553*14414594SDavid du Colombier+   return 0;
4554*14414594SDavid du Colombier+ }
4555*14414594SDavid du Colombier+
4556*14414594SDavid du Colombier+ /*
4557*14414594SDavid du Colombier+  * U9FS advisory byte-level locks.
4558*14414594SDavid du Colombier+  * Currently unsupported.
4559*14414594SDavid du Colombier+  */
4560*14414594SDavid du Colombier+ static int
4561*14414594SDavid du Colombier+ u9fs_advlock(ap)
4562*14414594SDavid du Colombier+ 	struct vop_advlock_args /* {
4563*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4564*14414594SDavid du Colombier+ 		caddr_t  a_id;
4565*14414594SDavid du Colombier+ 		int  a_op;
4566*14414594SDavid du Colombier+ 		struct flock *a_fl;
4567*14414594SDavid du Colombier+ 		int  a_flags;
4568*14414594SDavid du Colombier+ 	} */ *ap;
4569*14414594SDavid du Colombier+ {
4570*14414594SDavid du Colombier+ 	register struct u9fsnode *np = VTOU9FS(ap->a_vp);
4571*14414594SDavid du Colombier+
4572*14414594SDavid du Colombier+ 	/*
4573*14414594SDavid du Colombier+ 	 * The following kludge is to allow diskless support to work
4574*14414594SDavid du Colombier+ 	 * until a real NFS lockd is implemented. Basically, just pretend
4575*14414594SDavid du Colombier+ 	 * that this is a local lock.
4576*14414594SDavid du Colombier+ 	 */
4577*14414594SDavid du Colombier+ 	return (lf_advlock(ap, &(np->n_lockf), np->n_size));
4578*14414594SDavid du Colombier+ }
4579*14414594SDavid du Colombier+
4580*14414594SDavid du Colombier+ /*
4581*14414594SDavid du Colombier+  * Print out the contents of an u9fsnode.
4582*14414594SDavid du Colombier+  */
4583*14414594SDavid du Colombier+ static int
4584*14414594SDavid du Colombier+ u9fs_print(ap)
4585*14414594SDavid du Colombier+ 	struct vop_print_args /* {
4586*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4587*14414594SDavid du Colombier+ 	} */ *ap;
4588*14414594SDavid du Colombier+ {
4589*14414594SDavid du Colombier+   panic("u9fs_print");
4590*14414594SDavid du Colombier+   return 0;
4591*14414594SDavid du Colombier+ }
4592*14414594SDavid du Colombier+
4593*14414594SDavid du Colombier+ /*
4594*14414594SDavid du Colombier+  * Just call u9fs_writebp() with the force argument set to 1.
4595*14414594SDavid du Colombier+  */
4596*14414594SDavid du Colombier+ static int
4597*14414594SDavid du Colombier+ u9fs_bwrite(ap)
4598*14414594SDavid du Colombier+ 	struct vop_bwrite_args /* {
4599*14414594SDavid du Colombier+ 		struct vnode *a_bp;
4600*14414594SDavid du Colombier+ 	} */ *ap;
4601*14414594SDavid du Colombier+ {
4602*14414594SDavid du Colombier+   panic("u9fs_bwrite");
4603*14414594SDavid du Colombier+   return 0;
4604*14414594SDavid du Colombier+ }
4605*14414594SDavid du Colombier+
4606*14414594SDavid du Colombier+ /*
4607*14414594SDavid du Colombier+  * Vnode op for VM getpages.
4608*14414594SDavid du Colombier+  */
4609*14414594SDavid du Colombier+ static int
4610*14414594SDavid du Colombier+ u9fs_getpages(ap)
4611*14414594SDavid du Colombier+ 	struct vop_getpages_args /* {
4612*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4613*14414594SDavid du Colombier+ 		vm_page_t *a_m;
4614*14414594SDavid du Colombier+ 		int a_count;
4615*14414594SDavid du Colombier+ 		int a_reqpage;
4616*14414594SDavid du Colombier+ 		vm_ooffset_t a_offset;
4617*14414594SDavid du Colombier+ 	} */ *ap;
4618*14414594SDavid du Colombier+ {
4619*14414594SDavid du Colombier+ 	int i, error, nextoff, size, toff, npages, count;
4620*14414594SDavid du Colombier+ 	struct uio uio;
4621*14414594SDavid du Colombier+ 	struct iovec iov;
4622*14414594SDavid du Colombier+ 	vm_offset_t kva;
4623*14414594SDavid du Colombier+ 	struct buf *bp;
4624*14414594SDavid du Colombier+ 	struct vnode *vp;
4625*14414594SDavid du Colombier+ 	struct proc *p;
4626*14414594SDavid du Colombier+ 	struct ucred *cred;
4627*14414594SDavid du Colombier+ 	struct u9fsmount *nmp;
4628*14414594SDavid du Colombier+ 	vm_page_t *pages;
4629*14414594SDavid du Colombier+
4630*14414594SDavid du Colombier+ 	vp = ap->a_vp;
4631*14414594SDavid du Colombier+ 	p = curproc;				/* XXX */
4632*14414594SDavid du Colombier+ 	cred = curproc->p_ucred;		/* XXX */
4633*14414594SDavid du Colombier+ 	nmp = VFSTOU9FS(vp->v_mount);
4634*14414594SDavid du Colombier+ 	pages = ap->a_m;
4635*14414594SDavid du Colombier+ 	count = ap->a_count;
4636*14414594SDavid du Colombier+
4637*14414594SDavid du Colombier+ 	if (vp->v_object == NULL) {
4638*14414594SDavid du Colombier+ 		printf("u9fs_getpages: called with non-merged cache vnode??\n");
4639*14414594SDavid du Colombier+ 		return VM_PAGER_ERROR;
4640*14414594SDavid du Colombier+ 	}
4641*14414594SDavid du Colombier+
4642*14414594SDavid du Colombier+ 	/*
4643*14414594SDavid du Colombier+ 	 * We use only the kva address for the buffer, but this is extremely
4644*14414594SDavid du Colombier+ 	 * convienient and fast.
4645*14414594SDavid du Colombier+ 	 */
4646*14414594SDavid du Colombier+ 	bp = getpbuf();
4647*14414594SDavid du Colombier+
4648*14414594SDavid du Colombier+ 	npages = btoc(count);
4649*14414594SDavid du Colombier+ 	kva = (vm_offset_t) bp->b_data;
4650*14414594SDavid du Colombier+ 	pmap_qenter(kva, pages, npages);
4651*14414594SDavid du Colombier+
4652*14414594SDavid du Colombier+ 	iov.iov_base = (caddr_t) kva;
4653*14414594SDavid du Colombier+ 	iov.iov_len = count;
4654*14414594SDavid du Colombier+ 	uio.uio_iov = &iov;
4655*14414594SDavid du Colombier+ 	uio.uio_iovcnt = 1;
4656*14414594SDavid du Colombier+ 	uio.uio_offset = IDX_TO_OFF(pages[0]->pindex);
4657*14414594SDavid du Colombier+ 	uio.uio_resid = count;
4658*14414594SDavid du Colombier+ 	uio.uio_segflg = UIO_SYSSPACE;
4659*14414594SDavid du Colombier+ 	uio.uio_rw = UIO_READ;
4660*14414594SDavid du Colombier+ 	uio.uio_procp = p;
4661*14414594SDavid du Colombier+
4662*14414594SDavid du Colombier+ 	error = u9fs_readrpc(vp, &uio, cred);
4663*14414594SDavid du Colombier+ 	pmap_qremove(kva, npages);
4664*14414594SDavid du Colombier+
4665*14414594SDavid du Colombier+ 	relpbuf(bp);
4666*14414594SDavid du Colombier+
4667*14414594SDavid du Colombier+ 	if (error && (uio.uio_resid == count))
4668*14414594SDavid du Colombier+ 		return VM_PAGER_ERROR;
4669*14414594SDavid du Colombier+
4670*14414594SDavid du Colombier+ 	size = count - uio.uio_resid;
4671*14414594SDavid du Colombier+
4672*14414594SDavid du Colombier+ 	for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
4673*14414594SDavid du Colombier+ 		vm_page_t m;
4674*14414594SDavid du Colombier+ 		nextoff = toff + PAGE_SIZE;
4675*14414594SDavid du Colombier+ 		m = pages[i];
4676*14414594SDavid du Colombier+
4677*14414594SDavid du Colombier+ 		m->flags &= ~PG_ZERO;
4678*14414594SDavid du Colombier+
4679*14414594SDavid du Colombier+ 		if (nextoff <= size) {
4680*14414594SDavid du Colombier+ 			m->valid = VM_PAGE_BITS_ALL;
4681*14414594SDavid du Colombier+ 			m->dirty = 0;
4682*14414594SDavid du Colombier+ 		} else {
4683*14414594SDavid du Colombier+ 			int nvalid = ((size + DEV_BSIZE - 1) - toff) & ~(DEV_BSIZE - 1);
4684*14414594SDavid du Colombier+ 			vm_page_set_validclean(m, 0, nvalid);
4685*14414594SDavid du Colombier+ 		}
4686*14414594SDavid du Colombier+
4687*14414594SDavid du Colombier+ 		if (i != ap->a_reqpage) {
4688*14414594SDavid du Colombier+ 			/*
4689*14414594SDavid du Colombier+ 			 * Whether or not to leave the page activated is up in
4690*14414594SDavid du Colombier+ 			 * the air, but we should put the page on a page queue
4691*14414594SDavid du Colombier+ 			 * somewhere (it already is in the object).  Result:
4692*14414594SDavid du Colombier+ 			 * It appears that emperical results show that
4693*14414594SDavid du Colombier+ 			 * deactivating pages is best.
4694*14414594SDavid du Colombier+ 			 */
4695*14414594SDavid du Colombier+
4696*14414594SDavid du Colombier+ 			/*
4697*14414594SDavid du Colombier+ 			 * Just in case someone was asking for this page we
4698*14414594SDavid du Colombier+ 			 * now tell them that it is ok to use.
4699*14414594SDavid du Colombier+ 			 */
4700*14414594SDavid du Colombier+ 			if (!error) {
4701*14414594SDavid du Colombier+ 				if (m->flags & PG_WANTED)
4702*14414594SDavid du Colombier+ 					vm_page_activate(m);
4703*14414594SDavid du Colombier+ 				else
4704*14414594SDavid du Colombier+ 					vm_page_deactivate(m);
4705*14414594SDavid du Colombier+ 				vm_page_wakeup(m);
4706*14414594SDavid du Colombier+ 			} else {
4707*14414594SDavid du Colombier+ 				vnode_pager_freepage(m);
4708*14414594SDavid du Colombier+ 			}
4709*14414594SDavid du Colombier+ 		}
4710*14414594SDavid du Colombier+ 	}
4711*14414594SDavid du Colombier+ 	return 0;
4712*14414594SDavid du Colombier+ }
4713*14414594SDavid du Colombier+
4714*14414594SDavid du Colombier+ /*
4715*14414594SDavid du Colombier+  * Vnode op for VM putpages.
4716*14414594SDavid du Colombier+  */
4717*14414594SDavid du Colombier+ static int
4718*14414594SDavid du Colombier+ u9fs_putpages(ap)
4719*14414594SDavid du Colombier+ 	struct vop_putpages_args /* {
4720*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4721*14414594SDavid du Colombier+ 		vm_page_t *a_m;
4722*14414594SDavid du Colombier+ 		int a_count;
4723*14414594SDavid du Colombier+ 		int a_sync;
4724*14414594SDavid du Colombier+ 		int *a_rtvals;
4725*14414594SDavid du Colombier+ 		vm_ooffset_t a_offset;
4726*14414594SDavid du Colombier+ 	} */ *ap;
4727*14414594SDavid du Colombier+ {
4728*14414594SDavid du Colombier+   panic("u9fs_putpages");
4729*14414594SDavid du Colombier+   return 0;
4730*14414594SDavid du Colombier+ }
4731*14414594SDavid du Colombier+
4732*14414594SDavid du Colombier+ static int
4733*14414594SDavid du Colombier+ u9fs_inactive(ap)
4734*14414594SDavid du Colombier+ 	struct vop_inactive_args /* {
4735*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4736*14414594SDavid du Colombier+ 		struct proc *a_p;
4737*14414594SDavid du Colombier+ 	} */ *ap;
4738*14414594SDavid du Colombier+ {
4739*14414594SDavid du Colombier+   VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
4740*14414594SDavid du Colombier+   return 0;
4741*14414594SDavid du Colombier+ }
4742*14414594SDavid du Colombier+
4743*14414594SDavid du Colombier+ /*
4744*14414594SDavid du Colombier+  * Reclaim an u9fsnode so that it can be used for other purposes.
4745*14414594SDavid du Colombier+  */
4746*14414594SDavid du Colombier+ static int
4747*14414594SDavid du Colombier+ u9fs_reclaim(ap)
4748*14414594SDavid du Colombier+ 	struct vop_reclaim_args /* {
4749*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4750*14414594SDavid du Colombier+ 	} */ *ap;
4751*14414594SDavid du Colombier+ {
4752*14414594SDavid du Colombier+ 	register struct vnode *vp = ap->a_vp;
4753*14414594SDavid du Colombier+ 	register struct u9fsnode *np = VTOU9FS(vp);
4754*14414594SDavid du Colombier+ 	register struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
4755*14414594SDavid du Colombier+ 	struct proc * p = curproc;
4756*14414594SDavid du Colombier+
4757*14414594SDavid du Colombier+ 	/* some vnodes do not have fids due to previous access failure */
4758*14414594SDavid du Colombier+ 	if( np->n_fid ) {
4759*14414594SDavid du Colombier+ 	  /* clunk fids */
4760*14414594SDavid du Colombier+ 	  u9fs_free_fid(np->n_fid, nmp, p);
4761*14414594SDavid du Colombier+ 	  if( np->n_rdfid )
4762*14414594SDavid du Colombier+ 	    u9fs_free_fid(np->n_rdfid, nmp, p);
4763*14414594SDavid du Colombier+ 	  if( np->n_wrfid )
4764*14414594SDavid du Colombier+ 	    u9fs_free_fid(np->n_wrfid, nmp, p);
4765*14414594SDavid du Colombier+ 	}
4766*14414594SDavid du Colombier+
4767*14414594SDavid du Colombier+ 	LIST_REMOVE(np, n_hash);
4768*14414594SDavid du Colombier+ 	cache_purge(vp);
4769*14414594SDavid du Colombier+ 	zfree(u9fsnode_zone, vp->v_data);
4770*14414594SDavid du Colombier+ 	vp->v_data = (void *)0;
4771*14414594SDavid du Colombier+
4772*14414594SDavid du Colombier+ 	return (0);
4773*14414594SDavid du Colombier+ }
4774*14414594SDavid du Colombier+
4775*14414594SDavid du Colombier+ /*
4776*14414594SDavid du Colombier+  * Vnode op for write using bio
4777*14414594SDavid du Colombier+  */
4778*14414594SDavid du Colombier+ static int
4779*14414594SDavid du Colombier+ u9fs_write(ap)
4780*14414594SDavid du Colombier+ 	struct vop_write_args /* {
4781*14414594SDavid du Colombier+ 		struct vnode *a_vp;
4782*14414594SDavid du Colombier+ 		struct uio *a_uio;
4783*14414594SDavid du Colombier+ 		int  a_ioflag;
4784*14414594SDavid du Colombier+ 		struct ucred *a_cred;
4785*14414594SDavid du Colombier+ 	} */ *ap;
4786*14414594SDavid du Colombier+ {
4787*14414594SDavid du Colombier+   if (ap->a_vp->v_type != VREG)
4788*14414594SDavid du Colombier+     return (EIO);
4789*14414594SDavid du Colombier+
4790*14414594SDavid du Colombier+   return u9fs_biowrite(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
4791*14414594SDavid du Colombier+ }
4792*14414594SDavid du Colombier+
4793*14414594SDavid du Colombier+ /*
4794*14414594SDavid du Colombier+  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
4795*14414594SDavid du Colombier+  * done. Currently nothing to do.
4796*14414594SDavid du Colombier+  */
4797*14414594SDavid du Colombier+ /* ARGSUSED */
4798*14414594SDavid du Colombier+ static int
4799*14414594SDavid du Colombier+ u9fs_abortop(ap)
4800*14414594SDavid du Colombier+ 	struct vop_abortop_args /* {
4801*14414594SDavid du Colombier+ 		struct vnode *a_dvp;
4802*14414594SDavid du Colombier+ 		struct componentname *a_cnp;
4803*14414594SDavid du Colombier+ 	} */ *ap;
4804*14414594SDavid du Colombier+ {
4805*14414594SDavid du Colombier+ 	return (0);
4806*14414594SDavid du Colombier+ }
4807*14414594SDavid du Colombier+
4808*14414594SDavid du Colombier+ /*
4809*14414594SDavid du Colombier+  * u9fs write call
4810*14414594SDavid du Colombier+  */
4811*14414594SDavid du Colombier+ int
4812*14414594SDavid du Colombier+ u9fs_writerpc(vp, uiop, cred)
4813*14414594SDavid du Colombier+ 	register struct vnode *vp;
4814*14414594SDavid du Colombier+ 	register struct uio *uiop;
4815*14414594SDavid du Colombier+ 	struct ucred *cred;
4816*14414594SDavid du Colombier+ {
4817*14414594SDavid du Colombier+   struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
4818*14414594SDavid du Colombier+   int error = 0, len, tsiz, rlen;
4819*14414594SDavid du Colombier+   struct u9fsreq req, rep;
4820*14414594SDavid du Colombier+   struct u9fsnode * np = VTOU9FS(vp);
4821*14414594SDavid du Colombier+   struct proc * p = uiop->uio_procp;
4822*14414594SDavid du Colombier+   struct mbuf * top;
4823*14414594SDavid du Colombier+
4824*14414594SDavid du Colombier+   tsiz = uiop->uio_resid;
4825*14414594SDavid du Colombier+   if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
4826*14414594SDavid du Colombier+     return (EFBIG);
4827*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
4828*14414594SDavid du Colombier+   req.r_nmp = nmp;
4829*14414594SDavid du Colombier+   req.r_procp = p;
4830*14414594SDavid du Colombier+   req.r_type = Twrite;
4831*14414594SDavid du Colombier+   req.r_fid = np->n_wrfid;
4832*14414594SDavid du Colombier+   while (tsiz > 0) {
4833*14414594SDavid du Colombier+     len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
4834*14414594SDavid du Colombier+     req.r_offset = uiop->uio_offset;
4835*14414594SDavid du Colombier+     req.r_count = len;
4836*14414594SDavid du Colombier+     error = u9fs_uiotombuf(uiop, &top, len);
4837*14414594SDavid du Colombier+     if( error )
4838*14414594SDavid du Colombier+       break;
4839*14414594SDavid du Colombier+     req.r_data = (char *)top;
4840*14414594SDavid du Colombier+     error = u9fs_request(&req, &rep, 1);
4841*14414594SDavid du Colombier+     if( error )
4842*14414594SDavid du Colombier+       break;
4843*14414594SDavid du Colombier+     rlen = rep.r_count;
4844*14414594SDavid du Colombier+     if( rlen < len ) {
4845*14414594SDavid du Colombier+       error = EIO;
4846*14414594SDavid du Colombier+       break;
4847*14414594SDavid du Colombier+     }
4848*14414594SDavid du Colombier+     tsiz -= len;
4849*14414594SDavid du Colombier+
4850*14414594SDavid du Colombier+     /* each write message increments version number by one.
4851*14414594SDavid du Colombier+        to avoid flushing our write cache, update the version */
4852*14414594SDavid du Colombier+     if( np->n_qid.vers )
4853*14414594SDavid du Colombier+       np->n_qid.vers++;
4854*14414594SDavid du Colombier+     else
4855*14414594SDavid du Colombier+       np->n_qid.vers = np->n_dir.dir_qid.vers + 1;
4856*14414594SDavid du Colombier+   }
4857*14414594SDavid du Colombier+   if (error)
4858*14414594SDavid du Colombier+     uiop->uio_resid = tsiz;
4859*14414594SDavid du Colombier+   return (error);
4860*14414594SDavid du Colombier+ }
4861*14414594SDavid du Colombier+
4862*14414594SDavid du Colombier+ /*
4863*14414594SDavid du Colombier+  * Readdir rpc call.
4864*14414594SDavid du Colombier+  * Called from below the buffer cache by u9fs_doio().
4865*14414594SDavid du Colombier+  */
4866*14414594SDavid du Colombier+ int
4867*14414594SDavid du Colombier+ u9fs_readdirrpc(vp, uiop, cred)
4868*14414594SDavid du Colombier+ 	struct vnode *vp;
4869*14414594SDavid du Colombier+ 	register struct uio *uiop;
4870*14414594SDavid du Colombier+ 	struct ucred *cred;
4871*14414594SDavid du Colombier+
4872*14414594SDavid du Colombier+ {
4873*14414594SDavid du Colombier+ 	register int len, left;
4874*14414594SDavid du Colombier+ 	register struct dirent *dp;
4875*14414594SDavid du Colombier+ 	struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
4876*14414594SDavid du Colombier+ 	struct u9fsnode *np = VTOU9FS(vp);
4877*14414594SDavid du Colombier+ 	int error = 0, tlen, more_dirs = 1, bigenough;
4878*14414594SDavid du Colombier+ 	struct u9fsreq req, rep;
4879*14414594SDavid du Colombier+ 	int count;
4880*14414594SDavid du Colombier+ 	struct u9fsdir u9dir;
4881*14414594SDavid du Colombier+
4882*14414594SDavid du Colombier+ 	bigenough = uiop->uio_resid >= sizeof(struct dirent);
4883*14414594SDavid du Colombier+ 	bzero(&req, sizeof(req));
4884*14414594SDavid du Colombier+ 	req.r_nmp = nmp;
4885*14414594SDavid du Colombier+ 	req.r_type = Tread;
4886*14414594SDavid du Colombier+ 	req.r_fid = np->n_rdfid;
4887*14414594SDavid du Colombier+ 	req.r_count = nmp->nm_readdirsize;
4888*14414594SDavid du Colombier+ 	while ( more_dirs && bigenough ) {
4889*14414594SDavid du Colombier+ 	  req.r_offset = uiop->uio_offset;
4890*14414594SDavid du Colombier+ 	  error = u9fs_request(&req, &rep, 0);
4891*14414594SDavid du Colombier+ 	  if( error )
4892*14414594SDavid du Colombier+ 	    return error;
4893*14414594SDavid du Colombier+
4894*14414594SDavid du Colombier+ 	  count = rep.r_count;
4895*14414594SDavid du Colombier+ 	  more_dirs = (count == req.r_count);
4896*14414594SDavid du Colombier+ 	  len = 0;
4897*14414594SDavid du Colombier+ 	  dp = (struct dirent *)uiop->uio_iov->iov_base;
4898*14414594SDavid du Colombier+ 	  left = uiop->uio_resid;
4899*14414594SDavid du Colombier+ 	  while( len < count ) {
4900*14414594SDavid du Colombier+ 	    /* XXX: too conservative, but OK */
4901*14414594SDavid du Colombier+ 	    if( left < sizeof(*dp) ) {
4902*14414594SDavid du Colombier+ 	      bigenough = 0;
4903*14414594SDavid du Colombier+ 	      break;
4904*14414594SDavid du Colombier+ 	    }
4905*14414594SDavid du Colombier+ 	    if( u9p_m_m2d(&req.r_mrep, & u9dir) ) {
4906*14414594SDavid du Colombier+ 	      printf("u9p_m_m2d failed!\n");
4907*14414594SDavid du Colombier+ 	      return (EIO);
4908*14414594SDavid du Colombier+ 	    }
4909*14414594SDavid du Colombier+
4910*14414594SDavid du Colombier+ 	    dp->d_fileno = u9dir.dir_qid.path;
4911*14414594SDavid du Colombier+ 	    if( U9P_PERM_CHDIR(u9dir.dir_mode) )
4912*14414594SDavid du Colombier+ 	      dp->d_type = DT_DIR;
4913*14414594SDavid du Colombier+ 	    else
4914*14414594SDavid du Colombier+ 	      dp->d_type = DT_REG;
4915*14414594SDavid du Colombier+ 	    u9dir.dir_name[U9FS_NAMELEN-1] = 0; /* just to be sure */
4916*14414594SDavid du Colombier+ 	    dp->d_namlen = strlen(u9dir.dir_name);
4917*14414594SDavid du Colombier+ 	    memcpy(dp->d_name, u9dir.dir_name, dp->d_namlen+1);
4918*14414594SDavid du Colombier+ 	    tlen = DIRHDSIZ + dp->d_namlen + 4;
4919*14414594SDavid du Colombier+ 	    tlen = tlen - (tlen & 0x3);
4920*14414594SDavid du Colombier+ 	    dp->d_reclen = tlen;
4921*14414594SDavid du Colombier+ 	    dp = (struct dirent *)(((char *)dp) + tlen);
4922*14414594SDavid du Colombier+ 	    left -= tlen;
4923*14414594SDavid du Colombier+ 	    len += sizeof(u9dir);
4924*14414594SDavid du Colombier+ 	  }
4925*14414594SDavid du Colombier+ 	  tlen = uiop->uio_resid - left;
4926*14414594SDavid du Colombier+ 	  uiop->uio_resid = left;
4927*14414594SDavid du Colombier+ 	  uiop->uio_iov->iov_base += tlen;
4928*14414594SDavid du Colombier+ 	  uiop->uio_iov->iov_len -= tlen;
4929*14414594SDavid du Colombier+ 	  uiop->uio_offset += len;
4930*14414594SDavid du Colombier+ 	  m_freem(req.r_mrep);
4931*14414594SDavid du Colombier+ 	}
4932*14414594SDavid du Colombier+ 	return 0;
4933*14414594SDavid du Colombier+ }
4934*14414594SDavid du Colombier+
4935*14414594SDavid du Colombier+ /*
4936*14414594SDavid du Colombier+  * u9fs read rpc call
4937*14414594SDavid du Colombier+  * Ditto above
4938*14414594SDavid du Colombier+  */
4939*14414594SDavid du Colombier+ int
4940*14414594SDavid du Colombier+ u9fs_readrpc(vp, uiop, cred)
4941*14414594SDavid du Colombier+ 	register struct vnode *vp;
4942*14414594SDavid du Colombier+ 	struct uio *uiop;
4943*14414594SDavid du Colombier+ 	struct ucred *cred;
4944*14414594SDavid du Colombier+ {
4945*14414594SDavid du Colombier+   struct u9fsmount *nmp;
4946*14414594SDavid du Colombier+   struct u9fsnode *np = VTOU9FS(vp);
4947*14414594SDavid du Colombier+   int error = 0, len, retlen, tsiz;
4948*14414594SDavid du Colombier+   struct u9fsreq req, rep;
4949*14414594SDavid du Colombier+
4950*14414594SDavid du Colombier+   nmp = VFSTOU9FS(vp->v_mount);
4951*14414594SDavid du Colombier+   tsiz = uiop->uio_resid;
4952*14414594SDavid du Colombier+   if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
4953*14414594SDavid du Colombier+     return (EFBIG);
4954*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
4955*14414594SDavid du Colombier+   req.r_nmp = nmp;
4956*14414594SDavid du Colombier+   req.r_type = Tread;
4957*14414594SDavid du Colombier+   req.r_fid = np->n_rdfid;
4958*14414594SDavid du Colombier+   while (tsiz > 0) {
4959*14414594SDavid du Colombier+     len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
4960*14414594SDavid du Colombier+     req.r_count = len;
4961*14414594SDavid du Colombier+     req.r_offset = uiop->uio_offset;
4962*14414594SDavid du Colombier+     error = u9fs_request(&req, &rep, 0);
4963*14414594SDavid du Colombier+     if( error )
4964*14414594SDavid du Colombier+       return error;
4965*14414594SDavid du Colombier+     retlen = rep.r_count;
4966*14414594SDavid du Colombier+     if( retlen && (error = u9fs_mbuftouio(req.r_mrep, uiop, retlen)) ) {
4967*14414594SDavid du Colombier+       m_freem(req.r_mrep);
4968*14414594SDavid du Colombier+       return error;
4969*14414594SDavid du Colombier+     }
4970*14414594SDavid du Colombier+
4971*14414594SDavid du Colombier+     m_freem(req.r_mrep);
4972*14414594SDavid du Colombier+     req.r_mrep = 0;
4973*14414594SDavid du Colombier+     tsiz -= retlen;
4974*14414594SDavid du Colombier+     if (retlen < len)
4975*14414594SDavid du Colombier+       tsiz = 0;
4976*14414594SDavid du Colombier+   }
4977*14414594SDavid du Colombier+   return (0);
4978*14414594SDavid du Colombier+ }
4979*14414594SDavid du Colombier+
4980*14414594SDavid du Colombier+ static void u9fs_free_fid(fid, nmp, p)
4981*14414594SDavid du Colombier+      u_short fid;
4982*14414594SDavid du Colombier+      struct u9fsmount * nmp;
4983*14414594SDavid du Colombier+      struct proc * p;
4984*14414594SDavid du Colombier+ {
4985*14414594SDavid du Colombier+   struct u9fsreq req, rep;
4986*14414594SDavid du Colombier+
4987*14414594SDavid du Colombier+   /* clunk fid */
4988*14414594SDavid du Colombier+   bzero(&req, sizeof(req));
4989*14414594SDavid du Colombier+   req.r_nmp = nmp;
4990*14414594SDavid du Colombier+   req.r_procp = p;
4991*14414594SDavid du Colombier+   req.r_type = Tclunk;
4992*14414594SDavid du Colombier+   req.r_fid = fid;
4993*14414594SDavid du Colombier+   u9fs_request(&req, &rep, 1);
4994*14414594SDavid du Colombier+   u9fs_id_free(nmp->nm_fids, fid);
4995*14414594SDavid du Colombier+ }
4996*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9p.c ./9fs/9p.c
4997*14414594SDavid du Colombier*** /usr/src/sys/9fs/9p.c	Wed Dec 31 19:00:00 1969
4998*14414594SDavid du Colombier--- ./9fs/9p.c	Thu Nov 25 15:04:16 1999
4999*14414594SDavid du Colombier***************
5000*14414594SDavid du Colombier*** 0 ****
5001*14414594SDavid du Colombier--- 1,974 ----
5002*14414594SDavid du Colombier+ #include <sys/param.h>
5003*14414594SDavid du Colombier+ #include <sys/systm.h>
5004*14414594SDavid du Colombier+ #include <sys/socket.h>
5005*14414594SDavid du Colombier+ #include <sys/socketvar.h>
5006*14414594SDavid du Colombier+ #include <netinet/in.h>
5007*14414594SDavid du Colombier+ #include <sys/mbuf.h>
5008*14414594SDavid du Colombier+ #include <sys/malloc.h>
5009*14414594SDavid du Colombier+ #include <sys/vnode.h>
5010*14414594SDavid du Colombier+ #include <sys/mount.h>
5011*14414594SDavid du Colombier+
5012*14414594SDavid du Colombier+ #include <9fs/bitstring.h>
5013*14414594SDavid du Colombier+ #include <9fs/9p.h>
5014*14414594SDavid du Colombier+ #include <9fs/9auth.h>
5015*14414594SDavid du Colombier+ #include <9fs/9fs.h>
5016*14414594SDavid du Colombier+
5017*14414594SDavid du Colombier+ int u9p_usetcp = 0;
5018*14414594SDavid du Colombier+ struct u9fs_reqq u9fs_reqq;
5019*14414594SDavid du Colombier+
5020*14414594SDavid du Colombier+ #define	N2HCHAR(x)		x = *p++
5021*14414594SDavid du Colombier+ #define	N2HSHORT(x)	x = (p[0] | (p[1]<<8)); p += 2
5022*14414594SDavid du Colombier+ #define	N2HLONG(x)		x = (p[0] | (p[1]<<8) |\
5023*14414594SDavid du Colombier+ 				(p[2]<<16) | (p[3]<<24)); p += 4
5024*14414594SDavid du Colombier+ #define	N2HQUAD(x)	x = (u_int64_t)(p[0] | (p[1]<<8) |\
5025*14414594SDavid du Colombier+ 					(p[2]<<16) | (p[3]<<24)) |\
5026*14414594SDavid du Colombier+ 				((u_int64_t)(p[4] | (p[5]<<8) |\
5027*14414594SDavid du Colombier+ 					(p[6]<<16) | (p[7]<<24)) << 32); p += 8
5028*14414594SDavid du Colombier+ #define	N2HSTRING(x,n)	bcopy(p, x, n); p += n
5029*14414594SDavid du Colombier+
5030*14414594SDavid du Colombier+ #define	H2NCHAR(x)	*p++ = x
5031*14414594SDavid du Colombier+ #define	H2NSHORT(x)	p[0]=x; p[1]=x>>8; p += 2
5032*14414594SDavid du Colombier+ #define	H2NLONG(x)		p[0]=x; p[1]=x>>8; p[2]=x>>16; p[3]=x>>24; p += 4
5033*14414594SDavid du Colombier+ #define	H2NQUAD(x)	p[0]=x;	p[1]=x>>8;\
5034*14414594SDavid du Colombier+ 			p[2]=x>>16;	p[3]=x>>24;\
5035*14414594SDavid du Colombier+ 			p[4]=x>>32;	p[5]=x>>40;\
5036*14414594SDavid du Colombier+ 			p[6]=x>>48;	p[7]=x>>56;\
5037*14414594SDavid du Colombier+ 			p += 8
5038*14414594SDavid du Colombier+ #define	H2NSTRING(x,n)	bcopy(x, p, n); p += n
5039*14414594SDavid du Colombier+
5040*14414594SDavid du Colombier+ static void u9p_print __P((u_char * m, int len, struct u9fsreq * f));
5041*14414594SDavid du Colombier+
5042*14414594SDavid du Colombier+ static char * u9p_types[] = {
5043*14414594SDavid du Colombier+   "Tnop",
5044*14414594SDavid du Colombier+   "Rnop",
5045*14414594SDavid du Colombier+   "Tosession",
5046*14414594SDavid du Colombier+   "Rosession",
5047*14414594SDavid du Colombier+   "Terror",
5048*14414594SDavid du Colombier+   "Rerror",
5049*14414594SDavid du Colombier+   "Tflush",
5050*14414594SDavid du Colombier+   "Rflush",
5051*14414594SDavid du Colombier+   "Toattach",
5052*14414594SDavid du Colombier+   "Roattach",
5053*14414594SDavid du Colombier+   "Tclone",
5054*14414594SDavid du Colombier+   "Rclone",
5055*14414594SDavid du Colombier+   "Twalk",
5056*14414594SDavid du Colombier+   "Rwalk",
5057*14414594SDavid du Colombier+   "Topen",
5058*14414594SDavid du Colombier+   "Ropen",
5059*14414594SDavid du Colombier+   "Tcreate",
5060*14414594SDavid du Colombier+   "Rcreate",
5061*14414594SDavid du Colombier+   "Tread",
5062*14414594SDavid du Colombier+   "Rread",
5063*14414594SDavid du Colombier+   "Twrite",
5064*14414594SDavid du Colombier+   "Rwrite",
5065*14414594SDavid du Colombier+   "Tclunk",
5066*14414594SDavid du Colombier+   "Rclunk",
5067*14414594SDavid du Colombier+   "Tremove",
5068*14414594SDavid du Colombier+   "Rremove",
5069*14414594SDavid du Colombier+   "Tstat",
5070*14414594SDavid du Colombier+   "Rstat",
5071*14414594SDavid du Colombier+   "Twstat",
5072*14414594SDavid du Colombier+   "Rwstat",
5073*14414594SDavid du Colombier+   "Tclwalk",
5074*14414594SDavid du Colombier+   "Rclwalk",
5075*14414594SDavid du Colombier+   "Tauth",
5076*14414594SDavid du Colombier+   "Rauth",
5077*14414594SDavid du Colombier+   "Tsession",
5078*14414594SDavid du Colombier+   "Rsession",
5079*14414594SDavid du Colombier+   "Tattach",
5080*14414594SDavid du Colombier+   "Rattach",
5081*14414594SDavid du Colombier+   "Ttunnel",
5082*14414594SDavid du Colombier+   "Rtunnel",
5083*14414594SDavid du Colombier+   "Tmax"
5084*14414594SDavid du Colombier+ };
5085*14414594SDavid du Colombier+
5086*14414594SDavid du Colombier+ int u9p_m2s(char *ap, int n, struct u9fsreq *f)
5087*14414594SDavid du Colombier+ {
5088*14414594SDavid du Colombier+ 	u_char *p;
5089*14414594SDavid du Colombier+
5090*14414594SDavid du Colombier+ 	p = (u_char*)ap;
5091*14414594SDavid du Colombier+ 	N2HCHAR(f->r_type);
5092*14414594SDavid du Colombier+ 	N2HSHORT(f->r_tag);
5093*14414594SDavid du Colombier+ 	switch(f->r_type)
5094*14414594SDavid du Colombier+ 	{
5095*14414594SDavid du Colombier+ 	default:
5096*14414594SDavid du Colombier+ 		return 0;
5097*14414594SDavid du Colombier+
5098*14414594SDavid du Colombier+ 	case Tnop:
5099*14414594SDavid du Colombier+ 	case Tosession:
5100*14414594SDavid du Colombier+ 		break;
5101*14414594SDavid du Colombier+
5102*14414594SDavid du Colombier+ 	case Tsession:
5103*14414594SDavid du Colombier+ 		N2HSTRING(f->r_chal, sizeof(f->r_chal));
5104*14414594SDavid du Colombier+ 		break;
5105*14414594SDavid du Colombier+
5106*14414594SDavid du Colombier+ 	case Tflush:
5107*14414594SDavid du Colombier+ 		N2HSHORT(f->r_oldtag);
5108*14414594SDavid du Colombier+ 		break;
5109*14414594SDavid du Colombier+
5110*14414594SDavid du Colombier+ 	case Tattach:
5111*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5112*14414594SDavid du Colombier+ 		N2HSTRING(f->r_uname, sizeof(f->r_uname));
5113*14414594SDavid du Colombier+ 		N2HSTRING(f->r_aname, sizeof(f->r_aname));
5114*14414594SDavid du Colombier+ 		N2HSTRING(f->r_ticket, sizeof(f->r_ticket));
5115*14414594SDavid du Colombier+ 		N2HSTRING(f->r_auth, sizeof(f->r_auth));
5116*14414594SDavid du Colombier+ 		break;
5117*14414594SDavid du Colombier+
5118*14414594SDavid du Colombier+ 	case Toattach:
5119*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5120*14414594SDavid du Colombier+ 		N2HSTRING(f->r_uname, sizeof(f->r_uname));
5121*14414594SDavid du Colombier+ 		N2HSTRING(f->r_aname, sizeof(f->r_aname));
5122*14414594SDavid du Colombier+ 		N2HSTRING(f->r_ticket, U9FS_NAMELEN);
5123*14414594SDavid du Colombier+ 		break;
5124*14414594SDavid du Colombier+
5125*14414594SDavid du Colombier+ 	case Tauth:
5126*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5127*14414594SDavid du Colombier+ 		N2HSTRING(f->r_uname, sizeof(f->r_uname));
5128*14414594SDavid du Colombier+ 		N2HSTRING(f->r_ticket, 8+U9FS_NAMELEN);
5129*14414594SDavid du Colombier+ 		break;
5130*14414594SDavid du Colombier+
5131*14414594SDavid du Colombier+ 	case Tclone:
5132*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5133*14414594SDavid du Colombier+ 		N2HSHORT(f->r_newfid);
5134*14414594SDavid du Colombier+ 		break;
5135*14414594SDavid du Colombier+
5136*14414594SDavid du Colombier+ 	case Twalk:
5137*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5138*14414594SDavid du Colombier+ 		N2HSTRING(f->r_name, sizeof(f->r_name));
5139*14414594SDavid du Colombier+ 		break;
5140*14414594SDavid du Colombier+
5141*14414594SDavid du Colombier+ 	case Topen:
5142*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5143*14414594SDavid du Colombier+ 		N2HCHAR(f->r_mode);
5144*14414594SDavid du Colombier+ 		break;
5145*14414594SDavid du Colombier+
5146*14414594SDavid du Colombier+ 	case Tcreate:
5147*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5148*14414594SDavid du Colombier+ 		N2HSTRING(f->r_name, sizeof(f->r_name));
5149*14414594SDavid du Colombier+ 		N2HLONG(f->r_perm);
5150*14414594SDavid du Colombier+ 		N2HCHAR(f->r_mode);
5151*14414594SDavid du Colombier+ 		break;
5152*14414594SDavid du Colombier+
5153*14414594SDavid du Colombier+ 	case Tread:
5154*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5155*14414594SDavid du Colombier+ 		N2HQUAD(f->r_offset);
5156*14414594SDavid du Colombier+ 		N2HSHORT(f->r_count);
5157*14414594SDavid du Colombier+ 		break;
5158*14414594SDavid du Colombier+
5159*14414594SDavid du Colombier+ 	case Twrite:
5160*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5161*14414594SDavid du Colombier+ 		N2HQUAD(f->r_offset);
5162*14414594SDavid du Colombier+ 		N2HSHORT(f->r_count);
5163*14414594SDavid du Colombier+ 		p++;	/* pad(1) */
5164*14414594SDavid du Colombier+ 		f->r_data = (char*)p; p += f->r_count;
5165*14414594SDavid du Colombier+ 		break;
5166*14414594SDavid du Colombier+
5167*14414594SDavid du Colombier+ 	case Ttunnel:
5168*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5169*14414594SDavid du Colombier+ 		break;
5170*14414594SDavid du Colombier+
5171*14414594SDavid du Colombier+ 	case Tclunk:
5172*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5173*14414594SDavid du Colombier+ 		break;
5174*14414594SDavid du Colombier+
5175*14414594SDavid du Colombier+ 	case Tremove:
5176*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5177*14414594SDavid du Colombier+ 		break;
5178*14414594SDavid du Colombier+
5179*14414594SDavid du Colombier+ 	case Tstat:
5180*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5181*14414594SDavid du Colombier+ 		break;
5182*14414594SDavid du Colombier+
5183*14414594SDavid du Colombier+ 	case Twstat:
5184*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5185*14414594SDavid du Colombier+ 		N2HSTRING(f->r_stat, sizeof(f->r_stat));
5186*14414594SDavid du Colombier+ 		break;
5187*14414594SDavid du Colombier+
5188*14414594SDavid du Colombier+ 	case Tclwalk:
5189*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5190*14414594SDavid du Colombier+ 		N2HSHORT(f->r_newfid);
5191*14414594SDavid du Colombier+ 		N2HSTRING(f->r_name, sizeof(f->r_name));
5192*14414594SDavid du Colombier+ 		break;
5193*14414594SDavid du Colombier+ /*
5194*14414594SDavid du Colombier+  */
5195*14414594SDavid du Colombier+ 	case Rnop:
5196*14414594SDavid du Colombier+ 	case Rosession:
5197*14414594SDavid du Colombier+ 		break;
5198*14414594SDavid du Colombier+
5199*14414594SDavid du Colombier+ 	case Rsession:
5200*14414594SDavid du Colombier+ 		N2HSTRING(f->r_chal, sizeof(f->r_chal));
5201*14414594SDavid du Colombier+ 		N2HSTRING(f->r_authid, sizeof(f->r_authid));
5202*14414594SDavid du Colombier+ 		N2HSTRING(f->r_authdom, sizeof(f->r_authdom));
5203*14414594SDavid du Colombier+ 		break;
5204*14414594SDavid du Colombier+
5205*14414594SDavid du Colombier+ 	case Rerror:
5206*14414594SDavid du Colombier+ 		N2HSTRING(f->r_ename, sizeof(f->r_ename));
5207*14414594SDavid du Colombier+ 		break;
5208*14414594SDavid du Colombier+
5209*14414594SDavid du Colombier+ 	case Rflush:
5210*14414594SDavid du Colombier+ 		break;
5211*14414594SDavid du Colombier+
5212*14414594SDavid du Colombier+ 	case Rattach:
5213*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5214*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.path);
5215*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.vers);
5216*14414594SDavid du Colombier+ 		N2HSTRING(f->r_rauth, sizeof(f->r_rauth));
5217*14414594SDavid du Colombier+ 		break;
5218*14414594SDavid du Colombier+
5219*14414594SDavid du Colombier+ 	case Roattach:
5220*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5221*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.path);
5222*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.vers);
5223*14414594SDavid du Colombier+ 		break;
5224*14414594SDavid du Colombier+
5225*14414594SDavid du Colombier+ 	case Rauth:
5226*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5227*14414594SDavid du Colombier+ 		N2HSTRING(f->r_ticket, 8+8+7+7);
5228*14414594SDavid du Colombier+ 		break;
5229*14414594SDavid du Colombier+
5230*14414594SDavid du Colombier+ 	case Rclone:
5231*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5232*14414594SDavid du Colombier+ 		break;
5233*14414594SDavid du Colombier+
5234*14414594SDavid du Colombier+ 	case Rwalk:
5235*14414594SDavid du Colombier+ 	case Rclwalk:
5236*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5237*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.path);
5238*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.vers);
5239*14414594SDavid du Colombier+ 		break;
5240*14414594SDavid du Colombier+
5241*14414594SDavid du Colombier+ 	case Ropen:
5242*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5243*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.path);
5244*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.vers);
5245*14414594SDavid du Colombier+ 		break;
5246*14414594SDavid du Colombier+
5247*14414594SDavid du Colombier+ 	case Rcreate:
5248*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5249*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.path);
5250*14414594SDavid du Colombier+ 		N2HLONG(f->r_qid.vers);
5251*14414594SDavid du Colombier+ 		break;
5252*14414594SDavid du Colombier+
5253*14414594SDavid du Colombier+ 	case Rread:
5254*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5255*14414594SDavid du Colombier+ 		N2HSHORT(f->r_count);
5256*14414594SDavid du Colombier+ 		p++;	/* pad(1) */
5257*14414594SDavid du Colombier+ 		f->r_data = (char*)p; p += f->r_count;
5258*14414594SDavid du Colombier+ 		break;
5259*14414594SDavid du Colombier+
5260*14414594SDavid du Colombier+ 	case Rwrite:
5261*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5262*14414594SDavid du Colombier+ 		N2HSHORT(f->r_count);
5263*14414594SDavid du Colombier+ 		break;
5264*14414594SDavid du Colombier+
5265*14414594SDavid du Colombier+ 	case Rtunnel:
5266*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5267*14414594SDavid du Colombier+ 		break;
5268*14414594SDavid du Colombier+
5269*14414594SDavid du Colombier+ 	case Rclunk:
5270*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5271*14414594SDavid du Colombier+ 		break;
5272*14414594SDavid du Colombier+
5273*14414594SDavid du Colombier+ 	case Rremove:
5274*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5275*14414594SDavid du Colombier+ 		break;
5276*14414594SDavid du Colombier+
5277*14414594SDavid du Colombier+ 	case Rstat:
5278*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5279*14414594SDavid du Colombier+ 		N2HSTRING(f->r_stat, sizeof(f->r_stat));
5280*14414594SDavid du Colombier+ 		break;
5281*14414594SDavid du Colombier+
5282*14414594SDavid du Colombier+ 	case Rwstat:
5283*14414594SDavid du Colombier+ 		N2HSHORT(f->r_fid);
5284*14414594SDavid du Colombier+ 		break;
5285*14414594SDavid du Colombier+ 	}
5286*14414594SDavid du Colombier+ 	if((u_char*)ap+n == p)
5287*14414594SDavid du Colombier+ 		return n;
5288*14414594SDavid du Colombier+ 	return 0;
5289*14414594SDavid du Colombier+ }
5290*14414594SDavid du Colombier+
5291*14414594SDavid du Colombier+ void u9p_print(u_char * m, int len, struct u9fsreq * f)
5292*14414594SDavid du Colombier+ {
5293*14414594SDavid du Colombier+   struct u9fsreq u9fsreq;
5294*14414594SDavid du Colombier+
5295*14414594SDavid du Colombier+   if( f == 0 )
5296*14414594SDavid du Colombier+     f = & u9fsreq;
5297*14414594SDavid du Colombier+
5298*14414594SDavid du Colombier+   if( len < 3 ) {
5299*14414594SDavid du Colombier+     printf("truncated-9p %d", len);
5300*14414594SDavid du Colombier+     return;
5301*14414594SDavid du Colombier+   }
5302*14414594SDavid du Colombier+
5303*14414594SDavid du Colombier+   if( u9p_m2s((char *)m, len, f) == 0 )
5304*14414594SDavid du Colombier+     return;
5305*14414594SDavid du Colombier+
5306*14414594SDavid du Colombier+   printf("%s tag %d ", u9p_types[f->r_type-Tnop], f->r_tag);
5307*14414594SDavid du Colombier+
5308*14414594SDavid du Colombier+   switch( f->r_type ) {
5309*14414594SDavid du Colombier+ 	default:
5310*14414594SDavid du Colombier+ 	  return;
5311*14414594SDavid du Colombier+
5312*14414594SDavid du Colombier+ 	case Tnop:
5313*14414594SDavid du Colombier+ 	case Tosession:
5314*14414594SDavid du Colombier+ 	case Toattach:
5315*14414594SDavid du Colombier+ 	case Tauth:
5316*14414594SDavid du Colombier+ 		break;
5317*14414594SDavid du Colombier+
5318*14414594SDavid du Colombier+ 	case Tsession:
5319*14414594SDavid du Colombier+ 	case Rsession:
5320*14414594SDavid du Colombier+ 	  printf("chal 0x%x 0x%x", *(u_int *)&f->r_chal[0], *(u_int *)&f->r_chal[4]);
5321*14414594SDavid du Colombier+ 		break;
5322*14414594SDavid du Colombier+
5323*14414594SDavid du Colombier+ 	case Tflush:
5324*14414594SDavid du Colombier+ 	  printf("oldtag %d", f->r_oldtag);
5325*14414594SDavid du Colombier+ 		break;
5326*14414594SDavid du Colombier+
5327*14414594SDavid du Colombier+ 	case Tclone:
5328*14414594SDavid du Colombier+ 	  printf("fid %d newfid %d", f->r_fid, f->r_newfid);
5329*14414594SDavid du Colombier+ 		break;
5330*14414594SDavid du Colombier+
5331*14414594SDavid du Colombier+ 	case Twalk:
5332*14414594SDavid du Colombier+ 	  printf("fid %d name %s", f->r_fid, f->r_name);
5333*14414594SDavid du Colombier+ 		break;
5334*14414594SDavid du Colombier+
5335*14414594SDavid du Colombier+ 	case Topen:
5336*14414594SDavid du Colombier+ 	  printf("fid %d %c", f->r_fid, f->r_mode);
5337*14414594SDavid du Colombier+ 		break;
5338*14414594SDavid du Colombier+
5339*14414594SDavid du Colombier+ 	case Tcreate:
5340*14414594SDavid du Colombier+ 	  printf("fid %d name %s perm 0x%x mode %c", f->r_fid,
5341*14414594SDavid du Colombier+ 		 f->r_name, f->r_perm, f->r_mode);
5342*14414594SDavid du Colombier+ 		break;
5343*14414594SDavid du Colombier+
5344*14414594SDavid du Colombier+ 	case Tread:
5345*14414594SDavid du Colombier+ 	case Twrite:
5346*14414594SDavid du Colombier+ 	  printf("fid %d offset 0x%llx count %d", f->r_fid,
5347*14414594SDavid du Colombier+ 		 f->r_offset, f->r_count);
5348*14414594SDavid du Colombier+ 		break;
5349*14414594SDavid du Colombier+
5350*14414594SDavid du Colombier+ 	case Tattach:
5351*14414594SDavid du Colombier+ 	case Ttunnel:
5352*14414594SDavid du Colombier+ 	case Tclunk:
5353*14414594SDavid du Colombier+ 	case Tremove:
5354*14414594SDavid du Colombier+ 	case Tstat:
5355*14414594SDavid du Colombier+ 	case Twstat:
5356*14414594SDavid du Colombier+ 	case Rclone:
5357*14414594SDavid du Colombier+ 	case Rtunnel:
5358*14414594SDavid du Colombier+ 	case Rclunk:
5359*14414594SDavid du Colombier+ 	case Rremove:
5360*14414594SDavid du Colombier+ 	case Rstat:
5361*14414594SDavid du Colombier+ 	case Rwstat:
5362*14414594SDavid du Colombier+ 	  printf("fid %d", f->r_fid);
5363*14414594SDavid du Colombier+ 		break;
5364*14414594SDavid du Colombier+
5365*14414594SDavid du Colombier+ 	case Tclwalk:
5366*14414594SDavid du Colombier+ 	  printf("fid %d ", f->r_fid);
5367*14414594SDavid du Colombier+ 	  printf("newfid  %d ", f->r_newfid);
5368*14414594SDavid du Colombier+ 	  printf("name %s", f->r_name);
5369*14414594SDavid du Colombier+ 		break;
5370*14414594SDavid du Colombier+ /*
5371*14414594SDavid du Colombier+  */
5372*14414594SDavid du Colombier+ 	case Rnop:
5373*14414594SDavid du Colombier+ 	case Rosession:
5374*14414594SDavid du Colombier+ 	case Rflush:
5375*14414594SDavid du Colombier+ 	case Roattach:
5376*14414594SDavid du Colombier+ 	case Rauth:
5377*14414594SDavid du Colombier+ 		break;
5378*14414594SDavid du Colombier+
5379*14414594SDavid du Colombier+ 	case Rerror:
5380*14414594SDavid du Colombier+ 	  printf("ename %s", f->r_ename);
5381*14414594SDavid du Colombier+ 		break;
5382*14414594SDavid du Colombier+
5383*14414594SDavid du Colombier+ 	case Rattach:
5384*14414594SDavid du Colombier+ 	case Rwalk:
5385*14414594SDavid du Colombier+ 	case Rclwalk:
5386*14414594SDavid du Colombier+ 	case Ropen:
5387*14414594SDavid du Colombier+ 	case Rcreate:
5388*14414594SDavid du Colombier+ 	  printf("fid %d ", f->r_fid);
5389*14414594SDavid du Colombier+ 	  printf("qid 0x%x 0x%x", f->r_qid.path, f->r_qid.vers);
5390*14414594SDavid du Colombier+ 		break;
5391*14414594SDavid du Colombier+
5392*14414594SDavid du Colombier+ 	case Rread:
5393*14414594SDavid du Colombier+ 	  printf("fid %d count %d ", f->r_fid, f->r_count);
5394*14414594SDavid du Colombier+ 	  break;
5395*14414594SDavid du Colombier+
5396*14414594SDavid du Colombier+ 	case Rwrite:
5397*14414594SDavid du Colombier+ 	  printf("fid %d count %d", f->r_fid, f->r_count);
5398*14414594SDavid du Colombier+ 		break;
5399*14414594SDavid du Colombier+   }
5400*14414594SDavid du Colombier+ }
5401*14414594SDavid du Colombier+
5402*14414594SDavid du Colombier+ int
5403*14414594SDavid du Colombier+ u9p_s2m(struct u9fsreq *f, char *ap, int copydata)
5404*14414594SDavid du Colombier+ {
5405*14414594SDavid du Colombier+ 	u_char *p;
5406*14414594SDavid du Colombier+
5407*14414594SDavid du Colombier+ 	p = (u_char*)ap;
5408*14414594SDavid du Colombier+ 	H2NCHAR(f->r_type);
5409*14414594SDavid du Colombier+ 	H2NSHORT(f->r_tag);
5410*14414594SDavid du Colombier+ 	switch(f->r_type)
5411*14414594SDavid du Colombier+ 	{
5412*14414594SDavid du Colombier+ 	default:
5413*14414594SDavid du Colombier+ 		return 0;
5414*14414594SDavid du Colombier+
5415*14414594SDavid du Colombier+ 	case Tosession:
5416*14414594SDavid du Colombier+ 	case Tnop:
5417*14414594SDavid du Colombier+ 		break;
5418*14414594SDavid du Colombier+
5419*14414594SDavid du Colombier+ 	case Tsession:
5420*14414594SDavid du Colombier+ 		H2NSTRING(f->r_chal, sizeof(f->r_chal));
5421*14414594SDavid du Colombier+ 		break;
5422*14414594SDavid du Colombier+
5423*14414594SDavid du Colombier+ 	case Tflush:
5424*14414594SDavid du Colombier+ 		H2NSHORT(f->r_oldtag);
5425*14414594SDavid du Colombier+ 		break;
5426*14414594SDavid du Colombier+
5427*14414594SDavid du Colombier+ 	case Tattach:
5428*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5429*14414594SDavid du Colombier+ 		H2NSTRING(f->r_uname, sizeof(f->r_uname));
5430*14414594SDavid du Colombier+ 		H2NSTRING(f->r_aname, sizeof(f->r_aname));
5431*14414594SDavid du Colombier+ 		H2NSTRING(f->r_ticket, sizeof(f->r_ticket));
5432*14414594SDavid du Colombier+ 		H2NSTRING(f->r_auth, sizeof(f->r_auth));
5433*14414594SDavid du Colombier+ 		break;
5434*14414594SDavid du Colombier+
5435*14414594SDavid du Colombier+ 	case Toattach:
5436*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5437*14414594SDavid du Colombier+ 		H2NSTRING(f->r_uname, sizeof(f->r_uname));
5438*14414594SDavid du Colombier+ 		H2NSTRING(f->r_aname, sizeof(f->r_aname));
5439*14414594SDavid du Colombier+ 		H2NSTRING(f->r_ticket, U9FS_NAMELEN);
5440*14414594SDavid du Colombier+ 		break;
5441*14414594SDavid du Colombier+
5442*14414594SDavid du Colombier+ 	case Tauth:
5443*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5444*14414594SDavid du Colombier+ 		H2NSTRING(f->r_uname, sizeof(f->r_uname));
5445*14414594SDavid du Colombier+ 		H2NSTRING(f->r_ticket, 8+U9FS_NAMELEN);
5446*14414594SDavid du Colombier+ 		break;
5447*14414594SDavid du Colombier+
5448*14414594SDavid du Colombier+ 	case Tclone:
5449*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5450*14414594SDavid du Colombier+ 		H2NSHORT(f->r_newfid);
5451*14414594SDavid du Colombier+ 		break;
5452*14414594SDavid du Colombier+
5453*14414594SDavid du Colombier+ 	case Twalk:
5454*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5455*14414594SDavid du Colombier+ 		H2NSTRING(f->r_name, sizeof(f->r_name));
5456*14414594SDavid du Colombier+ 		break;
5457*14414594SDavid du Colombier+
5458*14414594SDavid du Colombier+ 	case Topen:
5459*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5460*14414594SDavid du Colombier+ 		H2NCHAR(f->r_mode);
5461*14414594SDavid du Colombier+ 		break;
5462*14414594SDavid du Colombier+
5463*14414594SDavid du Colombier+ 	case Tcreate:
5464*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5465*14414594SDavid du Colombier+ 		H2NSTRING(f->r_name, sizeof(f->r_name));
5466*14414594SDavid du Colombier+ 		H2NLONG(f->r_perm);
5467*14414594SDavid du Colombier+ 		H2NCHAR(f->r_mode);
5468*14414594SDavid du Colombier+ 		break;
5469*14414594SDavid du Colombier+
5470*14414594SDavid du Colombier+ 	case Tread:
5471*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5472*14414594SDavid du Colombier+ 		H2NQUAD(f->r_offset);
5473*14414594SDavid du Colombier+ 		H2NSHORT(f->r_count);
5474*14414594SDavid du Colombier+ 		break;
5475*14414594SDavid du Colombier+
5476*14414594SDavid du Colombier+ 	case Twrite:
5477*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5478*14414594SDavid du Colombier+ 		H2NQUAD(f->r_offset);
5479*14414594SDavid du Colombier+ 		H2NSHORT(f->r_count);
5480*14414594SDavid du Colombier+ 		p++;	/* pad(1) */
5481*14414594SDavid du Colombier+ 		if( copydata ) {
5482*14414594SDavid du Colombier+ 		  H2NSTRING(f->r_data, f->r_count);
5483*14414594SDavid du Colombier+ 		}
5484*14414594SDavid du Colombier+ 		break;
5485*14414594SDavid du Colombier+
5486*14414594SDavid du Colombier+ 	case Ttunnel:
5487*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5488*14414594SDavid du Colombier+ 		break;
5489*14414594SDavid du Colombier+
5490*14414594SDavid du Colombier+ 	case Tclunk:
5491*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5492*14414594SDavid du Colombier+ 		break;
5493*14414594SDavid du Colombier+
5494*14414594SDavid du Colombier+ 	case Tremove:
5495*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5496*14414594SDavid du Colombier+ 		break;
5497*14414594SDavid du Colombier+
5498*14414594SDavid du Colombier+ 	case Tstat:
5499*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5500*14414594SDavid du Colombier+ 		break;
5501*14414594SDavid du Colombier+
5502*14414594SDavid du Colombier+ 	case Twstat:
5503*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5504*14414594SDavid du Colombier+ 		H2NSTRING(f->r_stat, sizeof(f->r_stat));
5505*14414594SDavid du Colombier+ 		break;
5506*14414594SDavid du Colombier+
5507*14414594SDavid du Colombier+ 	case Tclwalk:
5508*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5509*14414594SDavid du Colombier+ 		H2NSHORT(f->r_newfid);
5510*14414594SDavid du Colombier+ 		H2NSTRING(f->r_name, sizeof(f->r_name));
5511*14414594SDavid du Colombier+ 		break;
5512*14414594SDavid du Colombier+ /*
5513*14414594SDavid du Colombier+  */
5514*14414594SDavid du Colombier+ 	case Rosession:
5515*14414594SDavid du Colombier+ 	case Rnop:
5516*14414594SDavid du Colombier+ 		break;
5517*14414594SDavid du Colombier+
5518*14414594SDavid du Colombier+ 	case Rsession:
5519*14414594SDavid du Colombier+ 		H2NSTRING(f->r_chal, sizeof(f->r_chal));
5520*14414594SDavid du Colombier+ 		H2NSTRING(f->r_authid, sizeof(f->r_authid));
5521*14414594SDavid du Colombier+ 		H2NSTRING(f->r_authdom, sizeof(f->r_authdom));
5522*14414594SDavid du Colombier+ 		break;
5523*14414594SDavid du Colombier+
5524*14414594SDavid du Colombier+ 	case Rerror:
5525*14414594SDavid du Colombier+ 		H2NSTRING(f->r_ename, sizeof(f->r_ename));
5526*14414594SDavid du Colombier+ 		break;
5527*14414594SDavid du Colombier+
5528*14414594SDavid du Colombier+ 	case Rflush:
5529*14414594SDavid du Colombier+ 		break;
5530*14414594SDavid du Colombier+
5531*14414594SDavid du Colombier+ 	case Rattach:
5532*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5533*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.path);
5534*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.vers);
5535*14414594SDavid du Colombier+ 		H2NSTRING(f->r_rauth, sizeof(f->r_rauth));
5536*14414594SDavid du Colombier+ 		break;
5537*14414594SDavid du Colombier+
5538*14414594SDavid du Colombier+ 	case Roattach:
5539*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5540*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.path);
5541*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.vers);
5542*14414594SDavid du Colombier+ 		break;
5543*14414594SDavid du Colombier+
5544*14414594SDavid du Colombier+ 	case Rauth:
5545*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5546*14414594SDavid du Colombier+ 		H2NSTRING(f->r_ticket, 8+8+7+7);
5547*14414594SDavid du Colombier+ 		break;
5548*14414594SDavid du Colombier+
5549*14414594SDavid du Colombier+ 	case Rclone:
5550*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5551*14414594SDavid du Colombier+ 		break;
5552*14414594SDavid du Colombier+
5553*14414594SDavid du Colombier+ 	case Rwalk:
5554*14414594SDavid du Colombier+ 	case Rclwalk:
5555*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5556*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.path);
5557*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.vers);
5558*14414594SDavid du Colombier+ 		break;
5559*14414594SDavid du Colombier+
5560*14414594SDavid du Colombier+ 	case Ropen:
5561*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5562*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.path);
5563*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.vers);
5564*14414594SDavid du Colombier+ 		break;
5565*14414594SDavid du Colombier+
5566*14414594SDavid du Colombier+ 	case Rcreate:
5567*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5568*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.path);
5569*14414594SDavid du Colombier+ 		H2NLONG(f->r_qid.vers);
5570*14414594SDavid du Colombier+ 		break;
5571*14414594SDavid du Colombier+
5572*14414594SDavid du Colombier+ 	case Rread:
5573*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5574*14414594SDavid du Colombier+ 		H2NSHORT(f->r_count);
5575*14414594SDavid du Colombier+ 		p++;	/* pad(1) */
5576*14414594SDavid du Colombier+ 		if( copydata ) {
5577*14414594SDavid du Colombier+ 		  H2NSTRING(f->r_data, f->r_count);
5578*14414594SDavid du Colombier+ 		}
5579*14414594SDavid du Colombier+ 		break;
5580*14414594SDavid du Colombier+
5581*14414594SDavid du Colombier+ 	case Rwrite:
5582*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5583*14414594SDavid du Colombier+ 		H2NSHORT(f->r_count);
5584*14414594SDavid du Colombier+ 		break;
5585*14414594SDavid du Colombier+
5586*14414594SDavid du Colombier+ 	case Rtunnel:
5587*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5588*14414594SDavid du Colombier+ 		break;
5589*14414594SDavid du Colombier+
5590*14414594SDavid du Colombier+ 	case Rclunk:
5591*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5592*14414594SDavid du Colombier+ 		break;
5593*14414594SDavid du Colombier+
5594*14414594SDavid du Colombier+ 	case Rremove:
5595*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5596*14414594SDavid du Colombier+ 		break;
5597*14414594SDavid du Colombier+
5598*14414594SDavid du Colombier+ 	case Rstat:
5599*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5600*14414594SDavid du Colombier+ 		if( copydata )
5601*14414594SDavid du Colombier+ 		  H2NSTRING(f->r_stat, sizeof(f->r_stat));
5602*14414594SDavid du Colombier+ 		break;
5603*14414594SDavid du Colombier+
5604*14414594SDavid du Colombier+ 	case Rwstat:
5605*14414594SDavid du Colombier+ 		H2NSHORT(f->r_fid);
5606*14414594SDavid du Colombier+ 		break;
5607*14414594SDavid du Colombier+ 	}
5608*14414594SDavid du Colombier+ 	return p - (u_char*)ap;
5609*14414594SDavid du Colombier+ }
5610*14414594SDavid du Colombier+
5611*14414594SDavid du Colombier+ int
5612*14414594SDavid du Colombier+ u9p_m2d(char *ap, struct u9fsdir *f)
5613*14414594SDavid du Colombier+ {
5614*14414594SDavid du Colombier+ 	u_char *p;
5615*14414594SDavid du Colombier+
5616*14414594SDavid du Colombier+ 	p = (u_char*)ap;
5617*14414594SDavid du Colombier+ 	N2HSTRING(f->dir_name, sizeof(f->dir_name));
5618*14414594SDavid du Colombier+ 	N2HSTRING(f->dir_uid, sizeof(f->dir_uid));
5619*14414594SDavid du Colombier+ 	N2HSTRING(f->dir_gid, sizeof(f->dir_gid));
5620*14414594SDavid du Colombier+ 	N2HLONG(f->dir_qid.path);
5621*14414594SDavid du Colombier+ 	N2HLONG(f->dir_qid.vers);
5622*14414594SDavid du Colombier+ 	N2HLONG(f->dir_mode);
5623*14414594SDavid du Colombier+ 	N2HLONG(f->dir_atime);
5624*14414594SDavid du Colombier+ 	N2HLONG(f->dir_mtime);
5625*14414594SDavid du Colombier+ 	N2HQUAD(f->dir_length);
5626*14414594SDavid du Colombier+ 	N2HSHORT(f->dir_type);
5627*14414594SDavid du Colombier+ 	N2HSHORT(f->dir_dev);
5628*14414594SDavid du Colombier+ 	return p - (u_char*)ap;
5629*14414594SDavid du Colombier+ }
5630*14414594SDavid du Colombier+
5631*14414594SDavid du Colombier+ int
5632*14414594SDavid du Colombier+ u9p_d2m(struct u9fsdir *f, char *ap)
5633*14414594SDavid du Colombier+ {
5634*14414594SDavid du Colombier+ 	u_char *p;
5635*14414594SDavid du Colombier+
5636*14414594SDavid du Colombier+ 	p = (u_char*)ap;
5637*14414594SDavid du Colombier+ 	H2NSTRING(f->dir_name, sizeof(f->dir_name));
5638*14414594SDavid du Colombier+ 	H2NSTRING(f->dir_uid, sizeof(f->dir_uid));
5639*14414594SDavid du Colombier+ 	H2NSTRING(f->dir_gid, sizeof(f->dir_gid));
5640*14414594SDavid du Colombier+ 	H2NLONG(f->dir_qid.path);
5641*14414594SDavid du Colombier+ 	H2NLONG(f->dir_qid.vers);
5642*14414594SDavid du Colombier+ 	H2NLONG(f->dir_mode);
5643*14414594SDavid du Colombier+ 	H2NLONG(f->dir_atime);
5644*14414594SDavid du Colombier+ 	H2NLONG(f->dir_mtime);
5645*14414594SDavid du Colombier+ 	H2NQUAD(f->dir_length);
5646*14414594SDavid du Colombier+ 	H2NSHORT(f->dir_type);
5647*14414594SDavid du Colombier+ 	H2NSHORT(f->dir_dev);
5648*14414594SDavid du Colombier+ 	return p - (u_char*)ap;
5649*14414594SDavid du Colombier+ }
5650*14414594SDavid du Colombier+
5651*14414594SDavid du Colombier+ /* parse 9P types */
5652*14414594SDavid du Colombier+ int u9p_type(char * t)
5653*14414594SDavid du Colombier+ {
5654*14414594SDavid du Colombier+   int i;
5655*14414594SDavid du Colombier+
5656*14414594SDavid du Colombier+   for(i = 0; i < sizeof(u9p_types)/sizeof(u9p_types[0]); i++) {
5657*14414594SDavid du Colombier+     if( strcmp(u9p_types[i], t) == 0 )
5658*14414594SDavid du Colombier+       return (i+Tnop);
5659*14414594SDavid du Colombier+   }
5660*14414594SDavid du Colombier+   return 0;
5661*14414594SDavid du Colombier+ }
5662*14414594SDavid du Colombier+
5663*14414594SDavid du Colombier+ /* m is freed if shorter than s */
5664*14414594SDavid du Colombier+ #if 1
5665*14414594SDavid du Colombier+ #define U9P_PULLUP(m,s)  if( (*(m))->m_len < (s) && ((*(m)) = m_pullup((*(m)),(s))) == 0 ) return 1; p = mtod((*(m)), u_char *)
5666*14414594SDavid du Colombier+ #else
5667*14414594SDavid du Colombier+ #define U9P_PULLUP(m,s)  if( (*(m))->m_len < (s) && ((*(m)) = m_pullup((*(m)),(s))) == 0 ) panic("PULLUP"); p = mtod((*(m)), u_char *)
5668*14414594SDavid du Colombier+ #endif
5669*14414594SDavid du Colombier+
5670*14414594SDavid du Colombier+ #define U9P_ADJ(m,s) (*(m))->m_len -= (s); (*(m))->m_data += (s)
5671*14414594SDavid du Colombier+
5672*14414594SDavid du Colombier+ u_short u9p_m_tag(struct mbuf ** m)
5673*14414594SDavid du Colombier+ {
5674*14414594SDavid du Colombier+   char * p;
5675*14414594SDavid du Colombier+   u_short t;
5676*14414594SDavid du Colombier+
5677*14414594SDavid du Colombier+   U9P_PULLUP(m,3);
5678*14414594SDavid du Colombier+   p = mtod(*m, char *);
5679*14414594SDavid du Colombier+   p++;
5680*14414594SDavid du Colombier+   N2HSHORT(t);
5681*14414594SDavid du Colombier+
5682*14414594SDavid du Colombier+   return t;
5683*14414594SDavid du Colombier+ }
5684*14414594SDavid du Colombier+
5685*14414594SDavid du Colombier+ int
5686*14414594SDavid du Colombier+ u9p_m_m2s(struct mbuf **m, struct u9fsreq *f)
5687*14414594SDavid du Colombier+ {
5688*14414594SDavid du Colombier+   u_char *p;
5689*14414594SDavid du Colombier+
5690*14414594SDavid du Colombier+   U9P_PULLUP(m,3);
5691*14414594SDavid du Colombier+   N2HCHAR(f->r_type);
5692*14414594SDavid du Colombier+   N2HSHORT(f->r_tag);
5693*14414594SDavid du Colombier+   U9P_ADJ(m, sizeof(f->r_type)+sizeof(f->r_tag));
5694*14414594SDavid du Colombier+
5695*14414594SDavid du Colombier+   switch(f->r_type) {
5696*14414594SDavid du Colombier+   default:
5697*14414594SDavid du Colombier+     goto drop;
5698*14414594SDavid du Colombier+
5699*14414594SDavid du Colombier+   case Tnop:
5700*14414594SDavid du Colombier+     break;
5701*14414594SDavid du Colombier+
5702*14414594SDavid du Colombier+   case Tsession:
5703*14414594SDavid du Colombier+     U9P_PULLUP(m,sizeof(f->r_chal));
5704*14414594SDavid du Colombier+     N2HSTRING(f->r_chal, sizeof(f->r_chal));
5705*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_chal));
5706*14414594SDavid du Colombier+     break;
5707*14414594SDavid du Colombier+
5708*14414594SDavid du Colombier+   case Tflush:
5709*14414594SDavid du Colombier+     U9P_PULLUP(m,sizeof(f->r_oldtag));
5710*14414594SDavid du Colombier+     N2HSHORT(f->r_oldtag);
5711*14414594SDavid du Colombier+     U9P_ADJ(m, f->r_oldtag);
5712*14414594SDavid du Colombier+     break;
5713*14414594SDavid du Colombier+
5714*14414594SDavid du Colombier+   case Tattach:
5715*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_uname)+sizeof(f->r_aname));
5716*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5717*14414594SDavid du Colombier+     N2HSTRING(f->r_uname, sizeof(f->r_uname));
5718*14414594SDavid du Colombier+     N2HSTRING(f->r_aname, sizeof(f->r_aname));
5719*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_uname)+sizeof(f->r_aname));
5720*14414594SDavid du Colombier+
5721*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_ticket)+sizeof(f->r_auth));
5722*14414594SDavid du Colombier+     N2HSTRING(f->r_ticket, sizeof(f->r_ticket));
5723*14414594SDavid du Colombier+     N2HSTRING(f->r_auth, sizeof(f->r_auth));
5724*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_ticket)+sizeof(f->r_auth));
5725*14414594SDavid du Colombier+     break;
5726*14414594SDavid du Colombier+
5727*14414594SDavid du Colombier+   case Tclone:
5728*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_newfid));
5729*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5730*14414594SDavid du Colombier+     N2HSHORT(f->r_newfid);
5731*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_newfid));
5732*14414594SDavid du Colombier+     break;
5733*14414594SDavid du Colombier+
5734*14414594SDavid du Colombier+   case Twalk:
5735*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_name));
5736*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5737*14414594SDavid du Colombier+     N2HSTRING(f->r_name, sizeof(f->r_name));
5738*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_name));
5739*14414594SDavid du Colombier+     break;
5740*14414594SDavid du Colombier+
5741*14414594SDavid du Colombier+   case Topen:
5742*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_mode));
5743*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5744*14414594SDavid du Colombier+     N2HCHAR(f->r_mode);
5745*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_mode));
5746*14414594SDavid du Colombier+     break;
5747*14414594SDavid du Colombier+
5748*14414594SDavid du Colombier+   case Tcreate:
5749*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_name)
5750*14414594SDavid du Colombier+ 	       +sizeof(f->r_perm)+sizeof(f->r_mode));
5751*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5752*14414594SDavid du Colombier+     N2HSTRING(f->r_name, sizeof(f->r_name));
5753*14414594SDavid du Colombier+     N2HLONG(f->r_perm);
5754*14414594SDavid du Colombier+     N2HCHAR(f->r_mode);
5755*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_name)
5756*14414594SDavid du Colombier+ 	    +sizeof(f->r_perm)+sizeof(f->r_mode));
5757*14414594SDavid du Colombier+     break;
5758*14414594SDavid du Colombier+
5759*14414594SDavid du Colombier+   case Tread:
5760*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count));
5761*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5762*14414594SDavid du Colombier+     N2HQUAD(f->r_offset);
5763*14414594SDavid du Colombier+     N2HSHORT(f->r_count);
5764*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count));
5765*14414594SDavid du Colombier+     break;
5766*14414594SDavid du Colombier+
5767*14414594SDavid du Colombier+   case Twrite:
5768*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count));
5769*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5770*14414594SDavid du Colombier+     N2HQUAD(f->r_offset);
5771*14414594SDavid du Colombier+     N2HSHORT(f->r_count);
5772*14414594SDavid du Colombier+     p++;	/* pad(1) */
5773*14414594SDavid du Colombier+     f->r_data = (char*)p; p += f->r_count;
5774*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count)+1);
5775*14414594SDavid du Colombier+     break;
5776*14414594SDavid du Colombier+
5777*14414594SDavid du Colombier+   case Tclunk:
5778*14414594SDavid du Colombier+   case Tremove:
5779*14414594SDavid du Colombier+   case Tstat:
5780*14414594SDavid du Colombier+    U9P_PULLUP(m, sizeof(f->r_fid));
5781*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5782*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid));
5783*14414594SDavid du Colombier+     break;
5784*14414594SDavid du Colombier+
5785*14414594SDavid du Colombier+   case Twstat:
5786*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid));
5787*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5788*14414594SDavid du Colombier+     m_copydata(*m, sizeof(f->r_fid), sizeof(f->r_stat), f->r_stat);
5789*14414594SDavid du Colombier+     m_adj(*m, sizeof(f->r_fid)+sizeof(f->r_stat));
5790*14414594SDavid du Colombier+     break;
5791*14414594SDavid du Colombier+
5792*14414594SDavid du Colombier+   case Tclwalk:
5793*14414594SDavid du Colombier+      U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_newfid)+sizeof(f->r_name));
5794*14414594SDavid du Colombier+      N2HSHORT(f->r_fid);
5795*14414594SDavid du Colombier+      N2HSHORT(f->r_newfid);
5796*14414594SDavid du Colombier+      N2HSTRING(f->r_name, sizeof(f->r_name));
5797*14414594SDavid du Colombier+      U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_newfid)+sizeof(f->r_name));
5798*14414594SDavid du Colombier+      break;
5799*14414594SDavid du Colombier+ /*
5800*14414594SDavid du Colombier+  */
5801*14414594SDavid du Colombier+   case Rnop:
5802*14414594SDavid du Colombier+     break;
5803*14414594SDavid du Colombier+
5804*14414594SDavid du Colombier+   case Rsession:
5805*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_authid)+sizeof(f->r_authdom));
5806*14414594SDavid du Colombier+     N2HSTRING(f->r_chal, sizeof(f->r_chal));
5807*14414594SDavid du Colombier+     N2HSTRING(f->r_authid, sizeof(f->r_authid));
5808*14414594SDavid du Colombier+     N2HSTRING(f->r_authdom, sizeof(f->r_authdom));
5809*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_authid)+sizeof(f->r_authdom));
5810*14414594SDavid du Colombier+     break;
5811*14414594SDavid du Colombier+
5812*14414594SDavid du Colombier+   case Rerror:
5813*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_ename));
5814*14414594SDavid du Colombier+     N2HSTRING(f->r_ename, sizeof(f->r_ename));
5815*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_ename));
5816*14414594SDavid du Colombier+     break;
5817*14414594SDavid du Colombier+
5818*14414594SDavid du Colombier+   case Rflush:
5819*14414594SDavid du Colombier+     break;
5820*14414594SDavid du Colombier+
5821*14414594SDavid du Colombier+   case Rattach:
5822*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5823*14414594SDavid du Colombier+ 	       +sizeof(f->r_qid.vers)+sizeof(f->r_rauth));
5824*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5825*14414594SDavid du Colombier+     N2HLONG(f->r_qid.path);
5826*14414594SDavid du Colombier+     N2HLONG(f->r_qid.vers);
5827*14414594SDavid du Colombier+     N2HSTRING(f->r_rauth, sizeof(f->r_rauth));
5828*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5829*14414594SDavid du Colombier+ 	    +sizeof(f->r_qid.vers)+sizeof(f->r_rauth));
5830*14414594SDavid du Colombier+     break;
5831*14414594SDavid du Colombier+
5832*14414594SDavid du Colombier+   case Rclone:
5833*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid));
5834*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5835*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid));
5836*14414594SDavid du Colombier+     break;
5837*14414594SDavid du Colombier+
5838*14414594SDavid du Colombier+   case Rwalk:
5839*14414594SDavid du Colombier+   case Rclwalk:
5840*14414594SDavid du Colombier+   case Ropen:
5841*14414594SDavid du Colombier+   case Rcreate:
5842*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5843*14414594SDavid du Colombier+                +sizeof(f->r_qid.vers));
5844*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5845*14414594SDavid du Colombier+     N2HLONG(f->r_qid.path);
5846*14414594SDavid du Colombier+     N2HLONG(f->r_qid.vers);
5847*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5848*14414594SDavid du Colombier+             +sizeof(f->r_qid.vers));
5849*14414594SDavid du Colombier+     break;
5850*14414594SDavid du Colombier+
5851*14414594SDavid du Colombier+   case Rread:
5852*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_count));
5853*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5854*14414594SDavid du Colombier+     N2HSHORT(f->r_count);
5855*14414594SDavid du Colombier+     p++;	/* pad(1) */
5856*14414594SDavid du Colombier+     f->r_data = (char*)p; p += f->r_count;
5857*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_count)+1);
5858*14414594SDavid du Colombier+     break;
5859*14414594SDavid du Colombier+
5860*14414594SDavid du Colombier+   case Rwrite:
5861*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_count));
5862*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5863*14414594SDavid du Colombier+     N2HSHORT(f->r_count);
5864*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_count));
5865*14414594SDavid du Colombier+     break;
5866*14414594SDavid du Colombier+
5867*14414594SDavid du Colombier+   case Rclunk:
5868*14414594SDavid du Colombier+   case Rremove:
5869*14414594SDavid du Colombier+   case Rwstat:
5870*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid));
5871*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5872*14414594SDavid du Colombier+     U9P_ADJ(m, sizeof(f->r_fid));
5873*14414594SDavid du Colombier+     break;
5874*14414594SDavid du Colombier+
5875*14414594SDavid du Colombier+   case Rstat:
5876*14414594SDavid du Colombier+     U9P_PULLUP(m, sizeof(f->r_fid));
5877*14414594SDavid du Colombier+     N2HSHORT(f->r_fid);
5878*14414594SDavid du Colombier+     m_copydata(*m, sizeof(f->r_fid), sizeof(f->r_stat), f->r_stat);
5879*14414594SDavid du Colombier+     m_adj(*m, sizeof(f->r_fid)+sizeof(f->r_stat));
5880*14414594SDavid du Colombier+     break;
5881*14414594SDavid du Colombier+
5882*14414594SDavid du Colombier+   }
5883*14414594SDavid du Colombier+   return 0;
5884*14414594SDavid du Colombier+
5885*14414594SDavid du Colombier+  drop:
5886*14414594SDavid du Colombier+   m_freem(*m);
5887*14414594SDavid du Colombier+   return 1;
5888*14414594SDavid du Colombier+ }
5889*14414594SDavid du Colombier+
5890*14414594SDavid du Colombier+ struct mbuf *
5891*14414594SDavid du Colombier+ u9p_m_s2m (struct u9fsreq *f)
5892*14414594SDavid du Colombier+ {
5893*14414594SDavid du Colombier+   register struct mbuf * m;
5894*14414594SDavid du Colombier+   struct mbuf * m0;
5895*14414594SDavid du Colombier+   char * ap;
5896*14414594SDavid du Colombier+   int sz;
5897*14414594SDavid du Colombier+
5898*14414594SDavid du Colombier+   /* we want one contiguous piece */
5899*14414594SDavid du Colombier+   if( f->r_type == Tattach || f->r_type == Rstat || f->r_type == Twstat )
5900*14414594SDavid du Colombier+     sz = 146; /* sizeof a Tattach */
5901*14414594SDavid du Colombier+   else
5902*14414594SDavid du Colombier+     sz = 87; /* sizeof a Tsession */
5903*14414594SDavid du Colombier+
5904*14414594SDavid du Colombier+   MGETHDR(m, M_WAIT, MT_DATA);
5905*14414594SDavid du Colombier+   if( sz > MHLEN )
5906*14414594SDavid du Colombier+     MCLGET(m, M_WAIT);
5907*14414594SDavid du Colombier+   m->m_len = 0;
5908*14414594SDavid du Colombier+
5909*14414594SDavid du Colombier+   if ( M_TRAILINGSPACE(m) < sz )
5910*14414594SDavid du Colombier+     panic("u9p_m_s2m");
5911*14414594SDavid du Colombier+
5912*14414594SDavid du Colombier+   ap = mtod(m, char *);
5913*14414594SDavid du Colombier+   m->m_len = u9p_s2m(f, ap, 0);
5914*14414594SDavid du Colombier+   m->m_pkthdr.len = m->m_len;
5915*14414594SDavid du Colombier+
5916*14414594SDavid du Colombier+   /* append data mbufs  */
5917*14414594SDavid du Colombier+   switch ( f->r_type ) {
5918*14414594SDavid du Colombier+   default:
5919*14414594SDavid du Colombier+     break;
5920*14414594SDavid du Colombier+   case Twrite:
5921*14414594SDavid du Colombier+   case Rread:
5922*14414594SDavid du Colombier+     m0 = (struct mbuf *)f->r_data;
5923*14414594SDavid du Colombier+     m->m_next = m0;
5924*14414594SDavid du Colombier+     m->m_pkthdr.len += f->r_count;
5925*14414594SDavid du Colombier+     break;
5926*14414594SDavid du Colombier+   }
5927*14414594SDavid du Colombier+
5928*14414594SDavid du Colombier+   return m;
5929*14414594SDavid du Colombier+ }
5930*14414594SDavid du Colombier+
5931*14414594SDavid du Colombier+ int
5932*14414594SDavid du Colombier+ u9p_m_m2d (struct mbuf **m, struct u9fsdir *f)
5933*14414594SDavid du Colombier+ {
5934*14414594SDavid du Colombier+   u_char *p;
5935*14414594SDavid du Colombier+
5936*14414594SDavid du Colombier+   U9P_PULLUP(m, sizeof(f->dir_name)+sizeof(f->dir_uid)+sizeof(f->dir_gid));
5937*14414594SDavid du Colombier+   N2HSTRING(f->dir_name, sizeof(f->dir_name));
5938*14414594SDavid du Colombier+   N2HSTRING(f->dir_uid, sizeof(f->dir_uid));
5939*14414594SDavid du Colombier+   N2HSTRING(f->dir_gid, sizeof(f->dir_gid));
5940*14414594SDavid du Colombier+   U9P_ADJ(m, sizeof(f->dir_name)+sizeof(f->dir_uid)+sizeof(f->dir_gid));
5941*14414594SDavid du Colombier+
5942*14414594SDavid du Colombier+   U9P_PULLUP(m, sizeof(f->dir_qid)+sizeof(f->dir_mode)
5943*14414594SDavid du Colombier+ 	     +sizeof(f->dir_atime)+sizeof(f->dir_mtime)
5944*14414594SDavid du Colombier+ 	     +sizeof(f->dir_length)+sizeof(f->dir_type)+sizeof(f->dir_dev));
5945*14414594SDavid du Colombier+   N2HLONG(f->dir_qid.path);
5946*14414594SDavid du Colombier+   N2HLONG(f->dir_qid.vers);
5947*14414594SDavid du Colombier+   N2HLONG(f->dir_mode);
5948*14414594SDavid du Colombier+   N2HLONG(f->dir_atime);
5949*14414594SDavid du Colombier+   N2HLONG(f->dir_mtime);
5950*14414594SDavid du Colombier+   N2HQUAD(f->dir_length);
5951*14414594SDavid du Colombier+   N2HSHORT(f->dir_type);
5952*14414594SDavid du Colombier+   N2HSHORT(f->dir_dev);
5953*14414594SDavid du Colombier+   U9P_ADJ(m, sizeof(f->dir_qid)+sizeof(f->dir_mode)
5954*14414594SDavid du Colombier+ 	     +sizeof(f->dir_atime)+sizeof(f->dir_mtime)
5955*14414594SDavid du Colombier+ 	     +sizeof(f->dir_length)+sizeof(f->dir_type)+sizeof(f->dir_dev));
5956*14414594SDavid du Colombier+
5957*14414594SDavid du Colombier+   return 0;
5958*14414594SDavid du Colombier+ }
5959*14414594SDavid du Colombier+
5960*14414594SDavid du Colombier+ struct mbuf * u9p_m_d2m (struct u9fsdir *f)
5961*14414594SDavid du Colombier+ {
5962*14414594SDavid du Colombier+   char * ap;
5963*14414594SDavid du Colombier+   struct mbuf * m;
5964*14414594SDavid du Colombier+   MGET(m, M_WAIT, MT_DATA);
5965*14414594SDavid du Colombier+   MCLGET(m, M_WAIT);
5966*14414594SDavid du Colombier+   m->m_len = 0;
5967*14414594SDavid du Colombier+
5968*14414594SDavid du Colombier+   if ( M_TRAILINGSPACE(m) < sizeof(struct u9fsdir) )
5969*14414594SDavid du Colombier+     panic("u9p_m_d2m");
5970*14414594SDavid du Colombier+
5971*14414594SDavid du Colombier+   ap = mtod(m, char *);
5972*14414594SDavid du Colombier+   m->m_len = u9p_d2m(f, ap);
5973*14414594SDavid du Colombier+
5974*14414594SDavid du Colombier+   return m;
5975*14414594SDavid du Colombier+ }
5976*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9p.h ./9fs/9p.h
5977*14414594SDavid du Colombier*** /usr/src/sys/9fs/9p.h	Wed Dec 31 19:00:00 1969
5978*14414594SDavid du Colombier--- ./9fs/9p.h	Thu Nov 25 15:45:46 1999
5979*14414594SDavid du Colombier***************
5980*14414594SDavid du Colombier*** 0 ****
5981*14414594SDavid du Colombier--- 1,183 ----
5982*14414594SDavid du Colombier+ #ifndef _9FS_9P_H_
5983*14414594SDavid du Colombier+ #define _9FS_9P_H_
5984*14414594SDavid du Colombier+
5985*14414594SDavid du Colombier+
5986*14414594SDavid du Colombier+ #define U9FS_AUTHLEN 13
5987*14414594SDavid du Colombier+ #define U9FS_NAMELEN    28
5988*14414594SDavid du Colombier+ #define U9FS_TICKETLEN  72
5989*14414594SDavid du Colombier+ #define U9FS_ERRLEN     64
5990*14414594SDavid du Colombier+ #define U9FS_DOMLEN     48
5991*14414594SDavid du Colombier+ #define U9FS_CHALLEN    8
5992*14414594SDavid du Colombier+ #define U9FS_DIRLEN     116
5993*14414594SDavid du Colombier+ #define U9FS_MAXFDATA  8192
5994*14414594SDavid du Colombier+ #define U9FS_MAXDDATA  (((int)U9FS_MAXFDATA/U9FS_DIRLEN)*U9FS_DIRLEN)
5995*14414594SDavid du Colombier+
5996*14414594SDavid du Colombier+ #define U9P_MODE_RD    0x0
5997*14414594SDavid du Colombier+ #define U9P_MODE_WR    0x1
5998*14414594SDavid du Colombier+ #define U9P_MODE_RDWR  0x2
5999*14414594SDavid du Colombier+ #define U9P_MODE_EX    0x3
6000*14414594SDavid du Colombier+ #define U9P_MODE_TRUNC 0x10
6001*14414594SDavid du Colombier+ #define U9P_MODE_CLOSE 0x40
6002*14414594SDavid du Colombier+
6003*14414594SDavid du Colombier+ #define U9P_PERM_CHDIR(m) (0x80000000&(m))
6004*14414594SDavid du Colombier+ #define U9P_PERM_OWNER(m) ((m)&0x7)
6005*14414594SDavid du Colombier+ #define U9P_PERM_GROUP(m) (((m)>>3)&0x7)
6006*14414594SDavid du Colombier+ #define U9P_PERM_OTHER(m) (((m)>>6)&0x7)
6007*14414594SDavid du Colombier+ #define U9P_PERM_ALL(m)   ((m)&0777)
6008*14414594SDavid du Colombier+ #define U9P_PERM_EXCL(m)    ((m)&0x20000000)
6009*14414594SDavid du Colombier+ #define U9P_PERM_APPEND(m)  ((m)&0x40000000)
6010*14414594SDavid du Colombier+ #define U9P_PERM_NONPERM(m) ((m)&0xfffffe00)
6011*14414594SDavid du Colombier+
6012*14414594SDavid du Colombier+ /* this is too small */
6013*14414594SDavid du Colombier+ typedef u_int32_t u9fsfh_t;
6014*14414594SDavid du Colombier+
6015*14414594SDavid du Colombier+ struct u9fs_qid {
6016*14414594SDavid du Colombier+ 	u9fsfh_t	path;
6017*14414594SDavid du Colombier+ 	u_int32_t	vers;
6018*14414594SDavid du Colombier+ };
6019*14414594SDavid du Colombier+
6020*14414594SDavid du Colombier+ struct	u9fsreq {
6021*14414594SDavid du Colombier+   TAILQ_ENTRY(u9fsreq) r_chain;
6022*14414594SDavid du Colombier+   struct u9fsreq * r_rep;
6023*14414594SDavid du Colombier+   struct mbuf * r_mrep;
6024*14414594SDavid du Colombier+   struct proc	*r_procp;	/* Proc that did I/O system call */
6025*14414594SDavid du Colombier+   struct u9fsmount *r_nmp;
6026*14414594SDavid du Colombier+
6027*14414594SDavid du Colombier+   /* actual content of the 9P message */
6028*14414594SDavid du Colombier+ 	char	r_type;
6029*14414594SDavid du Colombier+ 	short	r_fid;
6030*14414594SDavid du Colombier+ 	u_short	r_tag;
6031*14414594SDavid du Colombier+ 	union {
6032*14414594SDavid du Colombier+ 		struct {
6033*14414594SDavid du Colombier+ 			u_short	oldtag;		/* Tflush */
6034*14414594SDavid du Colombier+ 			struct u9fs_qid qid;		/* Rattach, Rwalk, Ropen, Rcreate */
6035*14414594SDavid du Colombier+ 			char	rauth[U9FS_AUTHLEN];	/* Rattach */
6036*14414594SDavid du Colombier+ 		} u1;
6037*14414594SDavid du Colombier+ 		struct {
6038*14414594SDavid du Colombier+ 			char	uname[U9FS_NAMELEN];		/* Tattach */
6039*14414594SDavid du Colombier+ 			char	aname[U9FS_NAMELEN];		/* Tattach */
6040*14414594SDavid du Colombier+ 			char	ticket[U9FS_TICKETLEN];	/* Tattach */
6041*14414594SDavid du Colombier+ 			char	auth[U9FS_AUTHLEN];	/* Tattach */
6042*14414594SDavid du Colombier+ 		} u2;
6043*14414594SDavid du Colombier+ 		struct {
6044*14414594SDavid du Colombier+ 			char	ename[U9FS_ERRLEN];		/* Rerror */
6045*14414594SDavid du Colombier+ 			char	authid[U9FS_NAMELEN];	/* Rsession */
6046*14414594SDavid du Colombier+ 			char	authdom[U9FS_DOMLEN];	/* Rsession */
6047*14414594SDavid du Colombier+ 			char	chal[U9FS_CHALLEN];		/* Tsession/Rsession */
6048*14414594SDavid du Colombier+ 		} u3;
6049*14414594SDavid du Colombier+ 		struct {
6050*14414594SDavid du Colombier+ 			u_int32_t	perm;		/* Tcreate */
6051*14414594SDavid du Colombier+ 			short	newfid;		/* Tclone, Tclwalk */
6052*14414594SDavid du Colombier+ 			char	name[U9FS_NAMELEN];	/* Twalk, Tclwalk, Tcreate */
6053*14414594SDavid du Colombier+ 			char	mode;		/* Tcreate, Topen */
6054*14414594SDavid du Colombier+ 		} u4;
6055*14414594SDavid du Colombier+ 		struct {
6056*14414594SDavid du Colombier+ 			u_int64_t	offset;		/* Tread, Twrite */
6057*14414594SDavid du Colombier+ 			u_short	        count;		/* Tread, Twrite, Rread */
6058*14414594SDavid du Colombier+ 			char	*data;		/* Twrite, Rread */
6059*14414594SDavid du Colombier+ 		} u5;
6060*14414594SDavid du Colombier+ 			char	stat[U9FS_DIRLEN];	/* Twstat, Rstat */
6061*14414594SDavid du Colombier+ 	} u;
6062*14414594SDavid du Colombier+ };
6063*14414594SDavid du Colombier+
6064*14414594SDavid du Colombier+ #define r_oldtag u.u1.oldtag
6065*14414594SDavid du Colombier+ #define r_qid u.u1.qid
6066*14414594SDavid du Colombier+ #define r_rauth u.u1.rauth
6067*14414594SDavid du Colombier+ #define r_uname u.u2.uname
6068*14414594SDavid du Colombier+ #define r_aname u.u2.aname
6069*14414594SDavid du Colombier+ #define r_ticket  u.u2.ticket
6070*14414594SDavid du Colombier+ #define r_auth  u.u2.auth
6071*14414594SDavid du Colombier+ #define r_ename  u.u3.ename
6072*14414594SDavid du Colombier+ #define r_authid  u.u3.authid
6073*14414594SDavid du Colombier+ #define r_authdom  u.u3.authdom
6074*14414594SDavid du Colombier+ #define r_chal  u.u3.chal
6075*14414594SDavid du Colombier+ #define r_perm  u.u4.perm
6076*14414594SDavid du Colombier+ #define r_newfid  u.u4.newfid
6077*14414594SDavid du Colombier+ #define r_name  u.u4.name
6078*14414594SDavid du Colombier+ #define r_mode  u.u4.mode
6079*14414594SDavid du Colombier+ #define r_offset  u.u5.offset
6080*14414594SDavid du Colombier+ #define r_count  u.u5.count
6081*14414594SDavid du Colombier+ #define r_data  u.u5.data
6082*14414594SDavid du Colombier+ #define r_stat  u.stat
6083*14414594SDavid du Colombier+
6084*14414594SDavid du Colombier+ struct u9fsdir {
6085*14414594SDavid du Colombier+   char	dir_name[U9FS_NAMELEN];
6086*14414594SDavid du Colombier+   char	dir_uid[U9FS_NAMELEN];
6087*14414594SDavid du Colombier+   char	dir_gid[U9FS_NAMELEN];
6088*14414594SDavid du Colombier+   struct u9fs_qid	dir_qid;
6089*14414594SDavid du Colombier+   u_int32_t	dir_mode;
6090*14414594SDavid du Colombier+   u_int32_t	dir_atime;
6091*14414594SDavid du Colombier+   u_int32_t	dir_mtime;
6092*14414594SDavid du Colombier+   union {
6093*14414594SDavid du Colombier+     u_int64_t	length;
6094*14414594SDavid du Colombier+     struct {	/* little endian */
6095*14414594SDavid du Colombier+       u_int32_t	llength;
6096*14414594SDavid du Colombier+       u_int32_t	hlength;
6097*14414594SDavid du Colombier+     } l;
6098*14414594SDavid du Colombier+   } u;
6099*14414594SDavid du Colombier+   u_short	dir_type;
6100*14414594SDavid du Colombier+   u_short	dir_dev;
6101*14414594SDavid du Colombier+ };
6102*14414594SDavid du Colombier+
6103*14414594SDavid du Colombier+ #define dir_length u.length
6104*14414594SDavid du Colombier+ #define dir_llength u.l.llength
6105*14414594SDavid du Colombier+ #define dir_hlength u.l.hlength
6106*14414594SDavid du Colombier+
6107*14414594SDavid du Colombier+ enum
6108*14414594SDavid du Colombier+ {
6109*14414594SDavid du Colombier+ 	Tnop =		50,
6110*14414594SDavid du Colombier+ 	Rnop,
6111*14414594SDavid du Colombier+ 	Tosession =	52,	/* illegal */
6112*14414594SDavid du Colombier+ 	Rosession,		/* illegal */
6113*14414594SDavid du Colombier+ 	Terror =	54,	/* illegal */
6114*14414594SDavid du Colombier+ 	Rerror,
6115*14414594SDavid du Colombier+ 	Tflush =	56,
6116*14414594SDavid du Colombier+ 	Rflush,
6117*14414594SDavid du Colombier+ 	Toattach =	58,	/* illegal */
6118*14414594SDavid du Colombier+ 	Roattach,		/* illegal */
6119*14414594SDavid du Colombier+ 	Tclone =	60,
6120*14414594SDavid du Colombier+ 	Rclone,
6121*14414594SDavid du Colombier+ 	Twalk =		62,
6122*14414594SDavid du Colombier+ 	Rwalk,
6123*14414594SDavid du Colombier+ 	Topen =		64,
6124*14414594SDavid du Colombier+ 	Ropen,
6125*14414594SDavid du Colombier+ 	Tcreate =	66,
6126*14414594SDavid du Colombier+ 	Rcreate,
6127*14414594SDavid du Colombier+ 	Tread =		68,
6128*14414594SDavid du Colombier+ 	Rread,
6129*14414594SDavid du Colombier+ 	Twrite =	70,
6130*14414594SDavid du Colombier+ 	Rwrite,
6131*14414594SDavid du Colombier+ 	Tclunk =	72,
6132*14414594SDavid du Colombier+ 	Rclunk,
6133*14414594SDavid du Colombier+ 	Tremove =	74,
6134*14414594SDavid du Colombier+ 	Rremove,
6135*14414594SDavid du Colombier+ 	Tstat =		76,
6136*14414594SDavid du Colombier+ 	Rstat,
6137*14414594SDavid du Colombier+ 	Twstat =	78,
6138*14414594SDavid du Colombier+ 	Rwstat,
6139*14414594SDavid du Colombier+ 	Tclwalk =	80,
6140*14414594SDavid du Colombier+ 	Rclwalk,
6141*14414594SDavid du Colombier+ 	Tauth =		82,	/* illegal */
6142*14414594SDavid du Colombier+ 	Rauth,			/* illegal */
6143*14414594SDavid du Colombier+ 	Tsession =	84,
6144*14414594SDavid du Colombier+ 	Rsession,
6145*14414594SDavid du Colombier+ 	Tattach =	86,
6146*14414594SDavid du Colombier+ 	Rattach,
6147*14414594SDavid du Colombier+ 	Ttunnel =	88,
6148*14414594SDavid du Colombier+ 	Rtunnel,
6149*14414594SDavid du Colombier+ 	Tmax
6150*14414594SDavid du Colombier+ };
6151*14414594SDavid du Colombier+
6152*14414594SDavid du Colombier+ int u9p_m2s __P((char *ap, int n, struct u9fsreq *f));
6153*14414594SDavid du Colombier+ int u9p_s2m __P((struct u9fsreq *f, char *ap, int copydata));
6154*14414594SDavid du Colombier+ int u9p_m2d __P((char *ap, struct u9fsdir *f));
6155*14414594SDavid du Colombier+ int u9p_d2m __P((struct u9fsdir *f, char *ap));
6156*14414594SDavid du Colombier+ int u9p_type __P((char * t));
6157*14414594SDavid du Colombier+
6158*14414594SDavid du Colombier+ int u9p_m_m2s __P((struct mbuf **m, struct u9fsreq *f));
6159*14414594SDavid du Colombier+ struct mbuf * u9p_m_s2m __P((struct u9fsreq *f));
6160*14414594SDavid du Colombier+ int u9p_m_m2d __P((struct mbuf **m, struct u9fsdir *f));
6161*14414594SDavid du Colombier+ struct mbuf * u9p_m_d2m __P((struct u9fsdir *f));
6162*14414594SDavid du Colombier+ u_short u9p_m_tag __P((struct mbuf **m));
6163*14414594SDavid du Colombier+
6164*14414594SDavid du Colombier+ #endif
6165*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/bitstring.h ./9fs/bitstring.h
6166*14414594SDavid du Colombier*** /usr/src/sys/9fs/bitstring.h	Wed Dec 31 19:00:00 1969
6167*14414594SDavid du Colombier--- ./9fs/bitstring.h	Thu Oct 21 12:34:50 1999
6168*14414594SDavid du Colombier***************
6169*14414594SDavid du Colombier*** 0 ****
6170*14414594SDavid du Colombier--- 1,143 ----
6171*14414594SDavid du Colombier+ /*
6172*14414594SDavid du Colombier+  * Copyright (c) 1989, 1993
6173*14414594SDavid du Colombier+  *	The Regents of the University of California.  All rights reserved.
6174*14414594SDavid du Colombier+  *
6175*14414594SDavid du Colombier+  * This code is derived from software contributed to Berkeley by
6176*14414594SDavid du Colombier+  * Paul Vixie.
6177*14414594SDavid du Colombier+  *
6178*14414594SDavid du Colombier+  * Redistribution and use in source and binary forms, with or without
6179*14414594SDavid du Colombier+  * modification, are permitted provided that the following conditions
6180*14414594SDavid du Colombier+  * are met:
6181*14414594SDavid du Colombier+  * 1. Redistributions of source code must retain the above copyright
6182*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer.
6183*14414594SDavid du Colombier+  * 2. Redistributions in binary form must reproduce the above copyright
6184*14414594SDavid du Colombier+  *    notice, this list of conditions and the following disclaimer in the
6185*14414594SDavid du Colombier+  *    documentation and/or other materials provided with the distribution.
6186*14414594SDavid du Colombier+  * 3. All advertising materials mentioning features or use of this software
6187*14414594SDavid du Colombier+  *    must display the following acknowledgement:
6188*14414594SDavid du Colombier+  *	This product includes software developed by the University of
6189*14414594SDavid du Colombier+  *	California, Berkeley and its contributors.
6190*14414594SDavid du Colombier+  * 4. Neither the name of the University nor the names of its contributors
6191*14414594SDavid du Colombier+  *    may be used to endorse or promote products derived from this software
6192*14414594SDavid du Colombier+  *    without specific prior written permission.
6193*14414594SDavid du Colombier+  *
6194*14414594SDavid du Colombier+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
6195*14414594SDavid du Colombier+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6196*14414594SDavid du Colombier+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6197*14414594SDavid du Colombier+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6198*14414594SDavid du Colombier+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6199*14414594SDavid du Colombier+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6200*14414594SDavid du Colombier+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6201*14414594SDavid du Colombier+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6202*14414594SDavid du Colombier+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6203*14414594SDavid du Colombier+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6204*14414594SDavid du Colombier+  * SUCH DAMAGE.
6205*14414594SDavid du Colombier+  *
6206*14414594SDavid du Colombier+  *	@(#)bitstring.h	8.1 (Berkeley) 7/19/93
6207*14414594SDavid du Colombier+  */
6208*14414594SDavid du Colombier+
6209*14414594SDavid du Colombier+ #ifndef _BITSTRING_H_
6210*14414594SDavid du Colombier+ #define	_BITSTRING_H_
6211*14414594SDavid du Colombier+
6212*14414594SDavid du Colombier+ typedef	unsigned char bitstr_t;
6213*14414594SDavid du Colombier+
6214*14414594SDavid du Colombier+ /* internal macros */
6215*14414594SDavid du Colombier+ 				/* byte of the bitstring bit is in */
6216*14414594SDavid du Colombier+ #define	_bit_byte(bit) \
6217*14414594SDavid du Colombier+ 	((bit) >> 3)
6218*14414594SDavid du Colombier+
6219*14414594SDavid du Colombier+ 				/* mask for the bit within its byte */
6220*14414594SDavid du Colombier+ #define	_bit_mask(bit) \
6221*14414594SDavid du Colombier+ 	(1 << ((bit)&0x7))
6222*14414594SDavid du Colombier+
6223*14414594SDavid du Colombier+ /* external macros */
6224*14414594SDavid du Colombier+ 				/* bytes in a bitstring of nbits bits */
6225*14414594SDavid du Colombier+ #define	bitstr_size(nbits) \
6226*14414594SDavid du Colombier+ 	((((nbits) - 1) >> 3) + 1)
6227*14414594SDavid du Colombier+
6228*14414594SDavid du Colombier+ 				/* allocate a bitstring */
6229*14414594SDavid du Colombier+ #define	bit_alloc(space, nbits, type, flags) \
6230*14414594SDavid du Colombier+ 	MALLOC((space), bitstr_t *, \
6231*14414594SDavid du Colombier+         (u_int)bitstr_size(nbits)*sizeof(bitstr_t), (type), (flags))
6232*14414594SDavid du Colombier+
6233*14414594SDavid du Colombier+ 				/* allocate a bitstring on the stack */
6234*14414594SDavid du Colombier+ #define	bit_decl(name, nbits) \
6235*14414594SDavid du Colombier+ 	(name)[bitstr_size(nbits)]
6236*14414594SDavid du Colombier+
6237*14414594SDavid du Colombier+ 				/* is bit N of bitstring name set? */
6238*14414594SDavid du Colombier+ #define	bit_test(name, bit) \
6239*14414594SDavid du Colombier+ 	((name)[_bit_byte(bit)] & _bit_mask(bit))
6240*14414594SDavid du Colombier+
6241*14414594SDavid du Colombier+ 				/* set bit N of bitstring name */
6242*14414594SDavid du Colombier+ #define	bit_set(name, bit) \
6243*14414594SDavid du Colombier+ 	(name)[_bit_byte(bit)] |= _bit_mask(bit)
6244*14414594SDavid du Colombier+
6245*14414594SDavid du Colombier+ 				/* clear bit N of bitstring name */
6246*14414594SDavid du Colombier+ #define	bit_clear(name, bit) \
6247*14414594SDavid du Colombier+ 	(name)[_bit_byte(bit)] &= ~_bit_mask(bit)
6248*14414594SDavid du Colombier+
6249*14414594SDavid du Colombier+ 				/* clear bits start ... stop in bitstring */
6250*14414594SDavid du Colombier+ #define	bit_nclear(name, start, stop) { \
6251*14414594SDavid du Colombier+ 	register bitstr_t *_name = name; \
6252*14414594SDavid du Colombier+ 	register int _start = start, _stop = stop; \
6253*14414594SDavid du Colombier+ 	register int _startbyte = _bit_byte(_start); \
6254*14414594SDavid du Colombier+ 	register int _stopbyte = _bit_byte(_stop); \
6255*14414594SDavid du Colombier+ 	if (_startbyte == _stopbyte) { \
6256*14414594SDavid du Colombier+ 		_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
6257*14414594SDavid du Colombier+ 				      (0xff << ((_stop&0x7) + 1))); \
6258*14414594SDavid du Colombier+ 	} else { \
6259*14414594SDavid du Colombier+ 		_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
6260*14414594SDavid du Colombier+ 		while (++_startbyte < _stopbyte) \
6261*14414594SDavid du Colombier+ 			_name[_startbyte] = 0; \
6262*14414594SDavid du Colombier+ 		_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
6263*14414594SDavid du Colombier+ 	} \
6264*14414594SDavid du Colombier+ }
6265*14414594SDavid du Colombier+
6266*14414594SDavid du Colombier+ 				/* set bits start ... stop in bitstring */
6267*14414594SDavid du Colombier+ #define	bit_nset(name, start, stop) { \
6268*14414594SDavid du Colombier+ 	register bitstr_t *_name = name; \
6269*14414594SDavid du Colombier+ 	register int _start = start, _stop = stop; \
6270*14414594SDavid du Colombier+ 	register int _startbyte = _bit_byte(_start); \
6271*14414594SDavid du Colombier+ 	register int _stopbyte = _bit_byte(_stop); \
6272*14414594SDavid du Colombier+ 	if (_startbyte == _stopbyte) { \
6273*14414594SDavid du Colombier+ 		_name[_startbyte] |= ((0xff << (_start&0x7)) & \
6274*14414594SDavid du Colombier+ 				    (0xff >> (7 - (_stop&0x7)))); \
6275*14414594SDavid du Colombier+ 	} else { \
6276*14414594SDavid du Colombier+ 		_name[_startbyte] |= 0xff << ((_start)&0x7); \
6277*14414594SDavid du Colombier+ 		while (++_startbyte < _stopbyte) \
6278*14414594SDavid du Colombier+ 	    		_name[_startbyte] = 0xff; \
6279*14414594SDavid du Colombier+ 		_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
6280*14414594SDavid du Colombier+ 	} \
6281*14414594SDavid du Colombier+ }
6282*14414594SDavid du Colombier+
6283*14414594SDavid du Colombier+ 				/* find first bit clear in name */
6284*14414594SDavid du Colombier+ #define	bit_ffc(name, nbits, value) { \
6285*14414594SDavid du Colombier+ 	register bitstr_t *_name = name; \
6286*14414594SDavid du Colombier+ 	register int _byte, _nbits = nbits; \
6287*14414594SDavid du Colombier+ 	register int _stopbyte = _bit_byte(_nbits), _value = -1; \
6288*14414594SDavid du Colombier+ 	for (_byte = 0; _byte <= _stopbyte; ++_byte) \
6289*14414594SDavid du Colombier+ 		if (_name[_byte] != 0xff) { \
6290*14414594SDavid du Colombier+ 			_value = _byte << 3; \
6291*14414594SDavid du Colombier+ 			for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
6292*14414594SDavid du Colombier+ 			    ++_value, _stopbyte >>= 1); \
6293*14414594SDavid du Colombier+ 			break; \
6294*14414594SDavid du Colombier+ 		} \
6295*14414594SDavid du Colombier+ 	*(value) = _value; \
6296*14414594SDavid du Colombier+ }
6297*14414594SDavid du Colombier+
6298*14414594SDavid du Colombier+ 				/* find first bit set in name */
6299*14414594SDavid du Colombier+ #define	bit_ffs(name, nbits, value) { \
6300*14414594SDavid du Colombier+ 	register bitstr_t *_name = name; \
6301*14414594SDavid du Colombier+ 	register int _byte, _nbits = nbits; \
6302*14414594SDavid du Colombier+ 	register int _stopbyte = _bit_byte(_nbits), _value = -1; \
6303*14414594SDavid du Colombier+ 	for (_byte = 0; _byte <= _stopbyte; ++_byte) \
6304*14414594SDavid du Colombier+ 		if (_name[_byte]) { \
6305*14414594SDavid du Colombier+ 			_value = _byte << 3; \
6306*14414594SDavid du Colombier+ 			for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
6307*14414594SDavid du Colombier+ 			    ++_value, _stopbyte >>= 1); \
6308*14414594SDavid du Colombier+ 			break; \
6309*14414594SDavid du Colombier+ 		} \
6310*14414594SDavid du Colombier+ 	*(value) = _value; \
6311*14414594SDavid du Colombier+ }
6312*14414594SDavid du Colombier+
6313*14414594SDavid du Colombier+ #endif /* !_BITSTRING_H_ */
6314*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/conf/files ./conf/files
6315*14414594SDavid du Colombier*** /usr/src/sys/conf/files	Fri Apr 30 15:32:40 1999
6316*14414594SDavid du Colombier--- ./conf/files	Thu Nov 25 15:34:34 1999
6317*14414594SDavid du Colombier***************
6318*14414594SDavid du Colombier*** 535,540 ****
6319*14414594SDavid du Colombier--- 535,541 ----
6320*14414594SDavid du Colombier  netinet/tcp_timer.c	optional inet
6321*14414594SDavid du Colombier  netinet/tcp_usrreq.c	optional inet
6322*14414594SDavid du Colombier  netinet/udp_usrreq.c	optional inet
6323*14414594SDavid du Colombier+ netinet/il.c		optional  il
6324*14414594SDavid du Colombier  netipx/ipx.c		optional ipx
6325*14414594SDavid du Colombier  netipx/ipx_cksum.c	optional ipx
6326*14414594SDavid du Colombier  netipx/ipx_input.c	optional ipx
6327*14414594SDavid du Colombier***************
6328*14414594SDavid du Colombier*** 571,576 ****
6329*14414594SDavid du Colombier--- 572,586 ----
6330*14414594SDavid du Colombier  nfs/nfs_syscalls.c	optional nfs
6331*14414594SDavid du Colombier  nfs/nfs_vfsops.c	optional nfs
6332*14414594SDavid du Colombier  nfs/nfs_vnops.c		optional nfs
6333*14414594SDavid du Colombier+ 9fs/9fs_vfsops.c	optional u9fs
6334*14414594SDavid du Colombier+ 9fs/9fs_vnops.c		optional u9fs
6335*14414594SDavid du Colombier+ 9fs/9p.c		optional u9fs
6336*14414594SDavid du Colombier+ 9fs/9auth.c		optional u9fs
6337*14414594SDavid du Colombier+ 9fs/9crypt.c		optional u9fs
6338*14414594SDavid du Colombier+ 9fs/9fs_subr.c		optional u9fs
6339*14414594SDavid du Colombier+ 9fs/9fs_socket.c	optional u9fs
6340*14414594SDavid du Colombier+ 9fs/9fs_bio.c		optional u9fs
6341*14414594SDavid du Colombier+ 9fs/9fs_node.c		optional u9fs
6342*14414594SDavid du Colombier  nfs/bootp_subr.c	optional bootp
6343*14414594SDavid du Colombier  nfs/krpc_subr.c		optional bootp
6344*14414594SDavid du Colombier  pccard/pccard.c		optional card
6345*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/conf/options ./conf/options
6346*14414594SDavid du Colombier*** /usr/src/sys/conf/options	Tue May 11 01:35:28 1999
6347*14414594SDavid du Colombier--- ./conf/options	Mon Oct 11 19:59:14 1999
6348*14414594SDavid du Colombier***************
6349*14414594SDavid du Colombier*** 202,207 ****
6350*14414594SDavid du Colombier--- 202,208 ----
6351*14414594SDavid du Colombier  BRIDGE			opt_bdg.h
6352*14414594SDavid du Colombier  MROUTING		opt_mrouting.h
6353*14414594SDavid du Colombier  INET			opt_inet.h
6354*14414594SDavid du Colombier+ IL			opt_inet.h
6355*14414594SDavid du Colombier  IPDIVERT
6356*14414594SDavid du Colombier  DUMMYNET		opt_ipdn.h
6357*14414594SDavid du Colombier  IPFIREWALL		opt_ipfw.h
6358*14414594SDavid du Colombier***************
6359*14414594SDavid du Colombier*** 314,319 ****
6360*14414594SDavid du Colombier--- 315,322 ----
6361*14414594SDavid du Colombier  NFS_MUIDHASHSIZ		opt_nfs.h
6362*14414594SDavid du Colombier  NFS_NOSERVER		opt_nfs.h
6363*14414594SDavid du Colombier  NFS_DEBUG		opt_nfs.h
6364*14414594SDavid du Colombier+
6365*14414594SDavid du Colombier+ U9FS
6366*14414594SDavid du Colombier
6367*14414594SDavid du Colombier  # give bktr an opt_bktr.h file
6368*14414594SDavid du Colombier  OVERRIDE_CARD		opt_bktr.h
6369*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/i386/conf/IL ./i386/conf/IL
6370*14414594SDavid du Colombier*** /usr/src/sys/i386/conf/IL	Wed Dec 31 19:00:00 1969
6371*14414594SDavid du Colombier--- ./i386/conf/IL	Sat Oct 23 14:01:36 1999
6372*14414594SDavid du Colombier***************
6373*14414594SDavid du Colombier*** 0 ****
6374*14414594SDavid du Colombier--- 1,234 ----
6375*14414594SDavid du Colombier+ #
6376*14414594SDavid du Colombier+ # GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks
6377*14414594SDavid du Colombier+ #
6378*14414594SDavid du Colombier+ # For more information read the handbook part System Administration ->
6379*14414594SDavid du Colombier+ # Configuring the FreeBSD Kernel -> The Configuration File.
6380*14414594SDavid du Colombier+ # The handbook is available in /usr/share/doc/handbook or online as
6381*14414594SDavid du Colombier+ # latest version from the FreeBSD World Wide Web server
6382*14414594SDavid du Colombier+ # <URL:http://www.FreeBSD.ORG/>
6383*14414594SDavid du Colombier+ #
6384*14414594SDavid du Colombier+ # An exhaustive list of options and more detailed explanations of the
6385*14414594SDavid du Colombier+ # device lines is present in the ./LINT configuration file. If you are
6386*14414594SDavid du Colombier+ # in doubt as to the purpose or necessity of a line, check first in LINT.
6387*14414594SDavid du Colombier+ #
6388*14414594SDavid du Colombier+ #	$Id: GENERIC,v 1.143.2.2 1999/02/15 02:50:07 des Exp $
6389*14414594SDavid du Colombier+
6390*14414594SDavid du Colombier+ machine		"i386"
6391*14414594SDavid du Colombier+ cpu		"I586_CPU"
6392*14414594SDavid du Colombier+ cpu		"I686_CPU"
6393*14414594SDavid du Colombier+ ident		GENERIC
6394*14414594SDavid du Colombier+ maxusers	128
6395*14414594SDavid du Colombier+
6396*14414594SDavid du Colombier+ #options		DDB
6397*14414594SDavid du Colombier+ options		IL			# plan9's IL
6398*14414594SDavid du Colombier+ options		"U9FS"			# plan9's 9fs client
6399*14414594SDavid du Colombier+ options		INET			#InterNETworking
6400*14414594SDavid du Colombier+ options		FFS			#Berkeley Fast Filesystem
6401*14414594SDavid du Colombier+ options		FFS_ROOT		#FFS usable as root device [keep this!]
6402*14414594SDavid du Colombier+ options		MFS			#Memory Filesystem
6403*14414594SDavid du Colombier+ options		MFS_ROOT		#MFS usable as root device, "MFS" req'ed
6404*14414594SDavid du Colombier+ options		NFS			#Network Filesystem
6405*14414594SDavid du Colombier+ options		NFS_ROOT		#NFS usable as root device, "NFS" req'ed
6406*14414594SDavid du Colombier+ options		"CD9660"		#ISO 9660 Filesystem
6407*14414594SDavid du Colombier+ options		"CD9660_ROOT"		#CD-ROM usable as root. "CD9660" req'ed
6408*14414594SDavid du Colombier+ options		PROCFS			#Process filesystem
6409*14414594SDavid du Colombier+ options         FDESC                   #File descriptor filesystem
6410*14414594SDavid du Colombier+ options		"COMPAT_43"		#Compatible with BSD 4.3 [KEEP THIS!]
6411*14414594SDavid du Colombier+ options		SCSI_DELAY=15000	#Be pessimistic about Joe SCSI device
6412*14414594SDavid du Colombier+ options		UCONSOLE		#Allow users to grab the console
6413*14414594SDavid du Colombier+ options		FAILSAFE		#Be conservative
6414*14414594SDavid du Colombier+ options		USERCONFIG		#boot -c editor
6415*14414594SDavid du Colombier+ options		VISUAL_USERCONFIG	#visual boot -c editor
6416*14414594SDavid du Colombier+ options		NMBCLUSTERS=4096
6417*14414594SDavid du Colombier+ options		MAXFILES=10000
6418*14414594SDavid du Colombier+
6419*14414594SDavid du Colombier+ config		kernel	root on wd0
6420*14414594SDavid du Colombier+
6421*14414594SDavid du Colombier+ # To make an SMP kernel, the next two are needed
6422*14414594SDavid du Colombier+ #options	SMP			# Symmetric MultiProcessor Kernel
6423*14414594SDavid du Colombier+ #options	APIC_IO			# Symmetric (APIC) I/O
6424*14414594SDavid du Colombier+ # Optionally these may need tweaked, (defaults shown):
6425*14414594SDavid du Colombier+ #options	NCPU=2			# number of CPUs
6426*14414594SDavid du Colombier+ #options	NBUS=4			# number of busses
6427*14414594SDavid du Colombier+ #options	NAPIC=1			# number of IO APICs
6428*14414594SDavid du Colombier+ #options	NINTR=24		# number of INTs
6429*14414594SDavid du Colombier+
6430*14414594SDavid du Colombier+ controller	isa0
6431*14414594SDavid du Colombier+ controller	eisa0
6432*14414594SDavid du Colombier+ controller	pci0
6433*14414594SDavid du Colombier+
6434*14414594SDavid du Colombier+ controller	fdc0	at isa? port "IO_FD1" bio irq 6 drq 2
6435*14414594SDavid du Colombier+ disk		fd0	at fdc0 drive 0
6436*14414594SDavid du Colombier+ disk		fd1	at fdc0 drive 1
6437*14414594SDavid du Colombier+
6438*14414594SDavid du Colombier+ options		"CMD640"	# work around CMD640 chip deficiency
6439*14414594SDavid du Colombier+ controller	wdc0	at isa? port "IO_WD1" bio irq 14 flags 0xa0ff vector wdintr
6440*14414594SDavid du Colombier+ disk		wd0	at wdc0 drive 0
6441*14414594SDavid du Colombier+ disk		wd1	at wdc0 drive 1
6442*14414594SDavid du Colombier+
6443*14414594SDavid du Colombier+ controller	wdc1	at isa? port "IO_WD2" bio irq 15 flags 0xa0ff vector wdintr
6444*14414594SDavid du Colombier+ disk		wd2	at wdc1 drive 0
6445*14414594SDavid du Colombier+ disk		wd3	at wdc1 drive 1
6446*14414594SDavid du Colombier+
6447*14414594SDavid du Colombier+ options		ATAPI		#Enable ATAPI support for IDE bus
6448*14414594SDavid du Colombier+ options		ATAPI_STATIC	#Don't do it as an LKM
6449*14414594SDavid du Colombier+ #device		acd0		#IDE CD-ROM
6450*14414594SDavid du Colombier+ #device		wfd0		#IDE Floppy (e.g. LS-120)
6451*14414594SDavid du Colombier+
6452*14414594SDavid du Colombier+ # A single entry for any of these controllers (ncr, ahb, ahc) is
6453*14414594SDavid du Colombier+ # sufficient for any number of installed devices.
6454*14414594SDavid du Colombier+ #controller	ncr0
6455*14414594SDavid du Colombier+ #controller	ahb0
6456*14414594SDavid du Colombier+ #controller	ahc0
6457*14414594SDavid du Colombier+ #controller	isp0
6458*14414594SDavid du Colombier+
6459*14414594SDavid du Colombier+ # This controller offers a number of configuration options, too many to
6460*14414594SDavid du Colombier+ # document here  - see the LINT file in this directory and look up the
6461*14414594SDavid du Colombier+ # dpt0 entry there for much fuller documentation on this.
6462*14414594SDavid du Colombier+ controller      dpt0
6463*14414594SDavid du Colombier+
6464*14414594SDavid du Colombier+ #controller	adv0	at isa? port ? cam irq ?
6465*14414594SDavid du Colombier+ #controller	adw0
6466*14414594SDavid du Colombier+ #controller	bt0	at isa? port ? cam irq ?
6467*14414594SDavid du Colombier+ #controller	aha0	at isa? port ? cam irq ?
6468*14414594SDavid du Colombier+ #controller	aic0	at isa? port 0x340 bio irq 11
6469*14414594SDavid du Colombier+
6470*14414594SDavid du Colombier+ controller	scbus0
6471*14414594SDavid du Colombier+
6472*14414594SDavid du Colombier+ device		da0
6473*14414594SDavid du Colombier+
6474*14414594SDavid du Colombier+ device		sa0
6475*14414594SDavid du Colombier+
6476*14414594SDavid du Colombier+ device		pass0
6477*14414594SDavid du Colombier+
6478*14414594SDavid du Colombier+ device		cd0	#Only need one of these, the code dynamically grows
6479*14414594SDavid du Colombier+
6480*14414594SDavid du Colombier+ #device		wt0	at isa? port 0x300 bio irq 5 drq 1
6481*14414594SDavid du Colombier+ #device		mcd0	at isa? port 0x300 bio irq 10
6482*14414594SDavid du Colombier+
6483*14414594SDavid du Colombier+ #controller	matcd0	at isa? port 0x230 bio
6484*14414594SDavid du Colombier+
6485*14414594SDavid du Colombier+ #device		scd0	at isa? port 0x230 bio
6486*14414594SDavid du Colombier+
6487*14414594SDavid du Colombier+ # atkbdc0 controlls both the keyboard and the PS/2 mouse
6488*14414594SDavid du Colombier+ controller	atkbdc0	at isa? port IO_KBD tty
6489*14414594SDavid du Colombier+ device		atkbd0	at isa? tty irq 1
6490*14414594SDavid du Colombier+ device		psm0	at isa? tty irq 12
6491*14414594SDavid du Colombier+
6492*14414594SDavid du Colombier+ device		vga0	at isa? port ? conflicts
6493*14414594SDavid du Colombier+
6494*14414594SDavid du Colombier+ # splash screen/screen saver
6495*14414594SDavid du Colombier+ pseudo-device	splash
6496*14414594SDavid du Colombier+
6497*14414594SDavid du Colombier+ # syscons is the default console driver, resembling an SCO console
6498*14414594SDavid du Colombier+ device		sc0	at isa? tty
6499*14414594SDavid du Colombier+ # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver
6500*14414594SDavid du Colombier+ #device		vt0	at isa? tty
6501*14414594SDavid du Colombier+ #options		XSERVER			# support for X server
6502*14414594SDavid du Colombier+ #options		FAT_CURSOR		# start with block cursor
6503*14414594SDavid du Colombier+ # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines
6504*14414594SDavid du Colombier+ #options		PCVT_SCANSET=2		# IBM keyboards are non-std
6505*14414594SDavid du Colombier+
6506*14414594SDavid du Colombier+ device		npx0	at isa? port IO_NPX irq 13
6507*14414594SDavid du Colombier+
6508*14414594SDavid du Colombier+ #
6509*14414594SDavid du Colombier+ # Laptop support (see LINT for more options)
6510*14414594SDavid du Colombier+ #
6511*14414594SDavid du Colombier+ device		apm0    at isa?	disable	flags 0x31 # Advanced Power Management
6512*14414594SDavid du Colombier+
6513*14414594SDavid du Colombier+ # PCCARD (PCMCIA) support
6514*14414594SDavid du Colombier+ #controller	card0
6515*14414594SDavid du Colombier+ #device		pcic0	at card?
6516*14414594SDavid du Colombier+ #device		pcic1	at card?
6517*14414594SDavid du Colombier+
6518*14414594SDavid du Colombier+ device		sio0	at isa? port "IO_COM1" flags 0x10 tty irq 4
6519*14414594SDavid du Colombier+ device		sio1	at isa? port "IO_COM2" tty irq 3
6520*14414594SDavid du Colombier+ device		sio2	at isa? disable port "IO_COM3" tty irq 5
6521*14414594SDavid du Colombier+ device		sio3	at isa? disable port "IO_COM4" tty irq 9
6522*14414594SDavid du Colombier+
6523*14414594SDavid du Colombier+ # Parallel port
6524*14414594SDavid du Colombier+ device		ppc0	at isa? port? net irq 7
6525*14414594SDavid du Colombier+ controller	ppbus0
6526*14414594SDavid du Colombier+ device		nlpt0	at ppbus?
6527*14414594SDavid du Colombier+ device		plip0	at ppbus?
6528*14414594SDavid du Colombier+ device		ppi0	at ppbus?
6529*14414594SDavid du Colombier+ #controller	vpo0	at ppbus?
6530*14414594SDavid du Colombier+
6531*14414594SDavid du Colombier+ #
6532*14414594SDavid du Colombier+ # The following Ethernet NICs are all PCI devices.
6533*14414594SDavid du Colombier+ #
6534*14414594SDavid du Colombier+ device ax0		# ASIX AX88140A
6535*14414594SDavid du Colombier+ device de0		# DEC/Intel DC21x4x (``Tulip'')
6536*14414594SDavid du Colombier+ device fxp0		# Intel EtherExpress PRO/100B (82557, 82558)
6537*14414594SDavid du Colombier+ device mx0		# Macronix 98713/98715/98725 (``PMAC'')
6538*14414594SDavid du Colombier+ device pn0		# Lite-On 82c168/82c169 (``PNIC'')
6539*14414594SDavid du Colombier+ device rl0		# RealTek 8129/8139
6540*14414594SDavid du Colombier+ device tl0		# Texas Instruments ThunderLAN
6541*14414594SDavid du Colombier+ device tx0		# SMC 9432TX (83c170 ``EPIC'')
6542*14414594SDavid du Colombier+ device vr0		# VIA Rhine, Rhine II
6543*14414594SDavid du Colombier+ device vx0		# 3Com 3c590, 3c595 (``Vortex'')
6544*14414594SDavid du Colombier+ device wb0		# Winbond W89C840F
6545*14414594SDavid du Colombier+ device xl0		# 3Com 3c90x (``Boomerang'', ``Cyclone'')
6546*14414594SDavid du Colombier+
6547*14414594SDavid du Colombier+ # Order is important here due to intrusive probes, do *not* alphabetize
6548*14414594SDavid du Colombier+ # this list of network interfaces until the probes have been fixed.
6549*14414594SDavid du Colombier+ # Right now it appears that the ie0 must be probed before ep0. See
6550*14414594SDavid du Colombier+ # revision 1.20 of this file.
6551*14414594SDavid du Colombier+
6552*14414594SDavid du Colombier+ #device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000
6553*14414594SDavid du Colombier+ #device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000
6554*14414594SDavid du Colombier+ #device ep0 at isa? port 0x300 net irq 10
6555*14414594SDavid du Colombier+ #device ex0 at isa? port? net irq?
6556*14414594SDavid du Colombier+ #device fe0 at isa? port 0x300 net irq ?
6557*14414594SDavid du Colombier+ #device le0 at isa? port 0x300 net irq 5 iomem 0xd0000
6558*14414594SDavid du Colombier+ #device lnc0 at isa? port 0x280 net irq 10 drq 0
6559*14414594SDavid du Colombier+ #device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000
6560*14414594SDavid du Colombier+ #device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000
6561*14414594SDavid du Colombier+ #device cs0 at isa? port 0x300 net irq ?
6562*14414594SDavid du Colombier+
6563*14414594SDavid du Colombier+ pseudo-device	loop
6564*14414594SDavid du Colombier+ pseudo-device	ether
6565*14414594SDavid du Colombier+ pseudo-device	sl	1
6566*14414594SDavid du Colombier+ pseudo-device	ppp	1
6567*14414594SDavid du Colombier+ pseudo-device	tun	1
6568*14414594SDavid du Colombier+ pseudo-device	pty	32
6569*14414594SDavid du Colombier+ pseudo-device	gzip		# Exec gzipped a.out's
6570*14414594SDavid du Colombier+
6571*14414594SDavid du Colombier+ # KTRACE enables the system-call tracing facility ktrace(2).
6572*14414594SDavid du Colombier+ # This adds 4 KB bloat to your kernel, and slightly increases
6573*14414594SDavid du Colombier+ # the costs of each syscall.
6574*14414594SDavid du Colombier+ options		KTRACE		#kernel tracing
6575*14414594SDavid du Colombier+
6576*14414594SDavid du Colombier+ # This provides support for System V shared memory and message queues.
6577*14414594SDavid du Colombier+ #
6578*14414594SDavid du Colombier+ options		SYSVSHM
6579*14414594SDavid du Colombier+ options		SYSVMSG
6580*14414594SDavid du Colombier+
6581*14414594SDavid du Colombier+ #  The `bpfilter' pseudo-device enables the Berkeley Packet Filter.  Be
6582*14414594SDavid du Colombier+ #  aware of the legal and administrative consequences of enabling this
6583*14414594SDavid du Colombier+ #  option.  The number of devices determines the maximum number of
6584*14414594SDavid du Colombier+ #  simultaneous BPF clients programs runnable.
6585*14414594SDavid du Colombier+ pseudo-device	bpfilter 4	#Berkeley packet filter
6586*14414594SDavid du Colombier+
6587*14414594SDavid du Colombier+
6588*14414594SDavid du Colombier+ # USB support
6589*14414594SDavid du Colombier+ #controller    uhci0
6590*14414594SDavid du Colombier+ #controller    ohci0
6591*14414594SDavid du Colombier+ #controller    usb0
6592*14414594SDavid du Colombier+ #
6593*14414594SDavid du Colombier+ # for the moment we have to specify the priorities of the device
6594*14414594SDavid du Colombier+ # drivers explicitly by the ordering in the list below. This will
6595*14414594SDavid du Colombier+ # be changed in the future.
6596*14414594SDavid du Colombier+ #
6597*14414594SDavid du Colombier+ #device        ums0
6598*14414594SDavid du Colombier+ #device        ukbd0
6599*14414594SDavid du Colombier+ #device        ulpt0
6600*14414594SDavid du Colombier+ #device        uhub0
6601*14414594SDavid du Colombier+ #device        ucom0
6602*14414594SDavid du Colombier+ #device        umodem0
6603*14414594SDavid du Colombier+ #device        hid0
6604*14414594SDavid du Colombier+ #device        ugen0
6605*14414594SDavid du Colombier+
6606*14414594SDavid du Colombier+ #
6607*14414594SDavid du Colombier+ #options       USB_DEBUG
6608*14414594SDavid du Colombier+ #options       USBVERBOSE
6609*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/il.c ./netinet/il.c
6610*14414594SDavid du Colombier*** /usr/src/sys/netinet/il.c	Wed Dec 31 19:00:00 1969
6611*14414594SDavid du Colombier--- ./netinet/il.c	Tue Nov 23 19:16:13 1999
6612*14414594SDavid du Colombier***************
6613*14414594SDavid du Colombier*** 0 ****
6614*14414594SDavid du Colombier--- 1,1147 ----
6615*14414594SDavid du Colombier+ #include <unistd.h>
6616*14414594SDavid du Colombier+ #include <ctype.h>
6617*14414594SDavid du Colombier+ #include <sys/types.h>
6618*14414594SDavid du Colombier+ #include <sys/param.h>
6619*14414594SDavid du Colombier+ #include <sys/time.h>
6620*14414594SDavid du Colombier+ #include <sys/systm.h>
6621*14414594SDavid du Colombier+ #include <vm/vm_zone.h>
6622*14414594SDavid du Colombier+
6623*14414594SDavid du Colombier+ #include <sys/malloc.h>
6624*14414594SDavid du Colombier+ #include <machine/param.h>
6625*14414594SDavid du Colombier+ #include <sys/mbuf.h>
6626*14414594SDavid du Colombier+ #include <sys/protosw.h>
6627*14414594SDavid du Colombier+ #include <sys/socket.h>
6628*14414594SDavid du Colombier+ #include <sys/socketvar.h>
6629*14414594SDavid du Colombier+ #include <sys/proc.h>
6630*14414594SDavid du Colombier+ #include <net/if.h>
6631*14414594SDavid du Colombier+ #include <net/route.h>
6632*14414594SDavid du Colombier+ #include <netinet/in_systm.h>
6633*14414594SDavid du Colombier+ #include <netinet/in.h>
6634*14414594SDavid du Colombier+ #include <netinet/in_var.h>
6635*14414594SDavid du Colombier+ #include <netinet/if_ether.h>
6636*14414594SDavid du Colombier+ #include <netinet/ip.h>
6637*14414594SDavid du Colombier+ #include <netinet/ip_var.h>
6638*14414594SDavid du Colombier+ #include <netinet/in_pcb.h>
6639*14414594SDavid du Colombier+ #include <errno.h>
6640*14414594SDavid du Colombier+
6641*14414594SDavid du Colombier+ #include <netinet/il.h>
6642*14414594SDavid du Colombier+ #include <netinet/il_var.h>
6643*14414594SDavid du Colombier+
6644*14414594SDavid du Colombier+ struct ilpcb * il_drop(struct ilpcb *ilpcb, int errno0);
6645*14414594SDavid du Colombier+ static struct ilpcb * il_close(struct ilpcb *ilpcb);
6646*14414594SDavid du Colombier+
6647*14414594SDavid du Colombier+ /* kernel protocol states needed */
6648*14414594SDavid du Colombier+ static struct inpcbhead ilb;
6649*14414594SDavid du Colombier+ static struct inpcbinfo ilbinfo;
6650*14414594SDavid du Colombier+
6651*14414594SDavid du Colombier+ u_long il_sendspace = 1024*64;
6652*14414594SDavid du Colombier+ u_long il_recvspace = 1024*64;
6653*14414594SDavid du Colombier+
6654*14414594SDavid du Colombier+ /*
6655*14414594SDavid du Colombier+  * Target size of IL PCB hash tables. Must be a power of two.
6656*14414594SDavid du Colombier+  *
6657*14414594SDavid du Colombier+  * Note that this can be overridden by the kernel environment
6658*14414594SDavid du Colombier+  * variable net.inet.tcp.tcbhashsize
6659*14414594SDavid du Colombier+  */
6660*14414594SDavid du Colombier+ #ifndef ILBHASHSIZE
6661*14414594SDavid du Colombier+ #define ILBHASHSIZE	512
6662*14414594SDavid du Colombier+ #endif
6663*14414594SDavid du Colombier+
6664*14414594SDavid du Colombier+ enum				/* Connection state */
6665*14414594SDavid du Colombier+ {
6666*14414594SDavid du Colombier+ 	ILS_CLOSED,
6667*14414594SDavid du Colombier+ 	ILS_SYNCER,
6668*14414594SDavid du Colombier+ 	ILS_SYNCEE,
6669*14414594SDavid du Colombier+ 	ILS_ESTABLISHED,
6670*14414594SDavid du Colombier+ 	ILS_LISTENING,
6671*14414594SDavid du Colombier+ 	ILS_CLOSING,
6672*14414594SDavid du Colombier+ 	ILS_OPENING,		/* only for file server */
6673*14414594SDavid du Colombier+ };
6674*14414594SDavid du Colombier+
6675*14414594SDavid du Colombier+ char	*ilstates[] =
6676*14414594SDavid du Colombier+ {
6677*14414594SDavid du Colombier+ 	"Closed",
6678*14414594SDavid du Colombier+ 	"Syncer",
6679*14414594SDavid du Colombier+ 	"Syncee",
6680*14414594SDavid du Colombier+ 	"Established",
6681*14414594SDavid du Colombier+ 	"Listening",
6682*14414594SDavid du Colombier+ 	"Closing",
6683*14414594SDavid du Colombier+ 	"Opening",		/* only for file server */
6684*14414594SDavid du Colombier+ };
6685*14414594SDavid du Colombier+
6686*14414594SDavid du Colombier+ enum				/* Packet types */
6687*14414594SDavid du Colombier+ {
6688*14414594SDavid du Colombier+ 	ILT_SYNC,
6689*14414594SDavid du Colombier+ 	ILT_DATA,
6690*14414594SDavid du Colombier+ 	ILT_DATAQUERY,
6691*14414594SDavid du Colombier+ 	ILT_ACK,
6692*14414594SDavid du Colombier+ 	ILT_QUERY,
6693*14414594SDavid du Colombier+ 	ILT_STATE,
6694*14414594SDavid du Colombier+ 	ILT_CLOSE
6695*14414594SDavid du Colombier+ };
6696*14414594SDavid du Colombier+
6697*14414594SDavid du Colombier+ char	*iltype[] =
6698*14414594SDavid du Colombier+ {
6699*14414594SDavid du Colombier+ 	"sync",
6700*14414594SDavid du Colombier+ 	"data",
6701*14414594SDavid du Colombier+ 	"dataquery",
6702*14414594SDavid du Colombier+ 	"ack",
6703*14414594SDavid du Colombier+ 	"query",
6704*14414594SDavid du Colombier+ 	"state",
6705*14414594SDavid du Colombier+ 	"close",
6706*14414594SDavid du Colombier+ };
6707*14414594SDavid du Colombier+
6708*14414594SDavid du Colombier+ /*
6709*14414594SDavid du Colombier+  * This is the actual shape of what we allocate using the zone
6710*14414594SDavid du Colombier+  * allocator.  Doing it this way allows us to protect both structures
6711*14414594SDavid du Colombier+  * using the same generation count, and also eliminates the overhead
6712*14414594SDavid du Colombier+  * of allocating tcpcbs separately.  By hiding the structure here,
6713*14414594SDavid du Colombier+  * we avoid changing most of the rest of the code (although it needs
6714*14414594SDavid du Colombier+  * to be changed, eventually, for greater efficiency).
6715*14414594SDavid du Colombier+  */
6716*14414594SDavid du Colombier+ #define	ALIGNMENT	32
6717*14414594SDavid du Colombier+ #define	ALIGNM1		(ALIGNMENT - 1)
6718*14414594SDavid du Colombier+ struct	inp_ilpcb {
6719*14414594SDavid du Colombier+ 	union {
6720*14414594SDavid du Colombier+ 		struct	inpcb inp;
6721*14414594SDavid du Colombier+ 		char	align[(sizeof(struct inpcb) + ALIGNM1) & ~ALIGNM1];
6722*14414594SDavid du Colombier+ 	} inp_tp_u;
6723*14414594SDavid du Colombier+ 	struct	ilpcb ilpcb;
6724*14414594SDavid du Colombier+ };
6725*14414594SDavid du Colombier+ #undef ALIGNMENT
6726*14414594SDavid du Colombier+ #undef ALIGNM1
6727*14414594SDavid du Colombier+
6728*14414594SDavid du Colombier+ static __inline struct mbuf * il_segq_top(struct ilpcb * ilpcb)
6729*14414594SDavid du Colombier+ {
6730*14414594SDavid du Colombier+   return (ilpcb->segq);
6731*14414594SDavid du Colombier+ }
6732*14414594SDavid du Colombier+
6733*14414594SDavid du Colombier+ static __inline void il_segq_dequeue(struct ilpcb * ilpcb)
6734*14414594SDavid du Colombier+ {
6735*14414594SDavid du Colombier+   struct mbuf * m = ilpcb->segq;
6736*14414594SDavid du Colombier+   ilpcb->segq = m->m_nextpkt;
6737*14414594SDavid du Colombier+   m->m_nextpkt = 0;
6738*14414594SDavid du Colombier+ }
6739*14414594SDavid du Colombier+
6740*14414594SDavid du Colombier+ static __inline void il_segq_insert(struct ilpcb * ilpcb, struct mbuf * m, u_long seq, struct ilhdr * il)
6741*14414594SDavid du Colombier+ {
6742*14414594SDavid du Colombier+   u_long pseq;
6743*14414594SDavid du Colombier+   struct mbuf * mp, * mq;
6744*14414594SDavid du Colombier+
6745*14414594SDavid du Colombier+   m->m_pkthdr.header = il;
6746*14414594SDavid du Colombier+
6747*14414594SDavid du Colombier+   mp = 0;
6748*14414594SDavid du Colombier+   mq = ilpcb->segq;
6749*14414594SDavid du Colombier+   while ( mq ) {
6750*14414594SDavid du Colombier+     il = mq->m_pkthdr.header;
6751*14414594SDavid du Colombier+     pseq = ntohl(*(u_long *)il->ilid);
6752*14414594SDavid du Colombier+     if( pseq > seq )
6753*14414594SDavid du Colombier+       break;
6754*14414594SDavid du Colombier+     if( pseq == seq ) { /* we already got this packet */
6755*14414594SDavid du Colombier+       m_freem(m);
6756*14414594SDavid du Colombier+       return;
6757*14414594SDavid du Colombier+     }
6758*14414594SDavid du Colombier+     mp = mq;
6759*14414594SDavid du Colombier+     mq = mq->m_nextpkt;
6760*14414594SDavid du Colombier+   }
6761*14414594SDavid du Colombier+
6762*14414594SDavid du Colombier+   if( mp == 0 ) {
6763*14414594SDavid du Colombier+     m->m_nextpkt = ilpcb->segq;
6764*14414594SDavid du Colombier+     ilpcb->segq = m;
6765*14414594SDavid du Colombier+     return;
6766*14414594SDavid du Colombier+   }
6767*14414594SDavid du Colombier+   mp->m_nextpkt = m;
6768*14414594SDavid du Colombier+   m->m_nextpkt = mq;
6769*14414594SDavid du Colombier+ }
6770*14414594SDavid du Colombier+
6771*14414594SDavid du Colombier+ void il_init()
6772*14414594SDavid du Colombier+ {
6773*14414594SDavid du Colombier+   LIST_INIT(&ilb);
6774*14414594SDavid du Colombier+   ilbinfo.listhead = &ilb;
6775*14414594SDavid du Colombier+   ilbinfo.hashbase = hashinit(ILBHASHSIZE, M_PCB, &ilbinfo.hashmask);
6776*14414594SDavid du Colombier+   ilbinfo.porthashbase = hashinit(ILBHASHSIZE, M_PCB,
6777*14414594SDavid du Colombier+ 				  &ilbinfo.porthashmask);
6778*14414594SDavid du Colombier+   ilbinfo.ipi_zone = zinit("ilpcb", sizeof(struct inp_ilpcb), maxsockets,
6779*14414594SDavid du Colombier+ 			   ZONE_INTERRUPT, 0);
6780*14414594SDavid du Colombier+ }
6781*14414594SDavid du Colombier+
6782*14414594SDavid du Colombier+ /* fill in il header and cksum, ip src/dst addresses */
6783*14414594SDavid du Colombier+ static int il_output(struct ilpcb * ilpcb, struct mbuf *m, int type, u_long seq, u_char spec)
6784*14414594SDavid du Colombier+ {
6785*14414594SDavid du Colombier+   struct ilhdr * il;
6786*14414594SDavid du Colombier+   struct ip * ip;
6787*14414594SDavid du Colombier+   int illen;
6788*14414594SDavid du Colombier+   struct inpcb * inp;
6789*14414594SDavid du Colombier+   struct socket * so;
6790*14414594SDavid du Colombier+
6791*14414594SDavid du Colombier+   /* XXX: check total size is less than IP_MAXPACKET */
6792*14414594SDavid du Colombier+
6793*14414594SDavid du Colombier+   if( m == 0 ) {
6794*14414594SDavid du Colombier+     inp = ilpcb->inpcb;
6795*14414594SDavid du Colombier+     so = inp->inp_socket;
6796*14414594SDavid du Colombier+     m = m_copypacket(so->so_snd.sb_mb, M_DONTWAIT);
6797*14414594SDavid du Colombier+   }
6798*14414594SDavid du Colombier+
6799*14414594SDavid du Colombier+   /*
6800*14414594SDavid du Colombier+    * Calculate data length and get a mbuf
6801*14414594SDavid du Colombier+    * for IL and IP headers.
6802*14414594SDavid du Colombier+    */
6803*14414594SDavid du Colombier+   illen = m->m_pkthdr.len; /* size of il payload */
6804*14414594SDavid du Colombier+   M_PREPEND(m, sizeof(struct ip) + sizeof(struct ilhdr), M_DONTWAIT);
6805*14414594SDavid du Colombier+   if( m == 0 )
6806*14414594SDavid du Colombier+     return ENOBUFS;
6807*14414594SDavid du Colombier+
6808*14414594SDavid du Colombier+   ip = mtod(m, struct ip *);
6809*14414594SDavid du Colombier+   il = (struct ilhdr *) (ip+1);
6810*14414594SDavid du Colombier+   bzero(ip, sizeof(*ip));
6811*14414594SDavid du Colombier+
6812*14414594SDavid du Colombier+   ip->ip_p = IPPROTO_IL;
6813*14414594SDavid du Colombier+   ip->ip_src = ilpcb->inpcb->inp_laddr;
6814*14414594SDavid du Colombier+   ip->ip_dst = ilpcb->inpcb->inp_faddr;
6815*14414594SDavid du Colombier+   ip->ip_len = m->m_pkthdr.len;
6816*14414594SDavid du Colombier+   ip->ip_ttl = ilpcb->inpcb->inp_ip_ttl;	/* XXX */
6817*14414594SDavid du Colombier+   ip->ip_tos = ilpcb->inpcb->inp_ip_tos;	/* XXX */
6818*14414594SDavid du Colombier+
6819*14414594SDavid du Colombier+   *(u_short *)il->illen = htons(illen + sizeof(struct ilhdr));
6820*14414594SDavid du Colombier+   il->iltype = type;
6821*14414594SDavid du Colombier+   il->ilspec = spec;
6822*14414594SDavid du Colombier+   *(u_short *)il->ilsrc = ilpcb->inpcb->inp_lport;
6823*14414594SDavid du Colombier+   *(u_short *)il->ildst = ilpcb->inpcb->inp_fport;
6824*14414594SDavid du Colombier+   if ( type != ILT_SYNC )
6825*14414594SDavid du Colombier+     *(u_long *)il->ilid = htonl(seq);
6826*14414594SDavid du Colombier+   else
6827*14414594SDavid du Colombier+     *(u_long *)il->ilid = htonl(ilpcb->start);
6828*14414594SDavid du Colombier+
6829*14414594SDavid du Colombier+   if( type != ILT_ACK && type != ILT_STATE) {
6830*14414594SDavid du Colombier+     if( ilpcb->rxt_timer == 0 )
6831*14414594SDavid du Colombier+       ilpcb->rxt_timer = ilpcb->rxt_timer_cur;
6832*14414594SDavid du Colombier+     if( ilpcb->death_timer == 0 )
6833*14414594SDavid du Colombier+       ilpcb->death_timer = ilpcb->death_timer_cur;
6834*14414594SDavid du Colombier+   }
6835*14414594SDavid du Colombier+
6836*14414594SDavid du Colombier+   *(u_long *)il->ilack = htonl(ilpcb->recvd);
6837*14414594SDavid du Colombier+   il->ilsum[0] = il->ilsum[1] = 0;
6838*14414594SDavid du Colombier+
6839*14414594SDavid du Colombier+   /* IL checksum does not cover IP header */
6840*14414594SDavid du Colombier+   m->m_data += sizeof(struct ip);
6841*14414594SDavid du Colombier+   m->m_len  -= sizeof(struct ip);
6842*14414594SDavid du Colombier+   *(u_short *)il->ilsum = in_cksum(m, illen + sizeof(struct ilhdr));
6843*14414594SDavid du Colombier+   m->m_data -= sizeof(struct ip);
6844*14414594SDavid du Colombier+   m->m_len  += sizeof(struct ip);
6845*14414594SDavid du Colombier+
6846*14414594SDavid du Colombier+   return ip_output(m, ilpcb->inpcb->inp_options, &ilpcb->inpcb->inp_route,
6847*14414594SDavid du Colombier+ 		   ilpcb->inpcb->inp_socket->so_options & SO_DONTROUTE ,0);
6848*14414594SDavid du Colombier+ }
6849*14414594SDavid du Colombier+
6850*14414594SDavid du Colombier+ static int il_send_empty(struct ilpcb * ilpcb, int type, u_char spec)
6851*14414594SDavid du Colombier+ {
6852*14414594SDavid du Colombier+   struct mbuf * m0;
6853*14414594SDavid du Colombier+
6854*14414594SDavid du Colombier+   MGETHDR(m0, M_DONTWAIT, MT_DATA);
6855*14414594SDavid du Colombier+   m0->m_len = 0;
6856*14414594SDavid du Colombier+   m0->m_pkthdr.len = 0;
6857*14414594SDavid du Colombier+   MH_ALIGN(m0, 0); /* leave space for the packet header */
6858*14414594SDavid du Colombier+
6859*14414594SDavid du Colombier+   return il_output(ilpcb, m0, type, ilpcb->next, spec);
6860*14414594SDavid du Colombier+ }
6861*14414594SDavid du Colombier+
6862*14414594SDavid du Colombier+ static int il_respond(struct ilpcb * ilpcb, struct ip * ip, struct ilhdr *il, int type, u_char spec)
6863*14414594SDavid du Colombier+ {
6864*14414594SDavid du Colombier+   struct mbuf * m;
6865*14414594SDavid du Colombier+   int illen;
6866*14414594SDavid du Colombier+   struct ip * ip0;
6867*14414594SDavid du Colombier+   struct ilhdr *il0;
6868*14414594SDavid du Colombier+   struct route * ro;
6869*14414594SDavid du Colombier+   struct route sro;
6870*14414594SDavid du Colombier+
6871*14414594SDavid du Colombier+   if( ilpcb ) {
6872*14414594SDavid du Colombier+     ro = & ilpcb->inpcb->inp_route;
6873*14414594SDavid du Colombier+   } else {
6874*14414594SDavid du Colombier+     ro = &sro;
6875*14414594SDavid du Colombier+     bzero(ro, sizeof *ro);
6876*14414594SDavid du Colombier+   }
6877*14414594SDavid du Colombier+
6878*14414594SDavid du Colombier+   MGETHDR(m, M_DONTWAIT, MT_DATA);
6879*14414594SDavid du Colombier+   m->m_len = 0;
6880*14414594SDavid du Colombier+   m->m_pkthdr.len = 0;
6881*14414594SDavid du Colombier+   MH_ALIGN(m, 0); /* leave space for the packet header */
6882*14414594SDavid du Colombier+   illen = m->m_pkthdr.len; /* size of il payload */
6883*14414594SDavid du Colombier+   M_PREPEND(m, sizeof(struct ip) + sizeof(struct ilhdr), M_DONTWAIT);
6884*14414594SDavid du Colombier+   if( m == 0 )
6885*14414594SDavid du Colombier+     return ENOBUFS;
6886*14414594SDavid du Colombier+
6887*14414594SDavid du Colombier+   ip0 = mtod(m, struct ip *);
6888*14414594SDavid du Colombier+   il0 = (struct ilhdr *) (ip0+1);
6889*14414594SDavid du Colombier+   bzero(ip0, sizeof(*ip0));
6890*14414594SDavid du Colombier+
6891*14414594SDavid du Colombier+   ip0->ip_p = IPPROTO_IL;
6892*14414594SDavid du Colombier+   ip0->ip_src = ip->ip_dst;
6893*14414594SDavid du Colombier+   ip0->ip_dst = ip->ip_src;
6894*14414594SDavid du Colombier+   ip0->ip_ttl = ip_defttl;
6895*14414594SDavid du Colombier+   ip0->ip_len = sizeof(struct ip) + sizeof(struct ilhdr);
6896*14414594SDavid du Colombier+   *(u_short *)il0->illen = htons(illen + sizeof(struct ilhdr));
6897*14414594SDavid du Colombier+   il0->iltype = type;
6898*14414594SDavid du Colombier+   il0->ilspec = spec;
6899*14414594SDavid du Colombier+   bcopy(il->ilsrc, il0->ildst, 2);
6900*14414594SDavid du Colombier+   bcopy(il->ildst, il0->ilsrc, 2);
6901*14414594SDavid du Colombier+   *(u_long *)il0->ilid = 0;
6902*14414594SDavid du Colombier+   bcopy(il->ilid, il0->ilack, 4);
6903*14414594SDavid du Colombier+   il0->ilsum[0] = il0->ilsum[1] = 0;
6904*14414594SDavid du Colombier+
6905*14414594SDavid du Colombier+   /* IL checksum does not cover IP header */
6906*14414594SDavid du Colombier+   m->m_data += sizeof(struct ip);
6907*14414594SDavid du Colombier+   m->m_len  -= sizeof(struct ip);
6908*14414594SDavid du Colombier+   *(u_short *)il0->ilsum = in_cksum(m, illen + sizeof(struct ilhdr));
6909*14414594SDavid du Colombier+   m->m_data -= sizeof(struct ip);
6910*14414594SDavid du Colombier+   m->m_len  += sizeof(struct ip);
6911*14414594SDavid du Colombier+
6912*14414594SDavid du Colombier+   return ip_output(m, 0, ro, 0 ,0);
6913*14414594SDavid du Colombier+ }
6914*14414594SDavid du Colombier+
6915*14414594SDavid du Colombier+ static struct ilpcb *
6916*14414594SDavid du Colombier+ il_newconn(struct ilpcb * ilpcb, struct in_addr ti_dst, u_short ti_dport,
6917*14414594SDavid du Colombier+ 	   struct in_addr ti_src, u_short ti_sport)
6918*14414594SDavid du Colombier+ {
6919*14414594SDavid du Colombier+   register struct ilpcb * ilpcb0;
6920*14414594SDavid du Colombier+   struct socket *so2, * so;
6921*14414594SDavid du Colombier+   struct inpcb * inp;
6922*14414594SDavid du Colombier+   struct sockaddr_in sin;
6923*14414594SDavid du Colombier+
6924*14414594SDavid du Colombier+   so = ilpcb->inpcb->inp_socket;
6925*14414594SDavid du Colombier+   so2 = sonewconn(so, 0);
6926*14414594SDavid du Colombier+   if (so2 == 0) {
6927*14414594SDavid du Colombier+     so2 = sodropablereq(so);
6928*14414594SDavid du Colombier+     if (so2) {
6929*14414594SDavid du Colombier+       il_drop(sotoilpcb(so2), ETIMEDOUT);
6930*14414594SDavid du Colombier+       so2 = sonewconn(so, 0);
6931*14414594SDavid du Colombier+     }
6932*14414594SDavid du Colombier+     if (!so2)
6933*14414594SDavid du Colombier+       return 0;
6934*14414594SDavid du Colombier+   }
6935*14414594SDavid du Colombier+   so = so2;
6936*14414594SDavid du Colombier+
6937*14414594SDavid du Colombier+   inp = (struct inpcb *)so->so_pcb;
6938*14414594SDavid du Colombier+   inp->inp_laddr = ti_dst;
6939*14414594SDavid du Colombier+   inp->inp_lport = ti_dport;
6940*14414594SDavid du Colombier+   if (in_pcbinshash(inp) != 0) {
6941*14414594SDavid du Colombier+ 				/*
6942*14414594SDavid du Colombier+ 				 * Undo the assignments above if we failed to put
6943*14414594SDavid du Colombier+ 				 * the PCB on the hash lists.
6944*14414594SDavid du Colombier+ 				 */
6945*14414594SDavid du Colombier+     inp->inp_laddr.s_addr = INADDR_ANY;
6946*14414594SDavid du Colombier+     inp->inp_lport = 0;
6947*14414594SDavid du Colombier+
6948*14414594SDavid du Colombier+     soabort(so);
6949*14414594SDavid du Colombier+     return 0;
6950*14414594SDavid du Colombier+   }
6951*14414594SDavid du Colombier+
6952*14414594SDavid du Colombier+   bzero((char *)&sin, sizeof(sin));
6953*14414594SDavid du Colombier+   sin.sin_family = AF_INET;
6954*14414594SDavid du Colombier+   sin.sin_len = sizeof(sin);
6955*14414594SDavid du Colombier+   sin.sin_addr = ti_src;
6956*14414594SDavid du Colombier+   sin.sin_port = ti_sport;
6957*14414594SDavid du Colombier+   if (in_pcbconnect(inp, (struct sockaddr *)&sin, &proc0)) {
6958*14414594SDavid du Colombier+     inp->inp_laddr.s_addr = INADDR_ANY;
6959*14414594SDavid du Colombier+     soabort(so);
6960*14414594SDavid du Colombier+     return 0;
6961*14414594SDavid du Colombier+   }
6962*14414594SDavid du Colombier+
6963*14414594SDavid du Colombier+   ilpcb0 = intoilpcb(inp);
6964*14414594SDavid du Colombier+   ilpcb0->state = ILS_LISTENING;
6965*14414594SDavid du Colombier+
6966*14414594SDavid du Colombier+   return ilpcb0;
6967*14414594SDavid du Colombier+ }
6968*14414594SDavid du Colombier+
6969*14414594SDavid du Colombier+ /* ack processing */
6970*14414594SDavid du Colombier+ static void il_proc_ack(struct ilpcb * ilpcb, struct socket * so, u_long ack)
6971*14414594SDavid du Colombier+ {
6972*14414594SDavid du Colombier+   if( ack >= ilpcb->unacked ) {
6973*14414594SDavid du Colombier+     ilpcb->rxt_timer = 0;
6974*14414594SDavid du Colombier+     ilpcb->death_timer = 0;
6975*14414594SDavid du Colombier+
6976*14414594SDavid du Colombier+     /* the rxt timer is not prop. to RTT */
6977*14414594SDavid du Colombier+     /* reset it so that the first rxt is always 1 second */
6978*14414594SDavid du Colombier+     ilpcb->rxt_timer_cur = 2;
6979*14414594SDavid du Colombier+
6980*14414594SDavid du Colombier+     if( ack >= ilpcb->next )
6981*14414594SDavid du Colombier+       ack = ilpcb->next - 1;
6982*14414594SDavid du Colombier+     while (ilpcb->unacked <= ack ) {
6983*14414594SDavid du Colombier+       sbdroprecord(&so->so_snd);
6984*14414594SDavid du Colombier+       ilpcb->unacked++;
6985*14414594SDavid du Colombier+     }
6986*14414594SDavid du Colombier+     if( ilpcb->unacked != ilpcb->next ) {
6987*14414594SDavid du Colombier+       ilpcb->rxt_timer = ilpcb->rxt_timer_cur;
6988*14414594SDavid du Colombier+       ilpcb->death_timer = ilpcb->death_timer_cur; /* do we need this here? */
6989*14414594SDavid du Colombier+     }
6990*14414594SDavid du Colombier+     sowwakeup(so);
6991*14414594SDavid du Colombier+   }
6992*14414594SDavid du Colombier+ }
6993*14414594SDavid du Colombier+
6994*14414594SDavid du Colombier+ static int il_proc_data(struct ilpcb * ilpcb, struct socket * so, struct mbuf * m, u_long seq, int spec)
6995*14414594SDavid du Colombier+ {
6996*14414594SDavid du Colombier+   struct mbuf * m0;
6997*14414594SDavid du Colombier+   struct ip * ip;
6998*14414594SDavid du Colombier+   int hlen = sizeof(struct ip) + sizeof(struct ilhdr);
6999*14414594SDavid du Colombier+   struct ilhdr * il;
7000*14414594SDavid du Colombier+   int needack = 0;
7001*14414594SDavid du Colombier+
7002*14414594SDavid du Colombier+   ip = mtod(m, struct ip *);
7003*14414594SDavid du Colombier+   il = (struct ilhdr *)(ip+1);
7004*14414594SDavid du Colombier+   if( seq == ilpcb->recvd + 1 ) {
7005*14414594SDavid du Colombier+     needack = 1;
7006*14414594SDavid du Colombier+     while(1) {
7007*14414594SDavid du Colombier+       ilpcb->recvd = seq;
7008*14414594SDavid du Colombier+
7009*14414594SDavid du Colombier+       m->m_len -= hlen;
7010*14414594SDavid du Colombier+       m->m_pkthdr.len -= hlen;
7011*14414594SDavid du Colombier+       m->m_data += hlen;
7012*14414594SDavid du Colombier+       sbappendrecord(&so->so_rcv, m);
7013*14414594SDavid du Colombier+
7014*14414594SDavid du Colombier+       if( (m0 = il_segq_top(ilpcb)) == 0 )
7015*14414594SDavid du Colombier+ 	break;
7016*14414594SDavid du Colombier+       ip = mtod(m0, struct ip *);
7017*14414594SDavid du Colombier+       il = (struct ilhdr *)(ip+1);
7018*14414594SDavid du Colombier+       seq = ntohl(*(u_long *)il->ilid);
7019*14414594SDavid du Colombier+       if( seq != ilpcb->recvd + 1 )
7020*14414594SDavid du Colombier+ 	break;
7021*14414594SDavid du Colombier+       il_segq_dequeue(ilpcb);
7022*14414594SDavid du Colombier+       m = m0;
7023*14414594SDavid du Colombier+     };
7024*14414594SDavid du Colombier+     sorwakeup(so);
7025*14414594SDavid du Colombier+   } else {
7026*14414594SDavid du Colombier+     if( seq > ilpcb->recvd )
7027*14414594SDavid du Colombier+       il_segq_insert(ilpcb, m, seq, il);
7028*14414594SDavid du Colombier+     else
7029*14414594SDavid du Colombier+       m_freem(m);
7030*14414594SDavid du Colombier+   }
7031*14414594SDavid du Colombier+
7032*14414594SDavid du Colombier+   return needack;
7033*14414594SDavid du Colombier+ }
7034*14414594SDavid du Colombier+
7035*14414594SDavid du Colombier+ /* assume we only have one connection */
7036*14414594SDavid du Colombier+ void il_input(struct mbuf * m, int iphlen)
7037*14414594SDavid du Colombier+ {
7038*14414594SDavid du Colombier+   struct ilhdr * il;
7039*14414594SDavid du Colombier+   struct ilpcb * ilpcb = 0;
7040*14414594SDavid du Colombier+   int len, type;
7041*14414594SDavid du Colombier+   u_long seq, ack;
7042*14414594SDavid du Colombier+   struct ip * ip;
7043*14414594SDavid du Colombier+   struct inpcb * inp;
7044*14414594SDavid du Colombier+   u_short sport, dport;
7045*14414594SDavid du Colombier+   struct socket * so;
7046*14414594SDavid du Colombier+   u_char spec;
7047*14414594SDavid du Colombier+
7048*14414594SDavid du Colombier+   /*
7049*14414594SDavid du Colombier+    * Strip IP options, if any; should skip this,
7050*14414594SDavid du Colombier+    * make available to user, and use on returned packets,
7051*14414594SDavid du Colombier+    * but we don't yet have a way to check the checksum
7052*14414594SDavid du Colombier+    * with options still present.
7053*14414594SDavid du Colombier+    */
7054*14414594SDavid du Colombier+   if (iphlen > sizeof (struct ip)) {
7055*14414594SDavid du Colombier+     ip_stripoptions(m, (struct mbuf *)0);
7056*14414594SDavid du Colombier+     iphlen = sizeof(struct ip);
7057*14414594SDavid du Colombier+   }
7058*14414594SDavid du Colombier+
7059*14414594SDavid du Colombier+   /*
7060*14414594SDavid du Colombier+    * Get IP and IL header together in first mbuf.
7061*14414594SDavid du Colombier+    */
7062*14414594SDavid du Colombier+   ip = mtod(m, struct ip *);
7063*14414594SDavid du Colombier+   if (m->m_len < iphlen + sizeof(struct ilhdr)) {
7064*14414594SDavid du Colombier+     if ((m = m_pullup(m, iphlen + sizeof(struct ilhdr))) == 0) {
7065*14414594SDavid du Colombier+       return;
7066*14414594SDavid du Colombier+     }
7067*14414594SDavid du Colombier+     ip = mtod(m, struct ip *);
7068*14414594SDavid du Colombier+   }
7069*14414594SDavid du Colombier+   il = (struct ilhdr *)((caddr_t)ip + iphlen);
7070*14414594SDavid du Colombier+
7071*14414594SDavid du Colombier+   len = ntohs(*(u_short *)il->illen);
7072*14414594SDavid du Colombier+   seq = ntohl(*(u_long *)il->ilid);
7073*14414594SDavid du Colombier+   ack = ntohl(*(u_long *)il->ilack);
7074*14414594SDavid du Colombier+   sport = *(u_short *)il->ilsrc;
7075*14414594SDavid du Colombier+   dport = *(u_short *)il->ildst;
7076*14414594SDavid du Colombier+   type = il->iltype;
7077*14414594SDavid du Colombier+   spec = il->ilspec;
7078*14414594SDavid du Colombier+
7079*14414594SDavid du Colombier+   inp = in_pcblookup_hash(&ilbinfo, ip->ip_src, sport, ip->ip_dst, dport, 1);
7080*14414594SDavid du Colombier+   if ( inp == 0 && type == ILT_SYNC )
7081*14414594SDavid du Colombier+     goto dropwithrest;
7082*14414594SDavid du Colombier+   if( inp == 0 )
7083*14414594SDavid du Colombier+     goto drop;
7084*14414594SDavid du Colombier+
7085*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7086*14414594SDavid du Colombier+   if( ilpcb == 0 )
7087*14414594SDavid du Colombier+     goto drop;
7088*14414594SDavid du Colombier+
7089*14414594SDavid du Colombier+   so = inp->inp_socket;
7090*14414594SDavid du Colombier+   if( type == ILT_QUERY ) { /* XXX: can we use the same mbuf to send? */
7091*14414594SDavid du Colombier+     il_send_empty(ilpcb, ILT_STATE, il->ilspec);
7092*14414594SDavid du Colombier+     goto drop;
7093*14414594SDavid du Colombier+   }
7094*14414594SDavid du Colombier+
7095*14414594SDavid du Colombier+  again:
7096*14414594SDavid du Colombier+   /* FSM transition */
7097*14414594SDavid du Colombier+   switch( ilpcb->state ) {
7098*14414594SDavid du Colombier+   case ILS_SYNCER:
7099*14414594SDavid du Colombier+     if( ack != ilpcb->start )
7100*14414594SDavid du Colombier+       goto drop;
7101*14414594SDavid du Colombier+     switch( type ) {
7102*14414594SDavid du Colombier+     case ILT_SYNC:
7103*14414594SDavid du Colombier+       ilpcb->unacked++;
7104*14414594SDavid du Colombier+       ilpcb->recvd = seq;
7105*14414594SDavid du Colombier+       il_send_empty(ilpcb, ILT_ACK, 0);
7106*14414594SDavid du Colombier+       ilpcb->state = ILS_ESTABLISHED;
7107*14414594SDavid du Colombier+       ilpcb->rxt_timer = 0;
7108*14414594SDavid du Colombier+       ilpcb->death_timer = 0;
7109*14414594SDavid du Colombier+       soisconnected(inp->inp_socket);
7110*14414594SDavid du Colombier+       break;
7111*14414594SDavid du Colombier+     case ILT_CLOSE:
7112*14414594SDavid du Colombier+       il_drop(ilpcb, ECONNREFUSED);
7113*14414594SDavid du Colombier+       break;
7114*14414594SDavid du Colombier+     }
7115*14414594SDavid du Colombier+     break;
7116*14414594SDavid du Colombier+
7117*14414594SDavid du Colombier+   case ILS_LISTENING:
7118*14414594SDavid du Colombier+     if( type == ILT_SYNC && ack == 0 && so->so_options & SO_ACCEPTCONN ) {
7119*14414594SDavid du Colombier+       ilpcb = il_newconn(ilpcb, ip->ip_dst, dport, ip->ip_src, sport);
7120*14414594SDavid du Colombier+
7121*14414594SDavid du Colombier+       ilpcb->next = ilpcb->start = random();
7122*14414594SDavid du Colombier+       ilpcb->unacked = ilpcb->next;
7123*14414594SDavid du Colombier+       ilpcb->rstart = ilpcb->recvd = seq;
7124*14414594SDavid du Colombier+       ilpcb->state = ILS_SYNCEE;
7125*14414594SDavid du Colombier+       il_send_empty(ilpcb, ILT_SYNC, 0);
7126*14414594SDavid du Colombier+       ilpcb->next++;
7127*14414594SDavid du Colombier+     } else
7128*14414594SDavid du Colombier+       il_respond(ilpcb, ip, il, ILT_CLOSE, 0);
7129*14414594SDavid du Colombier+     break;
7130*14414594SDavid du Colombier+
7131*14414594SDavid du Colombier+   case ILS_SYNCEE:
7132*14414594SDavid du Colombier+     if( ack == ilpcb->start ) {
7133*14414594SDavid du Colombier+       ilpcb->rxt_timer = 0;
7134*14414594SDavid du Colombier+       ilpcb->unacked++;
7135*14414594SDavid du Colombier+       ilpcb->state = ILS_ESTABLISHED;
7136*14414594SDavid du Colombier+       soisconnected(so);
7137*14414594SDavid du Colombier+       goto again;
7138*14414594SDavid du Colombier+       break;
7139*14414594SDavid du Colombier+     }
7140*14414594SDavid du Colombier+     if( type == ILT_SYNC && seq == ilpcb->recvd && ack == 0 )
7141*14414594SDavid du Colombier+       il_send_empty(ilpcb, ILT_SYNC, 0);
7142*14414594SDavid du Colombier+     break;
7143*14414594SDavid du Colombier+
7144*14414594SDavid du Colombier+   case ILS_ESTABLISHED:
7145*14414594SDavid du Colombier+     il_proc_ack(ilpcb, so, ack);
7146*14414594SDavid du Colombier+     switch( type ) {
7147*14414594SDavid du Colombier+     case ILT_DATA:
7148*14414594SDavid du Colombier+       if( il_proc_data(ilpcb, so, m, seq, spec) )
7149*14414594SDavid du Colombier+ 	ilpcb->flags |= ILF_NEEDACK;
7150*14414594SDavid du Colombier+       goto done;
7151*14414594SDavid du Colombier+       break;
7152*14414594SDavid du Colombier+     case ILT_DATAQUERY:
7153*14414594SDavid du Colombier+       il_proc_data(ilpcb, so, m, seq, spec);
7154*14414594SDavid du Colombier+       il_send_empty(ilpcb, ILT_STATE, spec);
7155*14414594SDavid du Colombier+       goto done;
7156*14414594SDavid du Colombier+       break;
7157*14414594SDavid du Colombier+     case ILT_CLOSE:
7158*14414594SDavid du Colombier+       if( ack < ilpcb->next && ack >= ilpcb->start ) {
7159*14414594SDavid du Colombier+ 	if( ilpcb->recvd+1 == seq )
7160*14414594SDavid du Colombier+ 	  ilpcb->recvd = seq;
7161*14414594SDavid du Colombier+ 	il_send_empty(ilpcb, ILT_CLOSE, 0);
7162*14414594SDavid du Colombier+ 	ilpcb->state = ILS_CLOSING;
7163*14414594SDavid du Colombier+       }
7164*14414594SDavid du Colombier+       break;
7165*14414594SDavid du Colombier+     case ILT_STATE:
7166*14414594SDavid du Colombier+       if( ack < ilpcb->rxt_max ) {
7167*14414594SDavid du Colombier+ 	ilpcb->rxt_max = ilpcb->next;
7168*14414594SDavid du Colombier+ 	il_output(ilpcb, 0, ILT_DATAQUERY, ilpcb->unacked, 1);
7169*14414594SDavid du Colombier+       }
7170*14414594SDavid du Colombier+       break;
7171*14414594SDavid du Colombier+     case ILT_SYNC:
7172*14414594SDavid du Colombier+       il_send_empty(ilpcb, ILT_ACK, 0);
7173*14414594SDavid du Colombier+       break;
7174*14414594SDavid du Colombier+     }
7175*14414594SDavid du Colombier+     break;
7176*14414594SDavid du Colombier+
7177*14414594SDavid du Colombier+   case	ILS_CLOSED:
7178*14414594SDavid du Colombier+     goto drop;
7179*14414594SDavid du Colombier+     break;
7180*14414594SDavid du Colombier+
7181*14414594SDavid du Colombier+   case ILS_CLOSING:
7182*14414594SDavid du Colombier+     if( type == ILT_CLOSE ) {
7183*14414594SDavid du Colombier+       if( ilpcb->recvd+1 == seq )
7184*14414594SDavid du Colombier+ 	ilpcb->recvd = seq;
7185*14414594SDavid du Colombier+       il_send_empty(ilpcb, ILT_CLOSE, 0);
7186*14414594SDavid du Colombier+       ilpcb->state = ILS_CLOSED;
7187*14414594SDavid du Colombier+       il_close(ilpcb);
7188*14414594SDavid du Colombier+     }
7189*14414594SDavid du Colombier+     break;
7190*14414594SDavid du Colombier+   }
7191*14414594SDavid du Colombier+
7192*14414594SDavid du Colombier+   m_freem(m);
7193*14414594SDavid du Colombier+  done:
7194*14414594SDavid du Colombier+   return;
7195*14414594SDavid du Colombier+
7196*14414594SDavid du Colombier+  dropwithrest:
7197*14414594SDavid du Colombier+   il_respond(ilpcb, ip, il, ILT_CLOSE, 0);
7198*14414594SDavid du Colombier+  drop:
7199*14414594SDavid du Colombier+   m_freem(m);
7200*14414594SDavid du Colombier+ }
7201*14414594SDavid du Colombier+
7202*14414594SDavid du Colombier+ static void il_sendseqinit(struct ilpcb * ilpcb)
7203*14414594SDavid du Colombier+ {
7204*14414594SDavid du Colombier+   ilpcb->start = ilpcb->next = random();
7205*14414594SDavid du Colombier+   ilpcb->unacked = ilpcb->next;
7206*14414594SDavid du Colombier+   ilpcb->state = ILS_SYNCER;
7207*14414594SDavid du Colombier+   ilpcb->next++;
7208*14414594SDavid du Colombier+ }
7209*14414594SDavid du Colombier+
7210*14414594SDavid du Colombier+ static void il_rxt_timeout(struct ilpcb * ilpcb)
7211*14414594SDavid du Colombier+ {
7212*14414594SDavid du Colombier+   switch ( ilpcb->state ) {
7213*14414594SDavid du Colombier+   case ILS_ESTABLISHED:
7214*14414594SDavid du Colombier+     il_output(ilpcb, 0, ILT_DATAQUERY, ilpcb->unacked, 1);
7215*14414594SDavid du Colombier+     ilpcb->rxtot++;
7216*14414594SDavid du Colombier+     break;
7217*14414594SDavid du Colombier+   case ILS_SYNCER:
7218*14414594SDavid du Colombier+   case ILS_SYNCEE:
7219*14414594SDavid du Colombier+     il_send_empty(ilpcb, ILT_SYNC, 0);
7220*14414594SDavid du Colombier+     break;
7221*14414594SDavid du Colombier+   case ILS_CLOSING:
7222*14414594SDavid du Colombier+     il_send_empty(ilpcb, ILT_CLOSE, 0);
7223*14414594SDavid du Colombier+     break;
7224*14414594SDavid du Colombier+   }
7225*14414594SDavid du Colombier+   ilpcb->rxt_timer = ilpcb->rxt_timer_cur;
7226*14414594SDavid du Colombier+ }
7227*14414594SDavid du Colombier+
7228*14414594SDavid du Colombier+ void il_ctlinput(int cmd, struct sockaddr *sa, void *vip)
7229*14414594SDavid du Colombier+ {}
7230*14414594SDavid du Colombier+
7231*14414594SDavid du Colombier+ int  il_ctloutput(struct socket *so, struct sockopt *sopt)
7232*14414594SDavid du Colombier+ { return 0; }
7233*14414594SDavid du Colombier+
7234*14414594SDavid du Colombier+ void il_drain()
7235*14414594SDavid du Colombier+ {}
7236*14414594SDavid du Colombier+
7237*14414594SDavid du Colombier+ void il_slowtimo()
7238*14414594SDavid du Colombier+ {
7239*14414594SDavid du Colombier+   struct ilpcb * ilpcb;
7240*14414594SDavid du Colombier+   struct inpcb * inp;
7241*14414594SDavid du Colombier+   int s;
7242*14414594SDavid du Colombier+
7243*14414594SDavid du Colombier+   s = splnet();
7244*14414594SDavid du Colombier+   for(inp = ilb.lh_first; inp; inp = inp->inp_list.le_next) {
7245*14414594SDavid du Colombier+     ilpcb = intoilpcb(inp);
7246*14414594SDavid du Colombier+     if(ilpcb->death_timer &&  --ilpcb->death_timer == 0 )
7247*14414594SDavid du Colombier+       il_drop(ilpcb, ETIMEDOUT);
7248*14414594SDavid du Colombier+
7249*14414594SDavid du Colombier+     if(ilpcb->rxt_timer &&  --ilpcb->rxt_timer == 0 ) {
7250*14414594SDavid du Colombier+       ilpcb->rxt_timer_cur <<= 1;
7251*14414594SDavid du Colombier+       il_rxt_timeout(ilpcb);
7252*14414594SDavid du Colombier+     }
7253*14414594SDavid du Colombier+   }
7254*14414594SDavid du Colombier+   splx(s);
7255*14414594SDavid du Colombier+ }
7256*14414594SDavid du Colombier+
7257*14414594SDavid du Colombier+ void il_fasttimo()
7258*14414594SDavid du Colombier+ {
7259*14414594SDavid du Colombier+   struct ilpcb * ilpcb;
7260*14414594SDavid du Colombier+   struct inpcb * inp;
7261*14414594SDavid du Colombier+   int s;
7262*14414594SDavid du Colombier+
7263*14414594SDavid du Colombier+   s = splnet();
7264*14414594SDavid du Colombier+   for(inp = ilb.lh_first; inp; inp = inp->inp_list.le_next) {
7265*14414594SDavid du Colombier+     ilpcb = intoilpcb(inp);
7266*14414594SDavid du Colombier+     if(ilpcb->flags & ILF_NEEDACK) {
7267*14414594SDavid du Colombier+       ilpcb->flags &= ~ILF_NEEDACK;
7268*14414594SDavid du Colombier+       il_send_empty(ilpcb, ILT_ACK, 0);
7269*14414594SDavid du Colombier+     }
7270*14414594SDavid du Colombier+   }
7271*14414594SDavid du Colombier+   splx(s);
7272*14414594SDavid du Colombier+ }
7273*14414594SDavid du Colombier+
7274*14414594SDavid du Colombier+ static struct ilpcb * il_newilpcb(struct inpcb * inp)
7275*14414594SDavid du Colombier+ {
7276*14414594SDavid du Colombier+   struct inp_ilpcb *it;
7277*14414594SDavid du Colombier+   register struct ilpcb *ilpcb;
7278*14414594SDavid du Colombier+
7279*14414594SDavid du Colombier+   it = (struct inp_ilpcb *)inp;
7280*14414594SDavid du Colombier+   ilpcb = &it->ilpcb;
7281*14414594SDavid du Colombier+   bzero((char *) ilpcb, sizeof(struct ilpcb));
7282*14414594SDavid du Colombier+
7283*14414594SDavid du Colombier+   ilpcb->state = ILS_CLOSED;
7284*14414594SDavid du Colombier+   ilpcb->inpcb = inp;
7285*14414594SDavid du Colombier+   ilpcb->rxt_timer_cur = 2;
7286*14414594SDavid du Colombier+   ilpcb->death_timer_cur = 20;
7287*14414594SDavid du Colombier+
7288*14414594SDavid du Colombier+   ilpcb->inpcb = inp;	/* XXX */
7289*14414594SDavid du Colombier+   inp->inp_ip_ttl = ip_defttl;
7290*14414594SDavid du Colombier+   inp->inp_ppcb = (caddr_t)ilpcb;
7291*14414594SDavid du Colombier+   return (ilpcb);		/* XXX */
7292*14414594SDavid du Colombier+ }
7293*14414594SDavid du Colombier+
7294*14414594SDavid du Colombier+ /*
7295*14414594SDavid du Colombier+  * Common subroutine to open a TCP connection to remote host specified
7296*14414594SDavid du Colombier+  * by struct sockaddr_in in mbuf *nam.  Call in_pcbbind to assign a local
7297*14414594SDavid du Colombier+  * port number if needed.  Call in_pcbladdr to do the routing and to choose
7298*14414594SDavid du Colombier+  * a local host address (interface).  If there is an existing incarnation
7299*14414594SDavid du Colombier+  * of the same connection in TIME-WAIT state and if the remote host was
7300*14414594SDavid du Colombier+  * sending CC options and if the connection duration was < MSL, then
7301*14414594SDavid du Colombier+  * truncate the previous TIME-WAIT state and proceed.
7302*14414594SDavid du Colombier+  * Initialize connection parameters and enter SYN-SENT state.
7303*14414594SDavid du Colombier+  */
7304*14414594SDavid du Colombier+ static int
7305*14414594SDavid du Colombier+ il_connect(struct ilpcb *ilpcb, struct sockaddr *nam, struct proc *p)
7306*14414594SDavid du Colombier+ {
7307*14414594SDavid du Colombier+ 	struct inpcb *inp = ilpcb->inpcb, *oinp;
7308*14414594SDavid du Colombier+ 	struct socket *so = inp->inp_socket;
7309*14414594SDavid du Colombier+ 	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
7310*14414594SDavid du Colombier+ 	struct sockaddr_in *ifaddr;
7311*14414594SDavid du Colombier+ 	int error;
7312*14414594SDavid du Colombier+
7313*14414594SDavid du Colombier+ 	if (inp->inp_lport == 0) {
7314*14414594SDavid du Colombier+ 		error = in_pcbbind(inp, (struct sockaddr *)0, p);
7315*14414594SDavid du Colombier+ 		if (error)
7316*14414594SDavid du Colombier+ 			return error;
7317*14414594SDavid du Colombier+ 	}
7318*14414594SDavid du Colombier+
7319*14414594SDavid du Colombier+ 	/*
7320*14414594SDavid du Colombier+ 	 * Cannot simply call in_pcbconnect, because there might be an
7321*14414594SDavid du Colombier+ 	 * earlier incarnation of this same connection still in
7322*14414594SDavid du Colombier+ 	 * TIME_WAIT state, creating an ADDRINUSE error.
7323*14414594SDavid du Colombier+ 	 */
7324*14414594SDavid du Colombier+ 	error = in_pcbladdr(inp, nam, &ifaddr);
7325*14414594SDavid du Colombier+ 	if (error)
7326*14414594SDavid du Colombier+ 		return error;
7327*14414594SDavid du Colombier+ 	oinp = in_pcblookup_hash(inp->inp_pcbinfo,
7328*14414594SDavid du Colombier+ 	    sin->sin_addr, sin->sin_port,
7329*14414594SDavid du Colombier+ 	    inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
7330*14414594SDavid du Colombier+ 						: ifaddr->sin_addr,
7331*14414594SDavid du Colombier+ 	    inp->inp_lport,  0);
7332*14414594SDavid du Colombier+ 	if (oinp) {
7333*14414594SDavid du Colombier+ 			return EADDRINUSE;
7334*14414594SDavid du Colombier+ 	}
7335*14414594SDavid du Colombier+ 	if (inp->inp_laddr.s_addr == INADDR_ANY)
7336*14414594SDavid du Colombier+ 		inp->inp_laddr = ifaddr->sin_addr;
7337*14414594SDavid du Colombier+ 	inp->inp_faddr = sin->sin_addr;
7338*14414594SDavid du Colombier+ 	inp->inp_fport = sin->sin_port;
7339*14414594SDavid du Colombier+ 	in_pcbrehash(inp);
7340*14414594SDavid du Colombier+
7341*14414594SDavid du Colombier+ #if 0
7342*14414594SDavid du Colombier+ 	ilpcb->t_template = tcp_template(tp);
7343*14414594SDavid du Colombier+ 	if (ilpcb->t_template == 0) {
7344*14414594SDavid du Colombier+ 		in_pcbdisconnect(inp);
7345*14414594SDavid du Colombier+ 		return ENOBUFS;
7346*14414594SDavid du Colombier+ 	}
7347*14414594SDavid du Colombier+ #endif
7348*14414594SDavid du Colombier+
7349*14414594SDavid du Colombier+ 	soisconnecting(so);
7350*14414594SDavid du Colombier+ 	il_sendseqinit(ilpcb);
7351*14414594SDavid du Colombier+
7352*14414594SDavid du Colombier+ 	return 0;
7353*14414594SDavid du Colombier+ }
7354*14414594SDavid du Colombier+
7355*14414594SDavid du Colombier+ static int il_usr_send(struct socket *so, int flags, struct mbuf * m, struct sockaddr *addr, struct mbuf *control, struct proc *p)
7356*14414594SDavid du Colombier+ {
7357*14414594SDavid du Colombier+   struct ilpcb * ilpcb;
7358*14414594SDavid du Colombier+   struct inpcb * inp = sotoinpcb(so);
7359*14414594SDavid du Colombier+   int error;
7360*14414594SDavid du Colombier+   struct mbuf * m0;
7361*14414594SDavid du Colombier+
7362*14414594SDavid du Colombier+   if (inp == 0) {
7363*14414594SDavid du Colombier+     m_freem(m);
7364*14414594SDavid du Colombier+     return EINVAL;
7365*14414594SDavid du Colombier+   }
7366*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7367*14414594SDavid du Colombier+
7368*14414594SDavid du Colombier+   if (sbspace(&so->so_snd) < -512) {
7369*14414594SDavid du Colombier+     m_freem(m);
7370*14414594SDavid du Colombier+     error = ENOBUFS;
7371*14414594SDavid du Colombier+     goto out;
7372*14414594SDavid du Colombier+   }
7373*14414594SDavid du Colombier+
7374*14414594SDavid du Colombier+   sbappendrecord(&so->so_snd, m);
7375*14414594SDavid du Colombier+   m0 = m_copypacket(m, M_DONTWAIT);
7376*14414594SDavid du Colombier+   error = il_output(ilpcb, m0, ILT_DATA, ilpcb->next++, 0);
7377*14414594SDavid du Colombier+
7378*14414594SDavid du Colombier+  out:
7379*14414594SDavid du Colombier+   return error;
7380*14414594SDavid du Colombier+ }
7381*14414594SDavid du Colombier+
7382*14414594SDavid du Colombier+ static int il_usr_attach(struct socket *so, int proto, struct proc *p)
7383*14414594SDavid du Colombier+ {
7384*14414594SDavid du Colombier+   int s = splnet();
7385*14414594SDavid du Colombier+   int error = 0;
7386*14414594SDavid du Colombier+   struct inpcb *inp = sotoinpcb(so);
7387*14414594SDavid du Colombier+   struct ilpcb *ilpcb = 0;
7388*14414594SDavid du Colombier+
7389*14414594SDavid du Colombier+   if (inp) {
7390*14414594SDavid du Colombier+     error = EISCONN;
7391*14414594SDavid du Colombier+     goto out;
7392*14414594SDavid du Colombier+   }
7393*14414594SDavid du Colombier+
7394*14414594SDavid du Colombier+   if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
7395*14414594SDavid du Colombier+     error = soreserve(so, il_sendspace, il_recvspace);
7396*14414594SDavid du Colombier+     if (error)
7397*14414594SDavid du Colombier+       goto out;
7398*14414594SDavid du Colombier+   }
7399*14414594SDavid du Colombier+
7400*14414594SDavid du Colombier+   error = in_pcballoc(so, &ilbinfo, p);
7401*14414594SDavid du Colombier+
7402*14414594SDavid du Colombier+   if (error)
7403*14414594SDavid du Colombier+     goto out;
7404*14414594SDavid du Colombier+
7405*14414594SDavid du Colombier+   inp = sotoinpcb(so);
7406*14414594SDavid du Colombier+   ilpcb = il_newilpcb(inp);
7407*14414594SDavid du Colombier+   if (ilpcb == 0) {
7408*14414594SDavid du Colombier+     int nofd = so->so_state & SS_NOFDREF;	/* XXX */
7409*14414594SDavid du Colombier+
7410*14414594SDavid du Colombier+     so->so_state &= ~SS_NOFDREF;	/* don't free the socket yet */
7411*14414594SDavid du Colombier+     in_pcbdetach(inp);
7412*14414594SDavid du Colombier+     so->so_state |= nofd;
7413*14414594SDavid du Colombier+     error = ENOBUFS;
7414*14414594SDavid du Colombier+     goto out;
7415*14414594SDavid du Colombier+   }
7416*14414594SDavid du Colombier+   ilpcb->state = ILS_CLOSED;
7417*14414594SDavid du Colombier+   ilpcb->segq = 0;
7418*14414594SDavid du Colombier+
7419*14414594SDavid du Colombier+  out:
7420*14414594SDavid du Colombier+   splx(s);
7421*14414594SDavid du Colombier+   return error;
7422*14414594SDavid du Colombier+
7423*14414594SDavid du Colombier+ }
7424*14414594SDavid du Colombier+
7425*14414594SDavid du Colombier+ static int il_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
7426*14414594SDavid du Colombier+ {
7427*14414594SDavid du Colombier+   int s = splnet();
7428*14414594SDavid du Colombier+   int error = 0;
7429*14414594SDavid du Colombier+   struct inpcb *inp = sotoinpcb(so);
7430*14414594SDavid du Colombier+   struct ilpcb *ilpcb;
7431*14414594SDavid du Colombier+   struct sockaddr_in *sinp;
7432*14414594SDavid du Colombier+
7433*14414594SDavid du Colombier+   if (inp == 0) {
7434*14414594SDavid du Colombier+     splx(s);
7435*14414594SDavid du Colombier+     return EINVAL;
7436*14414594SDavid du Colombier+   }
7437*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7438*14414594SDavid du Colombier+
7439*14414594SDavid du Colombier+ 	/*
7440*14414594SDavid du Colombier+ 	 * Must check for multicast addresses and disallow binding
7441*14414594SDavid du Colombier+ 	 * to them.
7442*14414594SDavid du Colombier+ 	 */
7443*14414594SDavid du Colombier+   sinp = (struct sockaddr_in *)nam;
7444*14414594SDavid du Colombier+   if (sinp->sin_family == AF_INET &&
7445*14414594SDavid du Colombier+       IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
7446*14414594SDavid du Colombier+     error = EAFNOSUPPORT;
7447*14414594SDavid du Colombier+     goto out;
7448*14414594SDavid du Colombier+   }
7449*14414594SDavid du Colombier+   error = in_pcbbind(inp, nam, p);
7450*14414594SDavid du Colombier+  out: splx(s);
7451*14414594SDavid du Colombier+   return error;
7452*14414594SDavid du Colombier+ }
7453*14414594SDavid du Colombier+
7454*14414594SDavid du Colombier+ /*
7455*14414594SDavid du Colombier+  * Initiate connection to peer.
7456*14414594SDavid du Colombier+  * Create a template for use in transmissions on this connection.
7457*14414594SDavid du Colombier+  * Enter SYN_SENT state, and mark socket as connecting.
7458*14414594SDavid du Colombier+  * Start keep-alive timer, and seed output sequence space.
7459*14414594SDavid du Colombier+  * Send initial segment on connection.
7460*14414594SDavid du Colombier+  */
7461*14414594SDavid du Colombier+ static int
7462*14414594SDavid du Colombier+ il_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
7463*14414594SDavid du Colombier+ {
7464*14414594SDavid du Colombier+   int s = splnet();
7465*14414594SDavid du Colombier+   int error = 0;
7466*14414594SDavid du Colombier+   struct inpcb *inp = sotoinpcb(so);
7467*14414594SDavid du Colombier+   struct ilpcb *ilpcb;
7468*14414594SDavid du Colombier+   struct sockaddr_in *sinp;
7469*14414594SDavid du Colombier+
7470*14414594SDavid du Colombier+   if (inp == 0) {
7471*14414594SDavid du Colombier+     splx(s);
7472*14414594SDavid du Colombier+     return EINVAL;
7473*14414594SDavid du Colombier+   }
7474*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7475*14414594SDavid du Colombier+
7476*14414594SDavid du Colombier+   /*
7477*14414594SDavid du Colombier+    * Must disallow TCP ``connections'' to multicast addresses.
7478*14414594SDavid du Colombier+    */
7479*14414594SDavid du Colombier+   sinp = (struct sockaddr_in *)nam;
7480*14414594SDavid du Colombier+   if (sinp->sin_family == AF_INET
7481*14414594SDavid du Colombier+       && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
7482*14414594SDavid du Colombier+     error = EAFNOSUPPORT;
7483*14414594SDavid du Colombier+     goto out;
7484*14414594SDavid du Colombier+   }
7485*14414594SDavid du Colombier+
7486*14414594SDavid du Colombier+   if ((error = il_connect(ilpcb, nam, p)) != 0)
7487*14414594SDavid du Colombier+     goto out;
7488*14414594SDavid du Colombier+
7489*14414594SDavid du Colombier+   error = il_send_empty(ilpcb, ILT_SYNC, 0);
7490*14414594SDavid du Colombier+
7491*14414594SDavid du Colombier+  out: splx(s);
7492*14414594SDavid du Colombier+   return error;
7493*14414594SDavid du Colombier+ }
7494*14414594SDavid du Colombier+
7495*14414594SDavid du Colombier+ /*
7496*14414594SDavid du Colombier+  * Close a TCP control block:
7497*14414594SDavid du Colombier+  *	discard all space held by the tcp
7498*14414594SDavid du Colombier+  *	discard internet protocol block
7499*14414594SDavid du Colombier+  *	wake up any sleepers
7500*14414594SDavid du Colombier+  */
7501*14414594SDavid du Colombier+ static struct ilpcb *
7502*14414594SDavid du Colombier+ il_close(struct ilpcb *ilpcb)
7503*14414594SDavid du Colombier+ {
7504*14414594SDavid du Colombier+ 	register struct mbuf *q;
7505*14414594SDavid du Colombier+ 	register struct mbuf *nq;
7506*14414594SDavid du Colombier+ 	struct inpcb *inp = ilpcb->inpcb;
7507*14414594SDavid du Colombier+ 	struct socket *so = inp->inp_socket;
7508*14414594SDavid du Colombier+
7509*14414594SDavid du Colombier+ 	/* free the reassembly queue, if any */
7510*14414594SDavid du Colombier+ 	for (q = ilpcb->segq; q; q = nq) {
7511*14414594SDavid du Colombier+ 		nq = q->m_nextpkt;
7512*14414594SDavid du Colombier+ 		ilpcb->segq = nq;
7513*14414594SDavid du Colombier+ 		m_freem(q);
7514*14414594SDavid du Colombier+ 	}
7515*14414594SDavid du Colombier+ 	inp->inp_ppcb = NULL;
7516*14414594SDavid du Colombier+ 	soisdisconnected(so);
7517*14414594SDavid du Colombier+ 	in_pcbdetach(inp);
7518*14414594SDavid du Colombier+ 	return ((struct ilpcb *)0);
7519*14414594SDavid du Colombier+ }
7520*14414594SDavid du Colombier+
7521*14414594SDavid du Colombier+ /*
7522*14414594SDavid du Colombier+  * User issued close, and wish to trail through shutdown states:
7523*14414594SDavid du Colombier+  * if never received SYN, just forget it.  If got a SYN from peer,
7524*14414594SDavid du Colombier+  * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
7525*14414594SDavid du Colombier+  * If already got a FIN from peer, then almost done; go to LAST_ACK
7526*14414594SDavid du Colombier+  * state.  In all other cases, have already sent FIN to peer (e.g.
7527*14414594SDavid du Colombier+  * after PRU_SHUTDOWN), and just have to play tedious game waiting
7528*14414594SDavid du Colombier+  * for peer to send FIN or not respond to keep-alives, etc.
7529*14414594SDavid du Colombier+  * We can let the user exit from the close as soon as the FIN is acked.
7530*14414594SDavid du Colombier+  */
7531*14414594SDavid du Colombier+ static struct ilpcb *
7532*14414594SDavid du Colombier+ il_usrclosed(struct ilpcb *ilpcb)
7533*14414594SDavid du Colombier+ {
7534*14414594SDavid du Colombier+
7535*14414594SDavid du Colombier+ 	switch (ilpcb->state) {
7536*14414594SDavid du Colombier+ 	case ILS_CLOSED:
7537*14414594SDavid du Colombier+ 	case ILS_LISTENING:
7538*14414594SDavid du Colombier+ 		ilpcb->state = ILS_CLOSED;
7539*14414594SDavid du Colombier+ 		ilpcb = il_close(ilpcb);
7540*14414594SDavid du Colombier+ 		break;
7541*14414594SDavid du Colombier+
7542*14414594SDavid du Colombier+ 	case ILS_SYNCER:
7543*14414594SDavid du Colombier+ 	case ILS_SYNCEE:
7544*14414594SDavid du Colombier+ 	case ILS_ESTABLISHED:
7545*14414594SDavid du Colombier+ 	  il_send_empty(ilpcb, ILT_CLOSE, 0);
7546*14414594SDavid du Colombier+ 	  ilpcb->state = ILS_CLOSING;
7547*14414594SDavid du Colombier+ 	  break;
7548*14414594SDavid du Colombier+
7549*14414594SDavid du Colombier+ 	case ILS_CLOSING:
7550*14414594SDavid du Colombier+ 		break;
7551*14414594SDavid du Colombier+ 	}
7552*14414594SDavid du Colombier+ 	return (ilpcb);
7553*14414594SDavid du Colombier+ }
7554*14414594SDavid du Colombier+
7555*14414594SDavid du Colombier+ /*
7556*14414594SDavid du Colombier+  * Drop a TCP connection, reporting
7557*14414594SDavid du Colombier+  * the specified error.  If connection is synchronized,
7558*14414594SDavid du Colombier+  * then send a RST to peer.
7559*14414594SDavid du Colombier+  */
7560*14414594SDavid du Colombier+ struct ilpcb *
7561*14414594SDavid du Colombier+ il_drop(ilpcb, errno0)
7562*14414594SDavid du Colombier+      register struct ilpcb *ilpcb;
7563*14414594SDavid du Colombier+      int errno0;
7564*14414594SDavid du Colombier+ {
7565*14414594SDavid du Colombier+   struct socket *so = ilpcb->inpcb->inp_socket;
7566*14414594SDavid du Colombier+
7567*14414594SDavid du Colombier+   panic("il_drop");
7568*14414594SDavid du Colombier+
7569*14414594SDavid du Colombier+   switch(ilpcb->state) {
7570*14414594SDavid du Colombier+   case ILS_SYNCEE:
7571*14414594SDavid du Colombier+   case ILS_ESTABLISHED:
7572*14414594SDavid du Colombier+   case ILS_CLOSING:
7573*14414594SDavid du Colombier+     il_send_empty(ilpcb, ILT_CLOSE, 0);
7574*14414594SDavid du Colombier+   default:
7575*14414594SDavid du Colombier+     break;
7576*14414594SDavid du Colombier+   }
7577*14414594SDavid du Colombier+   ilpcb->state = ILS_CLOSED;
7578*14414594SDavid du Colombier+   so->so_error = errno0;
7579*14414594SDavid du Colombier+   return (il_close(ilpcb));
7580*14414594SDavid du Colombier+ }
7581*14414594SDavid du Colombier+
7582*14414594SDavid du Colombier+ /*
7583*14414594SDavid du Colombier+  * Initiate (or continue) disconnect.
7584*14414594SDavid du Colombier+  * If embryonic state, just send reset (once).
7585*14414594SDavid du Colombier+  * If in ``let data drain'' option and linger null, just drop.
7586*14414594SDavid du Colombier+  * Otherwise (hard), mark socket disconnecting and drop
7587*14414594SDavid du Colombier+  * current input data; switch states based on user close, and
7588*14414594SDavid du Colombier+  * send segment to peer (with FIN).
7589*14414594SDavid du Colombier+  */
7590*14414594SDavid du Colombier+ static struct ilpcb *
7591*14414594SDavid du Colombier+ il_disconnect(struct ilpcb *ilpcb)
7592*14414594SDavid du Colombier+ {
7593*14414594SDavid du Colombier+   struct socket *so = ilpcb->inpcb->inp_socket;
7594*14414594SDavid du Colombier+
7595*14414594SDavid du Colombier+   soisdisconnecting(so);
7596*14414594SDavid du Colombier+   sbflush(&so->so_rcv);
7597*14414594SDavid du Colombier+   ilpcb = il_usrclosed(ilpcb);
7598*14414594SDavid du Colombier+
7599*14414594SDavid du Colombier+   return (ilpcb);
7600*14414594SDavid du Colombier+ }
7601*14414594SDavid du Colombier+
7602*14414594SDavid du Colombier+
7603*14414594SDavid du Colombier+ /*
7604*14414594SDavid du Colombier+  * pru_detach() detaches the IL protocol from the socket.
7605*14414594SDavid du Colombier+  * If the protocol state is non-embryonic, then can't
7606*14414594SDavid du Colombier+  * do this directly: have to initiate a pru_disconnect(),
7607*14414594SDavid du Colombier+  * which may finish later; embryonic TCB's can just
7608*14414594SDavid du Colombier+  * be discarded here.
7609*14414594SDavid du Colombier+  */
7610*14414594SDavid du Colombier+ static int
7611*14414594SDavid du Colombier+ il_usr_detach(struct socket *so)
7612*14414594SDavid du Colombier+ {
7613*14414594SDavid du Colombier+ 	int s = splnet();
7614*14414594SDavid du Colombier+ 	int error = 0;
7615*14414594SDavid du Colombier+ 	struct inpcb *inp = sotoinpcb(so);
7616*14414594SDavid du Colombier+ 	struct ilpcb *ilpcb;
7617*14414594SDavid du Colombier+
7618*14414594SDavid du Colombier+ 	if (inp == 0) {
7619*14414594SDavid du Colombier+ 		splx(s);
7620*14414594SDavid du Colombier+ 		return EINVAL;	/* XXX */
7621*14414594SDavid du Colombier+ 	}
7622*14414594SDavid du Colombier+ 	ilpcb = intoilpcb(inp);
7623*14414594SDavid du Colombier+ 	ilpcb = il_disconnect(ilpcb);
7624*14414594SDavid du Colombier+ 	splx(s);
7625*14414594SDavid du Colombier+ 	return error;
7626*14414594SDavid du Colombier+ }
7627*14414594SDavid du Colombier+
7628*14414594SDavid du Colombier+ /*
7629*14414594SDavid du Colombier+  * Mark the connection as being incapable of further output.
7630*14414594SDavid du Colombier+  */
7631*14414594SDavid du Colombier+ static int
7632*14414594SDavid du Colombier+ il_usr_shutdown(struct socket *so)
7633*14414594SDavid du Colombier+ {
7634*14414594SDavid du Colombier+ 	int s = splnet();
7635*14414594SDavid du Colombier+ 	int error = 0;
7636*14414594SDavid du Colombier+ 	struct inpcb *inp = sotoinpcb(so);
7637*14414594SDavid du Colombier+ 	struct ilpcb *ilpcb;
7638*14414594SDavid du Colombier+
7639*14414594SDavid du Colombier+   if (inp == 0) {
7640*14414594SDavid du Colombier+     splx(s);
7641*14414594SDavid du Colombier+     return EINVAL;
7642*14414594SDavid du Colombier+   }
7643*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7644*14414594SDavid du Colombier+
7645*14414594SDavid du Colombier+   socantsendmore(so);
7646*14414594SDavid du Colombier+   ilpcb = il_usrclosed(ilpcb);
7647*14414594SDavid du Colombier+   splx(s);
7648*14414594SDavid du Colombier+   return error;
7649*14414594SDavid du Colombier+ }
7650*14414594SDavid du Colombier+
7651*14414594SDavid du Colombier+ /*
7652*14414594SDavid du Colombier+  * Initiate disconnect from peer.
7653*14414594SDavid du Colombier+  * If connection never passed embryonic stage, just drop;
7654*14414594SDavid du Colombier+  * else if don't need to let data drain, then can just drop anyways,
7655*14414594SDavid du Colombier+  * else have to begin TCP shutdown process: mark socket disconnecting,
7656*14414594SDavid du Colombier+  * drain unread data, state switch to reflect user close, and
7657*14414594SDavid du Colombier+  * send segment (e.g. FIN) to peer.  Socket will be really disconnected
7658*14414594SDavid du Colombier+  * when peer sends FIN and acks ours.
7659*14414594SDavid du Colombier+  *
7660*14414594SDavid du Colombier+  * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
7661*14414594SDavid du Colombier+  */
7662*14414594SDavid du Colombier+ static int
7663*14414594SDavid du Colombier+ il_usr_disconnect(struct socket *so)
7664*14414594SDavid du Colombier+ {
7665*14414594SDavid du Colombier+   int s = splnet();
7666*14414594SDavid du Colombier+   int error = 0;
7667*14414594SDavid du Colombier+   struct inpcb *inp = sotoinpcb(so);
7668*14414594SDavid du Colombier+   struct ilpcb * ilpcb;
7669*14414594SDavid du Colombier+
7670*14414594SDavid du Colombier+   if (inp == 0) {
7671*14414594SDavid du Colombier+     splx(s);
7672*14414594SDavid du Colombier+     return EINVAL;
7673*14414594SDavid du Colombier+   }
7674*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7675*14414594SDavid du Colombier+
7676*14414594SDavid du Colombier+   il_disconnect(ilpcb);
7677*14414594SDavid du Colombier+   splx(s);
7678*14414594SDavid du Colombier+   return error;
7679*14414594SDavid du Colombier+ }
7680*14414594SDavid du Colombier+
7681*14414594SDavid du Colombier+ /*
7682*14414594SDavid du Colombier+  * Abort the TCP.
7683*14414594SDavid du Colombier+  */
7684*14414594SDavid du Colombier+ static int
7685*14414594SDavid du Colombier+ il_usr_abort(struct socket *so)
7686*14414594SDavid du Colombier+ {
7687*14414594SDavid du Colombier+ 	int s = splnet();
7688*14414594SDavid du Colombier+ 	int error = 0;
7689*14414594SDavid du Colombier+ 	struct inpcb *inp = sotoinpcb(so);
7690*14414594SDavid du Colombier+ 	struct ilpcb * ilpcb;
7691*14414594SDavid du Colombier+
7692*14414594SDavid du Colombier+   if (inp == 0) {
7693*14414594SDavid du Colombier+     splx(s);
7694*14414594SDavid du Colombier+     return EINVAL;
7695*14414594SDavid du Colombier+   }
7696*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7697*14414594SDavid du Colombier+
7698*14414594SDavid du Colombier+   ilpcb = il_drop(ilpcb, ECONNABORTED);
7699*14414594SDavid du Colombier+   splx(s);
7700*14414594SDavid du Colombier+   return error;
7701*14414594SDavid du Colombier+
7702*14414594SDavid du Colombier+ }
7703*14414594SDavid du Colombier+
7704*14414594SDavid du Colombier+ /*
7705*14414594SDavid du Colombier+  * Prepare to accept connections.
7706*14414594SDavid du Colombier+  */
7707*14414594SDavid du Colombier+ static int
7708*14414594SDavid du Colombier+ il_usr_listen(struct socket *so, struct proc *p)
7709*14414594SDavid du Colombier+ {
7710*14414594SDavid du Colombier+   int s = splnet();
7711*14414594SDavid du Colombier+   int error = 0;
7712*14414594SDavid du Colombier+   struct inpcb *inp = sotoinpcb(so);
7713*14414594SDavid du Colombier+   struct ilpcb *ilpcb;
7714*14414594SDavid du Colombier+
7715*14414594SDavid du Colombier+   if (inp == 0) {
7716*14414594SDavid du Colombier+     splx(s);
7717*14414594SDavid du Colombier+     return EINVAL;
7718*14414594SDavid du Colombier+   }
7719*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7720*14414594SDavid du Colombier+
7721*14414594SDavid du Colombier+   if (inp->inp_lport == 0)
7722*14414594SDavid du Colombier+     error = in_pcbbind(inp, (struct sockaddr *)0, p);
7723*14414594SDavid du Colombier+   if (error == 0)
7724*14414594SDavid du Colombier+     ilpcb->state = ILS_LISTENING;
7725*14414594SDavid du Colombier+
7726*14414594SDavid du Colombier+   splx(s);
7727*14414594SDavid du Colombier+   return error;
7728*14414594SDavid du Colombier+ }
7729*14414594SDavid du Colombier+
7730*14414594SDavid du Colombier+ /*
7731*14414594SDavid du Colombier+  * Accept a connection.  Essentially all the work is
7732*14414594SDavid du Colombier+  * done at higher levels; just return the address
7733*14414594SDavid du Colombier+  * of the peer, storing through addr.
7734*14414594SDavid du Colombier+  */
7735*14414594SDavid du Colombier+ static int
7736*14414594SDavid du Colombier+ il_usr_accept(struct socket *so, struct sockaddr **nam)
7737*14414594SDavid du Colombier+ {
7738*14414594SDavid du Colombier+   int s = splnet();
7739*14414594SDavid du Colombier+   int error = 0;
7740*14414594SDavid du Colombier+   struct inpcb *inp = sotoinpcb(so);
7741*14414594SDavid du Colombier+   struct ilpcb * ilpcb;
7742*14414594SDavid du Colombier+
7743*14414594SDavid du Colombier+   if (inp == 0) {
7744*14414594SDavid du Colombier+     splx(s);
7745*14414594SDavid du Colombier+     return EINVAL;
7746*14414594SDavid du Colombier+   }
7747*14414594SDavid du Colombier+   ilpcb = intoilpcb(inp);
7748*14414594SDavid du Colombier+
7749*14414594SDavid du Colombier+   in_setpeeraddr(so, nam);
7750*14414594SDavid du Colombier+   splx(s);
7751*14414594SDavid du Colombier+   return error;
7752*14414594SDavid du Colombier+ }
7753*14414594SDavid du Colombier+
7754*14414594SDavid du Colombier+ /* xxx - should be const */
7755*14414594SDavid du Colombier+ struct pr_usrreqs il_usrreqs = {
7756*14414594SDavid du Colombier+ 	il_usr_abort, il_usr_accept, il_usr_attach, il_usr_bind,
7757*14414594SDavid du Colombier+ 	il_usr_connect, pru_connect2_notsupp, in_control, il_usr_detach,
7758*14414594SDavid du Colombier+ 	il_usr_disconnect, il_usr_listen, in_setpeeraddr, pru_rcvd_notsupp,
7759*14414594SDavid du Colombier+ 	pru_rcvoob_notsupp, il_usr_send, pru_sense_null, il_usr_shutdown,
7760*14414594SDavid du Colombier+ 	in_setsockaddr, sosend, soreceive, sopoll
7761*14414594SDavid du Colombier+ };
7762*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/il.h ./netinet/il.h
7763*14414594SDavid du Colombier*** /usr/src/sys/netinet/il.h	Wed Dec 31 19:00:00 1969
7764*14414594SDavid du Colombier--- ./netinet/il.h	Thu Sep 30 11:24:51 1999
7765*14414594SDavid du Colombier***************
7766*14414594SDavid du Colombier*** 0 ****
7767*14414594SDavid du Colombier--- 1,17 ----
7768*14414594SDavid du Colombier+
7769*14414594SDavid du Colombier+ #ifndef NETINET_IL_H_
7770*14414594SDavid du Colombier+ #define NETINET_IL_H_
7771*14414594SDavid du Colombier+
7772*14414594SDavid du Colombier+ struct ilhdr
7773*14414594SDavid du Colombier+ {
7774*14414594SDavid du Colombier+ 	u_char	ilsum[2];	/* Checksum including header */
7775*14414594SDavid du Colombier+ 	u_char	illen[2];	/* Packet length */
7776*14414594SDavid du Colombier+ 	u_char	iltype;		/* Packet type */
7777*14414594SDavid du Colombier+ 	u_char	ilspec;		/* Special */
7778*14414594SDavid du Colombier+ 	u_char	ilsrc[2];	/* Src port */
7779*14414594SDavid du Colombier+ 	u_char	ildst[2];	/* Dst port */
7780*14414594SDavid du Colombier+ 	u_char	ilid[4];	/* Sequence id */
7781*14414594SDavid du Colombier+ 	u_char	ilack[4];	/* Acked sequence */
7782*14414594SDavid du Colombier+ };
7783*14414594SDavid du Colombier+
7784*14414594SDavid du Colombier+ #endif
7785*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/il_var.h ./netinet/il_var.h
7786*14414594SDavid du Colombier*** /usr/src/sys/netinet/il_var.h	Wed Dec 31 19:00:00 1969
7787*14414594SDavid du Colombier--- ./netinet/il_var.h	Thu Oct  7 10:45:05 1999
7788*14414594SDavid du Colombier***************
7789*14414594SDavid du Colombier*** 0 ****
7790*14414594SDavid du Colombier--- 1,46 ----
7791*14414594SDavid du Colombier+ #ifndef NETINET_IL_VAR_H_
7792*14414594SDavid du Colombier+ #define NETINET_IL_VAR_H_
7793*14414594SDavid du Colombier+
7794*14414594SDavid du Colombier+ struct ilpcb			/* Control block */
7795*14414594SDavid du Colombier+ {
7796*14414594SDavid du Colombier+   int	state;		/* Connection state */
7797*14414594SDavid du Colombier+   struct inpcb * inpcb;  /* back pointer to internet pcb */
7798*14414594SDavid du Colombier+   u_long unacked;
7799*14414594SDavid du Colombier+
7800*14414594SDavid du Colombier+ #define ILF_NEEDACK 1
7801*14414594SDavid du Colombier+   u_long flags;
7802*14414594SDavid du Colombier+
7803*14414594SDavid du Colombier+   u_long rxt_max;
7804*14414594SDavid du Colombier+   int rxt_timer;  /* number of ticks to the next timeout */
7805*14414594SDavid du Colombier+   int rxt_timer_cur;  /* current rxt timer period */
7806*14414594SDavid du Colombier+
7807*14414594SDavid du Colombier+   int death_timer;
7808*14414594SDavid du Colombier+   int death_timer_cur;
7809*14414594SDavid du Colombier+
7810*14414594SDavid du Colombier+   u_long	next;		/* Id of next to send */
7811*14414594SDavid du Colombier+   u_long	recvd;		/* Last packet received */
7812*14414594SDavid du Colombier+
7813*14414594SDavid du Colombier+   u_long	start;		/* Local start id */
7814*14414594SDavid du Colombier+   u_long	rstart;		/* Remote start id */
7815*14414594SDavid du Colombier+   int	rxtot;		/* number of retransmits on this connection */
7816*14414594SDavid du Colombier+
7817*14414594SDavid du Colombier+   struct mbuf * segq;
7818*14414594SDavid du Colombier+ };
7819*14414594SDavid du Colombier+
7820*14414594SDavid du Colombier+ #define	intoilpcb(ip)	((struct ilpcb *)(ip)->inp_ppcb)
7821*14414594SDavid du Colombier+ #define	sotoilpcb(so)	(intoilpcb(sotoinpcb(so)))
7822*14414594SDavid du Colombier+
7823*14414594SDavid du Colombier+ #ifdef KERNEL
7824*14414594SDavid du Colombier+ void il_init __P((void));
7825*14414594SDavid du Colombier+ void il_input __P((struct mbuf * m, int iphlen));
7826*14414594SDavid du Colombier+ void il_slowtimo __P((void));
7827*14414594SDavid du Colombier+ void il_fasttimo __P((void));
7828*14414594SDavid du Colombier+ void il_ctlinput __P((int cmd, struct sockaddr *sa, void *vip));
7829*14414594SDavid du Colombier+ int  il_ctloutput __P((struct socket *so, struct sockopt *sopt));
7830*14414594SDavid du Colombier+ void il_drain __P((void));
7831*14414594SDavid du Colombier+
7832*14414594SDavid du Colombier+ extern struct pr_usrreqs il_usrreqs;
7833*14414594SDavid du Colombier+
7834*14414594SDavid du Colombier+ #endif
7835*14414594SDavid du Colombier+
7836*14414594SDavid du Colombier+ #endif
7837*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/in_proto.c ./netinet/in_proto.c
7838*14414594SDavid du Colombier*** /usr/src/sys/netinet/in_proto.c	Sat Aug 22 23:07:14 1998
7839*14414594SDavid du Colombier--- ./netinet/in_proto.c	Wed Oct  6 17:55:12 1999
7840*14414594SDavid du Colombier***************
7841*14414594SDavid du Colombier*** 36,41 ****
7842*14414594SDavid du Colombier--- 36,42 ----
7843*14414594SDavid du Colombier
7844*14414594SDavid du Colombier  #include "opt_ipdivert.h"
7845*14414594SDavid du Colombier  #include "opt_ipx.h"
7846*14414594SDavid du Colombier+ #include "opt_inet.h"
7847*14414594SDavid du Colombier
7848*14414594SDavid du Colombier  #include <sys/param.h>
7849*14414594SDavid du Colombier  #include <sys/kernel.h>
7850*14414594SDavid du Colombier***************
7851*14414594SDavid du Colombier*** 71,76 ****
7852*14414594SDavid du Colombier--- 72,82 ----
7853*14414594SDavid du Colombier  #include <netns/ns_if.h>
7854*14414594SDavid du Colombier  #endif
7855*14414594SDavid du Colombier
7856*14414594SDavid du Colombier+ #ifdef IL
7857*14414594SDavid du Colombier+ #include <netinet/il.h>
7858*14414594SDavid du Colombier+ #include <netinet/il_var.h>
7859*14414594SDavid du Colombier+ #endif
7860*14414594SDavid du Colombier+
7861*14414594SDavid du Colombier  extern	struct domain inetdomain;
7862*14414594SDavid du Colombier  static	struct pr_usrreqs nousrreqs;
7863*14414594SDavid du Colombier
7864*14414594SDavid du Colombier***************
7865*14414594SDavid du Colombier*** 161,166 ****
7866*14414594SDavid du Colombier--- 167,181 ----
7867*14414594SDavid du Colombier    0,
7868*14414594SDavid du Colombier    0,		0,		0,		0,
7869*14414594SDavid du Colombier    &rip_usrreqs
7870*14414594SDavid du Colombier+ },
7871*14414594SDavid du Colombier+ #endif
7872*14414594SDavid du Colombier+ #ifdef IL
7873*14414594SDavid du Colombier+ { SOCK_SEQPACKET,	&inetdomain,	IPPROTO_IL,
7874*14414594SDavid du Colombier+ 	PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD|PR_ATOMIC,
7875*14414594SDavid du Colombier+   il_input,	0,		il_ctlinput,	il_ctloutput,
7876*14414594SDavid du Colombier+   0,
7877*14414594SDavid du Colombier+   il_init,	il_fasttimo,	il_slowtimo,	il_drain,
7878*14414594SDavid du Colombier+   &il_usrreqs
7879*14414594SDavid du Colombier  },
7880*14414594SDavid du Colombier  #endif
7881*14414594SDavid du Colombier  	/* raw wildcard */
7882*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/sys/vnode.h ./sys/vnode.h
7883*14414594SDavid du Colombier*** /usr/src/sys/sys/vnode.h	Sat Mar 20 04:37:49 1999
7884*14414594SDavid du Colombier--- ./sys/vnode.h	Fri Oct 15 17:44:42 1999
7885*14414594SDavid du Colombier***************
7886*14414594SDavid du Colombier*** 62,68 ****
7887*14414594SDavid du Colombier  enum vtagtype	{
7888*14414594SDavid du Colombier  	VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PC, VT_LFS, VT_LOFS, VT_FDESC,
7889*14414594SDavid du Colombier  	VT_PORTAL, VT_NULL, VT_UMAP, VT_KERNFS, VT_PROCFS, VT_AFS, VT_ISOFS,
7890*14414594SDavid du Colombier! 	VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS, VT_VFS, VT_CODA, VT_NTFS
7891*14414594SDavid du Colombier  };
7892*14414594SDavid du Colombier
7893*14414594SDavid du Colombier  /*
7894*14414594SDavid du Colombier--- 62,68 ----
7895*14414594SDavid du Colombier  enum vtagtype	{
7896*14414594SDavid du Colombier  	VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PC, VT_LFS, VT_LOFS, VT_FDESC,
7897*14414594SDavid du Colombier  	VT_PORTAL, VT_NULL, VT_UMAP, VT_KERNFS, VT_PROCFS, VT_AFS, VT_ISOFS,
7898*14414594SDavid du Colombier! 	VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS, VT_VFS, VT_CODA, VT_NTFS, VT_U9FS
7899*14414594SDavid du Colombier  };
7900*14414594SDavid du Colombier
7901*14414594SDavid du Colombier  /*
7902