Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
68 7u83 1
diff -N -c -r /usr/src/sys/9fs/9auth.c ./9fs/9auth.c
2
*** /usr/src/sys/9fs/9auth.c	Wed Dec 31 19:00:00 1969
3
--- ./9fs/9auth.c	Mon May 22 17:11:29 2000
4
***************
5
*** 0 ****
6
--- 1,238 ----
7
+ #include <sys/param.h>
8
+ #include <sys/systm.h>
9
+ #include <sys/socket.h>
10
+ #include <sys/socketvar.h>
11
+ #include <sys/protosw.h>
12
+ #include <sys/malloc.h>
13
+ #include <sys/mbuf.h>
14
+ #include <sys/uio.h>
15
+ 
16
+ #include <9fs/9p.h>
17
+ #include <9fs/9auth.h>
18
+ 
19
+ #define	N2HCHAR(x)		x = *p++
20
+ #define	N2HSHORT(x)	x = (p[0] | (p[1]<<8)); p += 2
21
+ #define	N2HLONG(x)		x = (p[0] | (p[1]<<8) |\
22
+ 				(p[2]<<16) | (p[3]<<24)); p += 4
23
+ #define	N2HQUAD(x)	x = (u_int64_t)(p[0] | (p[1]<<8) |\
24
+ 					(p[2]<<16) | (p[3]<<24)) |\
25
+ 				((u_int64_t)(p[4] | (p[5]<<8) |\
26
+ 					(p[6]<<16) | (p[7]<<24)) << 32); p += 8
27
+ #define	N2HSTRING(x,n)	bcopy(p, x, n); p += n
28
+ 
29
+ #define	H2NCHAR(x)	*p++ = x
30
+ #define	H2NSHORT(x)	p[0]=x; p[1]=x>>8; p += 2
31
+ #define	H2NLONG(x)		p[0]=x; p[1]=x>>8; p[2]=x>>16; p[3]=x>>24; p += 4
32
+ #define	H2NQUAD(x)	p[0]=x;	p[1]=x>>8;\
33
+ 			p[2]=x>>16;	p[3]=x>>24;\
34
+ 			p[4]=x>>32;	p[5]=x>>40;\
35
+ 			p[6]=x>>48;	p[7]=x>>56;\
36
+ 			p += 8
37
+ #define	H2NSTRING(x,n)	bcopy(x, p, n); p += n
38
+ 
39
+ static int u9auth_send __P((struct socket *so, struct mbuf *top, struct proc *p));
40
+ static int u9auth_recv __P((struct socket *so, struct mbuf **mp, struct proc *p));
41
+ 
42
+ static int u9auth_count = 0;
43
+ 
44
+ static int u9auth_tr2m(struct u9auth_ticketreq *f, char *ap)
45
+ {
46
+ 	int n;
47
+ 	u_char *p;
48
+ 
49
+ 	p = (u_char*)ap;
50
+         H2NCHAR(f->type);
51
+ 	H2NSTRING(f->authid, U9FS_NAMELEN);
52
+ 	H2NSTRING(f->authdom, U9FS_DOMLEN);
53
+ 	H2NSTRING(f->chal, U9FS_CHALLEN);
54
+ 	H2NSTRING(f->hostid, U9FS_NAMELEN);
55
+ 	H2NSTRING(f->uid, U9FS_NAMELEN);
56
+ 	n = p - (u_char*)ap;
57
+ 	return n;
58
+ }
59
+ 
60
+ static struct mbuf * u9auth_m_tr2m(struct u9auth_ticketreq * tktq)
61
+ {
62
+   register struct mbuf *m;
63
+   char * ap;
64
+   int sz = 141;
65
+ 
66
+   MGETHDR(m, M_WAIT, MT_DATA);
67
+   if( sz > MHLEN )
68
+     MCLGET(m, M_WAIT);
69
+   m->m_len = 0;
70
+ 
71
+   if ( M_TRAILINGSPACE(m) < sz )
72
+     panic("u9auth_m_tr2m");
73
+   
74
+   ap = mtod(m, char *);
75
+   m->m_len = u9auth_tr2m(tktq, ap);
76
+   m->m_pkthdr.len = m->m_len;
77
+ 
78
+   return (m);
79
+ }
80
+ 
81
+ static int
82
+ u9auth_send(so, top, p)
83
+ 	register struct socket *so;
84
+ 	register struct mbuf *top;
85
+ 	register struct proc *p;
86
+ 	
87
+ {
88
+   int error, soflags, flags;
89
+   
90
+   soflags = so->so_proto->pr_flags;
91
+   if (so->so_type == SOCK_SEQPACKET)
92
+     flags = MSG_EOR;
93
+   else
94
+     flags = 0;
95
+   
96
+   error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 0, top, 0, flags, p);
97
+ 
98
+   return (error);
99
+ }
100
+ 
101
+ static int
102
+ u9auth_recv(so, mp, p)	
103
+      register struct socket * so;
104
+      register struct mbuf **mp;
105
+      struct proc *p;
106
+ {
107
+   struct uio auio;
108
+   u_int32_t len;
109
+   int error = 0, sotype, rcvflg;
110
+ 
111
+   *mp = 0;
112
+   sotype = so->so_type;
113
+   
114
+   /*
115
+    * For reliable protocols, lock against other senders/receivers
116
+    * in case a reconnect is necessary.
117
+    * For SOCK_STREAM, first get the Record Mark to find out how much
118
+    * more there is to get.
119
+    * We must lock the socket against other receivers
120
+    * until we have an entire rpc request/reply.
121
+    */
122
+   if (sotype == SOCK_SEQPACKET ) {
123
+     if( (so->so_state & SS_ISCONNECTED) == 0 )
124
+       return (EACCES);
125
+ 		auio.uio_resid = len = 1000000;
126
+ 		auio.uio_procp = p;
127
+ 		do {
128
+ 			rcvflg = 0;
129
+ 			error =  so->so_proto->pr_usrreqs->pru_soreceive
130
+ 				(so, 0, &auio, mp,
131
+ 				(struct mbuf **)0, &rcvflg);
132
+ 		} while (error == EWOULDBLOCK);
133
+ 		len -= auio.uio_resid;    
134
+   }
135
+   if (error) {
136
+     m_freem(*mp);
137
+     *mp = 0;
138
+   }
139
+   return (error);  
140
+ }
141
+ 
142
+ static void
143
+ u9auth_m2t(char *ap, struct u9auth_ticket *f, char *key)
144
+ {
145
+ 	u_char *p;
146
+ 
147
+ 	if(key)
148
+ 		decrypt9(key, ap, U9AUTH_TICKETLEN);
149
+ 	p = (u_char*)ap;
150
+ 	N2HCHAR(f->num);
151
+ 	N2HSTRING(f->chal, U9FS_CHALLEN);
152
+ 	N2HSTRING(f->cuid, U9FS_NAMELEN);
153
+ 	f->cuid[U9FS_NAMELEN-1] = 0;
154
+ 	N2HSTRING(f->suid, U9FS_NAMELEN);
155
+ 	f->suid[U9FS_NAMELEN-1] = 0;
156
+ 	N2HSTRING(f->key, U9AUTH_DESKEYLEN);
157
+ };
158
+ 
159
+ static int 
160
+ u9auth_a2m(struct u9auth_authenticator *f, char *ap, char *key)
161
+ {
162
+ 	int n;
163
+ 	u_char *p;
164
+ 
165
+ 	p = (u_char*)ap;
166
+ 	H2NCHAR(f->num);
167
+ 	H2NSTRING(f->chal, U9FS_CHALLEN);
168
+ 	H2NLONG(f->id);
169
+ 	n = p - (u_char*)ap;
170
+ 	if(key)
171
+ 		encrypt9(key, ap, n);
172
+ 	return n;
173
+ }
174
+ 
175
+ void u9auth_genchal (char * chal)
176
+ {
177
+   u_long * lp = (u_long *)chal;
178
+ 
179
+   *lp++ = random();
180
+   *lp = random();
181
+ }
182
+ 
183
+ int u9auth_gettickets (struct socket * so, struct u9fsreq * rep,
184
+ 			   char * user, char * ckey, char * ts, char * authc,
185
+ 		       struct proc *p)
186
+ {
187
+   char * cp;
188
+   struct u9auth_ticketreq tktq;
189
+   struct u9auth_ticket tc;
190
+   struct u9auth_authenticator auth;
191
+   struct mbuf * m;
192
+   int error, len;
193
+   
194
+   bzero(&tktq, sizeof(tktq));
195
+   tktq.type = AuthTreq;
196
+   bcopy(rep->r_authid, tktq.authid, U9FS_NAMELEN);
197
+   bcopy(rep->r_authdom, tktq.authdom, U9FS_DOMLEN);
198
+   bcopy(rep->r_chal, tktq.chal, U9FS_CHALLEN);
199
+   strncpy(tktq.hostid, user, U9FS_NAMELEN);
200
+   strncpy(tktq.uid, user, U9FS_NAMELEN);
201
+ 
202
+   m = u9auth_m_tr2m(&tktq);
203
+   error = u9auth_send(so, m, p);
204
+   if( error ) 
205
+     goto bad;
206
+   error = u9auth_recv(so, &m, p);
207
+   if( error )
208
+     goto bad;
209
+ 
210
+   len = U9AUTH_TICKETLEN+1;
211
+   if( m->m_len < len && (m = m_pullup(m, len)) == 0 )
212
+     goto bad;
213
+ 
214
+   cp = mtod(m, char *);
215
+   switch( cp[0] ) {
216
+   case AuthOK:
217
+     u9auth_m2t(&cp[1], & tc, ckey);
218
+     bzero(&auth, sizeof(auth));
219
+     auth.num = AuthAc;
220
+     bcopy(tc.chal, auth.chal, sizeof(auth.chal));
221
+     auth.id = u9auth_count++;
222
+ 
223
+     m->m_len -= len;
224
+     m->m_data += len;
225
+ 
226
+     len = U9AUTH_TICKETLEN;
227
+     if( m->m_len < len && (m = m_pullup(m, len)) == 0 )
228
+       goto bad;
229
+     cp = mtod(m, char *);
230
+     bcopy(cp, ts, len);
231
+     break;
232
+   case AuthErr:
233
+   case AuthOKvar:
234
+     m_freem(m);
235
+     goto bad;
236
+     break;
237
+   }
238
+ 
239
+   u9auth_a2m(&auth, authc, tc.key);
240
+   return 0;
241
+  bad:
242
+   return error;
243
+ }
244
+ 
245
diff -N -c -r /usr/src/sys/9fs/9auth.h ./9fs/9auth.h
246
*** /usr/src/sys/9fs/9auth.h	Wed Dec 31 19:00:00 1969
247
--- ./9fs/9auth.h	Thu Nov 11 15:00:29 1999
248
***************
249
*** 0 ****
250
--- 1,129 ----
251
+ #ifndef P9AUTH_H
252
+ #define P9AUTH_H
253
+ 
254
+ #define U9AUTH_DOMLEN		48		/* length of an authentication domain name */
255
+ #define U9AUTH_DESKEYLEN	7		/* length of a des key for encrypt/decrypt */
256
+ #define U9AUTH_CHALLEN	8		/* length of a challenge */
257
+ #define U9AUTH_NETCHLEN	16		/* max network challenge length	*/
258
+ #define U9AUTH_CONFIGLEN	14
259
+ #define U9AUTH_SECRETLEN	32		/* max length of a secret */
260
+ #define U9AUTH_APOPCHLEN	256
261
+ #define U9AUTH_MD5LEN		16
262
+ #define U9AUTH_KEYDBOFF	8		/* length of random data at the start of key file */
263
+ #define U9AUTH_OKEYDBLEN	U9FSNAMELEN+U9AUTH_DESKEYLEN+4+2,	/* length of an entry in old key file */
264
+ #define U9AUTH_KEYDBLEN	OKEYDBLENSECRETLEN,	/* length of an entry in key file */
265
+ 
266
+ /* encryption numberings (anti-replay) */
267
+ enum
268
+ {
269
+ 	AuthTreq=1,	/* ticket request */
270
+ 	AuthChal=2,	/* challenge box request */
271
+ 	AuthPass=3,	/* change password */
272
+ 	AuthOK=4,	/* fixed length reply follows */
273
+ 	AuthErr=5,	/* error follows */
274
+ 	AuthMod=6,	/* modify user */
275
+ 	AuthApop=7,	/* apop authentication for pop3 */
276
+ 	AuthOKvar=9,	/* variable length reply follows */
277
+ 	AuthChap=10,	/* chap authentication for ppp */
278
+ 	AuthMSchap=11,	/* MS chap authentication for ppp */
279
+ 
280
+ 
281
+ 	AuthTs=64,	/* ticket encrypted with server's key */
282
+ 	AuthTc,		/* ticket encrypted with client's key */
283
+ 	AuthAs,		/* server generated authenticator */
284
+ 	AuthAc,		/* client generated authenticator */
285
+ 	AuthTp,		/* ticket encrypted with clien's key for password change */
286
+ };
287
+ 
288
+ struct u9auth_ticketreq
289
+ {
290
+ 	char	type;
291
+ 	char	authid[U9FS_NAMELEN];	/* server's encryption id */
292
+ 	char	authdom[U9AUTH_DOMLEN];	/* server's authentication domain */
293
+ 	char	chal[U9AUTH_CHALLEN];		/* challenge from server */
294
+ 	char	hostid[U9FS_NAMELEN];	/* host's encryption id */
295
+ 	char	uid[U9FS_NAMELEN];		/* uid of requesting user on host */
296
+ };
297
+ #define	U9AUTH_TICKREQLEN	(3*U9FS_NAMELEN+U9AUTH_CHALLEN+U9AUTH_DOMLEN+1)
298
+ 
299
+ struct u9auth_ticket
300
+ {
301
+ 	char	num;			/* replay protection */
302
+ 	char	chal[U9AUTH_CHALLEN];		/* server challenge */
303
+ 	char	cuid[U9FS_NAMELEN];		/* uid on client */
304
+ 	char	suid[U9FS_NAMELEN];		/* uid on server */
305
+ 	char	key[U9AUTH_DESKEYLEN];		/* nonce DES key */
306
+ };
307
+ #define	U9AUTH_TICKETLEN	(U9AUTH_CHALLEN+2*U9FS_NAMELEN+U9AUTH_DESKEYLEN+1)
308
+ 
309
+ struct u9auth_authenticator
310
+ {
311
+ 	char	num;			/* replay protection */
312
+ 	char	chal[U9AUTH_CHALLEN];
313
+ 	u_long	id;			/* authenticator id, ++'d with each auth */
314
+ };
315
+ #define	U9AUTH_AUTHENTLEN	(U9AUTH_CHALLEN+4+1)
316
+ 
317
+ struct u9auth_passwordreq
318
+ {
319
+ 	char	num;
320
+ 	char	old[U9FS_NAMELEN];
321
+ 	char	new[U9FS_NAMELEN];
322
+ 	char	changesecret;
323
+ 	char	secret[U9AUTH_SECRETLEN];	/* new secret */
324
+ };
325
+ #define	U9AUTH_PASSREQLEN	(2*U9FS_NAMELEN+1+1+U9AUTH_SECRETLEN)
326
+ 
327
+ struct u9auth_nvrsafe
328
+ {
329
+ 	char	machkey[U9AUTH_DESKEYLEN];
330
+ 	u_char	machsum;
331
+ 	char	authkey[U9AUTH_DESKEYLEN];
332
+ 	u_char	authsum;
333
+ 	char	config[U9AUTH_CONFIGLEN];
334
+ 	u_char	configsum;
335
+ 	char	authid[U9FS_NAMELEN];
336
+ 	u_char	authidsum;
337
+ 	char	authdom[U9AUTH_DOMLEN];
338
+ 	u_char	authdomsum;
339
+ };
340
+ 
341
+ struct u9auth_chalstate
342
+ {
343
+ 	int	afd;			/* /dev/authenticate */
344
+ 	int	asfd;			/* authdial() */
345
+ 	char	chal[U9AUTH_NETCHLEN];		/* challenge/response */
346
+ };
347
+ 
348
+ struct u9auth_apopchalstate
349
+ {
350
+ 	int	afd;			/* /dev/authenticate */
351
+ 	int	asfd;			/* authdial() */
352
+ 	char	chal[U9AUTH_APOPCHLEN];	/* challenge/response */
353
+ };
354
+ 
355
+ struct	u9auth_chapreply
356
+ {
357
+ 	u_char	id;
358
+ 	char	uid[U9FS_NAMELEN];
359
+ 	char	resp[U9AUTH_MD5LEN];
360
+ };
361
+ 
362
+ struct	u9auth_mSchapreply
363
+ {
364
+ 	char	uid[U9FS_NAMELEN];
365
+ 	char	LMresp[24];		/* Lan Manager response */
366
+ 	char	NTresp[24];		/* NT response */
367
+ };
368
+ 
369
+ #ifdef KERNEL
370
+ void u9auth_genchal __P((char *));
371
+ int  u9auth_gettickets __P((struct socket * so, struct u9fsreq * rep,
372
+ 			   char * user, char * ckey, char * ts, char * authc,
373
+ 			    struct proc * p));
374
+ int encrypt9 __P((void *key, void * vbuf, int n));
375
+ int decrypt9 __P((void *key, void * vbuf, int n));
376
+ 
377
+ #endif
378
+ 
379
+ #endif
380
diff -N -c -r /usr/src/sys/9fs/9crypt.c ./9fs/9crypt.c
381
*** /usr/src/sys/9fs/9crypt.c	Wed Dec 31 19:00:00 1969
382
--- ./9fs/9crypt.c	Thu Nov 11 12:23:02 1999
383
***************
384
*** 0 ****
385
--- 1,416 ----
386
+ /*
387
+  *	Data Encryption Standard
388
+  *	D.P.Mitchell  83/06/08.
389
+  *
390
+  *	block_cipher(key, block, decrypting)
391
+  */
392
+ #include <sys/param.h>
393
+ #include <sys/systm.h>
394
+ #include <sys/socket.h>
395
+ #include <sys/socketvar.h>
396
+ 
397
+ typedef unsigned char uchar;
398
+ typedef unsigned long ulong;
399
+ #define NAMELEN 28      /* length of path element, including '\0' */
400
+ #include <9fs/9p.h>
401
+ #include <9fs/9auth.h>
402
+ 
403
+ static	long	ip_low(char [8]);
404
+ static	long	ip_high(char [8]);
405
+ static	void	fp(long, long, char[8]);
406
+ static	void	key_setup(char[U9AUTH_DESKEYLEN], char[128]);
407
+ static	void	block_cipher(char[128], char[8], int);
408
+ 
409
+ /*
410
+  * destructively encrypt the buffer, which
411
+  * must be at least 8 characters long.
412
+  */
413
+ int
414
+ encrypt9(void *key, void *vbuf, int n)
415
+ {
416
+ 	char ekey[128], *buf;
417
+ 	int i, r;
418
+ 
419
+ 	if(n < 8)
420
+ 		return 0;
421
+ 	key_setup(key, ekey);
422
+ 	buf = vbuf;
423
+ 	n--;
424
+ 	r = n % 7;
425
+ 	n /= 7;
426
+ 	for(i = 0; i < n; i++){
427
+ 		block_cipher(ekey, buf, 0);
428
+ 		buf += 7;
429
+ 	}
430
+ 	if(r)
431
+ 		block_cipher(ekey, buf - 7 + r, 0);
432
+ 	return 1;
433
+ }
434
+ 
435
+ /*
436
+  * destructively decrypt the buffer, which
437
+  * must be at least 8 characters long.
438
+  */
439
+ int
440
+ decrypt9(void *key, void *vbuf, int n)
441
+ {
442
+ 	char ekey[128], *buf;
443
+ 	int i, r;
444
+ 
445
+ 	if(n < 8)
446
+ 		return 0;
447
+ 	key_setup(key, ekey);
448
+ 	buf = vbuf;
449
+ 	n--;
450
+ 	r = n % 7;
451
+ 	n /= 7;
452
+ 	buf += n * 7;
453
+ 	if(r)
454
+ 		block_cipher(ekey, buf - 7 + r, 1);
455
+ 	for(i = 0; i < n; i++){
456
+ 		buf -= 7;
457
+ 		block_cipher(ekey, buf, 1);
458
+ 	}
459
+ 	return 1;
460
+ }
461
+ 
462
+ /*
463
+  *	Tables for Combined S and P Boxes
464
+  */
465
+ 
466
+ static long  s0p[] = {
467
+ 0x00410100,0x00010000,0x40400000,0x40410100,0x00400000,0x40010100,0x40010000,0x40400000,
468
+ 0x40010100,0x00410100,0x00410000,0x40000100,0x40400100,0x00400000,0x00000000,0x40010000,
469
+ 0x00010000,0x40000000,0x00400100,0x00010100,0x40410100,0x00410000,0x40000100,0x00400100,
470
+ 0x40000000,0x00000100,0x00010100,0x40410000,0x00000100,0x40400100,0x40410000,0x00000000,
471
+ 0x00000000,0x40410100,0x00400100,0x40010000,0x00410100,0x00010000,0x40000100,0x00400100,
472
+ 0x40410000,0x00000100,0x00010100,0x40400000,0x40010100,0x40000000,0x40400000,0x00410000,
473
+ 0x40410100,0x00010100,0x00410000,0x40400100,0x00400000,0x40000100,0x40010000,0x00000000,
474
+ 0x00010000,0x00400000,0x40400100,0x00410100,0x40000000,0x40410000,0x00000100,0x40010100,
475
+ };
476
+ 
477
+ static long  s1p[] = {
478
+ 0x08021002,0x00000000,0x00021000,0x08020000,0x08000002,0x00001002,0x08001000,0x00021000,
479
+ 0x00001000,0x08020002,0x00000002,0x08001000,0x00020002,0x08021000,0x08020000,0x00000002,
480
+ 0x00020000,0x08001002,0x08020002,0x00001000,0x00021002,0x08000000,0x00000000,0x00020002,
481
+ 0x08001002,0x00021002,0x08021000,0x08000002,0x08000000,0x00020000,0x00001002,0x08021002,
482
+ 0x00020002,0x08021000,0x08001000,0x00021002,0x08021002,0x00020002,0x08000002,0x00000000,
483
+ 0x08000000,0x00001002,0x00020000,0x08020002,0x00001000,0x08000000,0x00021002,0x08001002,
484
+ 0x08021000,0x00001000,0x00000000,0x08000002,0x00000002,0x08021002,0x00021000,0x08020000,
485
+ 0x08020002,0x00020000,0x00001002,0x08001000,0x08001002,0x00000002,0x08020000,0x00021000,
486
+ };
487
+ 
488
+ static long  s2p[] = {
489
+ 0x20800000,0x00808020,0x00000020,0x20800020,0x20008000,0x00800000,0x20800020,0x00008020,
490
+ 0x00800020,0x00008000,0x00808000,0x20000000,0x20808020,0x20000020,0x20000000,0x20808000,
491
+ 0x00000000,0x20008000,0x00808020,0x00000020,0x20000020,0x20808020,0x00008000,0x20800000,
492
+ 0x20808000,0x00800020,0x20008020,0x00808000,0x00008020,0x00000000,0x00800000,0x20008020,
493
+ 0x00808020,0x00000020,0x20000000,0x00008000,0x20000020,0x20008000,0x00808000,0x20800020,
494
+ 0x00000000,0x00808020,0x00008020,0x20808000,0x20008000,0x00800000,0x20808020,0x20000000,
495
+ 0x20008020,0x20800000,0x00800000,0x20808020,0x00008000,0x00800020,0x20800020,0x00008020,
496
+ 0x00800020,0x00000000,0x20808000,0x20000020,0x20800000,0x20008020,0x00000020,0x00808000,
497
+ };
498
+ 
499
+ static long  s3p[] = {
500
+ 0x00080201,0x02000200,0x00000001,0x02080201,0x00000000,0x02080000,0x02000201,0x00080001,
501
+ 0x02080200,0x02000001,0x02000000,0x00000201,0x02000001,0x00080201,0x00080000,0x02000000,
502
+ 0x02080001,0x00080200,0x00000200,0x00000001,0x00080200,0x02000201,0x02080000,0x00000200,
503
+ 0x00000201,0x00000000,0x00080001,0x02080200,0x02000200,0x02080001,0x02080201,0x00080000,
504
+ 0x02080001,0x00000201,0x00080000,0x02000001,0x00080200,0x02000200,0x00000001,0x02080000,
505
+ 0x02000201,0x00000000,0x00000200,0x00080001,0x00000000,0x02080001,0x02080200,0x00000200,
506
+ 0x02000000,0x02080201,0x00080201,0x00080000,0x02080201,0x00000001,0x02000200,0x00080201,
507
+ 0x00080001,0x00080200,0x02080000,0x02000201,0x00000201,0x02000000,0x02000001,0x02080200,
508
+ };
509
+ 
510
+ static long  s4p[] = {
511
+ 0x01000000,0x00002000,0x00000080,0x01002084,0x01002004,0x01000080,0x00002084,0x01002000,
512
+ 0x00002000,0x00000004,0x01000004,0x00002080,0x01000084,0x01002004,0x01002080,0x00000000,
513
+ 0x00002080,0x01000000,0x00002004,0x00000084,0x01000080,0x00002084,0x00000000,0x01000004,
514
+ 0x00000004,0x01000084,0x01002084,0x00002004,0x01002000,0x00000080,0x00000084,0x01002080,
515
+ 0x01002080,0x01000084,0x00002004,0x01002000,0x00002000,0x00000004,0x01000004,0x01000080,
516
+ 0x01000000,0x00002080,0x01002084,0x00000000,0x00002084,0x01000000,0x00000080,0x00002004,
517
+ 0x01000084,0x00000080,0x00000000,0x01002084,0x01002004,0x01002080,0x00000084,0x00002000,
518
+ 0x00002080,0x01002004,0x01000080,0x00000084,0x00000004,0x00002084,0x01002000,0x01000004,
519
+ };
520
+ 
521
+ static long  s5p[] = {
522
+ 0x10000008,0x00040008,0x00000000,0x10040400,0x00040008,0x00000400,0x10000408,0x00040000,
523
+ 0x00000408,0x10040408,0x00040400,0x10000000,0x10000400,0x10000008,0x10040000,0x00040408,
524
+ 0x00040000,0x10000408,0x10040008,0x00000000,0x00000400,0x00000008,0x10040400,0x10040008,
525
+ 0x10040408,0x10040000,0x10000000,0x00000408,0x00000008,0x00040400,0x00040408,0x10000400,
526
+ 0x00000408,0x10000000,0x10000400,0x00040408,0x10040400,0x00040008,0x00000000,0x10000400,
527
+ 0x10000000,0x00000400,0x10040008,0x00040000,0x00040008,0x10040408,0x00040400,0x00000008,
528
+ 0x10040408,0x00040400,0x00040000,0x10000408,0x10000008,0x10040000,0x00040408,0x00000000,
529
+ 0x00000400,0x10000008,0x10000408,0x10040400,0x10040000,0x00000408,0x00000008,0x10040008,
530
+ };
531
+ 
532
+ static long  s6p[] = {
533
+ 0x00000800,0x00000040,0x00200040,0x80200000,0x80200840,0x80000800,0x00000840,0x00000000,
534
+ 0x00200000,0x80200040,0x80000040,0x00200800,0x80000000,0x00200840,0x00200800,0x80000040,
535
+ 0x80200040,0x00000800,0x80000800,0x80200840,0x00000000,0x00200040,0x80200000,0x00000840,
536
+ 0x80200800,0x80000840,0x00200840,0x80000000,0x80000840,0x80200800,0x00000040,0x00200000,
537
+ 0x80000840,0x00200800,0x80200800,0x80000040,0x00000800,0x00000040,0x00200000,0x80200800,
538
+ 0x80200040,0x80000840,0x00000840,0x00000000,0x00000040,0x80200000,0x80000000,0x00200040,
539
+ 0x00000000,0x80200040,0x00200040,0x00000840,0x80000040,0x00000800,0x80200840,0x00200000,
540
+ 0x00200840,0x80000000,0x80000800,0x80200840,0x80200000,0x00200840,0x00200800,0x80000800,
541
+ };
542
+ 
543
+ static long  s7p[] = {
544
+ 0x04100010,0x04104000,0x00004010,0x00000000,0x04004000,0x00100010,0x04100000,0x04104010,
545
+ 0x00000010,0x04000000,0x00104000,0x00004010,0x00104010,0x04004010,0x04000010,0x04100000,
546
+ 0x00004000,0x00104010,0x00100010,0x04004000,0x04104010,0x04000010,0x00000000,0x00104000,
547
+ 0x04000000,0x00100000,0x04004010,0x04100010,0x00100000,0x00004000,0x04104000,0x00000010,
548
+ 0x00100000,0x00004000,0x04000010,0x04104010,0x00004010,0x04000000,0x00000000,0x00104000,
549
+ 0x04100010,0x04004010,0x04004000,0x00100010,0x04104000,0x00000010,0x00100010,0x04004000,
550
+ 0x04104010,0x00100000,0x04100000,0x04000010,0x00104000,0x00004010,0x04004010,0x04100000,
551
+ 0x00000010,0x04104000,0x00104010,0x00000000,0x04000000,0x04100010,0x00004000,0x00104010,
552
+ };
553
+ 
554
+ /*
555
+  *	DES electronic codebook encryption of one block
556
+  */
557
+ static void
558
+ block_cipher(char expanded_key[128], char text[8], int decrypting)
559
+ {
560
+ 	char *key;
561
+ 	long crypto, temp, right, left;
562
+ 	int i, key_offset;
563
+ 
564
+ 	key = expanded_key;
565
+ 	left = ip_low(text);
566
+ 	right = ip_high(text);
567
+ 	if (decrypting) {
568
+ 		key_offset = 16;
569
+ 		key = key + 128 - 8;
570
+ 	} else
571
+ 		key_offset = 0;
572
+ 	for (i = 0; i < 16; i++) {
573
+ 		temp = (right << 1) | ((right >> 31) & 1);
574
+ 		crypto  = s0p[(temp         & 0x3f) ^ *key++];
575
+ 		crypto |= s1p[((temp >>  4) & 0x3f) ^ *key++];
576
+ 		crypto |= s2p[((temp >>  8) & 0x3f) ^ *key++];
577
+ 		crypto |= s3p[((temp >> 12) & 0x3f) ^ *key++];
578
+ 		crypto |= s4p[((temp >> 16) & 0x3f) ^ *key++];
579
+ 		crypto |= s5p[((temp >> 20) & 0x3f) ^ *key++];
580
+ 		crypto |= s6p[((temp >> 24) & 0x3f) ^ *key++];
581
+ 		temp = ((right & 1) << 5) | ((right >> 27) & 0x1f);
582
+ 		crypto |= s7p[temp ^ *key++];
583
+ 		temp = left;
584
+ 		left = right;
585
+ 		right = temp ^ crypto;
586
+ 		key -= key_offset;
587
+ 	}
588
+ 	/*
589
+ 	 *	standard final permutation (IPI)
590
+ 	 *	left and right are reversed here
591
+ 	 */
592
+ 	fp(right, left, text);
593
+ }
594
+ 
595
+ /*
596
+  *	Initial Permutation
597
+  */
598
+ static long iptab[] = {
599
+ 	0x00000000, 0x00008000, 0x00000000, 0x00008000,
600
+ 	0x00000080, 0x00008080, 0x00000080, 0x00008080
601
+ };
602
+ 
603
+ static long
604
+ ip_low(char block[8])
605
+ {
606
+ 	int i;
607
+ 	long l;
608
+ 
609
+ 	l = 0;
610
+ 	for(i = 0; i < 8; i++){
611
+ 		l |= iptab[(block[i] >> 4) & 7] >> i;
612
+ 		l |= iptab[block[i] & 7] << (16 - i);
613
+ 	}
614
+ 	return l;
615
+ }
616
+ 
617
+ static long
618
+ ip_high(char block[8])
619
+ {
620
+ 	int i;
621
+ 	long l;
622
+ 
623
+ 	l = 0;
624
+ 	for(i = 0; i < 8; i++){
625
+ 		l |= iptab[(block[i] >> 5) & 7] >> i;
626
+ 		l |= iptab[(block[i] >> 1) & 7] << (16 - i);
627
+ 	}
628
+ 	return l;
629
+ }
630
+ 
631
+ /*
632
+  *	Final Permutation
633
+  */
634
+ static unsigned long	fptab[] = {
635
+ 0x00000000,0x80000000,0x00800000,0x80800000,0x00008000,0x80008000,0x00808000,0x80808000,
636
+ 0x00000080,0x80000080,0x00800080,0x80800080,0x00008080,0x80008080,0x00808080,0x80808080,
637
+ };
638
+ 
639
+ static void
640
+ fp(long left, long right, char text[8])
641
+ {
642
+ 	unsigned long ta[2], t, v[2];
643
+ 	int i, j, sh;
644
+ 
645
+ 	ta[0] = right;
646
+ 	ta[1] = left;
647
+ 	v[0] = v[1] = 0;
648
+ 	for(i = 0; i < 2; i++){
649
+ 		t = ta[i];
650
+ 		sh = i;
651
+ 		for(j = 0; j < 4; j++){
652
+ 			v[1] |= fptab[t & 0xf] >> sh;
653
+ 			t >>= 4;
654
+ 			v[0] |= fptab[t & 0xf] >> sh;
655
+ 			t >>= 4;
656
+ 			sh += 2;
657
+ 		}
658
+ 	}
659
+ 	for(i = 0; i < 2; i++)
660
+ 		for(j = 0; j < 4; j++){
661
+ 			*text++ = v[i];
662
+ 			v[i] >>= 8;
663
+ 		}
664
+ }
665
+ 
666
+ /*
667
+  *	Key set-up
668
+  */
669
+ static uchar keyexpand[][15][2] = {
670
+ 	{   3,  2,   9,  8,  18,  8,  27, 32,  33,  2,  42, 16,  48,  8,  65, 16, 
671
+ 	   74,  2,  80,  2,  89,  4,  99, 16, 104,  4, 122, 32,   0,  0, },
672
+ 	{   1,  4,   8,  1,  18,  4,  25, 32,  34, 32,  41,  8,  50,  8,  59, 32, 
673
+ 	   64, 16,  75,  4,  90,  1,  97, 16, 106,  2, 112,  2, 123,  1, },
674
+ 	{   2,  1,  19,  8,  35,  1,  40,  1,  50,  4,  57, 32,  75,  2,  80, 32, 
675
+ 	   89,  1,  96, 16, 107,  4, 120,  8,   0,  0,   0,  0,   0,  0, },
676
+ 	{   4, 32,  20,  2,  31,  4,  37, 32,  47,  1,  54,  1,  63,  2,  68,  1, 
677
+ 	   78,  4,  84,  8, 101, 16, 108,  4, 119, 16, 126,  8,   0,  0, },
678
+ 	{   5,  4,  15,  4,  21, 32,  31,  1,  38,  1,  47,  2,  53,  2,  68,  8, 
679
+ 	   85, 16,  92,  4, 103, 16, 108, 32, 118, 32, 124,  2,   0,  0, },
680
+ 	{  15,  2,  21,  2,  39,  8,  46, 16,  55, 32,  61,  1,  71, 16,  76, 32, 
681
+ 	   86, 32,  93,  4, 102,  2, 108, 16, 117,  8, 126,  1,   0,  0, },
682
+ 	{  14, 16,  23, 32,  29,  1,  38,  8,  52,  2,  63,  4,  70,  2,  76, 16, 
683
+ 	   85,  8, 100,  1, 110,  4, 116,  8, 127,  8,   0,  0,   0,  0, },
684
+ 	{   1,  8,   8, 32,  17,  1,  24, 16,  35,  4,  50,  1,  57, 16,  67,  8, 
685
+ 	   83,  1,  88,  1,  98,  4, 105, 32, 114, 32, 123,  2,   0,  0, },
686
+ 	{   0,  1,  11, 16,  16,  4,  35,  2,  40, 32,  49,  1,  56, 16,  65,  2, 
687
+ 	   74, 16,  80,  8,  99,  8, 115,  1, 121,  4,   0,  0,   0,  0, },
688
+ 	{   9, 16,  18,  2,  24,  2,  33,  4,  43, 16,  48,  4,  66, 32,  73,  8, 
689
+ 	   82,  8,  91, 32,  97,  2, 106, 16, 112,  8, 122,  1,   0,  0, },
690
+ 	{  14, 32,  21,  4,  30,  2,  36, 16,  45,  8,  60,  1,  69,  2,  87,  8, 
691
+ 	   94, 16, 103, 32, 109,  1, 118,  8, 124, 32,   0,  0,   0,  0, },
692
+ 	{   7,  4,  14,  2,  20, 16,  29,  8,  44,  1,  54,  4,  60,  8,  71,  8, 
693
+ 	   78, 16,  87, 32,  93,  1, 102,  8, 116,  2, 125,  4,   0,  0, },
694
+ 	{   7,  2,  12,  1,  22,  4,  28,  8,  45, 16,  52,  4,  63, 16,  70,  8, 
695
+ 	   84,  2,  95,  4, 101, 32, 111,  1, 118,  1,   0,  0,   0,  0, },
696
+ 	{   6, 16,  13, 16,  20,  4,  31, 16,  36, 32,  46, 32,  53,  4,  62,  2, 
697
+ 	   69, 32,  79,  1,  86,  1,  95,  2, 101,  2, 119,  8,   0,  0, },
698
+ 	{   0, 32,  10,  8,  19, 32,  25,  2,  34, 16,  40,  8,  59,  8,  66,  2, 
699
+ 	   72,  2,  81,  4,  91, 16,  96,  4, 115,  2, 121,  8,   0,  0, },
700
+ 	{   3, 16,  10,  4,  17, 32,  26, 32,  33,  8,  42,  8,  51, 32,  57,  2, 
701
+ 	   67,  4,  82,  1,  89, 16,  98,  2, 104,  2, 113,  4, 120,  1, },
702
+ 	{   1, 16,  11,  8,  27,  1,  32,  1,  42,  4,  49, 32,  58, 32,  67,  2, 
703
+ 	   72, 32,  81,  1,  88, 16,  99,  4, 114,  1,   0,  0,   0,  0, },
704
+ 	{   6, 32,  12,  2,  23,  4,  29, 32,  39,  1,  46,  1,  55,  2,  61,  2, 
705
+ 	   70,  4,  76,  8,  93, 16, 100,  4, 111, 16, 116, 32,   0,  0, },
706
+ 	{   6,  2,  13, 32,  23,  1,  30,  1,  39,  2,  45,  2,  63,  8,  77, 16, 
707
+ 	   84,  4,  95, 16, 100, 32, 110, 32, 117,  4, 127,  4,   0,  0, },
708
+ 	{   4,  1,  13,  2,  31,  8,  38, 16,  47, 32,  53,  1,  62,  8,  68, 32, 
709
+ 	   78, 32,  85,  4,  94,  2, 100, 16, 109,  8, 127,  2,   0,  0, },
710
+ 	{   5, 16,  15, 32,  21,  1,  30,  8,  44,  2,  55,  4,  61, 32,  68, 16, 
711
+ 	   77,  8,  92,  1, 102,  4, 108,  8, 126, 16,   0,  0,   0,  0, },
712
+ 	{   2,  8,   9,  1,  16, 16,  27,  4,  42,  1,  49, 16,  58,  2,  75,  1, 
713
+ 	   80,  1,  90,  4,  97, 32, 106, 32, 113,  8, 120, 32,   0,  0, },
714
+ 	{   2,  4,   8,  4,  27,  2,  32, 32,  41,  1,  48, 16,  59,  4,  66, 16, 
715
+ 	   72,  8,  91,  8, 107,  1, 112,  1, 123, 16,   0,  0,   0,  0, },
716
+ 	{   3,  8,  10,  2,  16,  2,  25,  4,  35, 16,  40,  4,  59,  2,  65,  8, 
717
+ 	   74,  8,  83, 32,  89,  2,  98, 16, 104,  8, 121, 16,   0,  0, },
718
+ 	{   4,  2,  13,  4,  22,  2,  28, 16,  37,  8,  52,  1,  62,  4,  79,  8, 
719
+ 	   86, 16,  95, 32, 101,  1, 110,  8, 126, 32,   0,  0,   0,  0, },
720
+ 	{   5, 32,  12, 16,  21,  8,  36,  1,  46,  4,  52,  8,  70, 16,  79, 32, 
721
+ 	   85,  1,  94,  8, 108,  2, 119,  4, 126,  2,   0,  0,   0,  0, },
722
+ 	{   5,  2,  14,  4,  20,  8,  37, 16,  44,  4,  55, 16,  60, 32,  76,  2, 
723
+ 	   87,  4,  93, 32, 103,  1, 110,  1, 119,  2, 124,  1,   0,  0, },
724
+ 	{   7, 32,  12,  4,  23, 16,  28, 32,  38, 32,  45,  4,  54,  2,  60, 16, 
725
+ 	   71,  1,  78,  1,  87,  2,  93,  2, 111,  8, 118, 16, 125, 16, },
726
+ 	{   1,  1,  11, 32,  17,  2,  26, 16,  32,  8,  51,  8,  64,  2,  73,  4, 
727
+ 	   83, 16,  88,  4, 107,  2, 112, 32, 122,  8,   0,  0,   0,  0, },
728
+ 	{   0,  4,   9, 32,  18, 32,  25,  8,  34,  8,  43, 32,  49,  2,  58, 16, 
729
+ 	   74,  1,  81, 16,  90,  2,  96,  2, 105,  4, 115, 16, 122,  4, },
730
+ 	{   2,  2,  19,  1,  24,  1,  34,  4,  41, 32,  50, 32,  57,  8,  64, 32, 
731
+ 	   73,  1,  80, 16,  91,  4, 106,  1, 113, 16, 123,  8,   0,  0, },
732
+ 	{   3,  4,  10, 16,  16,  8,  35,  8,  51,  1,  56,  1,  67, 16,  72,  4, 
733
+ 	   91,  2,  96, 32, 105,  1, 112, 16, 121,  2,   0,  0,   0,  0, },
734
+ 	{   4, 16,  15,  1,  22,  1,  31,  2,  37,  2,  55,  8,  62, 16,  69, 16, 
735
+ 	   76,  4,  87, 16,  92, 32, 102, 32, 109,  4, 118,  2, 125, 32, },
736
+ 	{   6,  4,  23,  8,  30, 16,  39, 32,  45,  1,  54,  8,  70, 32,  77,  4, 
737
+ 	   86,  2,  92, 16, 101,  8, 116,  1, 125,  2,   0,  0,   0,  0, },
738
+ 	{   4,  4,  13,  1,  22,  8,  36,  2,  47,  4,  53, 32,  63,  1,  69,  8, 
739
+ 	   84,  1,  94,  4, 100,  8, 117, 16, 127, 32,   0,  0,   0,  0, },
740
+ 	{   3, 32,   8, 16,  19,  4,  34,  1,  41, 16,  50,  2,  56,  2,  67,  1, 
741
+ 	   72,  1,  82,  4,  89, 32,  98, 32, 105,  8, 114,  8, 121,  1, },
742
+ 	{   1, 32,  19,  2,  24, 32,  33,  1,  40, 16,  51,  4,  64,  8,  83,  8, 
743
+ 	   99,  1, 104,  1, 114,  4, 120,  4,   0,  0,   0,  0,   0,  0, },
744
+ 	{   8,  2,  17,  4,  27, 16,  32,  4,  51,  2,  56, 32,  66,  8,  75, 32, 
745
+ 	   81,  2,  90, 16,  96,  8, 115,  8, 122,  2,   0,  0,   0,  0, },
746
+ 	{   2, 16,  18,  1,  25, 16,  34,  2,  40,  2,  49,  4,  59, 16,  66,  4, 
747
+ 	   73, 32,  82, 32,  89,  8,  98,  8, 107, 32, 113,  2, 123,  4, },
748
+ 	{   7,  1,  13,  8,  28,  1,  38,  4,  44,  8,  61, 16,  71, 32,  77,  1, 
749
+ 	   86,  8, 100,  2, 111,  4, 117, 32, 124, 16,   0,  0,   0,  0, },
750
+ 	{  12,  8,  29, 16,  36,  4,  47, 16,  52, 32,  62, 32,  68,  2,  79,  4, 
751
+ 	   85, 32,  95,  1, 102,  1, 111,  2, 117,  2, 126,  4,   0,  0, },
752
+ 	{   5,  1,  15, 16,  20, 32,  30, 32,  37,  4,  46,  2,  52, 16,  61,  8, 
753
+ 	   70,  1,  79,  2,  85,  2, 103,  8, 110, 16, 119, 32, 124,  4, },
754
+ 	{   0, 16,   9,  2,  18, 16,  24,  8,  43,  8,  59,  1,  65,  4,  75, 16, 
755
+ 	   80,  4,  99,  2, 104, 32, 113,  1, 123, 32,   0,  0,   0,  0, },
756
+ 	{  10, 32,  17,  8,  26,  8,  35, 32,  41,  2,  50, 16,  56,  8,  66,  1, 
757
+ 	   73, 16,  82,  2,  88,  2,  97,  4, 107, 16, 112,  4, 121, 32, },
758
+ 	{   0,  2,  11,  1,  16,  1,  26,  4,  33, 32,  42, 32,  49,  8,  58,  8, 
759
+ 	   65,  1,  72, 16,  83,  4,  98,  1, 105, 16, 114,  2,   0,  0, },
760
+ 	{   8,  8,  27,  8,  43,  1,  48,  1,  58,  4,  64,  4,  83,  2,  88, 32, 
761
+ 	   97,  1, 104, 16, 115,  4, 122, 16,   0,  0,   0,  0,   0,  0, },
762
+ 	{   5,  8,  14,  1,  23,  2,  29,  2,  47,  8,  54, 16,  63, 32,  68,  4, 
763
+ 	   79, 16,  84, 32,  94, 32, 101,  4, 110,  2, 116, 16, 127,  1, },
764
+ 	{   4,  8,  15,  8,  22, 16,  31, 32,  37,  1,  46,  8,  60,  2,  69,  4, 
765
+ 	   78,  2,  84, 16,  93,  8, 108,  1, 118,  4,   0,  0,   0,  0, },
766
+ 	{   7, 16,  14,  8,  28,  2,  39,  4,  45, 32,  55,  1,  62,  1,  76,  1, 
767
+ 	   86,  4,  92,  8, 109, 16, 116,  4, 125,  1,   0,  0,   0,  0, },
768
+ 	{   1,  2,  11,  4,  26,  1,  33, 16,  42,  2,  48,  2,  57,  4,  64,  1, 
769
+ 	   74,  4,  81, 32,  90, 32,  97,  8, 106,  8, 115, 32, 120, 16, },
770
+ 	{   2, 32,  11,  2,  16, 32,  25,  1,  32, 16,  43,  4,  58,  1,  75,  8, 
771
+ 	   91,  1,  96,  1, 106,  4, 113, 32,   0,  0,   0,  0,   0,  0, },
772
+ 	{   3,  1,   9,  4,  19, 16,  24,  4,  43,  2,  48, 32,  57,  1,  67, 32, 
773
+ 	   73,  2,  82, 16,  88,  8, 107,  8, 120,  2,   0,  0,   0,  0, },
774
+ 	{   0,  8,  10,  1,  17, 16,  26,  2,  32,  2,  41,  4,  51, 16,  56,  4, 
775
+ 	   65, 32,  74, 32,  81,  8,  90,  8,  99, 32, 105,  2, 114, 16, },
776
+ 	{   6,  1,  20,  1,  30,  4,  36,  8,  53, 16,  60,  4,  69,  1,  78,  8, 
777
+ 	   92,  2, 103,  4, 109, 32, 119,  1, 125,  8,   0,  0,   0,  0, },
778
+ 	{   7,  8,  21, 16,  28,  4,  39, 16,  44, 32,  54, 32,  61,  4,  71,  4, 
779
+ 	   77, 32,  87,  1,  94,  1, 103,  2, 109,  2, 124,  8,   0,  0, },
780
+ 	{   6,  8,  12, 32,  22, 32,  29,  4,  38,  2,  44, 16,  53,  8,  71,  2, 
781
+ 	   77,  2,  95,  8, 102, 16, 111, 32, 117,  1, 127, 16,   0,  0, }
782
+ };
783
+ 
784
+ static void
785
+ key_setup(char key[U9AUTH_DESKEYLEN], char *ek)
786
+ {
787
+ 	int i, j, k, mask;
788
+ 	uchar (*x)[2];
789
+ 
790
+ 	bzero(ek, 128);
791
+ 	x = keyexpand[0];
792
+ 	for(i = 0; i < 7; i++){
793
+ 		k = key[i];
794
+ 		for(mask = 0x80; mask; mask >>= 1){
795
+ 			if(k & mask)
796
+ 				for(j = 0; j < 15; j++)
797
+ 					ek[x[j][0]] |= x[j][1];
798
+ 			x += 15;
799
+ 		}
800
+ 	}
801
+ }
802
diff -N -c -r /usr/src/sys/9fs/9fs.h ./9fs/9fs.h
803
*** /usr/src/sys/9fs/9fs.h	Wed Dec 31 19:00:00 1969
804
--- ./9fs/9fs.h	Mon May 22 11:31:29 2000
805
***************
806
*** 0 ****
807
--- 1,294 ----
808
+ /*
809
+  * Copyright (c) 1989, 1993, 1995
810
+  *	The Regents of the University of California.  All rights reserved.
811
+  *
812
+  * This code is derived from software contributed to Berkeley by
813
+  * Rick Macklem at The University of Guelph.
814
+  *
815
+  * Redistribution and use in source and binary forms, with or without
816
+  * modification, are permitted provided that the following conditions
817
+  * are met:
818
+  * 1. Redistributions of source code must retain the above copyright
819
+  *    notice, this list of conditions and the following disclaimer.
820
+  * 2. Redistributions in binary form must reproduce the above copyright
821
+  *    notice, this list of conditions and the following disclaimer in the
822
+  *    documentation and/or other materials provided with the distribution.
823
+  * 3. All advertising materials mentioning features or use of this software
824
+  *    must display the following acknowledgement:
825
+  *	This product includes software developed by the University of
826
+  *	California, Berkeley and its contributors.
827
+  * 4. Neither the name of the University nor the names of its contributors
828
+  *    may be used to endorse or promote products derived from this software
829
+  *    without specific prior written permission.
830
+  *
831
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
832
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
833
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
834
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
835
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
836
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
837
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
838
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
839
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
840
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
841
+  * SUCH DAMAGE.
842
+  *
843
+  *	@(#)nfs.h	8.4 (Berkeley) 5/1/95
844
+  * $Id: nfs.h,v 1.44 1998/09/07 05:42:15 bde Exp $
845
+  */
846
+ 
847
+ #ifndef _9FS_H_
848
+ #define _9FS_H_
849
+ 
850
+ #ifdef KERNEL
851
+ #include "opt_u9fs.h"
852
+ #endif
853
+ 
854
+ #define U9FS_FABLKSIZE   512
855
+ #define U9FS_PORT        17008
856
+ 
857
+ /*
858
+  * The set of signals the interrupt an I/O in progress for U9FSMNT_INT mounts.
859
+  * What should be in this set is open to debate, but I believe that since
860
+  * I/O system calls on ufs are never interrupted by signals the set should
861
+  * be minimal. My reasoning is that many current programs that use signals
862
+  * such as SIGALRM will not expect file I/O system calls to be interrupted
863
+  * by them and break.
864
+  */
865
+ #define	U9FSINT_SIGMASK	(sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \
866
+ 			 sigmask(SIGHUP)|sigmask(SIGQUIT))
867
+ 
868
+ /*
869
+  * U9FS mount option flags
870
+  */
871
+ #define	U9FSMNT_SOFT		0x00000001  /* soft mount (hard is default) */
872
+ #define	U9FSMNT_MAXGRPS		0x00000020  /* set maximum grouplist size */
873
+ #define	U9FSMNT_INT		0x00000040  /* allow interrupts on hard mount */
874
+ #define	U9FSMNT_KERB		0x00000400  /* Use Kerberos authentication */
875
+ #define	U9FSMNT_READAHEAD	0x00002000  /* set read ahead */
876
+ 
877
+ #define U9FSSTA_HASWRITEVERF	0x00040000  /* Has write verifier for V3 */
878
+ #define U9FSSTA_GOTPATHCONF	0x00080000  /* Got the V3 pathconf info */
879
+ #define U9FSSTA_GOTFSINFO	0x00100000  /* Got the V3 fsinfo */
880
+ #define	U9FSSTA_MNTD		0x00200000  /* Mnt server for mnt point */
881
+ #define	U9FSSTA_DISMINPROG	0x00400000  /* Dismount in progress */
882
+ #define	U9FSSTA_DISMNT		0x00800000  /* Dismounted */
883
+ #define	U9FSSTA_SNDLOCK		0x01000000  /* Send socket lock */
884
+ #define	U9FSSTA_WANTSND		0x02000000  /* Want above */
885
+ #define	U9FSSTA_RCVLOCK		0x04000000  /* Rcv socket lock */
886
+ #define	U9FSSTA_WANTRCV		0x08000000  /* Want above */
887
+ #define	U9FSSTA_WAITAUTH		0x10000000  /* Wait for authentication */
888
+ #define	U9FSSTA_HASAUTH		0x20000000  /* Has authenticator */
889
+ #define	U9FSSTA_WANTAUTH		0x40000000  /* Wants an authenticator */
890
+ #define	U9FSSTA_AUTHERR		0x80000000  /* Authentication error */
891
+ 
892
+ #define	U9FSNOHASH(fhsum) (&u9fsnodehashtbl[(fhsum) % u9fsnodehash])
893
+ 
894
+ /*
895
+  * Arguments to mount 9FS
896
+  */
897
+ #define U9FS_ARGSVERSION	1	/* change when nfs_args changes */
898
+ struct u9fs_args {
899
+ 	int		version;	/* args structure version number */
900
+ 	struct sockaddr	*addr;		/* file server address */
901
+ 	int		addrlen;	/* length of address */
902
+ 	int		sotype;		/* Socket type */
903
+ 	int		proto;		/* and Protocol */
904
+ 	int		fhsize;		/* Size, in bytes, of fh */
905
+ 	int		flags;		/* flags */
906
+ 	int		wsize;		/* write size in bytes */
907
+ 	int		rsize;		/* read size in bytes */
908
+ 	int		readdirsize;	/* readdir size in bytes */
909
+ 	char		*hostname;	/* server's name */
910
+ 
911
+         struct sockaddr * authaddr;
912
+         int             authaddrlen;
913
+         int             authsotype;
914
+         int             authsoproto;
915
+ 
916
+         int             nusers;
917
+         char            user[U9FS_NAMELEN];
918
+         char            key[U9AUTH_DESKEYLEN];
919
+         struct p9user {
920
+ 	  uid_t p9_uid;
921
+ 	  char p9_name[U9FS_NAMELEN];
922
+ 	} * users;
923
+ };
924
+ 
925
+ #define U9FS_USER_HASHSIZE 512
926
+ 
927
+ struct u9fsuser {
928
+   LIST_ENTRY(u9fsuser) u_hash;
929
+   uid_t                u_uid;
930
+   char                 u_name[U9FS_NAMELEN];
931
+   char                 u_ckey[U9AUTH_DESKEYLEN];  /* user key */
932
+   char                 u_skey[U9AUTH_DESKEYLEN];  /* session key */
933
+ };
934
+ 
935
+ /*
936
+  * The u9fsnode is the u9fs equivalent to ufs's inode. Any similarity
937
+  * is purely coincidental.
938
+  * There is a unique u9fsnode allocated for each active file,
939
+  * each current directory, each mounted-on file, text file, and the root.
940
+  * An u9fsnode is 'named' by its file handle. (nget/u9fs_node.c)
941
+  * If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
942
+  * type definitions), file handles of > 32 bytes should probably be split out
943
+  * into a separate MALLOC()'d data structure. (Reduce the size of u9fsfh_t by
944
+  * changing the definition in u9fsproto.h of U9FS_SMALLFH.)
945
+  * NB: Hopefully the current order of the fields is such that everything will
946
+  *     be well aligned and, therefore, tightly packed.
947
+  */
948
+ struct u9fsnode {
949
+ 	LIST_ENTRY(u9fsnode)	n_hash;		/* Hash chain */
950
+ 	u_quad_t		n_size;		/* Current size of file */
951
+ 	struct vattr		n_vattr;	/* Vnode attribute cache */
952
+ 	time_t			n_attrstamp;	/* Attr. cache timestamp */
953
+ 	u_int32_t		n_mode;		/* ACCESS mode cache */
954
+ 	uid_t			n_modeuid;	/* credentials having mode */
955
+ 	time_t			n_modestamp;	/* mode cache timestamp */
956
+ 	time_t			n_mtime;	/* Prev modify time. */
957
+ 	time_t			n_ctime;	/* Prev create time. */
958
+         struct u9fs_qid         n_qid;
959
+ 	u_short			n_fid;		/* U9FS FID */
960
+         u_short                 n_rdfid;      
961
+         u_short                 n_wrfid;      
962
+ 	struct vnode		*n_vnode;	/* associated vnode */
963
+ 	struct lockf		*n_lockf;	/* Locking record of file */
964
+ 	int			n_error;	/* Save write error value */
965
+         struct u9fsdir          n_dir;
966
+ 	short			n_flag;		/* Flag for locking.. */
967
+         int                     n_opens;        /* number of opens */
968
+ };
969
+ 
970
+ #define n_atim		n_un1.nf_atim
971
+ #define n_mtim		n_un2.nf_mtim
972
+ #define n_sillyrename	n_un3.nf_silly
973
+ #define n_cookieverf	n_un1.nd_cookieverf
974
+ #define n_direofoffset	n_un2.nd_direof
975
+ #define n_cookies	n_un3.nd_cook
976
+ 
977
+ /*
978
+  * Flags for n_flag
979
+  */
980
+ #define	NFLUSHWANT	0x0001	/* Want wakeup from a flush in prog. */
981
+ #define	NFLUSHINPROG	0x0002	/* Avoid multiple calls to vinvalbuf() */
982
+ #define	NMODIFIED	0x0004	/* Might have a modified buffer in bio */
983
+ #define	NWRITEERR	0x0008	/* Flag write errors so close will know */
984
+ #define	NQU9FSNONCACHE	0x0020	/* Non-cachable lease */
985
+ #define	NQU9FSWRITE	0x0040	/* Write lease */
986
+ #define	NQU9FSEVICTED	0x0080	/* Has been evicted */
987
+ #define	NACC		0x0100	/* Special file accessed */
988
+ #define	NUPD		0x0200	/* Special file updated */
989
+ #define	NCHG		0x0400	/* Special file times changed */
990
+ #define NLOCKED		0x0800  /* node is locked */
991
+ #define NWANTED		0x0100  /* someone wants to lock */
992
+ 
993
+ /*
994
+  * Convert between u9fsnode pointers and vnode pointers
995
+  */
996
+ #define VTOU9FS(vp)	((struct u9fsnode *)(vp)->v_data)
997
+ #define U9FSTOV(np)	((struct vnode *)(np)->n_vnode)
998
+ 
999
+ /*
1000
+  * Mount structure.
1001
+  * One allocated on every U9FS mount.
1002
+  * Holds U9FS specific information for mount.
1003
+  */
1004
+ struct	u9fsmount {
1005
+ 	int	nm_flag;		/* Flags for soft/hard... */
1006
+ 	int	nm_state;		/* Internal state flags */
1007
+ 	struct	mount *nm_mountp;	/* Vfs structure for this filesystem */
1008
+ 	int	nm_numgrps;		/* Max. size of groupslist */
1009
+         u9fsfh_t nm_fh;                /* qid.path */
1010
+ 	u_short	nm_fid;	                /* fid of root dir */
1011
+ 	struct	socket *nm_so;		/* Rpc socket */
1012
+ 	int	nm_sotype;		/* Type of socket */
1013
+ 	int	nm_soproto;		/* and protocol */
1014
+ 	int	nm_soflags;		/* pr_flags for socket protocol */
1015
+ 	struct	sockaddr *nm_nam;	/* Addr of server */
1016
+ 	int	nm_sent;		/* Request send count */
1017
+ 	int	nm_cwnd;		/* Request send window */
1018
+ 	int	nm_rsize;		/* Max size of read rpc */
1019
+ 	int	nm_wsize;		/* Max size of write rpc */
1020
+ 	int	nm_readdirsize;		/* Size of a readdir rpc */
1021
+   
1022
+   struct lock   nm_lock;                /* lock for tag/fid freelist */
1023
+   bitstr_t * nm_tags;
1024
+   bitstr_t * nm_fids;
1025
+   TAILQ_HEAD(u9fs_reqq, u9fsreq) nm_reqq;
1026
+ 
1027
+         uid_t   nm_authuid;             /* Uid for authenticator */
1028
+ #if 0
1029
+ 	struct vnode *nm_inprog;	/* Vnode in prog by nqu9fs_clientd() */
1030
+ 	uid_t	nm_authuid;		/* Uid for authenticator */
1031
+ 	int	nm_authtype;		/* Authenticator type */
1032
+ 	int	nm_authlen;		/* and length */
1033
+ 	char	*nm_authstr;		/* Authenticator string */
1034
+ 	char	*nm_verfstr;		/* and the verifier */
1035
+ 	int	nm_verflen;
1036
+ 	u_char	nm_verf[U9FSX_V3WRITEVERF]; /* V3 write verifier */
1037
+ 	U9FSKERBKEY_T nm_key;		/* and the session key */
1038
+ 	int	nm_numuids;		/* Number of u9fsuid mappings */
1039
+ 	TAILQ_HEAD(, u9fsuid) nm_uidlruhead; /* Lists of u9fsuid mappings */
1040
+ 	LIST_HEAD(, u9fsuid) nm_uidhashtbl[U9FS_MUIDHASHSIZ];
1041
+ 	TAILQ_HEAD(, buf) nm_bufq;	/* async io buffer queue */
1042
+ 	short	nm_bufqlen;		/* number of buffers in queue */
1043
+ 	short	nm_bufqwant;		/* process wants to add to the queue */
1044
+ 	int	nm_bufqiods;		/* number of iods processing queue */
1045
+ #endif
1046
+ 	u_int64_t nm_maxfilesize;	/* maximum file size */
1047
+ };
1048
+ 
1049
+ #ifdef KERNEL
1050
+ 
1051
+ #ifdef MALLOC_DECLARE
1052
+ MALLOC_DECLARE(M_U9FSHASH);
1053
+ MALLOC_DECLARE(M_U9FSBITS);
1054
+ 
1055
+ extern        vop_t   **u9fs_vnodeop_p;
1056
+ 
1057
+ /* u9fs_node.c */
1058
+ void     u9fs_nhinit __P((void));
1059
+ int u9fs_nget __P((struct mount *mntp, u9fsfh_t fh, struct u9fsnode **npp, struct proc * p));
1060
+ 
1061
+ /* u9fs_subr.c */
1062
+ void u9fs_id_init __P((bitstr_t ** bits));
1063
+ u_short u9fs_id_new __P((bitstr_t * bits));
1064
+ void u9fs_id_free __P((bitstr_t * bits, u_short v));
1065
+ void u9fs_uhinit __P((void));
1066
+ uid_t u9fs_name2uid __P((char * name));
1067
+ struct u9fsuser *  u9fs_finduser __P((uid_t uid));
1068
+ void  u9fs_hashuser __P((uid_t uid, char *name));
1069
+ int u9fs_mbuftouio __P((struct mbuf *m, struct uio *uiop, int siz));
1070
+ int u9fs_uiotombuf __P((struct uio *uiop, struct mbuf **mq, int siz));
1071
+ 
1072
+ /* u9fs_vnopes.c */
1073
+ int u9fs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
1074
+ int u9fs_readrpc __P((struct vnode *vp, struct uio *uiop, struct ucred *cred));
1075
+ int u9fs_writerpc __P((struct vnode *vp, struct uio *uiop, struct ucred *cred));
1076
+ 
1077
+ /* u9fs_bio.c */
1078
+ int u9fs_bioread __P((struct vnode *, struct uio *, int, struct ucred *,int));
1079
+ int u9fs_biowrite __P((struct vnode *, struct uio *, int ioflag, struct ucred *));
1080
+ int u9fs_doio __P((struct buf *, struct ucred *, struct proc *));
1081
+ int	u9fs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct proc *, int));
1082
+ 
1083
+ 
1084
+ /* u9fs_socket.c */
1085
+ int u9fs_sigintr __P((struct u9fsmount *nmp, struct proc *p));
1086
+ void     u9fs_disconnect __P((struct socket *));
1087
+ int      u9fs_connect __P((struct socket ** sop, struct sockaddr * saddr, int sotype, int soproto, struct proc * p));
1088
+ int      u9fs_connect_9fs __P((struct u9fsmount *));
1089
+ int      u9fs_connect_9auth __P((struct u9fsmount *, struct u9fs_args *, struct socket **));
1090
+ int u9fs_request __P((struct u9fsreq * req, struct u9fsreq * rep, int relm));
1091
+ 
1092
+ #endif
1093
+ 
1094
+ /*
1095
+  * Convert mount ptr to u9fsmount ptr.
1096
+  */
1097
+ #define VFSTOU9FS(mp)	((struct u9fsmount *)((mp)->mnt_data))
1098
+ 
1099
+ #endif	/* KERNEL */
1100
+ 
1101
+ #endif
1102
diff -N -c -r /usr/src/sys/9fs/9fs_bio.c ./9fs/9fs_bio.c
1103
*** /usr/src/sys/9fs/9fs_bio.c	Wed Dec 31 19:00:00 1969
1104
--- ./9fs/9fs_bio.c	Fri Nov 26 12:28:50 1999
1105
***************
1106
*** 0 ****
1107
--- 1,550 ----
1108
+ #include <sys/param.h>
1109
+ #include <sys/sockio.h>
1110
+ #include <sys/proc.h>
1111
+ #include <sys/vnode.h>
1112
+ #include <sys/kernel.h>
1113
+ #include <sys/sysctl.h>
1114
+ #include <sys/malloc.h>
1115
+ #include <sys/mount.h>
1116
+ #include <sys/mbuf.h>
1117
+ #include <sys/socket.h>
1118
+ #include <sys/socketvar.h>
1119
+ #include <sys/systm.h>
1120
+ #include <sys/protosw.h>
1121
+ #include <sys/syslog.h>
1122
+ 
1123
+ #include <netinet/in.h>
1124
+ #include <netinet/tcp.h>
1125
+ 
1126
+ #include <vm/vm.h>
1127
+ #include <vm/vm_extern.h>
1128
+ #include <vm/vm_zone.h>
1129
+ #include <vm/vm_prot.h>
1130
+ #include <vm/vm_page.h>
1131
+ #include <vm/vm_object.h>
1132
+ #include <vm/vm_pager.h>
1133
+ #include <vm/vnode_pager.h>
1134
+ 
1135
+ #include <net/if.h>
1136
+ #include <net/route.h>
1137
+ #include <netinet/in.h>
1138
+ 
1139
+ #include <9fs/bitstring.h>
1140
+ #include <9fs/9p.h>
1141
+ #include <9fs/9auth.h>
1142
+ #include <9fs/9fs.h>
1143
+ 
1144
+ static struct buf *u9fs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size, struct proc *p));
1145
+ static void u9fs_prot_buf __P((struct buf *bp, int off, int n));
1146
+ 
1147
+ /*
1148
+  * Vnode op for read using bio
1149
+  */
1150
+ int
1151
+ u9fs_bioread(vp, uio, ioflag, cred, getpages)
1152
+ 	register struct vnode *vp;
1153
+ 	register struct uio *uio;
1154
+ 	int ioflag;
1155
+ 	struct ucred *cred;
1156
+ 	int getpages;
1157
+ {
1158
+ 	register struct u9fsnode *np = VTOU9FS(vp);
1159
+ 	register int biosize;
1160
+ 	off_t diff;
1161
+ 	struct buf *bp = 0;
1162
+ 	struct proc *p;
1163
+ 	struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
1164
+ 	daddr_t lbn;
1165
+ 	int error = 0, n = 0, on = 0, bufsize, not_readin;
1166
+ 
1167
+ 	if (uio->uio_resid == 0)
1168
+ 		return (0);
1169
+ 	if (uio->uio_offset < 0)
1170
+ 		return (EINVAL);
1171
+ 	p = uio->uio_procp;
1172
+ 	if (vp->v_type != VDIR &&
1173
+ 	    (uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
1174
+ 		return (EFBIG);
1175
+ 	biosize = vp->v_mount->mnt_stat.f_iosize;
1176
+ #if 0
1177
+ 	if( np->n_qid.vers ) { /* in cache, check revision */
1178
+ 	  error = VOP_GETATTR(vp, &vattr, cred, p);
1179
+ 	  if( error )
1180
+ 	    return error;
1181
+ 	  if( np->n_qid.vers != np->n_dir.dir_qid.vers ) {
1182
+ 	    /* content changed */
1183
+ 	    u9fs_vinvalbuf(vp, V_SAVE, cred, p, 1);
1184
+ 	  }
1185
+ 	}
1186
+ #endif
1187
+ 	do {
1188
+ 	    switch (vp->v_type) {
1189
+ 	    case VREG:
1190
+ 		lbn = uio->uio_offset / biosize;
1191
+ 		on = uio->uio_offset & (biosize - 1);
1192
+ 		not_readin = 1;
1193
+ 
1194
+ #if 0
1195
+ 		/*
1196
+ 		 * Start the read ahead(s), as required.
1197
+ 		 */
1198
+ 		if (u9fs_numasync > 0 && nmp->nm_readahead > 0) {
1199
+ 		    for (nra = 0; nra < nmp->nm_readahead &&
1200
+ 			(off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) {
1201
+ 			rabn = lbn + 1 + nra;
1202
+ 			if (!incore(vp, rabn)) {
1203
+ 			    rabp = u9fs_getcacheblk(vp, rabn, biosize, p);
1204
+ 			    if (!rabp)
1205
+ 				return (EINTR);
1206
+ 			    if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
1207
+ 				rabp->b_flags |= (B_READ | B_ASYNC);
1208
+ 				vfs_busy_pages(rabp, 0);
1209
+ 				if (u9fs_asyncio(rabp, cred)) {
1210
+ 				    rabp->b_flags |= B_INVAL|B_ERROR;
1211
+ 				    vfs_unbusy_pages(rabp);
1212
+ 				    brelse(rabp);
1213
+ 				}
1214
+ 			    } else
1215
+ 				brelse(rabp);
1216
+ 			}
1217
+ 		    }
1218
+ 		}
1219
+ #endif
1220
+ 
1221
+ 		/*
1222
+ 		 * If the block is in the cache and has the required data
1223
+ 		 * in a valid region, just copy it out.
1224
+ 		 * Otherwise, get the block and write back/read in,
1225
+ 		 * as required.
1226
+ 		 */
1227
+ again:
1228
+ 		bufsize = biosize;
1229
+ 		if ((off_t)(lbn + 1) * biosize > np->n_size && 
1230
+ 		    (off_t)(lbn + 1) * biosize - np->n_size < biosize) {
1231
+ 			bufsize = np->n_size - (off_t)lbn * biosize;
1232
+ 			bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1233
+ 		}
1234
+ 		bp = u9fs_getcacheblk(vp, lbn, bufsize, p);
1235
+ 		if (!bp)
1236
+ 			return (EINTR);
1237
+ 		/*
1238
+ 		 * If we are being called from u9fs_getpages, we must
1239
+ 		 * make sure the buffer is a vmio buffer.  The vp will
1240
+ 		 * already be setup for vmio but there may be some old
1241
+ 		 * non-vmio buffers attached to it.
1242
+ 		 */
1243
+ 		if (getpages && !(bp->b_flags & B_VMIO)) {
1244
+ #ifdef DIAGNOSTIC
1245
+ 			printf("u9fs_bioread: non vmio buf found, discarding\n");
1246
+ #endif
1247
+ 			bp->b_flags |= B_NOCACHE;
1248
+ 			if (bp->b_dirtyend > 0) {
1249
+ 				if ((bp->b_flags & B_DELWRI) == 0)
1250
+ 					panic("u9fsbioread");
1251
+ 				if (VOP_BWRITE(bp) == EINTR)
1252
+ 					return (EINTR);
1253
+ 			} else
1254
+ 				brelse(bp);
1255
+ 			goto again;
1256
+ 		}
1257
+ 		if ((bp->b_flags & B_CACHE) == 0) {
1258
+ 		    bp->b_flags |= B_READ;
1259
+ 		    bp->b_flags &= ~(B_DONE | B_ERROR | B_INVAL);
1260
+ 		    not_readin = 0;
1261
+ 		    vfs_busy_pages(bp, 0);
1262
+ 		    error = u9fs_doio(bp, cred, p);
1263
+ 		    if (error) {
1264
+ 			brelse(bp);
1265
+ 			return (error);
1266
+ 		    }
1267
+ 		    np->n_qid.vers = np->n_dir.dir_qid.vers;
1268
+ 		}
1269
+ 		if (bufsize > on) {
1270
+ 			n = min((unsigned)(bufsize - on), uio->uio_resid);
1271
+ 		} else {
1272
+ 			n = 0;
1273
+ 		}
1274
+ 		diff = np->n_size - uio->uio_offset;
1275
+ 		if (diff < n)
1276
+ 			n = diff;
1277
+ 		if (not_readin && n > 0) {
1278
+ 			if (on < bp->b_validoff || (on + n) > bp->b_validend) {
1279
+ 				bp->b_flags |= B_NOCACHE;
1280
+ 				if (bp->b_dirtyend > 0) {
1281
+ 				    if ((bp->b_flags & B_DELWRI) == 0)
1282
+ 					panic("u9fsbioread");
1283
+ 				    if (VOP_BWRITE(bp) == EINTR)
1284
+ 					return (EINTR);
1285
+ 				} else
1286
+ 				    brelse(bp);
1287
+ 				goto again;
1288
+ 			}
1289
+ 		}
1290
+ 		vp->v_lastr = lbn;
1291
+ 		diff = (on >= bp->b_validend) ? 0 : (bp->b_validend - on);
1292
+ 		if (diff < n)
1293
+ 			n = diff;
1294
+ 		break;
1295
+ 	    case VDIR:
1296
+ 	        biosize = nmp->nm_readdirsize;
1297
+ 		lbn = (uoff_t)uio->uio_offset / biosize;
1298
+ 		on = uio->uio_offset % biosize;
1299
+ 		bp = u9fs_getcacheblk(vp, lbn, biosize, p);
1300
+ 		if (!bp)
1301
+ 		    return (EINTR);
1302
+ 		if ((bp->b_flags & B_CACHE) == 0) {
1303
+ 		    bp->b_flags |= B_READ;
1304
+ 		    vfs_busy_pages(bp, 0);
1305
+ 		    error = u9fs_doio(bp, cred, p);
1306
+ 		    if (error) {
1307
+ 			    brelse(bp);
1308
+ 		    }
1309
+ 		    if (error)
1310
+ 			    return (error);
1311
+ 		    np->n_qid.vers = np->n_dir.dir_qid.vers;
1312
+ 		}
1313
+ 
1314
+ 		/*
1315
+ 		 * Make sure we use a signed variant of min() since
1316
+ 		 * the second term may be negative.
1317
+ 		 */
1318
+ 		n = lmin(uio->uio_resid, biosize - bp->b_resid - on);
1319
+ 		break;
1320
+ 	    default:
1321
+ 		printf(" u9fs_bioread: type %x unexpected\n",vp->v_type);
1322
+ 		break;
1323
+ 	    };
1324
+ 
1325
+ 	    if (n > 0) {
1326
+ 		    error = uiomove(bp->b_data + on, (int)n, uio);
1327
+ 	    }
1328
+ 	    brelse(bp);
1329
+ 	} while (error == 0 && uio->uio_resid > 0 && n > 0);
1330
+ 	return (error);
1331
+ }
1332
+ 
1333
+ /*
1334
+  * Vnode op for write using bio
1335
+  */
1336
+ int
1337
+ u9fs_biowrite(vp, uio, ioflag, cred)
1338
+      register struct vnode *vp;
1339
+      register struct uio *uio;
1340
+      register int  ioflag;
1341
+      register struct ucred *cred;
1342
+ {
1343
+   register int biosize;
1344
+   struct proc *p = uio->uio_procp;
1345
+   struct u9fsnode *np = VTOU9FS(vp);
1346
+   struct buf *bp;
1347
+   struct vattr vattr;
1348
+   struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
1349
+   daddr_t lbn;
1350
+   int bufsize;
1351
+   int n, on, error = 0;
1352
+ 
1353
+   if (ioflag & (IO_APPEND | IO_SYNC)) {
1354
+     if (ioflag & IO_APPEND) {
1355
+       error = VOP_GETATTR(vp, &vattr, cred, p);
1356
+       if (error)
1357
+ 	return (error);
1358
+       uio->uio_offset = np->n_size;
1359
+     }
1360
+   }
1361
+   if (uio->uio_offset < 0)
1362
+     return (EINVAL);
1363
+   if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
1364
+     return (EFBIG);
1365
+   if (uio->uio_resid == 0)
1366
+     return (0);
1367
+ 
1368
+ 	/*
1369
+ 	 * I use nm_rsize, not nm_wsize so that all buffer cache blocks
1370
+ 	 * will be the same size within a filesystem. nfs_writerpc will
1371
+ 	 * still use nm_wsize when sizing the rpc's.
1372
+ 	 */
1373
+ 	biosize = vp->v_mount->mnt_stat.f_iosize;
1374
+ 	do {
1375
+ 		lbn = uio->uio_offset / biosize;
1376
+ 		on = uio->uio_offset & (biosize-1);
1377
+ 		n = min((unsigned)(biosize - on), uio->uio_resid);
1378
+ 		if (uio->uio_offset + n > np->n_size) {
1379
+ 			np->n_size = uio->uio_offset + n;
1380
+ 			vnode_pager_setsize(vp, np->n_size);
1381
+ 		}
1382
+ 		bufsize = biosize;
1383
+ 		if ((off_t)(lbn + 1) * biosize > np->n_size) {
1384
+ 			bufsize = np->n_size - (off_t)lbn * biosize;
1385
+ 			bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1386
+ 		}
1387
+ 		bp = u9fs_getcacheblk(vp, lbn, bufsize, p);
1388
+ 		if (!bp)
1389
+ 			return (EINTR);
1390
+ 		if (bp->b_wcred == NOCRED) {
1391
+ 			crhold(cred);
1392
+ 			bp->b_wcred = cred;
1393
+ 		}
1394
+ 
1395
+ 		error = uiomove((char *)bp->b_data + on, n, uio);
1396
+ 		if (error) {
1397
+ 			bp->b_flags |= B_ERROR;
1398
+ 			brelse(bp);
1399
+ 			return (error);
1400
+ 		}
1401
+ 
1402
+ 		/*
1403
+ 		 * This will keep the buffer and mmaped regions more coherent.
1404
+ 		 */
1405
+ 		u9fs_prot_buf(bp, on, n);
1406
+ 		bp->b_dirtyoff = on;
1407
+ 		bp->b_dirtyend = on + n;
1408
+ 
1409
+ 		if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
1410
+ 		    bp->b_validoff > bp->b_dirtyend) {
1411
+ 		  /* XXX: destroys our read cache if not overlapping */
1412
+ 		  /* two choice: none implemented
1413
+ 		     1> keep the bigger(smaller) piece
1414
+ 		     2> read the missing segment		     
1415
+ 		  */
1416
+ 			bp->b_validoff = bp->b_dirtyoff;
1417
+ 			bp->b_validend = bp->b_dirtyend;
1418
+ 		} else {
1419
+ 			bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
1420
+ 			bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
1421
+ 		}
1422
+ 
1423
+ 		error = bwrite(bp);
1424
+ 		if( error ) {
1425
+ 		  bp->b_flags |= B_ERROR;
1426
+ 		  /* brelse(bp); */
1427
+ 		  return error;		  
1428
+ 		}
1429
+ 	} while (uio->uio_resid > 0 && n > 0);
1430
+ 	return 0;
1431
+ }
1432
+ 
1433
+ /*
1434
+  * Do an I/O operation to/from a cache block. This may be called
1435
+  * synchronously or from an u9fsiod.
1436
+  */
1437
+ int
1438
+ u9fs_doio(bp, cr, p)
1439
+ 	register struct buf *bp;
1440
+ 	struct ucred *cr;
1441
+ 	struct proc *p;
1442
+ {
1443
+ 	register struct uio *uiop;
1444
+ 	register struct vnode *vp;
1445
+ 	struct u9fsnode *np;
1446
+ 	struct u9fsmount *nmp;
1447
+ 	int error = 0, diff, len;
1448
+ 	struct uio uio;
1449
+ 	struct iovec io;
1450
+ 
1451
+ 	vp = bp->b_vp;
1452
+ 	np = VTOU9FS(vp);
1453
+ 	nmp = VFSTOU9FS(vp->v_mount);
1454
+ 	uiop = &uio;
1455
+ 	uiop->uio_iov = &io;
1456
+ 	uiop->uio_iovcnt = 1;
1457
+ 	uiop->uio_segflg = UIO_SYSSPACE;
1458
+ 	uiop->uio_procp = p;
1459
+ 
1460
+ 	if (bp->b_flags & B_READ ) {
1461
+ 	    io.iov_len = uiop->uio_resid = bp->b_bcount;
1462
+ 	    io.iov_base = bp->b_data;
1463
+ 	    uiop->uio_rw = UIO_READ;
1464
+ 	    switch (vp->v_type) {
1465
+ 	    case VREG:
1466
+ 		uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
1467
+ 		error = u9fs_readrpc(vp, uiop, cr);
1468
+ 		if (!error) {
1469
+ 		    bp->b_validoff = 0;
1470
+ 		    if (uiop->uio_resid) {
1471
+ 			/*
1472
+ 			 * If len > 0, there is a hole in the file and
1473
+ 			 * no writes after the hole have been pushed to
1474
+ 			 * the server yet.
1475
+ 			 * Just zero fill the rest of the valid area.
1476
+ 			 */
1477
+ 			diff = bp->b_bcount - uiop->uio_resid;
1478
+ 			len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE
1479
+ 				+ diff);
1480
+ 			if (len > 0) {
1481
+ 			    len = min(len, uiop->uio_resid);
1482
+ 			    bzero((char *)bp->b_data + diff, len);
1483
+ 			    bp->b_validend = diff + len;
1484
+ 			} else
1485
+ 			    bp->b_validend = diff;
1486
+ 		    } else
1487
+ 			bp->b_validend = bp->b_bcount;
1488
+ 		}
1489
+ 		break;
1490
+ 	    case VDIR:
1491
+ 		uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * nmp->nm_readdirsize;
1492
+ 		error = u9fs_readdirrpc(vp, uiop, cr);
1493
+ 		if (error == 0 && uiop->uio_resid == bp->b_bcount)
1494
+ 		  bp->b_flags |= B_INVAL;
1495
+ 		break;
1496
+ 	    default:
1497
+ 		printf("u9fs_doio:  type %x unexpected\n",vp->v_type);
1498
+ 		break;
1499
+ 	    };
1500
+ 	    if (error) {
1501
+ 		bp->b_flags |= B_ERROR;
1502
+ 		bp->b_error = error;
1503
+ 	    }
1504
+ 	} else {
1505
+ 	    if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)
1506
+ 		bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;
1507
+ 
1508
+ 	    if (bp->b_dirtyend > bp->b_dirtyoff) {
1509
+ 		io.iov_len = uiop->uio_resid = bp->b_dirtyend
1510
+ 		    - bp->b_dirtyoff;
1511
+ 		uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE
1512
+ 		    + bp->b_dirtyoff;
1513
+ 		io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
1514
+ 		uiop->uio_rw = UIO_WRITE;
1515
+ 		bp->b_flags |= B_WRITEINPROG;
1516
+ 		error = u9fs_writerpc(vp, uiop, cr);
1517
+ 		bp->b_flags &= ~B_WRITEINPROG;
1518
+ 
1519
+ 		if (error) {
1520
+ 		  bp->b_flags |= B_ERROR;
1521
+ 		  bp->b_error = np->n_error = error;
1522
+ 		  np->n_flag |= NWRITEERR;
1523
+ 		}
1524
+ 		bp->b_dirtyoff = bp->b_dirtyend = 0;
1525
+ 	    } else {
1526
+ 		bp->b_resid = 0;
1527
+ 		biodone(bp);
1528
+ 		return (0);
1529
+ 	    }
1530
+ 	}
1531
+ 	bp->b_resid = uiop->uio_resid;
1532
+ 	biodone(bp);
1533
+ 	return error;
1534
+ }
1535
+ 
1536
+ /*
1537
+  * Get an u9fs cache block.
1538
+  * Allocate a new one if the block isn't currently in the cache
1539
+  * and return the block marked busy. If the calling process is
1540
+  * interrupted by a signal for an interruptible mount point, return
1541
+  * NULL.
1542
+  */
1543
+ static struct buf *
1544
+ u9fs_getcacheblk(vp, bn, size, p)
1545
+ 	struct vnode *vp;
1546
+ 	daddr_t bn;
1547
+ 	int size;
1548
+ 	struct proc *p;
1549
+ {
1550
+ 	register struct buf *bp;
1551
+ 	struct mount *mp;
1552
+ 	struct u9fsmount *nmp;
1553
+ 
1554
+ 	mp = vp->v_mount;
1555
+ 	nmp = VFSTOU9FS(mp);
1556
+ 
1557
+ 	if (nmp->nm_flag & U9FSMNT_INT) {
1558
+ 		bp = getblk(vp, bn, size, PCATCH, 0);
1559
+ 		while (bp == (struct buf *)0) {
1560
+ 			if (u9fs_sigintr(nmp, p))
1561
+ 				return ((struct buf *)0);
1562
+ 			bp = getblk(vp, bn, size, 0, 2 * hz);
1563
+ 		}
1564
+ 	} else
1565
+ 		bp = getblk(vp, bn, size, 0, 0);
1566
+ 
1567
+ 	if (vp->v_type == VREG) {
1568
+ 		int biosize;
1569
+ 		biosize = mp->mnt_stat.f_iosize;
1570
+ 		bp->b_blkno = bn * (biosize / DEV_BSIZE);
1571
+ 	}
1572
+ 
1573
+ 	return (bp);
1574
+ }
1575
+ 
1576
+ static void
1577
+ u9fs_prot_buf(bp, off, n)
1578
+ 	struct buf *bp;
1579
+ 	int off;
1580
+ 	int n;
1581
+ {
1582
+ 	int pindex, boff, end;
1583
+ 
1584
+ 	if ((bp->b_flags & B_VMIO) == 0)
1585
+ 		return;
1586
+ 
1587
+ 	end = round_page(off + n);
1588
+ 	for (boff = trunc_page(off); boff < end; boff += PAGE_SIZE) {
1589
+ 		pindex = boff >> PAGE_SHIFT;
1590
+ 		vm_page_protect(bp->b_pages[pindex], VM_PROT_NONE);
1591
+ 	}
1592
+ }
1593
+ 
1594
+ /*
1595
+  * Flush and invalidate all dirty buffers. If another process is already
1596
+  * doing the flush, just wait for completion.
1597
+  */
1598
+ int
1599
+ u9fs_vinvalbuf(vp, flags, cred, p, intrflg)
1600
+ 	struct vnode *vp;
1601
+ 	int flags;
1602
+ 	struct ucred *cred;
1603
+ 	struct proc *p;
1604
+ 	int intrflg;
1605
+ {
1606
+ 	register struct u9fsnode *np = VTOU9FS(vp);
1607
+ 	struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
1608
+ 	int error = 0, slpflag, slptimeo;
1609
+ 
1610
+ 	if (vp->v_flag & VXLOCK) {
1611
+ 		return (0);
1612
+ 	}
1613
+ 
1614
+ 	if ((nmp->nm_flag & U9FSMNT_INT) == 0)
1615
+ 		intrflg = 0;
1616
+ 	if (intrflg) {
1617
+ 		slpflag = PCATCH;
1618
+ 		slptimeo = 2 * hz;
1619
+ 	} else {
1620
+ 		slpflag = 0;
1621
+ 		slptimeo = 0;
1622
+ 	}
1623
+ 	/*
1624
+ 	 * First wait for any other process doing a flush to complete.
1625
+ 	 */
1626
+ 	while (np->n_flag & NFLUSHINPROG) {
1627
+ 		np->n_flag |= NFLUSHWANT;
1628
+ 		error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "u9fsvinval",
1629
+ 			slptimeo);
1630
+ 		if (error && intrflg && u9fs_sigintr(nmp, p))
1631
+ 			return (EINTR);
1632
+ 	}
1633
+ 
1634
+ 	/*
1635
+ 	 * Now, flush as required.
1636
+ 	 */
1637
+ 	np->n_flag |= NFLUSHINPROG;
1638
+ 	error = vinvalbuf(vp, flags, cred, p, slpflag, 0);
1639
+ 	while (error) {
1640
+ 		if (intrflg && u9fs_sigintr(nmp, p)) {
1641
+ 			np->n_flag &= ~NFLUSHINPROG;
1642
+ 			if (np->n_flag & NFLUSHWANT) {
1643
+ 				np->n_flag &= ~NFLUSHWANT;
1644
+ 				wakeup((caddr_t)&np->n_flag);
1645
+ 			}
1646
+ 			return (EINTR);
1647
+ 		}
1648
+ 		error = vinvalbuf(vp, flags, cred, p, 0, slptimeo);
1649
+ 	}
1650
+ 	np->n_flag &= ~(NMODIFIED | NFLUSHINPROG);
1651
+ 	if (np->n_flag & NFLUSHWANT) {
1652
+ 		np->n_flag &= ~NFLUSHWANT;
1653
+ 		wakeup((caddr_t)&np->n_flag);
1654
+ 	}
1655
+ 	return (0);
1656
+ }
1657
+ 
1658
diff -N -c -r /usr/src/sys/9fs/9fs_node.c ./9fs/9fs_node.c
1659
*** /usr/src/sys/9fs/9fs_node.c	Wed Dec 31 19:00:00 1969
1660
--- ./9fs/9fs_node.c	Thu Nov 25 15:36:49 1999
1661
***************
1662
*** 0 ****
1663
--- 1,132 ----
1664
+ #include <sys/param.h>
1665
+ #include <sys/sockio.h>
1666
+ #include <sys/proc.h>
1667
+ #include <sys/vnode.h>
1668
+ #include <sys/kernel.h>
1669
+ #include <sys/sysctl.h>
1670
+ #include <sys/malloc.h>
1671
+ #include <sys/mount.h>
1672
+ #include <sys/mbuf.h>
1673
+ #include <sys/socket.h>
1674
+ #include <sys/socketvar.h>
1675
+ #include <sys/systm.h>
1676
+ #include <sys/protosw.h>
1677
+ #include <sys/syslog.h>
1678
+ 
1679
+ #include <netinet/in.h>
1680
+ #include <netinet/tcp.h>
1681
+ 
1682
+ #include <vm/vm.h>
1683
+ #include <vm/vm_extern.h>
1684
+ #include <vm/vm_zone.h>
1685
+ 
1686
+ #include <net/if.h>
1687
+ #include <net/route.h>
1688
+ #include <netinet/in.h>
1689
+ 
1690
+ #include <9fs/bitstring.h>
1691
+ #include <9fs/9p.h>
1692
+ #include <9fs/9auth.h>
1693
+ #include <9fs/9fs.h>
1694
+ 
1695
+ vm_zone_t u9fsnode_zone;
1696
+ static LIST_HEAD(u9fsnodehashhead, u9fsnode) *u9fsnodehashtbl;
1697
+ static u_long u9fsnodehash;
1698
+ MALLOC_DEFINE(M_U9FSHASH, "U9FS hash", "U9FS hash tables");
1699
+ 
1700
+ /*
1701
+  * Initialize hash links for u9fsnodes
1702
+  * and build u9fsnode free list.
1703
+  */
1704
+ void
1705
+ u9fs_nhinit()
1706
+ {
1707
+   u9fsnode_zone = zinit("U9FSNODE", sizeof(struct u9fsnode), 0, 0, 1);
1708
+   u9fsnodehashtbl = phashinit(desiredvnodes, M_U9FSHASH, &u9fsnodehash);
1709
+ }
1710
+ 
1711
+ /*
1712
+  * Look up a vnode/u9fsnode by file handle.
1713
+  * Callers must check for mount points!!
1714
+  * In all cases, a pointer to a
1715
+  * u9fsnode structure is returned.
1716
+  */
1717
+ static int u9fs_node_hash_lock;
1718
+ 
1719
+ int
1720
+ u9fs_nget(mntp, fh, npp, p)
1721
+      struct mount *mntp;
1722
+      register u9fsfh_t fh;
1723
+      struct u9fsnode **npp;
1724
+      struct proc * p;
1725
+ {
1726
+   struct u9fsnode *np;
1727
+   struct u9fsnodehashhead *nhpp;
1728
+   register struct vnode *vp;
1729
+   struct vnode *nvp;
1730
+   int error;
1731
+ 
1732
+   nhpp = U9FSNOHASH(fh);
1733
+ loop:
1734
+   for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
1735
+     if (mntp != U9FSTOV(np)->v_mount || fh != np->n_qid.path )
1736
+       continue;
1737
+     vp = U9FSTOV(np);
1738
+     if (vget(vp, LK_EXCLUSIVE, p))
1739
+       goto loop;
1740
+     *npp = np;
1741
+     return(0);
1742
+   }
1743
+   /*
1744
+    * Obtain a lock to prevent a race condition if the getnewvnode()
1745
+    * or MALLOC() below happens to block.
1746
+    */
1747
+   if (u9fs_node_hash_lock) {
1748
+     while (u9fs_node_hash_lock) {
1749
+       u9fs_node_hash_lock = -1;
1750
+       tsleep(&u9fs_node_hash_lock, PVM, "u9fsngt", 0);
1751
+     }
1752
+     goto loop;
1753
+   }
1754
+   u9fs_node_hash_lock = 1;
1755
+ 
1756
+   /*
1757
+    * allocate before getnewvnode since doing so afterward
1758
+    * might cause a bogus v_data pointer to get dereferenced
1759
+    * elsewhere if zalloc should block.
1760
+    */
1761
+   np = zalloc(u9fsnode_zone);
1762
+   
1763
+   error = getnewvnode(VT_U9FS, mntp, u9fs_vnodeop_p, &nvp);
1764
+   if (error) {
1765
+     if (u9fs_node_hash_lock < 0)
1766
+       wakeup(&u9fs_node_hash_lock);
1767
+     u9fs_node_hash_lock = 0;
1768
+     *npp = 0;
1769
+     zfree(u9fsnode_zone, np);
1770
+     return (error);
1771
+   }
1772
+   vp = nvp;
1773
+   bzero((caddr_t)np, sizeof *np);
1774
+   vp->v_data = np;
1775
+   np->n_vnode = vp;
1776
+   /*
1777
+    * Insert the u9fsnode in the hash queue for its new file handle
1778
+    */
1779
+   LIST_INSERT_HEAD(nhpp, np, n_hash);
1780
+   np->n_qid.path = fh;
1781
+   np->n_qid.vers = 0; /* not in cache yet */
1782
+   np->n_fid = 0; /* should be set by the caller */
1783
+   *npp = np;
1784
+ 
1785
+   if (u9fs_node_hash_lock < 0)
1786
+     wakeup(&u9fs_node_hash_lock);
1787
+   u9fs_node_hash_lock = 0;
1788
+ 
1789
+   /*
1790
+    * Lock the new u9fsnode.
1791
+    */
1792
+   vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1793
+   
1794
+   return (0);
1795
+ }
1796
diff -N -c -r /usr/src/sys/9fs/9fs_socket.c ./9fs/9fs_socket.c
1797
*** /usr/src/sys/9fs/9fs_socket.c	Wed Dec 31 19:00:00 1969
1798
--- ./9fs/9fs_socket.c	Thu Nov 25 15:48:46 1999
1799
***************
1800
*** 0 ****
1801
--- 1,503 ----
1802
+ #include <sys/param.h>
1803
+ #include <sys/sockio.h>
1804
+ #include <sys/proc.h>
1805
+ #include <sys/vnode.h>
1806
+ #include <sys/kernel.h>
1807
+ #include <sys/sysctl.h>
1808
+ #include <sys/malloc.h>
1809
+ #include <sys/mount.h>
1810
+ #include <sys/mbuf.h>
1811
+ #include <sys/socket.h>
1812
+ #include <sys/socketvar.h>
1813
+ #include <sys/systm.h>
1814
+ #include <sys/protosw.h>
1815
+ #include <sys/syslog.h>
1816
+ 
1817
+ #include <netinet/in.h>
1818
+ #include <netinet/tcp.h>
1819
+ 
1820
+ #include <vm/vm.h>
1821
+ #include <vm/vm_extern.h>
1822
+ #include <vm/vm_zone.h>
1823
+ 
1824
+ #include <net/if.h>
1825
+ #include <net/route.h>
1826
+ #include <netinet/in.h>
1827
+ 
1828
+ #include <9fs/bitstring.h>
1829
+ #include <9fs/9p.h>
1830
+ #include <9fs/9auth.h>
1831
+ #include <9fs/9fs.h>
1832
+ 
1833
+ static int u9fs_reply __P((struct u9fsreq * req));
1834
+ static int u9fs_send __P((struct socket * so, struct mbuf * mreq, struct u9fsreq * req));
1835
+ static int u9fs_receive __P((struct socket * so, struct mbuf **mrep, struct u9fsreq * req));
1836
+ 
1837
+ static int u9fs_sndlock __P((int *flagp, int *statep, struct u9fsreq *rep));
1838
+ static void u9fs_sndunlock __P((int *flagp, int *statep));
1839
+ static int u9fs_rcvlock __P((struct u9fsreq *req));
1840
+ static void u9fs_rcvunlock __P((int *flagp, int *statep));
1841
+ 
1842
+ int
1843
+ u9fs_connect(struct socket ** sop, struct sockaddr * saddr, int sotype, int soproto, struct proc * p)
1844
+ {
1845
+   register struct socket * so;
1846
+   int error, s;
1847
+   
1848
+   *sop = 0;
1849
+   error = socreate(saddr->sa_family, sop, sotype, soproto, p);
1850
+   if( error )
1851
+     return error;
1852
+   so = *sop;
1853
+   error = soconnect(so, saddr, p);
1854
+   if( error )
1855
+     return error;
1856
+ 
1857
+   /*
1858
+    * Wait for the connection to complete. Cribbed from the
1859
+    * connect system call but with the wait timing out so
1860
+    * that interruptible mounts don't hang here for a long time.
1861
+    */
1862
+   s = splnet();
1863
+   while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
1864
+     (void) tsleep((caddr_t)&so->so_timeo, PSOCK,
1865
+ 		  "u9fscon", 2 * hz);
1866
+ 
1867
+   if (so->so_error) {
1868
+     error = so->so_error;
1869
+     so->so_error = 0;
1870
+     splx(s);
1871
+     return error;
1872
+   }
1873
+   splx(s);
1874
+ 
1875
+   return (0);
1876
+ }
1877
+ 
1878
+ int u9fs_connect_9auth(struct u9fsmount * nmp, struct u9fs_args * argp, struct socket ** sop)
1879
+ {
1880
+   int error;
1881
+   struct proc * p = & proc0;
1882
+   struct sockaddr *nam;
1883
+ 
1884
+   error = getsockaddr(&nam, (caddr_t)argp->authaddr, argp->authaddrlen);
1885
+   if( error )
1886
+     return error;
1887
+   error = u9fs_connect(sop, nam, argp->authsotype, 
1888
+ 		       argp->authsoproto, p);
1889
+   if( error == 0 )
1890
+     return 0;
1891
+ 
1892
+   u9fs_disconnect(*sop);
1893
+   *sop = 0;
1894
+   return error;
1895
+ }
1896
+ 
1897
+ /*
1898
+  * Initialize sockets and congestion for a new U9FS connection.
1899
+  * We do not free the sockaddr if error.
1900
+  */
1901
+ int
1902
+ u9fs_connect_9fs(nmp)
1903
+      register struct u9fsmount *nmp;
1904
+ {
1905
+   register struct socket *so;
1906
+   int error, rcvreserve, sndreserve;
1907
+   struct proc *p = &proc0; /* only used for socreate and sobind */
1908
+ 
1909
+   error = u9fs_connect(&nmp->nm_so, nmp->nm_nam, nmp->nm_sotype, 
1910
+ 		       nmp->nm_soproto, p);
1911
+   if (error)
1912
+     goto bad;
1913
+   so = nmp->nm_so;
1914
+   nmp->nm_soflags = so->so_proto->pr_flags;
1915
+ 
1916
+   if (nmp->nm_flag & (U9FSMNT_SOFT | U9FSMNT_INT)) {
1917
+     so->so_rcv.sb_timeo = (5 * hz);
1918
+     so->so_snd.sb_timeo = (5 * hz);
1919
+   } else {
1920
+     so->so_rcv.sb_timeo = 0;
1921
+     so->so_snd.sb_timeo = 0;
1922
+   }
1923
+ 
1924
+   /* XXX: i dont understand this, only one outstanding request? */
1925
+   if (nmp->nm_sotype == SOCK_SEQPACKET) {
1926
+     sndreserve = (nmp->nm_wsize) * 2;
1927
+     rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize)) * 2;
1928
+   } else {
1929
+     if (nmp->nm_sotype != SOCK_STREAM)
1930
+       panic("u9fscon sotype");
1931
+     if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
1932
+       struct sockopt sopt;
1933
+       int val;
1934
+       
1935
+       bzero(&sopt, sizeof sopt);
1936
+       sopt.sopt_level = SOL_SOCKET;
1937
+       sopt.sopt_name = SO_KEEPALIVE;
1938
+       sopt.sopt_val = &val;
1939
+       sopt.sopt_valsize = sizeof val;
1940
+       val = 1;
1941
+       sosetopt(so, &sopt);
1942
+     }
1943
+     if (so->so_proto->pr_protocol == IPPROTO_TCP) {
1944
+       struct sockopt sopt;
1945
+       int val;
1946
+       
1947
+       bzero(&sopt, sizeof sopt);
1948
+       sopt.sopt_level = IPPROTO_TCP;
1949
+       sopt.sopt_name = TCP_NODELAY;
1950
+       sopt.sopt_val = &val;
1951
+       sopt.sopt_valsize = sizeof val;
1952
+       val = 1;
1953
+       sosetopt(so, &sopt);
1954
+     }
1955
+     sndreserve = (nmp->nm_wsize) * 2;
1956
+     rcvreserve = (nmp->nm_rsize) * 2;
1957
+   }
1958
+   error = soreserve(so, sndreserve, rcvreserve);
1959
+   if (error)
1960
+     goto bad;
1961
+   so->so_rcv.sb_flags |= SB_NOINTR;
1962
+   so->so_snd.sb_flags |= SB_NOINTR;
1963
+ 
1964
+   /* Initialize other non-zero congestion variables */
1965
+   nmp->nm_sent = 0;
1966
+   return (0);
1967
+ 
1968
+ bad:
1969
+   u9fs_disconnect(nmp->nm_so);
1970
+   nmp->nm_so = 0;
1971
+   return (error);
1972
+ }
1973
+ 
1974
+ /*
1975
+  * U9FS disconnect. Clean up and unlink.
1976
+  */
1977
+ void
1978
+ u9fs_disconnect(struct socket * so)
1979
+ {
1980
+     soshutdown(so, 2);
1981
+     soclose(so);
1982
+ }
1983
+ 
1984
+ /*
1985
+  * Lock a socket against others.
1986
+  * Necessary for STREAM sockets to ensure you get an entire rpc request/reply
1987
+  * and also to avoid race conditions between the processes with u9fs requests
1988
+  * in progress when a reconnect is necessary.
1989
+  */
1990
+ static int
1991
+ u9fs_sndlock(flagp, statep, rep)
1992
+ 	register int *flagp;
1993
+ 	register int *statep;
1994
+ 	struct u9fsreq *rep;
1995
+ {
1996
+ 	struct proc *p;
1997
+ 	int slpflag = 0, slptimeo = 0;
1998
+ 
1999
+ 	if (rep) {
2000
+ 		p = rep->r_procp;
2001
+ 		if (rep->r_nmp->nm_flag & U9FSMNT_INT)
2002
+ 			slpflag = PCATCH;
2003
+ 	} else
2004
+ 		p = (struct proc *)0;
2005
+ 	while (*statep & U9FSSTA_SNDLOCK) {
2006
+ 		if (u9fs_sigintr(rep->r_nmp, p))
2007
+ 			return (EINTR);
2008
+ 		*statep |= U9FSSTA_WANTSND;
2009
+ 		(void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1),
2010
+ 			"u9fsndlck", slptimeo);
2011
+ 		if (slpflag == PCATCH) {
2012
+ 			slpflag = 0;
2013
+ 			slptimeo = 2 * hz;
2014
+ 		}
2015
+ 	}
2016
+ 	*statep |= U9FSSTA_SNDLOCK;
2017
+ 	return (0);
2018
+ }
2019
+ 
2020
+ 
2021
+ /*
2022
+  * Unlock the stream socket for others.
2023
+  */
2024
+ static void
2025
+ u9fs_sndunlock(flagp, statep)
2026
+ 	register int *flagp;
2027
+ 	register int *statep;
2028
+ {
2029
+ 
2030
+ 	if ((*statep & U9FSSTA_SNDLOCK) == 0)
2031
+ 		panic("u9fs sndunlock");
2032
+ 	*statep &= ~U9FSSTA_SNDLOCK;
2033
+ 	if (*statep & U9FSSTA_WANTSND) {
2034
+ 		*statep &= ~U9FSSTA_WANTSND;
2035
+ 		wakeup((caddr_t)flagp);
2036
+ 	}
2037
+ }
2038
+ 
2039
+ /*
2040
+  * Test for a termination condition pending on the process.
2041
+  * This is used for U9FSMNT_INT mounts.
2042
+  */
2043
+ int
2044
+ u9fs_sigintr(nmp, p)
2045
+ 	struct u9fsmount *nmp;
2046
+ 	struct proc * p;
2047
+ {
2048
+ 	if (!(nmp->nm_flag & U9FSMNT_INT))
2049
+ 		return (0);
2050
+ 	if (p && p->p_siglist &&
2051
+ 	    (((p->p_siglist & ~p->p_sigmask) & ~p->p_sigignore) &
2052
+ 	    U9FSINT_SIGMASK))
2053
+ 		return (EINTR);
2054
+ 	return (0);
2055
+ }
2056
+ 
2057
+ /*
2058
+  * This is the u9fs send routine. For connection based socket types, it
2059
+  * must be called with an u9fs_sndlock() on the socket.
2060
+  * "rep == NULL" indicates that it has been called from a server.
2061
+  * For the client side:
2062
+  * - return EINTR if the RPC is terminated, 0 otherwise
2063
+  * - set R_MUSTRESEND if the send fails for any reason
2064
+  * - do any cleanup required by recoverable socket errors (?)
2065
+  * For the server side:
2066
+  * - return EINTR or ERESTART if interrupted by a signal
2067
+  * - return EPIPE if a connection is lost for connection based sockets (TCP...)
2068
+  * - do any cleanup required by recoverable socket errors (?)
2069
+  */
2070
+ static int
2071
+ u9fs_send(so, top, req)
2072
+ 	register struct socket *so;
2073
+ 	register struct mbuf *top;
2074
+ 	struct u9fsreq *req;
2075
+ {
2076
+   int error, soflags, flags;
2077
+   
2078
+   soflags = so->so_proto->pr_flags;
2079
+   if (so->so_type == SOCK_SEQPACKET)
2080
+     flags = MSG_EOR;
2081
+   else
2082
+     flags = 0;
2083
+   
2084
+   error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 0, top, 0,
2085
+ 					       flags, req->r_procp);
2086
+   if (error)
2087
+     log(LOG_INFO, "u9fs send error %d for server %s\n",error,
2088
+ 	  req->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
2089
+ 
2090
+   return (error);
2091
+ }
2092
+ 
2093
+ static int
2094
+ u9fs_receive(so, mrep, req)	
2095
+      register struct socket * so;
2096
+      struct mbuf **mrep;
2097
+      struct u9fsreq * req;
2098
+ {
2099
+   struct uio auio;
2100
+   u_int32_t len;
2101
+   int error = 0, sotype, rcvflg;
2102
+   
2103
+   /*
2104
+    * Set up arguments for soreceive()
2105
+    */
2106
+   *mrep = (struct mbuf *)0;
2107
+   sotype = req->r_nmp->nm_sotype;
2108
+   
2109
+   /*
2110
+    * For reliable protocols, lock against other senders/receivers
2111
+    * in case a reconnect is necessary.
2112
+    * For SOCK_STREAM, first get the Record Mark to find out how much
2113
+    * more there is to get.
2114
+    * We must lock the socket against other receivers
2115
+    * until we have an entire rpc request/reply.
2116
+    */
2117
+   if (sotype == SOCK_SEQPACKET ) {
2118
+     if( (so->so_state & SS_ISCONNECTED) == 0 )
2119
+       return (EACCES);
2120
+ 		auio.uio_resid = len = 1000000;
2121
+ 		auio.uio_procp = req->r_procp;
2122
+ 		do {
2123
+ 			rcvflg = 0;
2124
+ 			error =  so->so_proto->pr_usrreqs->pru_soreceive
2125
+ 				(so, 0, &auio, mrep,
2126
+ 				(struct mbuf **)0, &rcvflg);
2127
+ 		} while (error == EWOULDBLOCK);
2128
+ 		len -= auio.uio_resid;    
2129
+   }
2130
+   if (error) {
2131
+     m_freem(*mrep);
2132
+     *mrep = (struct mbuf *)0;
2133
+   }
2134
+   return (error);  
2135
+ }
2136
+ 
2137
+ static int
2138
+ u9fs_rcvlock(req)
2139
+ 	register struct u9fsreq *req;
2140
+ {
2141
+ 	register int *flagp = &req->r_nmp->nm_flag;
2142
+ 	register int *statep = &req->r_nmp->nm_state;
2143
+ 	int slpflag, slptimeo = 0;
2144
+ 
2145
+ 	if (*flagp & U9FSMNT_INT)
2146
+ 		slpflag = PCATCH;
2147
+ 	else
2148
+ 		slpflag = 0;
2149
+ 	while (*statep & U9FSSTA_RCVLOCK) {
2150
+ 		if (u9fs_sigintr(req->r_nmp, req->r_procp))
2151
+ 			return (EINTR);
2152
+ 		*statep |= U9FSSTA_WANTRCV;
2153
+ 		(void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), "u9fsrcvlk",
2154
+ 			slptimeo);
2155
+ 		/*
2156
+ 		 * If our reply was recieved while we were sleeping,
2157
+ 		 * then just return without taking the lock to avoid a
2158
+ 		 * situation where a single iod could 'capture' the
2159
+ 		 * recieve lock.
2160
+ 		 */
2161
+ 		if (req->r_mrep != NULL)
2162
+ 			return (EALREADY);
2163
+ 		if (slpflag == PCATCH) {
2164
+ 			slpflag = 0;
2165
+ 			slptimeo = 2 * hz;
2166
+ 		}
2167
+ 	}
2168
+ 	*statep |= U9FSSTA_RCVLOCK;
2169
+ 	return (0);
2170
+ }
2171
+ 
2172
+ /*
2173
+  * Unlock the stream socket for others.
2174
+  */
2175
+ static void
2176
+ u9fs_rcvunlock(flagp, statep)
2177
+ 	register int *flagp;
2178
+ 	register int *statep;
2179
+ {
2180
+ 
2181
+ 	if ((*statep & U9FSSTA_RCVLOCK) == 0)
2182
+ 		panic("u9fs rcvunlock");
2183
+ 	*statep &= ~U9FSSTA_RCVLOCK;
2184
+ 	if (*statep & U9FSSTA_WANTRCV) {
2185
+ 		*statep &= ~U9FSSTA_WANTRCV;
2186
+ 		wakeup((caddr_t)flagp);
2187
+ 	}
2188
+ }
2189
+ 
2190
+ /*
2191
+  * Implement receipt of reply on a socket.
2192
+  * We must search through the list of received datagrams matching them
2193
+  * with outstanding requests using the xid, until ours is found.
2194
+  */
2195
+ /* ARGSUSED */
2196
+ static 
2197
+ int u9fs_reply(struct u9fsreq * req)
2198
+ {
2199
+   int error;
2200
+   struct mbuf * mrep;
2201
+   register struct u9fsmount *nmp = req->r_nmp;
2202
+   u_short tag;
2203
+   struct u9fsreq * qp;
2204
+ 
2205
+   /*
2206
+    * Loop around until we get our own reply
2207
+    */
2208
+   for (;;) {
2209
+     /*
2210
+      * Lock against other receivers so that I don't get stuck in
2211
+      * sbwait() after someone else has received my reply for me.
2212
+      * Also necessary for connection based protocols to avoid
2213
+      * race conditions during a reconnect.
2214
+      * If u9fs_rcvlock() returns EALREADY, that means that
2215
+      * the reply has already been recieved by another
2216
+      * process and we can return immediately.  In this
2217
+      * case, the lock is not taken to avoid races with
2218
+      * other processes.
2219
+      */
2220
+     error = u9fs_rcvlock(req);
2221
+     if (error == EALREADY)
2222
+       return (0);
2223
+     if (error)
2224
+       return (error);
2225
+     /*
2226
+      * Get the next Rpc reply off the socket
2227
+      */
2228
+     error = u9fs_receive(nmp->nm_so, &mrep, req);
2229
+     u9fs_rcvunlock(&nmp->nm_flag, &nmp->nm_state);
2230
+     if (error)
2231
+       return (error);
2232
+ 
2233
+     /* extract the tag */
2234
+     tag = u9p_m_tag(&mrep);
2235
+ 
2236
+     /*
2237
+      * Loop through the request list to match up the reply
2238
+      * Iff no match, just drop the datagram
2239
+      */
2240
+     for (qp = nmp->nm_reqq.tqh_first; qp != 0; qp = qp->r_chain.tqe_next) {
2241
+       if ( qp->r_mrep == 0 && qp->r_tag == tag )
2242
+ 	break;
2243
+     }
2244
+     if( qp == 0 ) {
2245
+       m_freem(mrep);
2246
+       continue;
2247
+     }
2248
+ 
2249
+     if( u9p_m_m2s(&mrep, qp->r_rep) ) { /* freed by m2s */
2250
+       continue;
2251
+     }
2252
+ 
2253
+     qp->r_mrep = mrep;  /* should not be freed until the reply is read */
2254
+ 
2255
+     if( qp == req )
2256
+       return 0;
2257
+   }
2258
+ }
2259
+ 
2260
+ int u9fs_request(struct u9fsreq * req, struct u9fsreq * rep, int relm)
2261
+ {
2262
+   struct mbuf * mreq;
2263
+   int error,s;
2264
+   struct u9fsmount * nmp;  
2265
+ 
2266
+   req->r_rep = rep;
2267
+   req->r_mrep = 0;
2268
+   nmp = req->r_nmp;
2269
+   req->r_tag = u9fs_id_new(nmp->nm_tags);
2270
+ 
2271
+   mreq = u9p_m_s2m(req);
2272
+ 
2273
+   /*
2274
+    * Chain request into list of outstanding requests. Be sure
2275
+    * to put it LAST so timer finds oldest requests first.
2276
+    */
2277
+   s = splsoftclock();
2278
+   TAILQ_INSERT_TAIL(&nmp->nm_reqq, req, r_chain);
2279
+   splx(s);
2280
+ 
2281
+   error = u9fs_send(nmp->nm_so, mreq, req);
2282
+ 
2283
+   if( !error )
2284
+     error = u9fs_reply(req);
2285
+ 
2286
+   /*
2287
+    * RPC done, unlink the request.
2288
+    */
2289
+   s = splsoftclock();
2290
+   TAILQ_REMOVE(&nmp->nm_reqq, req, r_chain);
2291
+   splx(s);
2292
+ 
2293
+   u9fs_id_free(nmp->nm_tags, req->r_tag);
2294
+ 
2295
+   if( !error && relm ) {
2296
+ 	m_freem(req->r_mrep);
2297
+ 	req->r_mrep = 0;
2298
+   }      
2299
+   if( rep->r_type == Rerror )
2300
+       error = EACCES;
2301
+ 
2302
+   return error;
2303
+ }
2304
+ 
2305
diff -N -c -r /usr/src/sys/9fs/9fs_subr.c ./9fs/9fs_subr.c
2306
*** /usr/src/sys/9fs/9fs_subr.c	Wed Dec 31 19:00:00 1969
2307
--- ./9fs/9fs_subr.c	Fri Nov 26 12:28:17 1999
2308
***************
2309
*** 0 ****
2310
--- 1,240 ----
2311
+ #include <sys/param.h>
2312
+ #include <sys/sockio.h>
2313
+ #include <sys/proc.h>
2314
+ #include <sys/vnode.h>
2315
+ #include <sys/kernel.h>
2316
+ #include <sys/sysctl.h>
2317
+ #include <sys/malloc.h>
2318
+ #include <sys/mount.h>
2319
+ #include <sys/mbuf.h>
2320
+ #include <sys/socket.h>
2321
+ #include <sys/socketvar.h>
2322
+ #include <sys/systm.h>
2323
+ #include <sys/protosw.h>
2324
+ #include <sys/syslog.h>
2325
+ 
2326
+ #include <netinet/in.h>
2327
+ #include <netinet/tcp.h>
2328
+ 
2329
+ #include <vm/vm.h>
2330
+ #include <vm/vm_extern.h>
2331
+ #include <vm/vm_zone.h>
2332
+ 
2333
+ #include <net/if.h>
2334
+ #include <net/route.h>
2335
+ #include <netinet/in.h>
2336
+ 
2337
+ #include <9fs/bitstring.h>
2338
+ #include <9fs/9p.h>
2339
+ #include <9fs/9auth.h>
2340
+ #include <9fs/9fs.h>
2341
+ 
2342
+ vm_zone_t u9fsuser_zone;
2343
+ LIST_HEAD(u9fsuserhashhead, u9fsuser) * u9fsuidhashtbl, * u9fsunamehashtbl;
2344
+ u_long u9fsuidhash;
2345
+ u_long u9fsunamehash;
2346
+ MALLOC_DEFINE(M_U9FSBITS, "U9FS bits", "U9FS tag/fid maps");
2347
+ 
2348
+ static int   u9fs_hashname __P((char * name));
2349
+ 
2350
+ void u9fs_uhinit()
2351
+ {
2352
+   u9fsuser_zone = zinit("U9FSUSER", sizeof(struct u9fsuser), 0, 0, 1);
2353
+   u9fsuidhashtbl   = phashinit(U9FS_USER_HASHSIZE, M_U9FSHASH, &u9fsuidhash);
2354
+   u9fsunamehashtbl = phashinit(U9FS_USER_HASHSIZE, M_U9FSHASH, &u9fsunamehash);
2355
+ }
2356
+ 
2357
+ void
2358
+ u9fs_id_init(bits)
2359
+      bitstr_t ** bits;
2360
+ {
2361
+   bit_alloc(*bits, 0x10000, M_U9FSBITS, M_WAITOK);
2362
+   bit_nset(*bits, 1, 0xffff);  /* we dont use zero */
2363
+ }
2364
+ 
2365
+ u_short
2366
+ u9fs_id_new(bits)
2367
+      bitstr_t * bits;
2368
+ {
2369
+   int v;
2370
+ 
2371
+   bit_ffs(bits, 0x10000, &v);
2372
+   if( v < 0 )
2373
+     panic("no more u9fs bits!");
2374
+ 
2375
+   bit_clear(bits, v);
2376
+   return ((u_short)v);
2377
+ }
2378
+ 
2379
+ void
2380
+ u9fs_id_free(bits, v)
2381
+      bitstr_t * bits;
2382
+      u_short v;
2383
+ {
2384
+   bit_set(bits, v);
2385
+ }
2386
+ 
2387
+ 
2388
+ static int u9fs_hashname(char * cp)
2389
+ {
2390
+   int h = 0;
2391
+ 
2392
+   cp[U9FS_NAMELEN-1] = 0;
2393
+   do
2394
+     h += *cp;
2395
+   while ( *cp++ );
2396
+ 
2397
+   return h;
2398
+ }
2399
+ 
2400
+ void u9fs_hashuser(uid_t uid, char * name)
2401
+ {
2402
+   int h;
2403
+   struct u9fsuser * u9p, *u9p2;
2404
+   struct u9fsuserhashhead * u9hp;
2405
+ 
2406
+   if( u9fs_name2uid(name) != 65534 ) /* already hashed by previous mount */
2407
+     return;
2408
+ 
2409
+   u9p = zalloc(u9fsuser_zone);
2410
+   bzero(u9p, sizeof(*u9p));
2411
+   u9p->u_uid = uid;
2412
+   strncpy(u9p->u_name, name, U9FS_NAMELEN);
2413
+   u9hp = & u9fsuidhashtbl[uid % u9fsuidhash];
2414
+   LIST_INSERT_HEAD(u9hp, u9p, u_hash);
2415
+   
2416
+   u9p2 = zalloc(u9fsuser_zone);
2417
+   bcopy(u9p, u9p2, sizeof(*u9p));
2418
+   h = u9fs_hashname(name);
2419
+   u9hp = & u9fsunamehashtbl[h%u9fsunamehash];
2420
+   LIST_INSERT_HEAD(u9hp, u9p2, u_hash);  
2421
+ }
2422
+ 
2423
+ /* name must be at least U9FS_NAMELEN long! */
2424
+ struct u9fsuser * u9fs_finduser(uid_t uid)
2425
+ {
2426
+   struct u9fsuser * u9p;
2427
+   struct u9fsuserhashhead * u9hp;
2428
+ 
2429
+   u9hp = & u9fsuidhashtbl[uid % u9fsuidhash];
2430
+   LIST_FOREACH(u9p, u9hp, u_hash)
2431
+     if( u9p->u_uid == uid )
2432
+       break;
2433
+ 
2434
+   return u9p;
2435
+ }
2436
+ 
2437
+ uid_t u9fs_name2uid(char *name)
2438
+ {
2439
+   struct u9fsuser * u9p;
2440
+   struct u9fsuserhashhead * u9hp;
2441
+   int h;
2442
+ 
2443
+   h = u9fs_hashname(name);
2444
+   u9hp = & u9fsunamehashtbl[h%u9fsunamehash];
2445
+   LIST_FOREACH(u9p, u9hp, u_hash)
2446
+     if( strcmp(u9p->u_name, name) == 0 )
2447
+       break;
2448
+ 
2449
+   if( u9p )
2450
+     return u9p->u_uid;
2451
+   else
2452
+     return 65534; /* nobody */
2453
+ }
2454
+ 
2455
+ /*
2456
+  * copies a uio scatter/gather list to an mbuf chain.
2457
+  */
2458
+ int
2459
+ u9fs_uiotombuf(uiop, mq, siz)
2460
+ 	register struct uio *uiop;
2461
+ 	struct mbuf **mq;
2462
+ 	int siz;
2463
+ {
2464
+   register struct mbuf *m;
2465
+   struct mbuf * top, **mp;
2466
+   int mlen, len, error = 0;
2467
+ 
2468
+   mp = & top;
2469
+   while(siz) {
2470
+     MGET(m, M_WAIT, MT_DATA);
2471
+     mlen = MLEN;
2472
+     if (siz >= MINCLSIZE) {
2473
+       MCLGET(m, M_WAIT);
2474
+       if ((m->m_flags & M_EXT))
2475
+ 	mlen = MCLBYTES;
2476
+     }
2477
+     len = min(mlen, siz);
2478
+     error = uiomove(mtod(m, caddr_t), (int)len, uiop);
2479
+     siz -= len;
2480
+     m->m_len = len;
2481
+     *mp = m;
2482
+     if (error)
2483
+       goto release;
2484
+     mp = &m->m_next;
2485
+   }
2486
+   *mq = top;
2487
+   return 0;
2488
+ 
2489
+  release:
2490
+   if( top )
2491
+     m_freem(top);
2492
+ 
2493
+   return error;
2494
+ }
2495
+ 
2496
+ /*
2497
+  * copies mbuf chain to the uio scatter/gather list
2498
+  */
2499
+ int
2500
+ u9fs_mbuftouio(m, uiop, siz)
2501
+      struct mbuf *m;
2502
+      register struct uio *uiop;
2503
+      int siz;
2504
+ {
2505
+   register char *mbufcp, *uiocp;
2506
+   register int xfer, left, len;
2507
+   long uiosiz;
2508
+ 
2509
+   mbufcp = mtod(m, char *);
2510
+   len = m->m_len;
2511
+   while (siz > 0) {
2512
+     if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
2513
+       return (EFBIG);
2514
+     left = uiop->uio_iov->iov_len;
2515
+     uiocp = uiop->uio_iov->iov_base;
2516
+     if (left > siz)
2517
+       left = siz;
2518
+     uiosiz = left;
2519
+     while (left > 0) {
2520
+       while (len == 0) {
2521
+ 	m = m->m_next;
2522
+ 	if (m == NULL)
2523
+ 	  return (EBADRPC);
2524
+ 	mbufcp = mtod(m, caddr_t);
2525
+ 	len = m->m_len;
2526
+       }
2527
+       xfer = (left > len) ? len : left;
2528
+       if (uiop->uio_segflg == UIO_SYSSPACE)
2529
+ 	bcopy(mbufcp, uiocp, xfer);
2530
+       else
2531
+ 	copyout(mbufcp, uiocp, xfer);
2532
+       left -= xfer;
2533
+       len -= xfer;
2534
+       mbufcp += xfer;
2535
+       uiocp += xfer;
2536
+       uiop->uio_offset += xfer;
2537
+       uiop->uio_resid -= xfer;
2538
+     }
2539
+     if (uiop->uio_iov->iov_len <= siz) {
2540
+       uiop->uio_iovcnt--;
2541
+       uiop->uio_iov++;
2542
+     } else {
2543
+       uiop->uio_iov->iov_base += uiosiz;
2544
+       uiop->uio_iov->iov_len -= uiosiz;
2545
+     }
2546
+     siz -= uiosiz;
2547
+   }
2548
+   return (0);
2549
+ }
2550
+ 
2551
diff -N -c -r /usr/src/sys/9fs/9fs_vfsops.c ./9fs/9fs_vfsops.c
2552
*** /usr/src/sys/9fs/9fs_vfsops.c	Wed Dec 31 19:00:00 1969
2553
--- ./9fs/9fs_vfsops.c	Mon May 22 16:33:47 2000
2554
***************
2555
*** 0 ****
2556
--- 1,639 ----
2557
+ /*
2558
+  * Copyright (c) 1989, 1993, 1995
2559
+  *	The Regents of the University of California.  All rights reserved.
2560
+  *
2561
+  * This code is derived from software contributed to Berkeley by
2562
+  * Rick Macklem at The University of Guelph.
2563
+  *
2564
+  * Redistribution and use in source and binary forms, with or without
2565
+  * modification, are permitted provided that the following conditions
2566
+  * are met:
2567
+  * 1. Redistributions of source code must retain the above copyright
2568
+  *    notice, this list of conditions and the following disclaimer.
2569
+  * 2. Redistributions in binary form must reproduce the above copyright
2570
+  *    notice, this list of conditions and the following disclaimer in the
2571
+  *    documentation and/or other materials provided with the distribution.
2572
+  * 3. All advertising materials mentioning features or use of this software
2573
+  *    must display the following acknowledgement:
2574
+  *	This product includes software developed by the University of
2575
+  *	California, Berkeley and its contributors.
2576
+  * 4. Neither the name of the University nor the names of its contributors
2577
+  *    may be used to endorse or promote products derived from this software
2578
+  *    without specific prior written permission.
2579
+  *
2580
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2581
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2582
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2583
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2584
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2585
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2586
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2587
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2588
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2589
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2590
+  * SUCH DAMAGE.
2591
+  *
2592
+  *	@(#)u9fs_vfsops.c	8.12 (Berkeley) 5/20/95
2593
+  * $Id: u9fs_vfsops.c,v 1.79 1998/12/04 22:54:54 archie Exp $
2594
+  */
2595
+ 
2596
+ #include <sys/param.h>
2597
+ #include <sys/sockio.h>
2598
+ #include <sys/proc.h>
2599
+ #include <sys/vnode.h>
2600
+ #include <sys/kernel.h>
2601
+ #include <sys/sysctl.h>
2602
+ #include <sys/malloc.h>
2603
+ #include <sys/mount.h>
2604
+ #include <sys/mbuf.h>
2605
+ #include <sys/socket.h>
2606
+ #include <sys/socketvar.h>
2607
+ #include <sys/systm.h>
2608
+ #include <sys/protosw.h>
2609
+ #include <sys/syslog.h>
2610
+ 
2611
+ #include <netinet/in.h>
2612
+ #include <netinet/tcp.h>
2613
+ 
2614
+ #include <vm/vm.h>
2615
+ #include <vm/vm_extern.h>
2616
+ #include <vm/vm_zone.h>
2617
+ 
2618
+ #include <net/if.h>
2619
+ #include <net/route.h>
2620
+ #include <netinet/in.h>
2621
+ 
2622
+ #include <9fs/bitstring.h>
2623
+ #include <9fs/9p.h>
2624
+ #include <9fs/9auth.h>
2625
+ #include <9fs/9fs.h>
2626
+ 
2627
+ vm_zone_t u9fsmount_zone;
2628
+ 
2629
+ static int	u9fs_mount __P(( struct mount *mp, char *path, caddr_t data,
2630
+ 			struct nameidata *ndp, struct proc *p));
2631
+ static int	u9fs_start __P(( struct mount *mp, int flags,
2632
+ 			struct proc *p));
2633
+ static int	u9fs_unmount __P(( struct mount *mp, int mntflags,
2634
+ 			struct proc *p));
2635
+ static int	u9fs_root __P(( struct mount *mp, struct vnode **vpp));
2636
+ static int	u9fs_quotactl __P(( struct mount *mp, int cmds, uid_t uid,
2637
+ 			caddr_t arg, struct proc *p));
2638
+ static int	u9fs_statfs __P(( struct mount *mp, struct statfs *sbp,
2639
+ 			struct proc *p));
2640
+ static int	u9fs_sync __P(( struct mount *mp, int waitfor,
2641
+ 			struct ucred *cred, struct proc *p));
2642
+ static int	u9fs_vptofh __P(( struct vnode *vp, struct fid *fhp));
2643
+ static int	u9fs_fhtovp __P((struct mount *mp, struct fid *fhp,
2644
+ 			struct sockaddr *nam, struct vnode **vpp,
2645
+ 			int *exflagsp, struct ucred **credanonp));
2646
+ static int	u9fs_vget __P((struct mount *, ino_t, struct vnode **));
2647
+ static int      u9fs_init __P((struct vfsconf *vfsp));
2648
+ int             u9fs_uninit __P((struct vfsconf *vfsp));
2649
+ 
2650
+ /* */
2651
+ static int	mountu9fs __P((struct u9fs_args *,struct mount *,
2652
+ 			struct sockaddr *,char *,char *,struct vnode **, struct proc *p));
2653
+ static int	u9fs_iosize __P((struct u9fsmount *nmp));
2654
+ static void	u9fs_decode_args __P((struct u9fsmount *nmp, struct u9fs_args *argp, struct proc *p));
2655
+ 
2656
+ /*
2657
+  * u9fs vfs operations.
2658
+  */
2659
+ static struct vfsops u9fs_vfsops = {
2660
+ 	u9fs_mount,
2661
+ 	u9fs_start,
2662
+ 	u9fs_unmount,
2663
+ 	u9fs_root,
2664
+ 	u9fs_quotactl,
2665
+ 	u9fs_statfs,
2666
+ 	u9fs_sync,
2667
+ 	u9fs_vget,
2668
+ 	u9fs_fhtovp,
2669
+ 	u9fs_vptofh,
2670
+ 	u9fs_init,
2671
+ 	u9fs_uninit,
2672
+ 	0
2673
+ };
2674
+ VFS_SET(u9fs_vfsops, u9fs, VFCF_NETWORK);
2675
+ 
2676
+ /*
2677
+  * u9fs statfs call
2678
+  */
2679
+ static int
2680
+ u9fs_statfs(mp, sbp, p)
2681
+ 	struct mount *mp;
2682
+ 	register struct statfs *sbp;
2683
+ 	struct proc *p;
2684
+ {
2685
+   /* we have a worm with infinite storage,
2686
+      stat not supported by 9fs */
2687
+   return 0;
2688
+ }
2689
+ 
2690
+ /*
2691
+  * Common code for mount and mountroot
2692
+  */
2693
+ static int
2694
+ mountu9fs(argp, mp, nam, pth, hst, vpp, p)
2695
+ 	register struct u9fs_args *argp;
2696
+ 	register struct mount *mp;
2697
+ 	struct sockaddr *nam;
2698
+ 	char *pth, *hst;
2699
+ 	struct vnode **vpp;
2700
+ 	struct proc *p;
2701
+ {
2702
+   register struct u9fsmount *nmp;
2703
+   struct u9fsnode *np;
2704
+   int error;
2705
+   struct vattr attrs;
2706
+   struct u9fsreq req, rep;
2707
+   char * mntpoint;
2708
+   struct u9fsuser * u9p;
2709
+   struct socket * so;
2710
+ 
2711
+   if (mp->mnt_flag & MNT_UPDATE) {
2712
+ #if 0
2713
+     nmp = VFSTONFS(mp);
2714
+ <    /* update paths, file handles, etc, here	XXX */
2715
+     FREE(nam, M_SONAME);
2716
+ #endif
2717
+     return (0);
2718
+   } else {
2719
+     nmp = zalloc(u9fsmount_zone);
2720
+     bzero((caddr_t)nmp, sizeof (struct u9fsmount));
2721
+ #if 0
2722
+     TAILQ_INIT(&nmp->nm_uidlruhead);
2723
+     TAILQ_INIT(&nmp->nm_bufq);
2724
+ #endif
2725
+     mp->mnt_data = (qaddr_t)nmp;
2726
+   }
2727
+   vfs_getnewfsid(mp);
2728
+   nmp->nm_mountp = mp;
2729
+ 
2730
+   nmp->nm_maxfilesize = (u_int64_t)0xffffffffffffffffLL;
2731
+ 
2732
+   nmp->nm_wsize = U9FS_MAXFDATA;
2733
+   nmp->nm_rsize = U9FS_MAXFDATA;
2734
+   nmp->nm_readdirsize = U9FS_MAXDDATA;
2735
+   bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
2736
+   bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
2737
+   nmp->nm_nam = nam;
2738
+ 
2739
+   mntpoint = index(hst, '/');
2740
+   if( mntpoint )
2741
+     mntpoint++;
2742
+ 
2743
+   /* Set up the sockets and per-host congestion */
2744
+   nmp->nm_sotype = argp->sotype;
2745
+   nmp->nm_soproto = argp->proto;
2746
+ 
2747
+   u9fs_decode_args(nmp, argp, p);
2748
+ 
2749
+   lockinit(& nmp->nm_lock, PVFS, "u9fsmount", 0, 0);
2750
+   u9fs_id_init(&nmp->nm_tags);
2751
+   u9fs_id_init(&nmp->nm_fids);
2752
+   TAILQ_INIT(&nmp->nm_reqq);
2753
+ 
2754
+   if ((error = u9fs_connect_9fs(nmp)))
2755
+     goto bad;
2756
+   
2757
+   /* "Tnop 1", "Tsession 1 0", "Tattach 1 1 none main 0 0", */
2758
+   bzero(&req, sizeof(req));
2759
+   req.r_nmp = nmp;
2760
+   req.r_procp = p;
2761
+ 
2762
+   req.r_type = Tnop;
2763
+   error = u9fs_request(& req, & rep, 1);
2764
+   if( error )
2765
+     return error;
2766
+ 
2767
+   req.r_type = Tsession;
2768
+   /* bzero(req.r_chal, sizeof(req.r_chal)); */
2769
+   u9auth_genchal(req.r_chal);
2770
+   error = u9fs_request(& req, & rep, 1);
2771
+   if( error )
2772
+     return error;
2773
+ 
2774
+   if( argp->authaddr ) {
2775
+     /* get tickets from the auth server */
2776
+     error = u9fs_connect_9auth(nmp, argp, & so);
2777
+     if( error )
2778
+       goto bad;
2779
+     u9p = u9fs_finduser(u9fs_name2uid(argp->user));
2780
+     error = u9auth_gettickets(so, & rep, argp->user, u9p->u_ckey, 
2781
+ 			      req.r_ticket, req.r_auth, p);
2782
+     u9fs_disconnect(so);
2783
+     if( error )
2784
+       goto bad;
2785
+   }
2786
+ 
2787
+   req.r_type = Tattach;
2788
+   req.r_fid = u9fs_id_new(nmp->nm_fids);
2789
+   strcpy(req.r_uname, argp->user);
2790
+   strcpy(req.r_aname, mntpoint);
2791
+   error = u9fs_request(& req, & rep, 1);
2792
+   if( error )
2793
+     return error;
2794
+   nmp->nm_fh = rep.r_qid.path;
2795
+   nmp->nm_fid = req.r_fid;
2796
+   /* XXX: we should have checked our challenge to the server! */
2797
+ 
2798
+   /*
2799
+    * This is silly, but it has to be set so that vinifod() works.
2800
+    * We do not want to do an u9fs_statfs() here since we can get
2801
+    * stuck on a dead server and we are holding a lock on the mount
2802
+    * point.
2803
+    */
2804
+   mp->mnt_stat.f_iosize = u9fs_iosize(nmp);
2805
+ 
2806
+   /*
2807
+    * A reference count is needed on the u9fsnode representing the
2808
+    * remote root.  If this object is not persistent, then backward
2809
+    * traversals of the mount point (i.e. "..") will not work if
2810
+    * the u9fsnode gets flushed out of the cache. Ufs does not have
2811
+    * this problem, because one can identify root inodes by their
2812
+    * number == ROOTINO (2).
2813
+    */
2814
+   error = u9fs_nget(mp, nmp->nm_fh, &np, p);
2815
+   np->n_fid = nmp->nm_fid;
2816
+ 
2817
+   nmp->nm_authuid = p->p_ucred->cr_uid;
2818
+ 
2819
+   if (error)
2820
+     goto bad;
2821
+   *vpp = U9FSTOV(np);
2822
+   
2823
+   /*
2824
+    * Get file attributes for the mountpoint.  This has the side
2825
+    * effect of filling in (*vpp)->v_type with the correct value.
2826
+    */
2827
+   VOP_GETATTR(*vpp, &attrs, p->p_ucred, p);
2828
+   
2829
+   /*
2830
+    * Lose the lock but keep the ref.
2831
+    */
2832
+   VOP_UNLOCK(*vpp, 0, p);
2833
+ 
2834
+   return (0);
2835
+ bad:
2836
+   u9fs_disconnect(nmp->nm_so);
2837
+   zfree(u9fsmount_zone, nmp);
2838
+   FREE(nam, M_SONAME);
2839
+   return (error);
2840
+ }
2841
+ 
2842
+ /*
2843
+  * VFS Operations.
2844
+  *
2845
+  * mount system call
2846
+  * It seems a bit dumb to copyinstr() the host and path here and then
2847
+  * bcopy() them in mountu9fs(), but I wanted to detect errors before
2848
+  * doing the sockargs() call because sockargs() allocates an mbuf and
2849
+  * an error after that means that I have to release the mbuf.
2850
+  */
2851
+ /* ARGSUSED */
2852
+ static int
2853
+ u9fs_mount(mp, path, data, ndp, p)
2854
+ 	struct mount *mp;
2855
+ 	char *path;
2856
+ 	caddr_t data;
2857
+ 	struct nameidata *ndp;
2858
+ 	struct proc *p;
2859
+ {
2860
+   int error;
2861
+   struct u9fs_args args;
2862
+   struct sockaddr *nam;
2863
+   struct vnode *vp;
2864
+   char pth[MNAMELEN], hst[MNAMELEN];
2865
+   size_t len;
2866
+ 
2867
+   if( path == NULL )
2868
+     return (EOPNOTSUPP);
2869
+ 
2870
+   error = copyin(data, (caddr_t)&args, sizeof (struct u9fs_args));
2871
+   if (error)
2872
+     return (error);
2873
+ 
2874
+   if (args.version != U9FS_ARGSVERSION)
2875
+     return (EPROGMISMATCH);
2876
+ 
2877
+   if (mp->mnt_flag & MNT_UPDATE) {
2878
+ #if 0
2879
+     register struct u9fsmount *nmp = VFSTONFS(mp);
2880
+     
2881
+     if (nmp == NULL)
2882
+       return (EIO);
2883
+     /*
2884
+      * When doing an update, we can't change from or to
2885
+      * v3 and/or nqu9fs, or change cookie translation
2886
+      */
2887
+     args.flags = (args.flags &
2888
+ 		  ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) |
2889
+       (nmp->nm_flag &
2890
+        (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/));
2891
+     u9fs_decode_args(nmp, &args, p);
2892
+ #endif
2893
+     return (0);
2894
+   }
2895
+ 
2896
+   error = copyinstr(path, pth, MNAMELEN-1, &len);
2897
+   if (error)
2898
+     return (error);
2899
+   bzero(&pth[len], MNAMELEN - len);
2900
+   error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
2901
+   if (error)
2902
+     return (error);
2903
+   bzero(&hst[len], MNAMELEN - len);
2904
+   /* sockargs() call must be after above copyin() calls */
2905
+   error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
2906
+   if (error)
2907
+     return (error);
2908
+   error = mountu9fs(&args, mp, nam, pth, hst, &vp, p);
2909
+   return (error);  
2910
+ }
2911
+ 
2912
+ /*
2913
+  * unmount system call
2914
+  */
2915
+ static int
2916
+ u9fs_unmount(mp, mntflags, p)
2917
+      struct mount *mp;
2918
+      int mntflags;
2919
+      struct proc *p;
2920
+ {
2921
+   register struct u9fsmount *nmp;
2922
+   struct u9fsnode *np;
2923
+   struct vnode *vp;
2924
+   int error, flags = 0;
2925
+   
2926
+   if (mntflags & MNT_FORCE)
2927
+     flags |= FORCECLOSE;
2928
+   nmp = VFSTOU9FS(mp);
2929
+ 
2930
+   if( p->p_ucred->cr_uid != nmp->nm_authuid )
2931
+     return (EPERM);
2932
+ 
2933
+   /*
2934
+    * Goes something like this..
2935
+    * - Check for activity on the root vnode (other than ourselves).
2936
+    * - Call vflush() to clear out vnodes for this file system,
2937
+    *   except for the root vnode.
2938
+    * - Decrement reference on the vnode representing remote root.
2939
+    * - Close the socket
2940
+    * - Free up the data structures
2941
+    */
2942
+   /*
2943
+    * We need to decrement the ref. count on the u9fsnode representing
2944
+    * the remote root.  See comment in mountu9fs().  The VFS unmount()
2945
+    * has done vput on this vnode, otherwise we would get deadlock!
2946
+    */
2947
+   error = u9fs_nget(mp, nmp->nm_fh, &np, p);
2948
+   if (error)
2949
+     return(error);
2950
+   vp = U9FSTOV(np);
2951
+   if (vp->v_usecount > 2) {
2952
+     vput(vp);
2953
+     return (EBUSY);
2954
+   }
2955
+ 
2956
+   error = vflush(mp, vp, flags);
2957
+   if (error) {
2958
+     vput(vp);
2959
+     return (error);
2960
+   }
2961
+ 
2962
+   /*
2963
+    * We are now committed to the unmount.
2964
+    */
2965
+   /*
2966
+    * There are two reference counts and one lock to get rid of here.
2967
+    */
2968
+   vput(vp);
2969
+   vrele(vp);
2970
+   vgone(vp);
2971
+   u9fs_disconnect(nmp->nm_so);
2972
+   FREE(nmp->nm_nam, M_SONAME);
2973
+ 
2974
+   zfree(u9fsmount_zone, nmp);
2975
+   return (0);
2976
+ }
2977
+ 
2978
+ /*
2979
+  * Return root of a filesystem
2980
+  */
2981
+ static int
2982
+ u9fs_root(mp, vpp)
2983
+ 	struct mount *mp;
2984
+ 	struct vnode **vpp;
2985
+ {
2986
+         register struct vnode *vp;
2987
+         struct u9fsmount *nmp;
2988
+         struct u9fsnode *np;
2989
+         int error;
2990
+ 
2991
+         nmp = VFSTOU9FS(mp);
2992
+         error = u9fs_nget(mp, nmp->nm_fh, &np, curproc); /* XXX */
2993
+         if (error)
2994
+                 return (error);
2995
+         vp = U9FSTOV(np);
2996
+         if (vp->v_type == VNON)
2997
+             vp->v_type = VDIR;
2998
+         vp->v_flag = VROOT;
2999
+         *vpp = vp;
3000
+         return (0);
3001
+ }
3002
+ 
3003
+ extern int syncprt;
3004
+ 
3005
+ /*
3006
+  * Flush out the buffer cache
3007
+  */
3008
+ /* ARGSUSED */
3009
+ static int
3010
+ u9fs_sync(mp, waitfor, cred, p)
3011
+ 	struct mount *mp;
3012
+ 	int waitfor;
3013
+ 	struct ucred *cred;
3014
+ 	struct proc *p;
3015
+ {
3016
+   /* no cache yet */
3017
+   return 0;
3018
+ }
3019
+ 
3020
+ /*
3021
+  * U9FS flat namespace lookup.
3022
+  * Currently unsupported.
3023
+  */
3024
+ /* ARGSUSED */
3025
+ static int
3026
+ u9fs_vget(mp, ino, vpp)
3027
+ 	struct mount *mp;
3028
+ 	ino_t ino;
3029
+ 	struct vnode **vpp;
3030
+ {
3031
+ 
3032
+ 	return (EOPNOTSUPP);
3033
+ }
3034
+ 
3035
+ /*
3036
+  * At this point, this should never happen
3037
+  */
3038
+ /* ARGSUSED */
3039
+ static int
3040
+ u9fs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
3041
+ 	register struct mount *mp;
3042
+ 	struct fid *fhp;
3043
+ 	struct sockaddr *nam;
3044
+ 	struct vnode **vpp;
3045
+ 	int *exflagsp;
3046
+ 	struct ucred **credanonp;
3047
+ {
3048
+ 
3049
+ 	return (EINVAL);
3050
+ }
3051
+ 
3052
+ /*
3053
+  * Vnode pointer to File handle, should never happen either
3054
+  */
3055
+ /* ARGSUSED */
3056
+ static int
3057
+ u9fs_vptofh(vp, fhp)
3058
+ 	struct vnode *vp;
3059
+ 	struct fid *fhp;
3060
+ {
3061
+ 
3062
+ 	return (EINVAL);
3063
+ }
3064
+ 
3065
+ /*
3066
+  * Vfs start routine, a no-op.
3067
+  */
3068
+ /* ARGSUSED */
3069
+ static int
3070
+ u9fs_start(mp, flags, p)
3071
+ 	struct mount *mp;
3072
+ 	int flags;
3073
+ 	struct proc *p;
3074
+ {
3075
+ 
3076
+ 	return (0);
3077
+ }
3078
+ 
3079
+ /*
3080
+  * Do operations associated with quotas, not supported
3081
+  */
3082
+ /* ARGSUSED */
3083
+ static int
3084
+ u9fs_quotactl(mp, cmd, uid, arg, p)
3085
+ 	struct mount *mp;
3086
+ 	int cmd;
3087
+ 	uid_t uid;
3088
+ 	caddr_t arg;
3089
+ 	struct proc *p;
3090
+ {
3091
+ 
3092
+ 	return (EOPNOTSUPP);
3093
+ }
3094
+ 
3095
+ /*
3096
+  * Called once to initialize data structures...
3097
+  */
3098
+ int
3099
+ u9fs_init(vfsp)
3100
+ 	struct vfsconf *vfsp;
3101
+ {
3102
+   u9fsmount_zone = zinit("U9FSMOUNT", sizeof(struct u9fsmount), 0, 0, 1);
3103
+   u9fs_nhinit();			/* Init the u9fsnode table */
3104
+   u9fs_uhinit();
3105
+   return 0;
3106
+ }
3107
+ 
3108
+ int
3109
+ u9fs_uninit(vfsp)
3110
+ 	struct vfsconf *vfsp;
3111
+ {
3112
+   return 0;
3113
+ }
3114
+ 
3115
+ static int
3116
+ u9fs_iosize(nmp)
3117
+      struct u9fsmount* nmp;
3118
+ {
3119
+   int iosize;
3120
+   
3121
+   /*
3122
+    * Calculate the size used for io buffers.  Use the larger
3123
+    * of the two sizes to minimise u9fs requests but make sure
3124
+    * that it is at least one VM page to avoid wasting buffer
3125
+    * space.
3126
+    */
3127
+   iosize = max(nmp->nm_rsize, nmp->nm_wsize);
3128
+   if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
3129
+   return iosize;
3130
+ }
3131
+ 
3132
+ static void
3133
+ u9fs_decode_args(nmp, argp, p)
3134
+      struct u9fsmount *nmp;
3135
+      struct u9fs_args *argp;
3136
+      struct proc * p;
3137
+ {
3138
+   int s, i;
3139
+   int maxio;
3140
+   struct p9user * p9p, p9u;
3141
+   struct u9fsuser * u9p;
3142
+   
3143
+   s = splnet();
3144
+   /* Update flags atomically.  Don't change the lock bits. */
3145
+   nmp->nm_flag = argp->flags | nmp->nm_flag;
3146
+   splx(s);
3147
+ 
3148
+   maxio = U9FS_MAXFDATA;
3149
+ 
3150
+   if (argp->wsize > 0) {
3151
+     nmp->nm_wsize = argp->wsize;
3152
+     /* Round down to multiple of blocksize */
3153
+     nmp->nm_wsize &= ~(U9FS_FABLKSIZE - 1);
3154
+     if (nmp->nm_wsize <= 0)
3155
+       nmp->nm_wsize = U9FS_FABLKSIZE;
3156
+   }
3157
+   if (nmp->nm_wsize > maxio)
3158
+     nmp->nm_wsize = maxio;
3159
+   if (nmp->nm_wsize > MAXBSIZE)
3160
+     nmp->nm_wsize = MAXBSIZE;
3161
+ 
3162
+   if (argp->rsize > 0) {
3163
+     nmp->nm_rsize = argp->rsize;
3164
+     /* Round down to multiple of blocksize */
3165
+     nmp->nm_rsize &= ~(U9FS_FABLKSIZE - 1);
3166
+     if (nmp->nm_rsize <= 0)
3167
+       nmp->nm_rsize = U9FS_FABLKSIZE;
3168
+   }
3169
+   if (nmp->nm_rsize > maxio)
3170
+     nmp->nm_rsize = maxio;
3171
+   if (nmp->nm_rsize > MAXBSIZE)
3172
+     nmp->nm_rsize = MAXBSIZE;
3173
+ 
3174
+   if (argp->readdirsize > 0) {
3175
+     nmp->nm_readdirsize = argp->readdirsize;
3176
+   }
3177
+   if (nmp->nm_readdirsize > maxio)
3178
+     nmp->nm_readdirsize = maxio;
3179
+   if (nmp->nm_readdirsize > nmp->nm_rsize)
3180
+     nmp->nm_readdirsize = nmp->nm_rsize;
3181
+ 
3182
+   if( argp->nusers ) {
3183
+     p9p = argp->users;
3184
+     for(i = 0; i < argp->nusers; i++) {
3185
+       copyin(p9p, &p9u, sizeof(p9u));
3186
+       u9fs_hashuser(p9u.p9_uid, p9u.p9_name);
3187
+       p9p ++;
3188
+     }
3189
+     printf("%d p9users loaded\n", argp->nusers);
3190
+   }
3191
+ 
3192
+   if( (u9p = u9fs_finduser(u9fs_name2uid(argp->user))) ) {
3193
+     bcopy(argp->key, u9p->u_ckey, U9AUTH_DESKEYLEN);
3194
+   }
3195
+ }
3196
diff -N -c -r /usr/src/sys/9fs/9fs_vnops.c ./9fs/9fs_vnops.c
3197
*** /usr/src/sys/9fs/9fs_vnops.c	Wed Dec 31 19:00:00 1969
3198
--- ./9fs/9fs_vnops.c	Mon May 22 11:40:00 2000
3199
***************
3200
*** 0 ****
3201
--- 1,1794 ----
3202
+ /*
3203
+  * Copyright (c) 1989, 1993
3204
+  *	The Regents of the University of California.  All rights reserved.
3205
+  *
3206
+  * This code is derived from software contributed to Berkeley by
3207
+  * Rick Macklem at The University of Guelph.
3208
+  *
3209
+  * Redistribution and use in source and binary forms, with or without
3210
+  * modification, are permitted provided that the following conditions
3211
+  * are met:
3212
+  * 1. Redistributions of source code must retain the above copyright
3213
+  *    notice, this list of conditions and the following disclaimer.
3214
+  * 2. Redistributions in binary form must reproduce the above copyright
3215
+  *    notice, this list of conditions and the following disclaimer in the
3216
+  *    documentation and/or other materials provided with the distribution.
3217
+  * 3. All advertising materials mentioning features or use of this software
3218
+  *    must display the following acknowledgement:
3219
+  *	This product includes software developed by the University of
3220
+  *	California, Berkeley and its contributors.
3221
+  * 4. Neither the name of the University nor the names of its contributors
3222
+  *    may be used to endorse or promote products derived from this software
3223
+  *    without specific prior written permission.
3224
+  *
3225
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3226
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3227
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3228
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3229
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3230
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3231
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3232
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3233
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3234
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3235
+  * SUCH DAMAGE.
3236
+  *
3237
+  *	@(#)u9fs_vnops.c	8.16 (Berkeley) 5/27/95
3238
+  * $Id: u9fs_vnops.c,v 1.116.2.3 1999/02/13 08:03:47 dillon Exp $
3239
+  */
3240
+ 
3241
+ 
3242
+ /*
3243
+  * vnode op calls for 9FS
3244
+  */
3245
+ 
3246
+ #include "opt_inet.h"
3247
+ 
3248
+ #include <sys/param.h>
3249
+ #include <sys/kernel.h>
3250
+ #include <sys/systm.h>
3251
+ #include <sys/resourcevar.h>
3252
+ #include <sys/proc.h>
3253
+ #include <sys/mount.h>
3254
+ #include <sys/buf.h>
3255
+ #include <sys/malloc.h>
3256
+ #include <sys/mbuf.h>
3257
+ #include <sys/namei.h>
3258
+ #include <sys/socket.h>
3259
+ #include <sys/vnode.h>
3260
+ #include <sys/dirent.h>
3261
+ #include <sys/fcntl.h>
3262
+ #include <sys/lockf.h>
3263
+ #include <sys/stat.h>
3264
+ #include <sys/sysctl.h>
3265
+ 
3266
+ #include <vm/vm.h>
3267
+ #include <vm/vm_extern.h>
3268
+ #include <vm/vm_zone.h>
3269
+ #include <vm/vm_prot.h>
3270
+ #include <vm/vm_page.h>
3271
+ #include <vm/vm_object.h>
3272
+ #include <vm/vm_pager.h>
3273
+ #include <vm/vnode_pager.h>
3274
+ 
3275
+ #include <net/if.h>
3276
+ #include <netinet/in.h>
3277
+ #include <netinet/in_var.h>
3278
+ 
3279
+ #include <9fs/bitstring.h>
3280
+ #include <9fs/9p.h>
3281
+ #include <9fs/9auth.h>
3282
+ #include <9fs/9fs.h>
3283
+ 
3284
+ #define u9fs_poll vop_nopoll
3285
+ static	int	u9fs_lookup __P((struct vop_lookup_args *));
3286
+ static	int	u9fs_create __P((struct vop_create_args *));
3287
+ static	int	u9fs_mknod __P((struct vop_mknod_args *));
3288
+ static	int	u9fs_open __P((struct vop_open_args *));
3289
+ static	int	u9fs_close __P((struct vop_close_args *));
3290
+ static	int	u9fs_access __P((struct vop_access_args *));
3291
+ static	int	u9fs_getattr __P((struct vop_getattr_args *));
3292
+ static	int	u9fs_setattr __P((struct vop_setattr_args *));
3293
+ static	int	u9fs_read __P((struct vop_read_args *));
3294
+ static	int	u9fs_mmap __P((struct vop_mmap_args *));
3295
+ static	int	u9fs_fsync __P((struct vop_fsync_args *));
3296
+ static	int	u9fs_remove __P((struct vop_remove_args *));
3297
+ static	int	u9fs_link __P((struct vop_link_args *));
3298
+ static	int	u9fs_rename __P((struct vop_rename_args *));
3299
+ static	int	u9fs_mkdir __P((struct vop_mkdir_args *));
3300
+ static	int	u9fs_rmdir __P((struct vop_rmdir_args *));
3301
+ static	int	u9fs_symlink __P((struct vop_symlink_args *));
3302
+ static	int	u9fs_readdir __P((struct vop_readdir_args *));
3303
+ static	int	u9fs_bmap __P((struct vop_bmap_args *));
3304
+ static	int	u9fs_strategy __P((struct vop_strategy_args *));
3305
+ static int	u9fs_readlink __P((struct vop_readlink_args *));
3306
+ static int	u9fs_print __P((struct vop_print_args *));
3307
+ static int	u9fs_advlock __P((struct vop_advlock_args *));
3308
+ static int	u9fs_bwrite __P((struct vop_bwrite_args *));
3309
+ static int   u9fs_abortop __P((struct vop_abortop_args *));
3310
+ static int   u9fs_getpages __P((struct vop_getpages_args *));
3311
+ static int   u9fs_putpages __P((struct vop_putpages_args *));
3312
+ static int   u9fs_inactive __P((struct vop_inactive_args *));
3313
+ static int   u9fs_reclaim __P((struct vop_reclaim_args *));
3314
+ static int   u9fs_write __P((struct vop_write_args *));
3315
+ 
3316
+ /*
3317
+  * Global vfs data structures for u9fs
3318
+  */
3319
+ vop_t **u9fs_vnodeop_p;
3320
+ static struct vnodeopv_entry_desc u9fs_vnodeop_entries[] = {
3321
+ 	{ &vop_default_desc,		(vop_t *) vop_defaultop },
3322
+ 	{ &vop_abortop_desc,		(vop_t *) u9fs_abortop },
3323
+ 	{ &vop_access_desc,		(vop_t *) u9fs_access },
3324
+ 	{ &vop_advlock_desc,		(vop_t *) u9fs_advlock },
3325
+ 	{ &vop_bmap_desc,		(vop_t *) u9fs_bmap },
3326
+ 	{ &vop_bwrite_desc,		(vop_t *) u9fs_bwrite },
3327
+ 	{ &vop_close_desc,		(vop_t *) u9fs_close },
3328
+ 	{ &vop_create_desc,		(vop_t *) u9fs_create },
3329
+ 	{ &vop_fsync_desc,		(vop_t *) u9fs_fsync },
3330
+ 	{ &vop_getattr_desc,		(vop_t *) u9fs_getattr },
3331
+ 	{ &vop_getpages_desc,		(vop_t *) u9fs_getpages },
3332
+ 	{ &vop_putpages_desc,		(vop_t *) u9fs_putpages },
3333
+ 	{ &vop_inactive_desc,		(vop_t *) u9fs_inactive },
3334
+ 	{ &vop_lease_desc,		(vop_t *) vop_null },
3335
+ 	{ &vop_link_desc,		(vop_t *) u9fs_link },
3336
+ 	{ &vop_lock_desc,		(vop_t *) vop_sharedlock },
3337
+ 	{ &vop_lookup_desc,		(vop_t *) u9fs_lookup },
3338
+ 	{ &vop_mkdir_desc,		(vop_t *) u9fs_mkdir },
3339
+ 	{ &vop_mknod_desc,		(vop_t *) u9fs_mknod },
3340
+ 	{ &vop_mmap_desc,		(vop_t *) u9fs_mmap },
3341
+ 	{ &vop_open_desc,		(vop_t *) u9fs_open },
3342
+ 	{ &vop_poll_desc,		(vop_t *) vop_nopoll },
3343
+ 	{ &vop_print_desc,		(vop_t *) u9fs_print },
3344
+ 	{ &vop_read_desc,		(vop_t *) u9fs_read },
3345
+ 	{ &vop_readdir_desc,		(vop_t *) u9fs_readdir },
3346
+ 	{ &vop_readlink_desc,		(vop_t *) u9fs_readlink },
3347
+ 	{ &vop_reclaim_desc,		(vop_t *) u9fs_reclaim },
3348
+ 	{ &vop_remove_desc,		(vop_t *) u9fs_remove },
3349
+ 	{ &vop_rename_desc,		(vop_t *) u9fs_rename },
3350
+ 	{ &vop_rmdir_desc,		(vop_t *) u9fs_rmdir },
3351
+ 	{ &vop_setattr_desc,		(vop_t *) u9fs_setattr },
3352
+ 	{ &vop_strategy_desc,		(vop_t *) u9fs_strategy },
3353
+ 	{ &vop_symlink_desc,		(vop_t *) u9fs_symlink },
3354
+ 	{ &vop_write_desc,		(vop_t *) u9fs_write },
3355
+ 	{ NULL, NULL }
3356
+ };
3357
+ static struct vnodeopv_desc u9fs_vnodeop_opv_desc =
3358
+ 	{ &u9fs_vnodeop_p, u9fs_vnodeop_entries };
3359
+ VNODEOP_SET(u9fs_vnodeop_opv_desc);
3360
+ 
3361
+ extern vm_zone_t u9fsnode_zone;
3362
+ 
3363
+ static int u9fs_trunc(struct vnode * vp, struct ucred * cred, struct proc * p);
3364
+ static void u9fs_free_fid __P((u_short fid, struct u9fsmount * nmp, struct proc * p));
3365
+ static void u9fs_updtcache __P((struct u9fsnode *, struct u9fsreq *));
3366
+ 
3367
+ #define     DIRHDSIZ        (sizeof (struct dirent) - (MAXNAMLEN + 1))
3368
+ 
3369
+ /* open returns a qid for cache consistent check */
3370
+ static void
3371
+ u9fs_updtcache(struct u9fsnode * np, struct u9fsreq * rep)
3372
+ {
3373
+   if( rep->r_type != Rerror )
3374
+     np->n_dir.dir_qid = rep->r_qid;
3375
+ }
3376
+ 
3377
+ static int
3378
+ u9fs_trunc(vp, cred, p)
3379
+      register struct vnode * vp;
3380
+      struct ucred * cred;
3381
+      struct proc * p;
3382
+ {
3383
+   struct u9fsnode *np = VTOU9FS(vp);
3384
+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3385
+   int error;
3386
+   u_short newfid;
3387
+   struct u9fsreq req, rep;
3388
+   u_char mode;
3389
+ 
3390
+   /*
3391
+    * Disallow write attempts on filesystems mounted read-only;
3392
+    * unless the file is a socket, fifo, or a block or character
3393
+    * device resident on the filesystem.
3394
+    */
3395
+   if ( (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3396
+     switch (vp->v_type) {
3397
+     case VREG:
3398
+     case VDIR:
3399
+     case VLNK:
3400
+       return (EROFS);
3401
+     default:
3402
+       break;
3403
+     }
3404
+   }
3405
+   mode = U9P_MODE_WR | U9P_MODE_TRUNC;
3406
+   bzero(&req, sizeof(req));
3407
+   req.r_nmp = nmp;
3408
+   req.r_procp = p;
3409
+   newfid = u9fs_id_new(nmp->nm_fids);
3410
+   req.r_type = Tclone;
3411
+   req.r_fid  = np->n_fid;
3412
+   req.r_newfid = newfid;
3413
+   error = u9fs_request(&req, &rep, 1);
3414
+   if( error )
3415
+     return error;
3416
+   req.r_type = Topen;
3417
+   req.r_fid = newfid;
3418
+   req.r_mode = mode;
3419
+   error = u9fs_request(&req, &rep, 1);
3420
+   if( !error )
3421
+     u9fs_vinvalbuf(vp, 0, cred, p, 0);
3422
+   if( error || np->n_wrfid ) {
3423
+     u9fs_free_fid(newfid, nmp, p);
3424
+     return error;
3425
+   }
3426
+ 
3427
+   if( !U9P_PERM_EXCL(np->n_dir.dir_mode))
3428
+     np->n_wrfid = newfid;
3429
+   else
3430
+     u9fs_free_fid(newfid, nmp, p);
3431
+ 
3432
+   return (0);  
3433
+ }
3434
+ 
3435
+ /*
3436
+  * u9fs access vnode op.
3437
+  */
3438
+ static int
3439
+ u9fs_access(ap)
3440
+ 	struct vop_access_args /* {
3441
+ 		struct vnode *a_vp;
3442
+ 		int  a_mode;
3443
+ 		struct ucred *a_cred;
3444
+ 		struct proc *a_p;
3445
+ 	} */ *ap;
3446
+ {
3447
+   register struct vnode *vp = ap->a_vp;
3448
+   struct u9fsnode *np = VTOU9FS(vp);
3449
+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3450
+   struct proc * p = ap->a_p;
3451
+   int error, a_mode = ap->a_mode;
3452
+   u_short * fidp = 0, *fidp2 = 0, newfid;
3453
+   struct u9fsreq req, rep;
3454
+   u_char mode;
3455
+   struct ucred * cred = ap->a_cred;
3456
+ 
3457
+   /* XXX: for the moment, only the authenticator has access */
3458
+   if( cred->cr_uid != nmp->nm_authuid )
3459
+     return (EPERM);
3460
+ 
3461
+   /*
3462
+    * Disallow write attempts on filesystems mounted read-only;
3463
+    * unless the file is a socket, fifo, or a block or character
3464
+    * device resident on the filesystem.
3465
+    */
3466
+   if ((a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3467
+     switch (vp->v_type) {
3468
+     case VREG:
3469
+     case VDIR:
3470
+     case VLNK:
3471
+       return (EROFS);
3472
+     default:
3473
+       break;
3474
+     }
3475
+   }
3476
+ 
3477
+   /* we cant open an exclusive open file here */
3478
+   if( U9P_PERM_EXCL(np->n_dir.dir_mode) )
3479
+     return 0;
3480
+ 
3481
+   /* check permission by actually opening it */
3482
+   /* translate mode */
3483
+   mode = 0;
3484
+   if( a_mode & VREAD ) {
3485
+     fidp = &np->n_rdfid;
3486
+     mode = U9P_MODE_RD;
3487
+   }
3488
+   if( a_mode & VWRITE ) {
3489
+     fidp = &np->n_wrfid;
3490
+     mode = U9P_MODE_WR;
3491
+   }
3492
+   if( (a_mode & (VREAD|VWRITE)) == (VREAD|VWRITE) ) {
3493
+     fidp2 = &np->n_rdfid;
3494
+     mode = U9P_MODE_RDWR;
3495
+   }
3496
+ 
3497
+   if( a_mode & VEXEC ) {
3498
+     fidp = &np->n_rdfid;
3499
+     if( vp->v_type == VREG )
3500
+       mode = U9P_MODE_EX;
3501
+   }
3502
+ 
3503
+   if( fidp2 == 0 )
3504
+     fidp2 = fidp;
3505
+ 
3506
+   /* open fid mode */
3507
+   bzero(&req, sizeof(req));
3508
+   req.r_nmp = nmp;
3509
+   req.r_procp = p;
3510
+   newfid = u9fs_id_new(nmp->nm_fids);
3511
+   req.r_type = Tclone;
3512
+   req.r_fid  = np->n_fid;
3513
+   req.r_newfid = newfid;
3514
+   error = u9fs_request(&req, &rep, 1);
3515
+   if( error )
3516
+     return error;
3517
+   req.r_type = Topen;
3518
+   req.r_fid = newfid;
3519
+   req.r_mode = mode;
3520
+   error = u9fs_request(&req, &rep, 1);
3521
+   u9fs_updtcache(np, &rep);
3522
+   if( error || (*fidp && *fidp2 ) ) {
3523
+     u9fs_free_fid(newfid, nmp, p);
3524
+     return error;
3525
+   }
3526
+ 
3527
+   *fidp = *fidp2 = newfid;
3528
+ 
3529
+   return (0);
3530
+ }
3531
+ 
3532
+ /*
3533
+  * u9fs open vnode op
3534
+  * Check to see if the type is ok
3535
+  * and that deletion is not in progress.
3536
+  * For paged in text files, you will need to flush the page cache
3537
+  * if consistency is lost.
3538
+  */
3539
+ /* ARGSUSED */
3540
+ static int
3541
+ u9fs_open(ap)
3542
+ 	struct vop_open_args /* {
3543
+ 		struct vnode *a_vp;
3544
+ 		int  a_mode;
3545
+ 		struct ucred *a_cred;
3546
+ 		struct proc *a_p;
3547
+ 	} */ *ap;
3548
+ {
3549
+   register struct vnode *vp = ap->a_vp;
3550
+   struct u9fsnode *np = VTOU9FS(vp);
3551
+   int error=0, a_mode = ap->a_mode;
3552
+   u_short * fidp = 0, *fidp2 = 0, newfid;
3553
+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3554
+   struct proc * p = ap->a_p;
3555
+   struct u9fsreq req, rep;
3556
+   u_char mode;
3557
+   struct ucred * cred = ap->a_cred;
3558
+ 
3559
+   /* assume access permissions have been checked via VOP_ACCESS */
3560
+   /* the file is actually opened except the rdwr case */
3561
+ 
3562
+   if( a_mode & (O_EXCL|O_SHLOCK|O_EXLOCK) ) {
3563
+ #if 0  /* XXX: what can we do here? */
3564
+     return (EOPNOTSUPP);
3565
+ #endif
3566
+   }
3567
+ 
3568
+   /* translate mode */
3569
+   mode = 0;
3570
+   if( a_mode & FREAD ) {
3571
+     fidp = &np->n_rdfid;
3572
+     mode = U9P_MODE_RD;
3573
+   }
3574
+   if( a_mode & FWRITE ) {
3575
+     fidp = &np->n_wrfid;
3576
+     mode = U9P_MODE_WR;
3577
+   }
3578
+   if( (a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE) ) {
3579
+     fidp2 = & np->n_rdfid;
3580
+     mode = U9P_MODE_RDWR;
3581
+   }
3582
+   if( fidp2 == 0)
3583
+     fidp2 = fidp;
3584
+ 
3585
+   if( U9P_PERM_EXCL(np->n_dir.dir_mode) ) {
3586
+     if( *fidp || *fidp2 )
3587
+       return ENOLCK;
3588
+ 
3589
+     /* open fid mode */
3590
+     bzero(&req, sizeof(req));
3591
+     req.r_nmp = nmp;
3592
+     req.r_procp = p;
3593
+     newfid = u9fs_id_new(nmp->nm_fids);
3594
+     req.r_type = Tclone;
3595
+     req.r_fid  = np->n_fid;
3596
+     req.r_newfid = newfid;
3597
+     error = u9fs_request(&req, &rep, 1);
3598
+     if( error )
3599
+       return error;
3600
+     req.r_type = Topen;
3601
+     req.r_fid = newfid;
3602
+     req.r_mode = mode;
3603
+     error = u9fs_request(&req, &rep, 1);
3604
+     if( error ) {
3605
+       u9fs_free_fid(newfid, nmp, p);
3606
+       return error;
3607
+     }
3608
+     u9fs_updtcache(np, &rep);
3609
+ 
3610
+     *fidp = *fidp2 = newfid;
3611
+   }
3612
+ 
3613
+   if( *fidp == 0 )
3614
+     panic("open");
3615
+ 
3616
+   if( *fidp2 == 0 ) {
3617
+     /* open fid mode */
3618
+     bzero(&req, sizeof(req));
3619
+     req.r_nmp = nmp;
3620
+     req.r_procp = p;
3621
+     newfid = u9fs_id_new(nmp->nm_fids);
3622
+     req.r_type = Tclone;
3623
+     req.r_fid  = np->n_fid;
3624
+     req.r_newfid = newfid;
3625
+     error = u9fs_request(&req, &rep, 1);
3626
+     if( error )
3627
+       return error;
3628
+     req.r_type = Topen;
3629
+     req.r_fid = newfid;
3630
+     req.r_mode = mode;
3631
+     error = u9fs_request(&req, &rep, 1);
3632
+     if( error ) {
3633
+       u9fs_free_fid(newfid, nmp, p);
3634
+       return error;
3635
+     }
3636
+     u9fs_updtcache(np, &rep);
3637
+     *fidp2 = newfid;
3638
+   }
3639
+ 
3640
+   if( np->n_qid.vers != np->n_dir.dir_qid.vers ) /* content changed */
3641
+     u9fs_vinvalbuf(vp, 0, cred, p, 0);
3642
+ 
3643
+   return 0;
3644
+ }
3645
+ 
3646
+ /*
3647
+  * u9fs close vnode op
3648
+  * What an U9FS client should do upon close after writing is a debatable issue.
3649
+  * Most U9FS clients push delayed writes to the server upon close, basically for
3650
+  * two reasons:
3651
+  * 1 - So that any write errors may be reported back to the client process
3652
+  *     doing the close system call. By far the two most likely errors are
3653
+  *     U9FSERR_NOSPC and U9FSERR_DQUOT to indicate space allocation failure.
3654
+  * 2 - To put a worst case upper bound on cache inconsistency between
3655
+  *     multiple clients for the file.
3656
+  * There is also a consistency problem for Version 2 of the protocol w.r.t.
3657
+  * not being able to tell if other clients are writing a file concurrently,
3658
+  * since there is no way of knowing if the changed modify time in the reply
3659
+  * is only due to the write for this client.
3660
+  * (U9FS Version 3 provides weak cache consistency data in the reply that
3661
+  *  should be sufficient to detect and handle this case.)
3662
+  *
3663
+  * The current code does the following:
3664
+  * for U9FS Version 2 - play it safe and flush/invalidate all dirty buffers
3665
+  * for U9FS Version 3 - flush dirty buffers to the server but don't invalidate
3666
+  *                     or commit them (this satisfies 1 and 2 except for the
3667
+  *                     case where the server crashes after this close but
3668
+  *                     before the commit RPC, which is felt to be "good
3669
+  *                     enough". Changing the last argument to u9fs_flush() to
3670
+  *                     a 1 would force a commit operation, if it is felt a
3671
+  *                     commit is necessary now.
3672
+  * for NQU9FS         - do nothing now, since 2 is dealt with via leases and
3673
+  *                     1 should be dealt with via an fsync() system call for
3674
+  *                     cases where write errors are important.
3675
+  */
3676
+ /* ARGSUSED */
3677
+ static int
3678
+ u9fs_close(ap)
3679
+ 	struct vop_close_args /* {
3680
+ 		struct vnodeop_desc *a_desc;
3681
+ 		struct vnode *a_vp;
3682
+ 		int  a_fflag;
3683
+ 		struct ucred *a_cred;
3684
+ 		struct proc *a_p;
3685
+ 	} */ *ap;
3686
+ { 
3687
+   int fflag = ap->a_fflag;
3688
+   struct vnode * vp = ap->a_vp;
3689
+   struct u9fsnode * np = VTOU9FS(vp);
3690
+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3691
+   struct proc * p = ap->a_p;
3692
+ 
3693
+   if( U9P_PERM_EXCL(np->n_dir.dir_mode) ) {
3694
+     if( (fflag & FREAD) ) {
3695
+       u9fs_free_fid(np->n_rdfid, nmp, p);
3696
+       np->n_rdfid = 0;
3697
+     }
3698
+ 
3699
+     if( (fflag & FWRITE) == FWRITE ) {
3700
+       u9fs_free_fid(np->n_wrfid, nmp, p);
3701
+       np->n_wrfid = 0;
3702
+     }
3703
+     
3704
+     if( (fflag & (FREAD|FWRITE)) == (FREAD|FWRITE) )
3705
+       np->n_wrfid = 0;
3706
+   }
3707
+ 
3708
+   return 0;
3709
+ }
3710
+ 
3711
+ /*
3712
+  * u9fs getattr call from vfs.
3713
+  */
3714
+ static int
3715
+ u9fs_getattr(ap)
3716
+ 	struct vop_getattr_args /* {
3717
+ 		struct vnode *a_vp;
3718
+ 		struct vattr *a_vap;
3719
+ 		struct ucred *a_cred;
3720
+ 		struct proc *a_p;
3721
+ 	} */ *ap;
3722
+ {
3723
+   register struct vnode *vp = ap->a_vp;
3724
+   register struct u9fsnode *np = VTOU9FS(vp);
3725
+   int error = 0;
3726
+   struct u9fsreq req, rep;
3727
+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3728
+   struct u9fsdir * dir;
3729
+   struct vattr * vap = ap->a_vap;
3730
+   
3731
+   /*
3732
+    * Update local times for special files.
3733
+    */
3734
+   if (np->n_flag & (NACC | NUPD))
3735
+     np->n_flag |= NCHG;
3736
+ #if 0
3737
+   /*
3738
+    * First look in the cache.
3739
+    */
3740
+   if (u9fs_getattrcache(vp, ap->a_vap) == 0)
3741
+     return (0);
3742
+ #endif
3743
+   if( np->n_fid == 0 )
3744
+     panic("u9fs_getattr");
3745
+ 
3746
+   /* stat fid */
3747
+   bzero(&req, sizeof(req));
3748
+   req.r_nmp = nmp;
3749
+   req.r_procp = ap->a_p;
3750
+   req.r_type = Tstat;
3751
+   req.r_fid = np->n_fid;
3752
+   error = u9fs_request(& req, & rep, 1);
3753
+   if( error )
3754
+     return error;
3755
+ 
3756
+   /* fill in vattr */
3757
+   dir = & np->n_dir;
3758
+   u9p_m2d(rep.r_stat, dir);
3759
+ 
3760
+   bzero(vap, sizeof(*vap));
3761
+   /* the plan9 file system has no other types. */
3762
+   /* XXX: we have not delt with devices yet */
3763
+   if( U9P_PERM_CHDIR(dir->dir_mode) )
3764
+     vap->va_type = VDIR;
3765
+   else
3766
+     vap->va_type = VREG;
3767
+ 
3768
+   vap->va_mode  = U9P_PERM_ALL(dir->dir_mode);
3769
+   vap->va_nlink = 1;
3770
+   vap->va_uid = u9fs_name2uid(dir->dir_uid);
3771
+   vap->va_gid = u9fs_name2uid(dir->dir_gid);
3772
+   vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
3773
+   vap->va_fileid = dir->dir_qid.path;
3774
+   vap->va_size = np->n_size = dir->dir_length;
3775
+   vap->va_blocksize = PAGE_SIZE;
3776
+   vap->va_atime.tv_sec = dir->dir_atime;
3777
+   vap->va_atime.tv_nsec = 0;
3778
+   vap->va_mtime.tv_sec = dir->dir_mtime;
3779
+   vap->va_mtime.tv_nsec = 0;
3780
+   vap->va_ctime.tv_sec = dir->dir_mtime;
3781
+   vap->va_ctime.tv_nsec = dir->dir_mtime;
3782
+   vap->va_gen = VNOVAL;
3783
+   vap->va_flags = 0;
3784
+   vap->va_bytes = vap->va_size;
3785
+   vap->va_filerev = dir->dir_qid.vers;
3786
+ 
3787
+   vp->v_type = vap->va_type;
3788
+   vp->v_tag = VT_U9FS;
3789
+ 
3790
+   return (error);
3791
+ }
3792
+ 
3793
+ /*
3794
+  * u9fs setattr call.
3795
+  */
3796
+ static int
3797
+ u9fs_setattr(ap)
3798
+ 	struct vop_setattr_args /* {
3799
+ 		struct vnodeop_desc *a_desc;
3800
+ 		struct vnode *a_vp;
3801
+ 		struct vattr *a_vap;
3802
+ 		struct ucred *a_cred;
3803
+ 		struct proc *a_p;
3804
+ 	} */ *ap;
3805
+ {
3806
+   register struct vnode *vp = ap->a_vp;
3807
+   register struct u9fsnode *np = VTOU9FS(vp);
3808
+   register struct vattr *vap = ap->a_vap;
3809
+   int error = 0;
3810
+   struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount);
3811
+   struct u9fsdir dir;
3812
+   struct u9fsuser * u9p;
3813
+   struct vattr attr;
3814
+   struct u9fsreq req, rep;
3815
+ 
3816
+   if( vp->v_mount->mnt_flag & MNT_RDONLY )
3817
+     return (EROFS);
3818
+ 
3819
+   if( vap->va_nlink != VNOVAL || vap->va_uid != VNOVAL ||
3820
+       vap->va_fsid != VNOVAL || vap->va_fileid != VNOVAL ||
3821
+ #if 0
3822
+       vap->va_size != VNOVAL || vap->va_blocksize != VNOVAL ||
3823
+ #endif
3824
+       vap->va_atime.tv_sec != VNOVAL || vap->va_ctime.tv_sec != VNOVAL ||
3825
+       vap->va_gen != VNOVAL ||
3826
+       vap->va_flags != VNOVAL || vap->va_bytes != VNOVAL ) {
3827
+ #if 0
3828
+     printf("%d %d %d %d %d %d %d %d %d %d %d\n", vap->va_nlink, vap->va_uid, vap->va_fsid, 
3829
+ 	       vap->va_fileid, vap->va_size, vap->va_blocksize, 
3830
+ 	       vap->va_atime.tv_sec, vap->va_ctime.tv_sec, vap->va_gen, 
3831
+ 	       vap->va_flags, vap->va_bytes);
3832
+     printf("unsupported setattr\n");
3833
+     /* touch tries to change ctime first. 
3834
+      * if fails, it touches the first byte
3835
+     */
3836
+ #endif
3837
+     return (EOPNOTSUPP);
3838
+   }
3839
+ 
3840
+   if( vap->va_size == 0 )
3841
+     u9fs_trunc(vp, ap->a_cred, ap->a_p);
3842
+ 
3843
+   bcopy(&np->n_dir, &dir, sizeof(dir));
3844
+   if( vap->va_mode  != (mode_t)VNOVAL ) {
3845
+     dir.dir_mode = U9P_PERM_NONPERM(dir.dir_mode)|U9P_PERM_ALL(vap->va_mode);
3846
+   }
3847
+   if( vap->va_gid != VNOVAL ) {
3848
+     if( (u9p = u9fs_finduser(vap->va_gid)) == 0 )
3849
+       return (EINVAL);
3850
+     strncpy(u9p->u_name, dir.dir_gid, U9FS_NAMELEN);
3851
+   }
3852
+   if( vap->va_mtime.tv_sec != VNOVAL ) {
3853
+     dir.dir_mtime = vap->va_mtime.tv_sec;
3854
+   }
3855
+ 
3856
+   /* stat fid */
3857
+   bzero(&req, sizeof(req));
3858
+   req.r_nmp = nmp;
3859
+   req.r_procp = ap->a_p;
3860
+   req.r_type = Twstat;
3861
+   req.r_fid = np->n_fid;
3862
+   u9p_d2m(&dir, req.r_stat);
3863
+   error = u9fs_request(& req, & rep, 1);
3864
+   if( error )
3865
+     return error;
3866
+   VOP_GETATTR(vp, &attr, ap->a_cred, ap->a_p);
3867
+ 
3868
+   return 0;
3869
+ }
3870
+ 
3871
+ /*
3872
+  * u9fs lookup call, one step at a time...
3873
+  * First look in cache
3874
+  * If not found, unlock the directory u9fsnode and do the rpc
3875
+  */
3876
+ static int
3877
+ u9fs_lookup(ap)
3878
+ 	struct vop_lookup_args /* {
3879
+ 		struct vnodeop_desc *a_desc;
3880
+ 		struct vnode *a_dvp;
3881
+ 		struct vnode **a_vpp;
3882
+ 		struct componentname *a_cnp;
3883
+ 	} */ *ap;
3884
+ {
3885
+ 	struct componentname *cnp = ap->a_cnp;
3886
+ 	struct vnode *dvp = ap->a_dvp;
3887
+ 	struct vnode **vpp = ap->a_vpp;
3888
+ 	int flags = cnp->cn_flags;
3889
+ 	struct vnode *newvp;
3890
+ 	struct u9fsmount *nmp;
3891
+ 	long len;
3892
+ 	u9fsfh_t fh;
3893
+ 	struct u9fsnode *np;
3894
+ 	int lockparent, wantparent, error = 0;
3895
+ 	struct proc *p = cnp->cn_proc;
3896
+ 	struct u9fsreq req, rep;
3897
+ 	u_short newfid;
3898
+ 	struct vattr attrs;
3899
+ 
3900
+ 	*vpp = NULLVP;
3901
+ 	if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
3902
+ 	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
3903
+ 		return (EROFS);
3904
+ 	if (dvp->v_type != VDIR)
3905
+ 		return (ENOTDIR);
3906
+ 	lockparent = flags & LOCKPARENT;
3907
+ 	wantparent = flags & (LOCKPARENT|WANTPARENT);
3908
+ 	nmp = VFSTOU9FS(dvp->v_mount);
3909
+ 	np = VTOU9FS(dvp);
3910
+ #if 0
3911
+ 	if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
3912
+ 		struct vattr vattr;
3913
+ 		int vpid;
3914
+ 
3915
+ 		if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) {
3916
+ 			*vpp = NULLVP;
3917
+ 			return (error);
3918
+ 		}
3919
+ 
3920
+ 		newvp = *vpp;
3921
+ 		vpid = newvp->v_id;
3922
+ 		/*
3923
+ 		 * See the comment starting `Step through' in ufs/ufs_lookup.c
3924
+ 		 * for an explanation of the locking protocol
3925
+ 		 */
3926
+ 		if (dvp == newvp) {
3927
+ 			VREF(newvp);
3928
+ 			error = 0;
3929
+ 		} else if (flags & ISDOTDOT) {
3930
+ 			VOP_UNLOCK(dvp, 0, p);
3931
+ 			error = vget(newvp, LK_EXCLUSIVE, p);
3932
+ 			if (!error && lockparent && (flags & ISLASTCN))
3933
+ 				error = vn_lock(dvp, LK_EXCLUSIVE, p);
3934
+ 		} else {
3935
+ 			error = vget(newvp, LK_EXCLUSIVE, p);
3936
+ 			if (!lockparent || error || !(flags & ISLASTCN))
3937
+ 				VOP_UNLOCK(dvp, 0, p);
3938
+ 		}
3939
+ 		if (!error) {
3940
+ 			if (vpid == newvp->v_id) {
3941
+ 			   if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p)
3942
+ 			    && vattr.va_ctime.tv_sec == VTOU9FS(newvp)->n_ctime) {
3943
+ 				u9fsstats.lookupcache_hits++;
3944
+ 				if (cnp->cn_nameiop != LOOKUP &&
3945
+ 				    (flags & ISLASTCN))
3946
+ 					cnp->cn_flags |= SAVENAME;
3947
+ 				return (0);
3948
+ 			   }
3949
+ 			   cache_purge(newvp);
3950
+ 			}
3951
+ 			vput(newvp);
3952
+ 			if (lockparent && dvp != newvp && (flags & ISLASTCN))
3953
+ 				VOP_UNLOCK(dvp, 0, p);
3954
+ 		}
3955
+ 		error = vn_lock(dvp, LK_EXCLUSIVE, p);
3956
+ 		*vpp = NULLVP;
3957
+ 		if (error)
3958
+ 			return (error);
3959
+ 	}
3960
+ #endif
3961
+ 	error = 0;
3962
+ 	newvp = NULLVP;
3963
+ 	len = cnp->cn_namelen;
3964
+ 
3965
+ 	/* Tclwalk tag fid newfid name */
3966
+ 	bzero(&req, sizeof(req));
3967
+ 	req.r_procp = p;
3968
+ 	req.r_nmp = nmp;
3969
+ 	req.r_type = Tclwalk;
3970
+ 	req.r_fid = np->n_fid;
3971
+ 	newfid = req.r_newfid = u9fs_id_new(nmp->nm_fids);
3972
+ 	bcopy(cnp->cn_nameptr, req.r_name, len);
3973
+ 	if( (error = u9fs_request(&req, &rep, 1)) ) {
3974
+ 	  u9fs_id_free(nmp->nm_fids, newfid);
3975
+ 	  return error;
3976
+ 	}
3977
+ 
3978
+ 	fh = rep.r_qid.path;
3979
+ 	if( fh == 0 ) {
3980
+ 	  u9fs_id_free(nmp->nm_fids, newfid);
3981
+ 	  error = ENOENT;
3982
+ 	  goto lastcheck;
3983
+ 	}
3984
+ 
3985
+ 	/*
3986
+ 	 * Handle RENAME case...
3987
+ 	 */
3988
+ 	if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
3989
+ #if 0
3990
+ 	  /* XXX: I dont understand this. rename foo foo? */
3991
+ 		if (U9FS_CMPFH(np, fhp, fhsize)) {
3992
+ 			m_freem(mrep);
3993
+ 			return (EISDIR);
3994
+ 		}
3995
+ #endif
3996
+ 		error = u9fs_nget(dvp->v_mount, fh, &np, p);
3997
+ 		if (error)
3998
+ 		  goto fail;
3999
+ 
4000
+ 		if ( np->n_fid )
4001
+ 		  u9fs_free_fid(newfid, nmp, p);
4002
+ 		else
4003
+ 		  np->n_fid = newfid;
4004
+ 
4005
+ 		newvp = U9FSTOV(np);
4006
+ 		*vpp = newvp;
4007
+ 		cnp->cn_flags |= SAVENAME;
4008
+ 		if (!lockparent)
4009
+ 			VOP_UNLOCK(dvp, 0, p);
4010
+ 		return (0);
4011
+ 	}
4012
+ 
4013
+ 	if (flags & ISDOTDOT) {
4014
+ 		VOP_UNLOCK(dvp, 0, p);
4015
+ 		error = u9fs_nget(dvp->v_mount, fh, &np, p);
4016
+ 		if (error) {
4017
+ 			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
4018
+ 			goto fail;
4019
+ 		}
4020
+ 		if( np->n_fid )
4021
+ 		  u9fs_free_fid(newfid, nmp, p);
4022
+ 		else
4023
+ 		  np->n_fid = req.r_newfid;
4024
+ 
4025
+ 		newvp = U9FSTOV(np);
4026
+ 		if (lockparent && (flags & ISLASTCN) &&
4027
+ 		    (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
4028
+ 		    	vput(newvp);
4029
+ 			return (error);
4030
+ 		}
4031
+ 	} else if (np->n_qid.path == fh) {
4032
+ 	        u9fs_free_fid(newfid, nmp, p);
4033
+ 		VREF(dvp);
4034
+ 		newvp = dvp;
4035
+ 	} else {
4036
+ 		error = u9fs_nget(dvp->v_mount, fh, &np, p);
4037
+ 		if (error)
4038
+ 		  goto fail;
4039
+ 
4040
+ 		if( np->n_fid )
4041
+ 		  u9fs_free_fid(newfid, nmp, p);
4042
+ 		else
4043
+ 		  np->n_fid = req.r_newfid;
4044
+ 
4045
+ 		if (!lockparent || !(flags & ISLASTCN))
4046
+ 			VOP_UNLOCK(dvp, 0, p);
4047
+ 		newvp = U9FSTOV(np);
4048
+ 
4049
+ 		VOP_GETATTR(newvp, & attrs, p->p_ucred, p);
4050
+ 	}
4051
+ 
4052
+ 	if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
4053
+ 		cnp->cn_flags |= SAVENAME;
4054
+ #if 0
4055
+ 	if ((cnp->cn_flags & MAKEENTRY) &&
4056
+ 	    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
4057
+ 		np->n_ctime = np->n_vattr.va_ctime.tv_sec;
4058
+ 		cache_enter(dvp, newvp, cnp);
4059
+ 	}
4060
+ #endif
4061
+ 	*vpp = newvp;
4062
+  lastcheck:
4063
+ 	if (error) {
4064
+ 		if (newvp != NULLVP) {
4065
+ 			vrele(newvp);
4066
+ 			*vpp = NULLVP;
4067
+ 		}
4068
+ 		if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
4069
+ 		    (flags & ISLASTCN) && error == ENOENT) {
4070
+ 			if (!lockparent)
4071
+ 				VOP_UNLOCK(dvp, 0, p);
4072
+ 			if (dvp->v_mount->mnt_flag & MNT_RDONLY)
4073
+ 				error = EROFS;
4074
+ 			else
4075
+ 				error = EJUSTRETURN;
4076
+ 		}
4077
+ 		if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
4078
+ 			cnp->cn_flags |= SAVENAME;
4079
+ 	}
4080
+ 	return (error);
4081
+ 
4082
+  fail:
4083
+ 	u9fs_free_fid(newfid, nmp, p);
4084
+ 	return (error);
4085
+ }
4086
+ 
4087
+ /*
4088
+  * u9fs read call.
4089
+  * Just call u9fs_bioread() to do the work.
4090
+  */
4091
+ static int
4092
+ u9fs_read(ap)
4093
+ 	struct vop_read_args /* {
4094
+ 		struct vnode *a_vp;
4095
+ 		struct uio *a_uio;
4096
+ 		int  a_ioflag;
4097
+ 		struct ucred *a_cred;
4098
+ 	} */ *ap;
4099
+ {
4100
+   register struct vnode *vp = ap->a_vp;
4101
+   
4102
+   if (vp->v_type != VREG)
4103
+     return (EPERM);
4104
+   return (u9fs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
4105
+ }
4106
+ 
4107
+ /*
4108
+  * u9fs readlink call
4109
+  */
4110
+ static int
4111
+ u9fs_readlink(ap)
4112
+ 	struct vop_readlink_args /* {
4113
+ 		struct vnode *a_vp;
4114
+ 		struct uio *a_uio;
4115
+ 		struct ucred *a_cred;
4116
+ 	} */ *ap;
4117
+ {
4118
+   return (EOPNOTSUPP);
4119
+ }
4120
+ 
4121
+ /*
4122
+  * u9fs mknod vop
4123
+  * just call u9fs_mknodrpc() to do the work.
4124
+  */
4125
+ /* ARGSUSED */
4126
+ static int
4127
+ u9fs_mknod(ap)
4128
+ 	struct vop_mknod_args /* {
4129
+ 		struct vnode *a_dvp;
4130
+ 		struct vnode **a_vpp;
4131
+ 		struct componentname *a_cnp;
4132
+ 		struct vattr *a_vap;
4133
+ 	} */ *ap;
4134
+ {
4135
+   return (EOPNOTSUPP);
4136
+ }
4137
+ 
4138
+ /*
4139
+  * u9fs file create call
4140
+  */
4141
+ static int
4142
+ u9fs_create(ap)
4143
+ 	struct vop_create_args /* {
4144
+ 		struct vnode *a_dvp;
4145
+ 		struct vnode **a_vpp;
4146
+ 		struct componentname *a_cnp;
4147
+ 		struct vattr *a_vap;
4148
+ 	} */ *ap;
4149
+ {
4150
+ 	register struct vnode *dvp = ap->a_dvp;
4151
+ 	register struct vattr *vap = ap->a_vap;
4152
+ 	register struct componentname *cnp = ap->a_cnp;
4153
+ 	struct u9fsnode *np = (struct u9fsnode *)0;
4154
+ 	struct vnode *newvp = (struct vnode *)0;
4155
+ 	int error = 0, len;
4156
+ 	struct vattr vattr;
4157
+ 	struct u9fsreq req, rep;
4158
+ 	struct u9fsmount *nmp;
4159
+ 	u9fsfh_t fh;
4160
+ 	struct proc * p;
4161
+ 	int pfid;
4162
+ 
4163
+ #if 0
4164
+ 	/*
4165
+ 	 * Oops, not for me..
4166
+ 	 */
4167
+ 	if (vap->va_type == VSOCK)
4168
+ 		return (u9fs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
4169
+ #endif
4170
+ 
4171
+ 	if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
4172
+ 		VOP_ABORTOP(dvp, cnp);
4173
+ 		return (error);
4174
+ 	}
4175
+ 
4176
+ 	nmp = VFSTOU9FS(dvp->v_mount);
4177
+ 	np = VTOU9FS(dvp);
4178
+ 	p = cnp->cn_proc;
4179
+ 
4180
+ 	bzero(&req, sizeof(req));
4181
+ 	req.r_nmp = nmp;
4182
+ 	req.r_procp = p;
4183
+ 
4184
+ 	req.r_type = Tclone;
4185
+ 	pfid = req.r_fid  = np->n_fid;
4186
+ 	req.r_newfid = u9fs_id_new(nmp->nm_fids);
4187
+ 	error = u9fs_request(&req, &rep, 1);
4188
+ 	if( error )
4189
+ 	  return error;
4190
+ 
4191
+ 	req.r_type = Tcreate;
4192
+ 	req.r_fid = req.r_newfid;
4193
+ 	len = cnp->cn_namelen;
4194
+ 	if( len > U9FS_NAMELEN )
4195
+ 	  len = U9FS_NAMELEN;
4196
+ 	strncpy(req.r_name, cnp->cn_nameptr, len);
4197
+ 	req.r_name[U9FS_NAMELEN] = 0;
4198
+ 	req.r_perm = U9P_PERM_ALL(vap->va_mode);
4199
+ 	if( vap->va_type == VDIR ) {
4200
+ 	  req.r_perm |= 0x80000000;
4201
+ 	  req.r_mode = U9P_MODE_RD;
4202
+ 	} else
4203
+ 	  req.r_mode = U9P_MODE_WR | U9P_MODE_TRUNC;
4204
+ 	if(vap->va_vaflags & VA_EXCLUSIVE) 
4205
+ 	  req.r_mode = U9P_MODE_EX;
4206
+ 
4207
+ 	error = u9fs_request(&req, &rep, 1);
4208
+ 	if( error )
4209
+ 	  return error;
4210
+ 
4211
+ 	fh = rep.r_qid.path;
4212
+ 	u9fs_nget(dvp->v_mount, fh, &np, p);
4213
+ 	newvp = U9FSTOV(np);
4214
+ 	if( vap->va_type == VDIR )
4215
+ 	  np->n_rdfid = req.r_fid;
4216
+ 	else
4217
+ 	  np->n_wrfid = req.r_fid;
4218
+ 	
4219
+ 	req.r_type = Tclwalk;
4220
+ 	req.r_fid  = pfid;
4221
+ 	req.r_newfid = u9fs_id_new(nmp->nm_fids);
4222
+ 	/* r_name is already filled */
4223
+ 	error = u9fs_request(&req, &rep, 1);
4224
+ 	if( error )
4225
+ 	  return error;
4226
+ 	np->n_fid = req.r_newfid;
4227
+ 	VOP_GETATTR(newvp, & vattr, p->p_ucred, p);
4228
+ 
4229
+ 	*ap->a_vpp = newvp;
4230
+ 	zfree(namei_zone, cnp->cn_pnbuf);
4231
+ 
4232
+ 	return 0;
4233
+ }
4234
+ 
4235
+ /*
4236
+  * u9fs file remove call
4237
+  * To try and make u9fs semantics closer to ufs semantics, a file that has
4238
+  * other processes using the vnode is renamed instead of removed and then
4239
+  * removed later on the last close.
4240
+  * - If v_usecount > 1
4241
+  *	  If a rename is not already in the works
4242
+  *	     call u9fs_sillyrename() to set it up
4243
+  *     else
4244
+  *	  do the remove rpc
4245
+  */
4246
+ static int
4247
+ u9fs_remove(ap)
4248
+ 	struct vop_remove_args /* {
4249
+ 		struct vnodeop_desc *a_desc;
4250
+ 		struct vnode * a_dvp;
4251
+ 		struct vnode * a_vp;
4252
+ 		struct componentname * a_cnp;
4253
+ 	} */ *ap;
4254
+ {
4255
+ 	register struct vnode *vp = ap->a_vp;
4256
+ 	register struct componentname *cnp = ap->a_cnp;
4257
+ 	struct u9fsnode *np;
4258
+ 	struct u9fsreq req, rep;
4259
+ 	struct u9fsmount *nmp;
4260
+ 	struct proc * p;
4261
+ 	int error;
4262
+ 
4263
+ 	nmp = VFSTOU9FS(vp->v_mount);
4264
+ 	np = VTOU9FS(vp);
4265
+ 	p = cnp->cn_proc;
4266
+ 	bzero(&req, sizeof(req));
4267
+ 	req.r_nmp = nmp;
4268
+ 	req.r_procp = p;
4269
+ 	req.r_type = Tremove;
4270
+ 	req.r_fid = np->n_fid;
4271
+ 	error = u9fs_request(&req, &rep, 1);
4272
+ 	if( error )
4273
+ 	  return error;
4274
+ 	zfree(namei_zone, cnp->cn_pnbuf);
4275
+ 	return 0;
4276
+ }
4277
+ 
4278
+ /*
4279
+  * u9fs file rename call
4280
+  */
4281
+ static int
4282
+ u9fs_rename(ap)
4283
+ 	struct vop_rename_args  /* {
4284
+ 		struct vnode *a_fdvp;
4285
+ 		struct vnode *a_fvp;
4286
+ 		struct componentname *a_fcnp;
4287
+ 		struct vnode *a_tdvp;
4288
+ 		struct vnode *a_tvp;
4289
+ 		struct componentname *a_tcnp;
4290
+ 	} */ *ap;
4291
+ {
4292
+ 	register struct vnode *fvp = ap->a_fvp;
4293
+ 	register struct vnode *tvp = ap->a_tvp;
4294
+ 	register struct vnode *fdvp = ap->a_fdvp;
4295
+ 	register struct vnode *tdvp = ap->a_tdvp;
4296
+ 	register struct componentname *tcnp = ap->a_tcnp;
4297
+ 	register struct componentname *fcnp = ap->a_fcnp;
4298
+ 	int error, len;
4299
+ 	struct u9fsmount * nmp;
4300
+ 	struct u9fsreq req, rep;
4301
+ 	struct u9fsdir dir;
4302
+ 	struct u9fsnode * np;
4303
+ 
4304
+ 	/* we cant do cross-directory renaming or move to an existing file */
4305
+ 	if( fdvp != tdvp || tvp != 0 || fvp->v_mount->mnt_flag & MNT_RDONLY ){
4306
+ 	  printf("rename to existing file not supported\n");
4307
+ 	  error = EOPNOTSUPP;
4308
+ 	  goto out;
4309
+ 	}
4310
+ 
4311
+ 	nmp = VFSTOU9FS(fvp->v_mount);
4312
+ 	np = VTOU9FS(fvp);
4313
+ 
4314
+ 	bcopy(&np->n_dir, &dir, sizeof(dir));
4315
+ 	len = tcnp->cn_namelen;
4316
+ 	if( len > U9FS_NAMELEN )
4317
+ 	  len = U9FS_NAMELEN;
4318
+ 	strncpy(dir.dir_name, tcnp->cn_nameptr, len);
4319
+ 	dir.dir_name[U9FS_NAMELEN-1] = 0;
4320
+ 	
4321
+ 	/* stat fid */
4322
+ 	bzero(&req, sizeof(req));
4323
+ 	req.r_nmp = nmp;
4324
+ 	req.r_procp = fcnp->cn_proc;
4325
+ 	req.r_type = Twstat;
4326
+ 	req.r_fid = np->n_fid;
4327
+ 	u9p_d2m(&dir, req.r_stat);
4328
+ 	error = u9fs_request(& req, & rep, 1);
4329
+ 
4330
+  out:
4331
+ 	if (tdvp == tvp)
4332
+ 		vrele(tdvp);
4333
+ 	else
4334
+ 		vput(tdvp);
4335
+ 	if (tvp)
4336
+ 		vput(tvp);
4337
+ 	vrele(fdvp);
4338
+ 	vrele(fvp);
4339
+ 
4340
+ 	return error;
4341
+ }
4342
+ 
4343
+ /*
4344
+  * u9fs hard link create call
4345
+  */
4346
+ static int
4347
+ u9fs_link(ap)
4348
+ 	struct vop_link_args /* {
4349
+ 		struct vnode *a_tdvp;
4350
+ 		struct vnode *a_vp;
4351
+ 		struct componentname *a_cnp;
4352
+ 	} */ *ap;
4353
+ {
4354
+   return (EOPNOTSUPP);
4355
+ }
4356
+ 
4357
+ /*
4358
+  * u9fs symbolic link create call
4359
+  */
4360
+ static int
4361
+ u9fs_symlink(ap)
4362
+ 	struct vop_symlink_args /* {
4363
+ 		struct vnode *a_dvp;
4364
+ 		struct vnode **a_vpp;
4365
+ 		struct componentname *a_cnp;
4366
+ 		struct vattr *a_vap;
4367
+ 		char *a_target;
4368
+ 	} */ *ap;
4369
+ {
4370
+   return (EOPNOTSUPP);
4371
+ }
4372
+ 
4373
+ /*
4374
+  * u9fs make dir call
4375
+  */
4376
+ static int
4377
+ u9fs_mkdir(ap)
4378
+ 	struct vop_mkdir_args /* {
4379
+ 		struct vnode *a_dvp;
4380
+ 		struct vnode **a_vpp;
4381
+ 		struct componentname *a_cnp;
4382
+ 		struct vattr *a_vap;
4383
+ 	} */ *ap;
4384
+ {
4385
+   struct vop_create_args cap;
4386
+ 
4387
+   cap.a_dvp = ap->a_dvp;
4388
+   cap.a_vpp = ap->a_vpp;
4389
+   cap.a_cnp = ap->a_cnp;
4390
+   cap.a_vap = ap->a_vap;
4391
+   return u9fs_create(&cap);
4392
+ }
4393
+ 
4394
+ /*
4395
+  * u9fs remove directory call
4396
+  */
4397
+ static int
4398
+ u9fs_rmdir(ap)
4399
+ 	struct vop_rmdir_args /* {
4400
+ 		struct vnode *a_dvp;
4401
+ 		struct vnode *a_vp;
4402
+ 		struct componentname *a_cnp;
4403
+ 	} */ *ap;
4404
+ {
4405
+ 	register struct vnode *vp = ap->a_vp;
4406
+ 	register struct componentname *cnp = ap->a_cnp;
4407
+ 	struct u9fsnode *np;
4408
+ 	struct u9fsreq req, rep;
4409
+ 	struct u9fsmount *nmp;
4410
+ 	struct proc * p;
4411
+ 	int error;
4412
+ 
4413
+ 	nmp = VFSTOU9FS(vp->v_mount);
4414
+ 	np = VTOU9FS(vp);
4415
+ 	p = cnp->cn_proc;
4416
+ 	bzero(&req, sizeof(req));
4417
+ 	req.r_nmp = nmp;
4418
+ 	req.r_procp = p;
4419
+ 	req.r_type = Tremove;
4420
+ 	req.r_fid = np->n_fid;
4421
+ 	error = u9fs_request(&req, &rep, 1);
4422
+ 	if( error )
4423
+ 	  return error;
4424
+ 	u9fs_id_free(nmp->nm_fids, np->n_fid);
4425
+ 	np->n_fid = 0;
4426
+ 	zfree(namei_zone, cnp->cn_pnbuf);
4427
+ 	return 0;
4428
+ }
4429
+ 
4430
+ /*
4431
+  * u9fs readdir call
4432
+  */
4433
+ static int
4434
+ u9fs_readdir(ap)
4435
+ 	struct vop_readdir_args /* {
4436
+ 		struct vnode *a_vp;
4437
+ 		struct uio *a_uio;
4438
+ 		struct ucred *a_cred;
4439
+ 	} */ *ap;
4440
+ {
4441
+   register struct vnode *vp = ap->a_vp;
4442
+   register struct uio *uio = ap->a_uio;
4443
+   int error;
4444
+   
4445
+   if (vp->v_type != VDIR)
4446
+     return (EPERM);
4447
+ 
4448
+   /*
4449
+    * Call u9fs_bioread() to do the real work.
4450
+    */
4451
+   error = u9fs_bioread(vp, uio, 0, ap->a_cred, 0);
4452
+   
4453
+   return (error);
4454
+ }
4455
+ 
4456
+ /*
4457
+  * Kludge City..
4458
+  * - make u9fs_bmap() essentially a no-op that does no translation
4459
+  * - do u9fs_strategy() by doing I/O with u9fs_readrpc/u9fs_writerpc
4460
+  *   (Maybe I could use the process's page mapping, but I was concerned that
4461
+  *    Kernel Write might not be enabled and also figured copyout() would do
4462
+  *    a lot more work than bcopy() and also it currently happens in the
4463
+  *    context of the swapper process (2).
4464
+  */
4465
+ static int
4466
+ u9fs_bmap(ap)
4467
+ 	struct vop_bmap_args /* {
4468
+ 		struct vnode *a_vp;
4469
+ 		daddr_t  a_bn;
4470
+ 		struct vnode **a_vpp;
4471
+ 		daddr_t *a_bnp;
4472
+ 		int *a_runp;
4473
+ 		int *a_runb;
4474
+ 	} */ *ap;
4475
+ {
4476
+   register struct vnode *vp = ap->a_vp;
4477
+   
4478
+   if (ap->a_vpp != NULL)
4479
+     *ap->a_vpp = vp;
4480
+   if (ap->a_bnp != NULL)
4481
+     *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
4482
+   if (ap->a_runp != NULL)
4483
+     *ap->a_runp = 0;
4484
+   if (ap->a_runb != NULL)
4485
+     *ap->a_runb = 0;
4486
+   return (0);
4487
+ 
4488
+   return 0;
4489
+ }
4490
+ 
4491
+ /*
4492
+  * Strategy routine.
4493
+  * For async requests when u9fsiod(s) are running, queue the request by
4494
+  * calling u9fs_asyncio(), otherwise just all u9fs_doio() to do the
4495
+  * request.
4496
+  */
4497
+ static int
4498
+ u9fs_strategy(ap)
4499
+ 	struct vop_strategy_args *ap;
4500
+ {
4501
+ 	register struct buf *bp = ap->a_bp;
4502
+ 	struct ucred *cr;
4503
+ 	struct proc *p;
4504
+ 	int error = 0;
4505
+ 
4506
+ 	if (bp->b_flags & B_PHYS)
4507
+ 		panic("nfs physio");
4508
+ 	if (bp->b_flags & B_ASYNC)
4509
+ 	        panic("u9fs async");
4510
+ 
4511
+ 	p = curproc;	/* XXX */
4512
+ 	if (bp->b_flags & B_READ)
4513
+ 		cr = bp->b_rcred;
4514
+ 	else
4515
+ 		cr = bp->b_wcred;
4516
+ 	error = u9fs_doio(bp, cr, p);
4517
+ 	return (error);  
4518
+ }
4519
+ 
4520
+ /*
4521
+  * Mmap a file
4522
+  *
4523
+  * NB Currently unsupported.
4524
+  */
4525
+ /* ARGSUSED */
4526
+ static int
4527
+ u9fs_mmap(ap)
4528
+ 	struct vop_mmap_args /* {
4529
+ 		struct vnode *a_vp;
4530
+ 		int  a_fflags;
4531
+ 		struct ucred *a_cred;
4532
+ 		struct proc *a_p;
4533
+ 	} */ *ap;
4534
+ {
4535
+ 	return (EINVAL);
4536
+ }
4537
+ 
4538
+ /*
4539
+  * fsync vnode op. Just call u9fs_flush() with commit == 1.
4540
+  */
4541
+ /* ARGSUSED */
4542
+ static int
4543
+ u9fs_fsync(ap)
4544
+ 	struct vop_fsync_args /* {
4545
+ 		struct vnodeop_desc *a_desc;
4546
+ 		struct vnode * a_vp;
4547
+ 		struct ucred * a_cred;
4548
+ 		int  a_waitfor;
4549
+ 		struct proc * a_p;
4550
+ 	} */ *ap;
4551
+ {
4552
+   /* we have a blocking writeback cache */
4553
+   return 0;
4554
+ }
4555
+ 
4556
+ /*
4557
+  * U9FS advisory byte-level locks.
4558
+  * Currently unsupported.
4559
+  */
4560
+ static int
4561
+ u9fs_advlock(ap)
4562
+ 	struct vop_advlock_args /* {
4563
+ 		struct vnode *a_vp;
4564
+ 		caddr_t  a_id;
4565
+ 		int  a_op;
4566
+ 		struct flock *a_fl;
4567
+ 		int  a_flags;
4568
+ 	} */ *ap;
4569
+ {
4570
+ 	register struct u9fsnode *np = VTOU9FS(ap->a_vp);
4571
+ 
4572
+ 	/*
4573
+ 	 * The following kludge is to allow diskless support to work
4574
+ 	 * until a real NFS lockd is implemented. Basically, just pretend
4575
+ 	 * that this is a local lock.
4576
+ 	 */
4577
+ 	return (lf_advlock(ap, &(np->n_lockf), np->n_size));
4578
+ }
4579
+ 
4580
+ /*
4581
+  * Print out the contents of an u9fsnode.
4582
+  */
4583
+ static int
4584
+ u9fs_print(ap)
4585
+ 	struct vop_print_args /* {
4586
+ 		struct vnode *a_vp;
4587
+ 	} */ *ap;
4588
+ {
4589
+   panic("u9fs_print");
4590
+   return 0;
4591
+ }
4592
+ 
4593
+ /*
4594
+  * Just call u9fs_writebp() with the force argument set to 1.
4595
+  */
4596
+ static int
4597
+ u9fs_bwrite(ap)
4598
+ 	struct vop_bwrite_args /* {
4599
+ 		struct vnode *a_bp;
4600
+ 	} */ *ap;
4601
+ {
4602
+   panic("u9fs_bwrite");
4603
+   return 0;
4604
+ }
4605
+ 
4606
+ /*
4607
+  * Vnode op for VM getpages.
4608
+  */
4609
+ static int
4610
+ u9fs_getpages(ap)
4611
+ 	struct vop_getpages_args /* {
4612
+ 		struct vnode *a_vp;
4613
+ 		vm_page_t *a_m;
4614
+ 		int a_count;
4615
+ 		int a_reqpage;
4616
+ 		vm_ooffset_t a_offset;
4617
+ 	} */ *ap;
4618
+ {
4619
+ 	int i, error, nextoff, size, toff, npages, count;
4620
+ 	struct uio uio;
4621
+ 	struct iovec iov;
4622
+ 	vm_offset_t kva;
4623
+ 	struct buf *bp;
4624
+ 	struct vnode *vp;
4625
+ 	struct proc *p;
4626
+ 	struct ucred *cred;
4627
+ 	struct u9fsmount *nmp;
4628
+ 	vm_page_t *pages;
4629
+ 
4630
+ 	vp = ap->a_vp;
4631
+ 	p = curproc;				/* XXX */
4632
+ 	cred = curproc->p_ucred;		/* XXX */
4633
+ 	nmp = VFSTOU9FS(vp->v_mount);
4634
+ 	pages = ap->a_m;
4635
+ 	count = ap->a_count;
4636
+ 
4637
+ 	if (vp->v_object == NULL) {
4638
+ 		printf("u9fs_getpages: called with non-merged cache vnode??\n");
4639
+ 		return VM_PAGER_ERROR;
4640
+ 	}
4641
+ 
4642
+ 	/*
4643
+ 	 * We use only the kva address for the buffer, but this is extremely
4644
+ 	 * convienient and fast.
4645
+ 	 */
4646
+ 	bp = getpbuf();
4647
+ 
4648
+ 	npages = btoc(count);
4649
+ 	kva = (vm_offset_t) bp->b_data;
4650
+ 	pmap_qenter(kva, pages, npages);
4651
+ 
4652
+ 	iov.iov_base = (caddr_t) kva;
4653
+ 	iov.iov_len = count;
4654
+ 	uio.uio_iov = &iov;
4655
+ 	uio.uio_iovcnt = 1;
4656
+ 	uio.uio_offset = IDX_TO_OFF(pages[0]->pindex);
4657
+ 	uio.uio_resid = count;
4658
+ 	uio.uio_segflg = UIO_SYSSPACE;
4659
+ 	uio.uio_rw = UIO_READ;
4660
+ 	uio.uio_procp = p;
4661
+ 
4662
+ 	error = u9fs_readrpc(vp, &uio, cred);
4663
+ 	pmap_qremove(kva, npages);
4664
+ 
4665
+ 	relpbuf(bp);
4666
+ 
4667
+ 	if (error && (uio.uio_resid == count))
4668
+ 		return VM_PAGER_ERROR;
4669
+ 
4670
+ 	size = count - uio.uio_resid;
4671
+ 
4672
+ 	for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
4673
+ 		vm_page_t m;
4674
+ 		nextoff = toff + PAGE_SIZE;
4675
+ 		m = pages[i];
4676
+ 
4677
+ 		m->flags &= ~PG_ZERO;
4678
+ 
4679
+ 		if (nextoff <= size) {
4680
+ 			m->valid = VM_PAGE_BITS_ALL;
4681
+ 			m->dirty = 0;
4682
+ 		} else {
4683
+ 			int nvalid = ((size + DEV_BSIZE - 1) - toff) & ~(DEV_BSIZE - 1);
4684
+ 			vm_page_set_validclean(m, 0, nvalid);
4685
+ 		}
4686
+ 		
4687
+ 		if (i != ap->a_reqpage) {
4688
+ 			/*
4689
+ 			 * Whether or not to leave the page activated is up in
4690
+ 			 * the air, but we should put the page on a page queue
4691
+ 			 * somewhere (it already is in the object).  Result:
4692
+ 			 * It appears that emperical results show that
4693
+ 			 * deactivating pages is best.
4694
+ 			 */
4695
+ 
4696
+ 			/*
4697
+ 			 * Just in case someone was asking for this page we
4698
+ 			 * now tell them that it is ok to use.
4699
+ 			 */
4700
+ 			if (!error) {
4701
+ 				if (m->flags & PG_WANTED)
4702
+ 					vm_page_activate(m);
4703
+ 				else
4704
+ 					vm_page_deactivate(m);
4705
+ 				vm_page_wakeup(m);
4706
+ 			} else {
4707
+ 				vnode_pager_freepage(m);
4708
+ 			}
4709
+ 		}
4710
+ 	}
4711
+ 	return 0;
4712
+ }
4713
+ 
4714
+ /*
4715
+  * Vnode op for VM putpages.
4716
+  */
4717
+ static int
4718
+ u9fs_putpages(ap)
4719
+ 	struct vop_putpages_args /* {
4720
+ 		struct vnode *a_vp;
4721
+ 		vm_page_t *a_m;
4722
+ 		int a_count;
4723
+ 		int a_sync;
4724
+ 		int *a_rtvals;
4725
+ 		vm_ooffset_t a_offset;
4726
+ 	} */ *ap;
4727
+ {
4728
+   panic("u9fs_putpages");
4729
+   return 0;
4730
+ }
4731
+ 
4732
+ static int
4733
+ u9fs_inactive(ap)
4734
+ 	struct vop_inactive_args /* {
4735
+ 		struct vnode *a_vp;
4736
+ 		struct proc *a_p;
4737
+ 	} */ *ap;
4738
+ {
4739
+   VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
4740
+   return 0;
4741
+ }
4742
+ 
4743
+ /*
4744
+  * Reclaim an u9fsnode so that it can be used for other purposes.
4745
+  */
4746
+ static int
4747
+ u9fs_reclaim(ap)
4748
+ 	struct vop_reclaim_args /* {
4749
+ 		struct vnode *a_vp;
4750
+ 	} */ *ap;
4751
+ {
4752
+ 	register struct vnode *vp = ap->a_vp;
4753
+ 	register struct u9fsnode *np = VTOU9FS(vp);
4754
+ 	register struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
4755
+ 	struct proc * p = curproc;
4756
+ 
4757
+ 	/* some vnodes do not have fids due to previous access failure */
4758
+ 	if( np->n_fid ) {
4759
+ 	  /* clunk fids */
4760
+ 	  u9fs_free_fid(np->n_fid, nmp, p);
4761
+ 	  if( np->n_rdfid )
4762
+ 	    u9fs_free_fid(np->n_rdfid, nmp, p);
4763
+ 	  if( np->n_wrfid )
4764
+ 	    u9fs_free_fid(np->n_wrfid, nmp, p);
4765
+ 	}
4766
+ 
4767
+ 	LIST_REMOVE(np, n_hash);
4768
+ 	cache_purge(vp);
4769
+ 	zfree(u9fsnode_zone, vp->v_data);
4770
+ 	vp->v_data = (void *)0;
4771
+ 
4772
+ 	return (0);
4773
+ }
4774
+ 
4775
+ /*
4776
+  * Vnode op for write using bio
4777
+  */
4778
+ static int
4779
+ u9fs_write(ap)
4780
+ 	struct vop_write_args /* {
4781
+ 		struct vnode *a_vp;
4782
+ 		struct uio *a_uio;
4783
+ 		int  a_ioflag;
4784
+ 		struct ucred *a_cred;
4785
+ 	} */ *ap;
4786
+ {
4787
+   if (ap->a_vp->v_type != VREG)
4788
+     return (EIO);
4789
+ 
4790
+   return u9fs_biowrite(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
4791
+ }
4792
+ 
4793
+ /*
4794
+  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
4795
+  * done. Currently nothing to do.
4796
+  */
4797
+ /* ARGSUSED */
4798
+ static int
4799
+ u9fs_abortop(ap)
4800
+ 	struct vop_abortop_args /* {
4801
+ 		struct vnode *a_dvp;
4802
+ 		struct componentname *a_cnp;
4803
+ 	} */ *ap;
4804
+ {
4805
+ 	return (0);
4806
+ }
4807
+ 
4808
+ /*
4809
+  * u9fs write call
4810
+  */
4811
+ int
4812
+ u9fs_writerpc(vp, uiop, cred)
4813
+ 	register struct vnode *vp;
4814
+ 	register struct uio *uiop;
4815
+ 	struct ucred *cred;
4816
+ {
4817
+   struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
4818
+   int error = 0, len, tsiz, rlen;
4819
+   struct u9fsreq req, rep;
4820
+   struct u9fsnode * np = VTOU9FS(vp);
4821
+   struct proc * p = uiop->uio_procp;
4822
+   struct mbuf * top;
4823
+ 
4824
+   tsiz = uiop->uio_resid;
4825
+   if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
4826
+     return (EFBIG);
4827
+   bzero(&req, sizeof(req));
4828
+   req.r_nmp = nmp;
4829
+   req.r_procp = p;
4830
+   req.r_type = Twrite;
4831
+   req.r_fid = np->n_wrfid;
4832
+   while (tsiz > 0) {
4833
+     len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
4834
+     req.r_offset = uiop->uio_offset;
4835
+     req.r_count = len;
4836
+     error = u9fs_uiotombuf(uiop, &top, len);
4837
+     if( error )
4838
+       break;
4839
+     req.r_data = (char *)top;
4840
+     error = u9fs_request(&req, &rep, 1);
4841
+     if( error )
4842
+       break;
4843
+     rlen = rep.r_count;
4844
+     if( rlen < len ) {
4845
+       error = EIO;
4846
+       break;
4847
+     }
4848
+     tsiz -= len;
4849
+ 
4850
+     /* each write message increments version number by one.
4851
+        to avoid flushing our write cache, update the version */
4852
+     if( np->n_qid.vers )
4853
+       np->n_qid.vers++;
4854
+     else 
4855
+       np->n_qid.vers = np->n_dir.dir_qid.vers + 1;
4856
+   }
4857
+   if (error)
4858
+     uiop->uio_resid = tsiz;
4859
+   return (error);
4860
+ }
4861
+ 
4862
+ /*
4863
+  * Readdir rpc call.
4864
+  * Called from below the buffer cache by u9fs_doio().
4865
+  */
4866
+ int
4867
+ u9fs_readdirrpc(vp, uiop, cred)
4868
+ 	struct vnode *vp;
4869
+ 	register struct uio *uiop;
4870
+ 	struct ucred *cred;
4871
+ 
4872
+ {
4873
+ 	register int len, left;
4874
+ 	register struct dirent *dp;
4875
+ 	struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);
4876
+ 	struct u9fsnode *np = VTOU9FS(vp);
4877
+ 	int error = 0, tlen, more_dirs = 1, bigenough;
4878
+ 	struct u9fsreq req, rep;
4879
+ 	int count;
4880
+ 	struct u9fsdir u9dir;
4881
+ 
4882
+ 	bigenough = uiop->uio_resid >= sizeof(struct dirent);
4883
+ 	bzero(&req, sizeof(req));
4884
+ 	req.r_nmp = nmp;
4885
+ 	req.r_type = Tread;
4886
+ 	req.r_fid = np->n_rdfid;
4887
+ 	req.r_count = nmp->nm_readdirsize;
4888
+ 	while ( more_dirs && bigenough ) {
4889
+ 	  req.r_offset = uiop->uio_offset;
4890
+ 	  error = u9fs_request(&req, &rep, 0);
4891
+ 	  if( error )
4892
+ 	    return error;
4893
+ 
4894
+ 	  count = rep.r_count;
4895
+ 	  more_dirs = (count == req.r_count);
4896
+ 	  len = 0;
4897
+ 	  dp = (struct dirent *)uiop->uio_iov->iov_base;
4898
+ 	  left = uiop->uio_resid;
4899
+ 	  while( len < count ) {
4900
+ 	    /* XXX: too conservative, but OK */
4901
+ 	    if( left < sizeof(*dp) ) {
4902
+ 	      bigenough = 0;
4903
+ 	      break;
4904
+ 	    }
4905
+ 	    if( u9p_m_m2d(&req.r_mrep, & u9dir) ) {
4906
+ 	      printf("u9p_m_m2d failed!\n");
4907
+ 	      return (EIO);
4908
+ 	    }
4909
+ 	    
4910
+ 	    dp->d_fileno = u9dir.dir_qid.path;
4911
+ 	    if( U9P_PERM_CHDIR(u9dir.dir_mode) )
4912
+ 	      dp->d_type = DT_DIR;
4913
+ 	    else
4914
+ 	      dp->d_type = DT_REG;
4915
+ 	    u9dir.dir_name[U9FS_NAMELEN-1] = 0; /* just to be sure */
4916
+ 	    dp->d_namlen = strlen(u9dir.dir_name);
4917
+ 	    memcpy(dp->d_name, u9dir.dir_name, dp->d_namlen+1);
4918
+ 	    tlen = DIRHDSIZ + dp->d_namlen + 4;
4919
+ 	    tlen = tlen - (tlen & 0x3);
4920
+ 	    dp->d_reclen = tlen;
4921
+ 	    dp = (struct dirent *)(((char *)dp) + tlen);
4922
+ 	    left -= tlen;
4923
+ 	    len += sizeof(u9dir);
4924
+ 	  }
4925
+ 	  tlen = uiop->uio_resid - left;
4926
+ 	  uiop->uio_resid = left;
4927
+ 	  uiop->uio_iov->iov_base += tlen;
4928
+ 	  uiop->uio_iov->iov_len -= tlen;
4929
+ 	  uiop->uio_offset += len;
4930
+ 	  m_freem(req.r_mrep);
4931
+ 	}
4932
+ 	return 0;
4933
+ }
4934
+ 
4935
+ /*
4936
+  * u9fs read rpc call
4937
+  * Ditto above
4938
+  */
4939
+ int
4940
+ u9fs_readrpc(vp, uiop, cred)
4941
+ 	register struct vnode *vp;
4942
+ 	struct uio *uiop;
4943
+ 	struct ucred *cred;
4944
+ {
4945
+   struct u9fsmount *nmp;
4946
+   struct u9fsnode *np = VTOU9FS(vp);
4947
+   int error = 0, len, retlen, tsiz;
4948
+   struct u9fsreq req, rep;
4949
+ 
4950
+   nmp = VFSTOU9FS(vp->v_mount);
4951
+   tsiz = uiop->uio_resid;
4952
+   if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
4953
+     return (EFBIG);
4954
+   bzero(&req, sizeof(req));
4955
+   req.r_nmp = nmp;
4956
+   req.r_type = Tread;
4957
+   req.r_fid = np->n_rdfid;
4958
+   while (tsiz > 0) {
4959
+     len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
4960
+     req.r_count = len;
4961
+     req.r_offset = uiop->uio_offset;
4962
+     error = u9fs_request(&req, &rep, 0);
4963
+     if( error )
4964
+       return error;
4965
+     retlen = rep.r_count;
4966
+     if( retlen && (error = u9fs_mbuftouio(req.r_mrep, uiop, retlen)) ) {
4967
+       m_freem(req.r_mrep);
4968
+       return error;
4969
+     }
4970
+     
4971
+     m_freem(req.r_mrep);
4972
+     req.r_mrep = 0;
4973
+     tsiz -= retlen;
4974
+     if (retlen < len)
4975
+       tsiz = 0;
4976
+   }
4977
+   return (0);
4978
+ }
4979
+ 
4980
+ static void u9fs_free_fid(fid, nmp, p)
4981
+      u_short fid;
4982
+      struct u9fsmount * nmp;
4983
+      struct proc * p;
4984
+ {
4985
+   struct u9fsreq req, rep;
4986
+ 
4987
+   /* clunk fid */
4988
+   bzero(&req, sizeof(req));
4989
+   req.r_nmp = nmp;
4990
+   req.r_procp = p;
4991
+   req.r_type = Tclunk;
4992
+   req.r_fid = fid;
4993
+   u9fs_request(&req, &rep, 1);
4994
+   u9fs_id_free(nmp->nm_fids, fid);
4995
+ }
4996
diff -N -c -r /usr/src/sys/9fs/9p.c ./9fs/9p.c
4997
*** /usr/src/sys/9fs/9p.c	Wed Dec 31 19:00:00 1969
4998
--- ./9fs/9p.c	Thu Nov 25 15:04:16 1999
4999
***************
5000
*** 0 ****
5001
--- 1,974 ----
5002
+ #include <sys/param.h>
5003
+ #include <sys/systm.h>
5004
+ #include <sys/socket.h>
5005
+ #include <sys/socketvar.h>
5006
+ #include <netinet/in.h>
5007
+ #include <sys/mbuf.h>
5008
+ #include <sys/malloc.h>
5009
+ #include <sys/vnode.h>
5010
+ #include <sys/mount.h>
5011
+ 
5012
+ #include <9fs/bitstring.h>
5013
+ #include <9fs/9p.h>
5014
+ #include <9fs/9auth.h>
5015
+ #include <9fs/9fs.h>
5016
+ 
5017
+ int u9p_usetcp = 0;
5018
+ struct u9fs_reqq u9fs_reqq;
5019
+ 
5020
+ #define	N2HCHAR(x)		x = *p++
5021
+ #define	N2HSHORT(x)	x = (p[0] | (p[1]<<8)); p += 2
5022
+ #define	N2HLONG(x)		x = (p[0] | (p[1]<<8) |\
5023
+ 				(p[2]<<16) | (p[3]<<24)); p += 4
5024
+ #define	N2HQUAD(x)	x = (u_int64_t)(p[0] | (p[1]<<8) |\
5025
+ 					(p[2]<<16) | (p[3]<<24)) |\
5026
+ 				((u_int64_t)(p[4] | (p[5]<<8) |\
5027
+ 					(p[6]<<16) | (p[7]<<24)) << 32); p += 8
5028
+ #define	N2HSTRING(x,n)	bcopy(p, x, n); p += n
5029
+ 
5030
+ #define	H2NCHAR(x)	*p++ = x
5031
+ #define	H2NSHORT(x)	p[0]=x; p[1]=x>>8; p += 2
5032
+ #define	H2NLONG(x)		p[0]=x; p[1]=x>>8; p[2]=x>>16; p[3]=x>>24; p += 4
5033
+ #define	H2NQUAD(x)	p[0]=x;	p[1]=x>>8;\
5034
+ 			p[2]=x>>16;	p[3]=x>>24;\
5035
+ 			p[4]=x>>32;	p[5]=x>>40;\
5036
+ 			p[6]=x>>48;	p[7]=x>>56;\
5037
+ 			p += 8
5038
+ #define	H2NSTRING(x,n)	bcopy(x, p, n); p += n
5039
+ 
5040
+ static void u9p_print __P((u_char * m, int len, struct u9fsreq * f));
5041
+ 
5042
+ static char * u9p_types[] = {
5043
+   "Tnop",
5044
+   "Rnop",
5045
+   "Tosession",
5046
+   "Rosession",
5047
+   "Terror",
5048
+   "Rerror",
5049
+   "Tflush",
5050
+   "Rflush",
5051
+   "Toattach",
5052
+   "Roattach",
5053
+   "Tclone",
5054
+   "Rclone",
5055
+   "Twalk",
5056
+   "Rwalk",
5057
+   "Topen",
5058
+   "Ropen",
5059
+   "Tcreate",
5060
+   "Rcreate",
5061
+   "Tread",
5062
+   "Rread",
5063
+   "Twrite",
5064
+   "Rwrite",
5065
+   "Tclunk",
5066
+   "Rclunk",
5067
+   "Tremove",
5068
+   "Rremove",
5069
+   "Tstat",
5070
+   "Rstat",
5071
+   "Twstat",
5072
+   "Rwstat",
5073
+   "Tclwalk",
5074
+   "Rclwalk",
5075
+   "Tauth",
5076
+   "Rauth",
5077
+   "Tsession",
5078
+   "Rsession",
5079
+   "Tattach",
5080
+   "Rattach",
5081
+   "Ttunnel",
5082
+   "Rtunnel",
5083
+   "Tmax"
5084
+ };
5085
+ 
5086
+ int u9p_m2s(char *ap, int n, struct u9fsreq *f)
5087
+ {
5088
+ 	u_char *p;
5089
+ 
5090
+ 	p = (u_char*)ap;
5091
+ 	N2HCHAR(f->r_type);
5092
+ 	N2HSHORT(f->r_tag);
5093
+ 	switch(f->r_type)
5094
+ 	{
5095
+ 	default:
5096
+ 		return 0;
5097
+ 
5098
+ 	case Tnop:
5099
+ 	case Tosession:
5100
+ 		break;
5101
+ 
5102
+ 	case Tsession:
5103
+ 		N2HSTRING(f->r_chal, sizeof(f->r_chal));
5104
+ 		break;
5105
+ 
5106
+ 	case Tflush:
5107
+ 		N2HSHORT(f->r_oldtag);
5108
+ 		break;
5109
+ 
5110
+ 	case Tattach:
5111
+ 		N2HSHORT(f->r_fid);
5112
+ 		N2HSTRING(f->r_uname, sizeof(f->r_uname));
5113
+ 		N2HSTRING(f->r_aname, sizeof(f->r_aname));
5114
+ 		N2HSTRING(f->r_ticket, sizeof(f->r_ticket));
5115
+ 		N2HSTRING(f->r_auth, sizeof(f->r_auth));
5116
+ 		break;
5117
+ 
5118
+ 	case Toattach:
5119
+ 		N2HSHORT(f->r_fid);
5120
+ 		N2HSTRING(f->r_uname, sizeof(f->r_uname));
5121
+ 		N2HSTRING(f->r_aname, sizeof(f->r_aname));
5122
+ 		N2HSTRING(f->r_ticket, U9FS_NAMELEN);
5123
+ 		break;
5124
+ 
5125
+ 	case Tauth:
5126
+ 		N2HSHORT(f->r_fid);
5127
+ 		N2HSTRING(f->r_uname, sizeof(f->r_uname));
5128
+ 		N2HSTRING(f->r_ticket, 8+U9FS_NAMELEN);
5129
+ 		break;
5130
+ 
5131
+ 	case Tclone:
5132
+ 		N2HSHORT(f->r_fid);
5133
+ 		N2HSHORT(f->r_newfid);
5134
+ 		break;
5135
+ 
5136
+ 	case Twalk:
5137
+ 		N2HSHORT(f->r_fid);
5138
+ 		N2HSTRING(f->r_name, sizeof(f->r_name));
5139
+ 		break;
5140
+ 
5141
+ 	case Topen:
5142
+ 		N2HSHORT(f->r_fid);
5143
+ 		N2HCHAR(f->r_mode);
5144
+ 		break;
5145
+ 
5146
+ 	case Tcreate:
5147
+ 		N2HSHORT(f->r_fid);
5148
+ 		N2HSTRING(f->r_name, sizeof(f->r_name));
5149
+ 		N2HLONG(f->r_perm);
5150
+ 		N2HCHAR(f->r_mode);
5151
+ 		break;
5152
+ 
5153
+ 	case Tread:
5154
+ 		N2HSHORT(f->r_fid);
5155
+ 		N2HQUAD(f->r_offset);
5156
+ 		N2HSHORT(f->r_count);
5157
+ 		break;
5158
+ 
5159
+ 	case Twrite:
5160
+ 		N2HSHORT(f->r_fid);
5161
+ 		N2HQUAD(f->r_offset);
5162
+ 		N2HSHORT(f->r_count);
5163
+ 		p++;	/* pad(1) */
5164
+ 		f->r_data = (char*)p; p += f->r_count;
5165
+ 		break;
5166
+ 
5167
+ 	case Ttunnel:
5168
+ 		N2HSHORT(f->r_fid);
5169
+ 		break;
5170
+ 
5171
+ 	case Tclunk:
5172
+ 		N2HSHORT(f->r_fid);
5173
+ 		break;
5174
+ 
5175
+ 	case Tremove:
5176
+ 		N2HSHORT(f->r_fid);
5177
+ 		break;
5178
+ 
5179
+ 	case Tstat:
5180
+ 		N2HSHORT(f->r_fid);
5181
+ 		break;
5182
+ 
5183
+ 	case Twstat:
5184
+ 		N2HSHORT(f->r_fid);
5185
+ 		N2HSTRING(f->r_stat, sizeof(f->r_stat));
5186
+ 		break;
5187
+ 
5188
+ 	case Tclwalk:
5189
+ 		N2HSHORT(f->r_fid);
5190
+ 		N2HSHORT(f->r_newfid);
5191
+ 		N2HSTRING(f->r_name, sizeof(f->r_name));
5192
+ 		break;
5193
+ /*
5194
+  */
5195
+ 	case Rnop:
5196
+ 	case Rosession:
5197
+ 		break;
5198
+ 
5199
+ 	case Rsession:
5200
+ 		N2HSTRING(f->r_chal, sizeof(f->r_chal));
5201
+ 		N2HSTRING(f->r_authid, sizeof(f->r_authid));
5202
+ 		N2HSTRING(f->r_authdom, sizeof(f->r_authdom));
5203
+ 		break;
5204
+ 
5205
+ 	case Rerror:
5206
+ 		N2HSTRING(f->r_ename, sizeof(f->r_ename));
5207
+ 		break;
5208
+ 
5209
+ 	case Rflush:
5210
+ 		break;
5211
+ 
5212
+ 	case Rattach:
5213
+ 		N2HSHORT(f->r_fid);
5214
+ 		N2HLONG(f->r_qid.path);
5215
+ 		N2HLONG(f->r_qid.vers);
5216
+ 		N2HSTRING(f->r_rauth, sizeof(f->r_rauth));
5217
+ 		break;
5218
+ 
5219
+ 	case Roattach:
5220
+ 		N2HSHORT(f->r_fid);
5221
+ 		N2HLONG(f->r_qid.path);
5222
+ 		N2HLONG(f->r_qid.vers);
5223
+ 		break;
5224
+ 
5225
+ 	case Rauth:
5226
+ 		N2HSHORT(f->r_fid);
5227
+ 		N2HSTRING(f->r_ticket, 8+8+7+7);
5228
+ 		break;
5229
+ 
5230
+ 	case Rclone:
5231
+ 		N2HSHORT(f->r_fid);
5232
+ 		break;
5233
+ 
5234
+ 	case Rwalk:
5235
+ 	case Rclwalk:
5236
+ 		N2HSHORT(f->r_fid);
5237
+ 		N2HLONG(f->r_qid.path);
5238
+ 		N2HLONG(f->r_qid.vers);
5239
+ 		break;
5240
+ 
5241
+ 	case Ropen:
5242
+ 		N2HSHORT(f->r_fid);
5243
+ 		N2HLONG(f->r_qid.path);
5244
+ 		N2HLONG(f->r_qid.vers);
5245
+ 		break;
5246
+ 
5247
+ 	case Rcreate:
5248
+ 		N2HSHORT(f->r_fid);
5249
+ 		N2HLONG(f->r_qid.path);
5250
+ 		N2HLONG(f->r_qid.vers);
5251
+ 		break;
5252
+ 
5253
+ 	case Rread:
5254
+ 		N2HSHORT(f->r_fid);
5255
+ 		N2HSHORT(f->r_count);
5256
+ 		p++;	/* pad(1) */
5257
+ 		f->r_data = (char*)p; p += f->r_count;
5258
+ 		break;
5259
+ 
5260
+ 	case Rwrite:
5261
+ 		N2HSHORT(f->r_fid);
5262
+ 		N2HSHORT(f->r_count);
5263
+ 		break;
5264
+ 
5265
+ 	case Rtunnel:
5266
+ 		N2HSHORT(f->r_fid);
5267
+ 		break;
5268
+ 
5269
+ 	case Rclunk:
5270
+ 		N2HSHORT(f->r_fid);
5271
+ 		break;
5272
+ 
5273
+ 	case Rremove:
5274
+ 		N2HSHORT(f->r_fid);
5275
+ 		break;
5276
+ 
5277
+ 	case Rstat:
5278
+ 		N2HSHORT(f->r_fid);
5279
+ 		N2HSTRING(f->r_stat, sizeof(f->r_stat));
5280
+ 		break;
5281
+ 
5282
+ 	case Rwstat:
5283
+ 		N2HSHORT(f->r_fid);
5284
+ 		break;
5285
+ 	}
5286
+ 	if((u_char*)ap+n == p)
5287
+ 		return n;
5288
+ 	return 0;
5289
+ }
5290
+ 
5291
+ void u9p_print(u_char * m, int len, struct u9fsreq * f)
5292
+ {
5293
+   struct u9fsreq u9fsreq;
5294
+ 
5295
+   if( f == 0 )
5296
+     f = & u9fsreq;
5297
+ 
5298
+   if( len < 3 ) {
5299
+     printf("truncated-9p %d", len);
5300
+     return;
5301
+   }
5302
+ 
5303
+   if( u9p_m2s((char *)m, len, f) == 0 )
5304
+     return;
5305
+ 
5306
+   printf("%s tag %d ", u9p_types[f->r_type-Tnop], f->r_tag);
5307
+ 
5308
+   switch( f->r_type ) {
5309
+ 	default:
5310
+ 	  return;
5311
+ 
5312
+ 	case Tnop:
5313
+ 	case Tosession:
5314
+ 	case Toattach:
5315
+ 	case Tauth:
5316
+ 		break;
5317
+ 
5318
+ 	case Tsession:
5319
+ 	case Rsession:
5320
+ 	  printf("chal 0x%x 0x%x", *(u_int *)&f->r_chal[0], *(u_int *)&f->r_chal[4]);
5321
+ 		break;
5322
+ 
5323
+ 	case Tflush:
5324
+ 	  printf("oldtag %d", f->r_oldtag);
5325
+ 		break;
5326
+ 
5327
+ 	case Tclone:
5328
+ 	  printf("fid %d newfid %d", f->r_fid, f->r_newfid);
5329
+ 		break;
5330
+ 
5331
+ 	case Twalk:
5332
+ 	  printf("fid %d name %s", f->r_fid, f->r_name);
5333
+ 		break;
5334
+ 
5335
+ 	case Topen:
5336
+ 	  printf("fid %d %c", f->r_fid, f->r_mode);
5337
+ 		break;
5338
+ 
5339
+ 	case Tcreate:
5340
+ 	  printf("fid %d name %s perm 0x%x mode %c", f->r_fid,
5341
+ 		 f->r_name, f->r_perm, f->r_mode);
5342
+ 		break;
5343
+ 
5344
+ 	case Tread:
5345
+ 	case Twrite:
5346
+ 	  printf("fid %d offset 0x%llx count %d", f->r_fid,
5347
+ 		 f->r_offset, f->r_count);
5348
+ 		break;
5349
+ 
5350
+ 	case Tattach:
5351
+ 	case Ttunnel:
5352
+ 	case Tclunk:
5353
+ 	case Tremove:
5354
+ 	case Tstat:
5355
+ 	case Twstat:
5356
+ 	case Rclone:
5357
+ 	case Rtunnel:
5358
+ 	case Rclunk:
5359
+ 	case Rremove:
5360
+ 	case Rstat:
5361
+ 	case Rwstat:
5362
+ 	  printf("fid %d", f->r_fid);
5363
+ 		break;
5364
+ 
5365
+ 	case Tclwalk:
5366
+ 	  printf("fid %d ", f->r_fid);
5367
+ 	  printf("newfid  %d ", f->r_newfid);
5368
+ 	  printf("name %s", f->r_name);
5369
+ 		break;
5370
+ /*
5371
+  */
5372
+ 	case Rnop:
5373
+ 	case Rosession:
5374
+ 	case Rflush:
5375
+ 	case Roattach:
5376
+ 	case Rauth:
5377
+ 		break;
5378
+ 
5379
+ 	case Rerror:
5380
+ 	  printf("ename %s", f->r_ename);
5381
+ 		break;
5382
+ 
5383
+ 	case Rattach:
5384
+ 	case Rwalk:
5385
+ 	case Rclwalk:
5386
+ 	case Ropen:
5387
+ 	case Rcreate:
5388
+ 	  printf("fid %d ", f->r_fid);
5389
+ 	  printf("qid 0x%x 0x%x", f->r_qid.path, f->r_qid.vers);
5390
+ 		break;
5391
+ 
5392
+ 	case Rread:
5393
+ 	  printf("fid %d count %d ", f->r_fid, f->r_count);
5394
+ 	  break;
5395
+ 
5396
+ 	case Rwrite:
5397
+ 	  printf("fid %d count %d", f->r_fid, f->r_count);
5398
+ 		break;
5399
+   }
5400
+ }
5401
+ 
5402
+ int
5403
+ u9p_s2m(struct u9fsreq *f, char *ap, int copydata)
5404
+ {
5405
+ 	u_char *p;
5406
+ 
5407
+ 	p = (u_char*)ap;
5408
+ 	H2NCHAR(f->r_type);
5409
+ 	H2NSHORT(f->r_tag);
5410
+ 	switch(f->r_type)
5411
+ 	{
5412
+ 	default:
5413
+ 		return 0;
5414
+ 
5415
+ 	case Tosession:
5416
+ 	case Tnop:
5417
+ 		break;
5418
+ 
5419
+ 	case Tsession:
5420
+ 		H2NSTRING(f->r_chal, sizeof(f->r_chal));
5421
+ 		break;
5422
+ 
5423
+ 	case Tflush:
5424
+ 		H2NSHORT(f->r_oldtag);
5425
+ 		break;
5426
+ 
5427
+ 	case Tattach:
5428
+ 		H2NSHORT(f->r_fid);
5429
+ 		H2NSTRING(f->r_uname, sizeof(f->r_uname));
5430
+ 		H2NSTRING(f->r_aname, sizeof(f->r_aname));
5431
+ 		H2NSTRING(f->r_ticket, sizeof(f->r_ticket));
5432
+ 		H2NSTRING(f->r_auth, sizeof(f->r_auth));
5433
+ 		break;
5434
+ 
5435
+ 	case Toattach:
5436
+ 		H2NSHORT(f->r_fid);
5437
+ 		H2NSTRING(f->r_uname, sizeof(f->r_uname));
5438
+ 		H2NSTRING(f->r_aname, sizeof(f->r_aname));
5439
+ 		H2NSTRING(f->r_ticket, U9FS_NAMELEN);
5440
+ 		break;
5441
+ 
5442
+ 	case Tauth:
5443
+ 		H2NSHORT(f->r_fid);
5444
+ 		H2NSTRING(f->r_uname, sizeof(f->r_uname));
5445
+ 		H2NSTRING(f->r_ticket, 8+U9FS_NAMELEN);
5446
+ 		break;
5447
+ 
5448
+ 	case Tclone:
5449
+ 		H2NSHORT(f->r_fid);
5450
+ 		H2NSHORT(f->r_newfid);
5451
+ 		break;
5452
+ 
5453
+ 	case Twalk:
5454
+ 		H2NSHORT(f->r_fid);
5455
+ 		H2NSTRING(f->r_name, sizeof(f->r_name));
5456
+ 		break;
5457
+ 
5458
+ 	case Topen:
5459
+ 		H2NSHORT(f->r_fid);
5460
+ 		H2NCHAR(f->r_mode);
5461
+ 		break;
5462
+ 
5463
+ 	case Tcreate:
5464
+ 		H2NSHORT(f->r_fid);
5465
+ 		H2NSTRING(f->r_name, sizeof(f->r_name));
5466
+ 		H2NLONG(f->r_perm);
5467
+ 		H2NCHAR(f->r_mode);
5468
+ 		break;
5469
+ 
5470
+ 	case Tread:
5471
+ 		H2NSHORT(f->r_fid);
5472
+ 		H2NQUAD(f->r_offset);
5473
+ 		H2NSHORT(f->r_count);
5474
+ 		break;
5475
+ 
5476
+ 	case Twrite:
5477
+ 		H2NSHORT(f->r_fid);
5478
+ 		H2NQUAD(f->r_offset);
5479
+ 		H2NSHORT(f->r_count);
5480
+ 		p++;	/* pad(1) */
5481
+ 		if( copydata ) {
5482
+ 		  H2NSTRING(f->r_data, f->r_count);
5483
+ 		}
5484
+ 		break;
5485
+ 
5486
+ 	case Ttunnel:
5487
+ 		H2NSHORT(f->r_fid);
5488
+ 		break;
5489
+ 
5490
+ 	case Tclunk:
5491
+ 		H2NSHORT(f->r_fid);
5492
+ 		break;
5493
+ 
5494
+ 	case Tremove:
5495
+ 		H2NSHORT(f->r_fid);
5496
+ 		break;
5497
+ 
5498
+ 	case Tstat:
5499
+ 		H2NSHORT(f->r_fid);
5500
+ 		break;
5501
+ 
5502
+ 	case Twstat:
5503
+ 		H2NSHORT(f->r_fid);
5504
+ 		H2NSTRING(f->r_stat, sizeof(f->r_stat));
5505
+ 		break;
5506
+ 
5507
+ 	case Tclwalk:
5508
+ 		H2NSHORT(f->r_fid);
5509
+ 		H2NSHORT(f->r_newfid);
5510
+ 		H2NSTRING(f->r_name, sizeof(f->r_name));
5511
+ 		break;
5512
+ /*
5513
+  */
5514
+ 	case Rosession:
5515
+ 	case Rnop:
5516
+ 		break;
5517
+ 
5518
+ 	case Rsession:
5519
+ 		H2NSTRING(f->r_chal, sizeof(f->r_chal));
5520
+ 		H2NSTRING(f->r_authid, sizeof(f->r_authid));
5521
+ 		H2NSTRING(f->r_authdom, sizeof(f->r_authdom));
5522
+ 		break;
5523
+ 
5524
+ 	case Rerror:
5525
+ 		H2NSTRING(f->r_ename, sizeof(f->r_ename));
5526
+ 		break;
5527
+ 
5528
+ 	case Rflush:
5529
+ 		break;
5530
+ 
5531
+ 	case Rattach:
5532
+ 		H2NSHORT(f->r_fid);
5533
+ 		H2NLONG(f->r_qid.path);
5534
+ 		H2NLONG(f->r_qid.vers);
5535
+ 		H2NSTRING(f->r_rauth, sizeof(f->r_rauth));
5536
+ 		break;
5537
+ 
5538
+ 	case Roattach:
5539
+ 		H2NSHORT(f->r_fid);
5540
+ 		H2NLONG(f->r_qid.path);
5541
+ 		H2NLONG(f->r_qid.vers);
5542
+ 		break;
5543
+ 
5544
+ 	case Rauth:
5545
+ 		H2NSHORT(f->r_fid);
5546
+ 		H2NSTRING(f->r_ticket, 8+8+7+7);
5547
+ 		break;
5548
+ 
5549
+ 	case Rclone:
5550
+ 		H2NSHORT(f->r_fid);
5551
+ 		break;
5552
+ 
5553
+ 	case Rwalk:
5554
+ 	case Rclwalk:
5555
+ 		H2NSHORT(f->r_fid);
5556
+ 		H2NLONG(f->r_qid.path);
5557
+ 		H2NLONG(f->r_qid.vers);
5558
+ 		break;
5559
+ 
5560
+ 	case Ropen:
5561
+ 		H2NSHORT(f->r_fid);
5562
+ 		H2NLONG(f->r_qid.path);
5563
+ 		H2NLONG(f->r_qid.vers);
5564
+ 		break;
5565
+ 
5566
+ 	case Rcreate:
5567
+ 		H2NSHORT(f->r_fid);
5568
+ 		H2NLONG(f->r_qid.path);
5569
+ 		H2NLONG(f->r_qid.vers);
5570
+ 		break;
5571
+ 
5572
+ 	case Rread:
5573
+ 		H2NSHORT(f->r_fid);
5574
+ 		H2NSHORT(f->r_count);
5575
+ 		p++;	/* pad(1) */
5576
+ 		if( copydata ) {
5577
+ 		  H2NSTRING(f->r_data, f->r_count);
5578
+ 		}
5579
+ 		break;
5580
+ 
5581
+ 	case Rwrite:
5582
+ 		H2NSHORT(f->r_fid);
5583
+ 		H2NSHORT(f->r_count);
5584
+ 		break;
5585
+ 
5586
+ 	case Rtunnel:
5587
+ 		H2NSHORT(f->r_fid);
5588
+ 		break;
5589
+ 
5590
+ 	case Rclunk:
5591
+ 		H2NSHORT(f->r_fid);
5592
+ 		break;
5593
+ 
5594
+ 	case Rremove:
5595
+ 		H2NSHORT(f->r_fid);
5596
+ 		break;
5597
+ 
5598
+ 	case Rstat:
5599
+ 		H2NSHORT(f->r_fid);
5600
+ 		if( copydata )
5601
+ 		  H2NSTRING(f->r_stat, sizeof(f->r_stat));
5602
+ 		break;
5603
+ 
5604
+ 	case Rwstat:
5605
+ 		H2NSHORT(f->r_fid);
5606
+ 		break;
5607
+ 	}
5608
+ 	return p - (u_char*)ap;
5609
+ }
5610
+ 
5611
+ int
5612
+ u9p_m2d(char *ap, struct u9fsdir *f)
5613
+ {
5614
+ 	u_char *p;
5615
+ 
5616
+ 	p = (u_char*)ap;
5617
+ 	N2HSTRING(f->dir_name, sizeof(f->dir_name));
5618
+ 	N2HSTRING(f->dir_uid, sizeof(f->dir_uid));
5619
+ 	N2HSTRING(f->dir_gid, sizeof(f->dir_gid));
5620
+ 	N2HLONG(f->dir_qid.path);
5621
+ 	N2HLONG(f->dir_qid.vers);
5622
+ 	N2HLONG(f->dir_mode);
5623
+ 	N2HLONG(f->dir_atime);
5624
+ 	N2HLONG(f->dir_mtime);
5625
+ 	N2HQUAD(f->dir_length);
5626
+ 	N2HSHORT(f->dir_type);
5627
+ 	N2HSHORT(f->dir_dev);
5628
+ 	return p - (u_char*)ap;
5629
+ }
5630
+ 
5631
+ int
5632
+ u9p_d2m(struct u9fsdir *f, char *ap)
5633
+ {
5634
+ 	u_char *p;
5635
+ 
5636
+ 	p = (u_char*)ap;
5637
+ 	H2NSTRING(f->dir_name, sizeof(f->dir_name));
5638
+ 	H2NSTRING(f->dir_uid, sizeof(f->dir_uid));
5639
+ 	H2NSTRING(f->dir_gid, sizeof(f->dir_gid));
5640
+ 	H2NLONG(f->dir_qid.path);
5641
+ 	H2NLONG(f->dir_qid.vers);
5642
+ 	H2NLONG(f->dir_mode);
5643
+ 	H2NLONG(f->dir_atime);
5644
+ 	H2NLONG(f->dir_mtime);
5645
+ 	H2NQUAD(f->dir_length);
5646
+ 	H2NSHORT(f->dir_type);
5647
+ 	H2NSHORT(f->dir_dev);
5648
+ 	return p - (u_char*)ap;
5649
+ }
5650
+ 
5651
+ /* parse 9P types */
5652
+ int u9p_type(char * t)
5653
+ {
5654
+   int i;
5655
+ 
5656
+   for(i = 0; i < sizeof(u9p_types)/sizeof(u9p_types[0]); i++) {
5657
+     if( strcmp(u9p_types[i], t) == 0 )
5658
+       return (i+Tnop);
5659
+   }
5660
+   return 0;
5661
+ }
5662
+ 
5663
+ /* m is freed if shorter than s */
5664
+ #if 1
5665
+ #define U9P_PULLUP(m,s)  if( (*(m))->m_len < (s) && ((*(m)) = m_pullup((*(m)),(s))) == 0 ) return 1; p = mtod((*(m)), u_char *)
5666
+ #else
5667
+ #define U9P_PULLUP(m,s)  if( (*(m))->m_len < (s) && ((*(m)) = m_pullup((*(m)),(s))) == 0 ) panic("PULLUP"); p = mtod((*(m)), u_char *)
5668
+ #endif
5669
+ 
5670
+ #define U9P_ADJ(m,s) (*(m))->m_len -= (s); (*(m))->m_data += (s)
5671
+ 
5672
+ u_short u9p_m_tag(struct mbuf ** m)
5673
+ {
5674
+   char * p;
5675
+   u_short t;
5676
+ 
5677
+   U9P_PULLUP(m,3);
5678
+   p = mtod(*m, char *);
5679
+   p++;
5680
+   N2HSHORT(t);
5681
+ 
5682
+   return t;
5683
+ }
5684
+ 
5685
+ int 
5686
+ u9p_m_m2s(struct mbuf **m, struct u9fsreq *f)
5687
+ {
5688
+   u_char *p;
5689
+ 
5690
+   U9P_PULLUP(m,3);
5691
+   N2HCHAR(f->r_type);
5692
+   N2HSHORT(f->r_tag);
5693
+   U9P_ADJ(m, sizeof(f->r_type)+sizeof(f->r_tag));
5694
+ 
5695
+   switch(f->r_type) {
5696
+   default:
5697
+     goto drop;
5698
+ 
5699
+   case Tnop:
5700
+     break;
5701
+ 
5702
+   case Tsession:
5703
+     U9P_PULLUP(m,sizeof(f->r_chal));
5704
+     N2HSTRING(f->r_chal, sizeof(f->r_chal));
5705
+     U9P_ADJ(m, sizeof(f->r_chal));
5706
+     break;
5707
+ 
5708
+   case Tflush:
5709
+     U9P_PULLUP(m,sizeof(f->r_oldtag));
5710
+     N2HSHORT(f->r_oldtag);
5711
+     U9P_ADJ(m, f->r_oldtag);
5712
+     break;
5713
+ 
5714
+   case Tattach:
5715
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_uname)+sizeof(f->r_aname));
5716
+     N2HSHORT(f->r_fid);
5717
+     N2HSTRING(f->r_uname, sizeof(f->r_uname));
5718
+     N2HSTRING(f->r_aname, sizeof(f->r_aname));
5719
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_uname)+sizeof(f->r_aname));
5720
+     
5721
+     U9P_PULLUP(m, sizeof(f->r_ticket)+sizeof(f->r_auth));
5722
+     N2HSTRING(f->r_ticket, sizeof(f->r_ticket));
5723
+     N2HSTRING(f->r_auth, sizeof(f->r_auth));
5724
+     U9P_ADJ(m, sizeof(f->r_ticket)+sizeof(f->r_auth));
5725
+     break;
5726
+ 
5727
+   case Tclone:
5728
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_newfid));
5729
+     N2HSHORT(f->r_fid);
5730
+     N2HSHORT(f->r_newfid);
5731
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_newfid));
5732
+     break;
5733
+ 
5734
+   case Twalk:
5735
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_name));
5736
+     N2HSHORT(f->r_fid);
5737
+     N2HSTRING(f->r_name, sizeof(f->r_name));
5738
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_name));
5739
+     break;
5740
+ 
5741
+   case Topen:
5742
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_mode));
5743
+     N2HSHORT(f->r_fid);
5744
+     N2HCHAR(f->r_mode);
5745
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_mode));
5746
+     break;
5747
+ 
5748
+   case Tcreate:
5749
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_name)
5750
+ 	       +sizeof(f->r_perm)+sizeof(f->r_mode));
5751
+     N2HSHORT(f->r_fid);
5752
+     N2HSTRING(f->r_name, sizeof(f->r_name));
5753
+     N2HLONG(f->r_perm);
5754
+     N2HCHAR(f->r_mode);
5755
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_name)
5756
+ 	    +sizeof(f->r_perm)+sizeof(f->r_mode));
5757
+     break;
5758
+ 
5759
+   case Tread:
5760
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count));
5761
+     N2HSHORT(f->r_fid);
5762
+     N2HQUAD(f->r_offset);
5763
+     N2HSHORT(f->r_count);
5764
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count));
5765
+     break;
5766
+ 
5767
+   case Twrite:
5768
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count));
5769
+     N2HSHORT(f->r_fid);
5770
+     N2HQUAD(f->r_offset);
5771
+     N2HSHORT(f->r_count);
5772
+     p++;	/* pad(1) */
5773
+     f->r_data = (char*)p; p += f->r_count;
5774
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count)+1);
5775
+     break;
5776
+ 
5777
+   case Tclunk:
5778
+   case Tremove:
5779
+   case Tstat: 
5780
+    U9P_PULLUP(m, sizeof(f->r_fid));
5781
+     N2HSHORT(f->r_fid);
5782
+     U9P_ADJ(m, sizeof(f->r_fid));
5783
+     break;
5784
+ 
5785
+   case Twstat:
5786
+     U9P_PULLUP(m, sizeof(f->r_fid));
5787
+     N2HSHORT(f->r_fid);
5788
+     m_copydata(*m, sizeof(f->r_fid), sizeof(f->r_stat), f->r_stat);
5789
+     m_adj(*m, sizeof(f->r_fid)+sizeof(f->r_stat));
5790
+     break;
5791
+ 
5792
+   case Tclwalk:
5793
+      U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_newfid)+sizeof(f->r_name));
5794
+      N2HSHORT(f->r_fid);
5795
+      N2HSHORT(f->r_newfid);
5796
+      N2HSTRING(f->r_name, sizeof(f->r_name));
5797
+      U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_newfid)+sizeof(f->r_name));
5798
+      break;
5799
+ /*
5800
+  */
5801
+   case Rnop:
5802
+     break;
5803
+ 
5804
+   case Rsession:
5805
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_authid)+sizeof(f->r_authdom));
5806
+     N2HSTRING(f->r_chal, sizeof(f->r_chal));
5807
+     N2HSTRING(f->r_authid, sizeof(f->r_authid));
5808
+     N2HSTRING(f->r_authdom, sizeof(f->r_authdom));
5809
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_authid)+sizeof(f->r_authdom));
5810
+     break;
5811
+ 
5812
+   case Rerror:
5813
+     U9P_PULLUP(m, sizeof(f->r_ename));
5814
+     N2HSTRING(f->r_ename, sizeof(f->r_ename));
5815
+     U9P_ADJ(m, sizeof(f->r_ename));
5816
+     break;
5817
+ 
5818
+   case Rflush:
5819
+     break;
5820
+ 
5821
+   case Rattach:
5822
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5823
+ 	       +sizeof(f->r_qid.vers)+sizeof(f->r_rauth));
5824
+     N2HSHORT(f->r_fid);
5825
+     N2HLONG(f->r_qid.path);
5826
+     N2HLONG(f->r_qid.vers);
5827
+     N2HSTRING(f->r_rauth, sizeof(f->r_rauth));
5828
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5829
+ 	    +sizeof(f->r_qid.vers)+sizeof(f->r_rauth));
5830
+     break;
5831
+ 
5832
+   case Rclone:
5833
+     U9P_PULLUP(m, sizeof(f->r_fid));
5834
+     N2HSHORT(f->r_fid);
5835
+     U9P_ADJ(m, sizeof(f->r_fid));
5836
+     break;
5837
+ 
5838
+   case Rwalk:
5839
+   case Rclwalk:
5840
+   case Ropen:
5841
+   case Rcreate:
5842
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5843
+                +sizeof(f->r_qid.vers));
5844
+     N2HSHORT(f->r_fid);
5845
+     N2HLONG(f->r_qid.path);
5846
+     N2HLONG(f->r_qid.vers);
5847
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_qid.path)
5848
+             +sizeof(f->r_qid.vers));
5849
+     break;
5850
+ 
5851
+   case Rread:
5852
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_count));
5853
+     N2HSHORT(f->r_fid);
5854
+     N2HSHORT(f->r_count);
5855
+     p++;	/* pad(1) */
5856
+     f->r_data = (char*)p; p += f->r_count;
5857
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_count)+1);
5858
+     break;
5859
+ 
5860
+   case Rwrite:
5861
+     U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_count));
5862
+     N2HSHORT(f->r_fid);
5863
+     N2HSHORT(f->r_count);
5864
+     U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_count));
5865
+     break;
5866
+ 
5867
+   case Rclunk:
5868
+   case Rremove:
5869
+   case Rwstat:
5870
+     U9P_PULLUP(m, sizeof(f->r_fid));
5871
+     N2HSHORT(f->r_fid);
5872
+     U9P_ADJ(m, sizeof(f->r_fid));
5873
+     break;
5874
+ 
5875
+   case Rstat:
5876
+     U9P_PULLUP(m, sizeof(f->r_fid));
5877
+     N2HSHORT(f->r_fid);
5878
+     m_copydata(*m, sizeof(f->r_fid), sizeof(f->r_stat), f->r_stat);
5879
+     m_adj(*m, sizeof(f->r_fid)+sizeof(f->r_stat));
5880
+     break;
5881
+     
5882
+   }
5883
+   return 0;
5884
+ 
5885
+  drop:
5886
+   m_freem(*m);
5887
+   return 1;
5888
+ }
5889
+ 
5890
+ struct mbuf * 
5891
+ u9p_m_s2m (struct u9fsreq *f)
5892
+ {
5893
+   register struct mbuf * m;
5894
+   struct mbuf * m0;
5895
+   char * ap;
5896
+   int sz;
5897
+   
5898
+   /* we want one contiguous piece */
5899
+   if( f->r_type == Tattach || f->r_type == Rstat || f->r_type == Twstat )
5900
+     sz = 146; /* sizeof a Tattach */
5901
+   else
5902
+     sz = 87; /* sizeof a Tsession */
5903
+   
5904
+   MGETHDR(m, M_WAIT, MT_DATA);  
5905
+   if( sz > MHLEN )
5906
+     MCLGET(m, M_WAIT);
5907
+   m->m_len = 0;
5908
+   
5909
+   if ( M_TRAILINGSPACE(m) < sz )
5910
+     panic("u9p_m_s2m");
5911
+   
5912
+   ap = mtod(m, char *);
5913
+   m->m_len = u9p_s2m(f, ap, 0);
5914
+   m->m_pkthdr.len = m->m_len;
5915
+   
5916
+   /* append data mbufs  */
5917
+   switch ( f->r_type ) {
5918
+   default:
5919
+     break;
5920
+   case Twrite:
5921
+   case Rread:
5922
+     m0 = (struct mbuf *)f->r_data;
5923
+     m->m_next = m0;
5924
+     m->m_pkthdr.len += f->r_count;
5925
+     break;
5926
+   }
5927
+ 
5928
+   return m;
5929
+ }
5930
+ 
5931
+ int 
5932
+ u9p_m_m2d (struct mbuf **m, struct u9fsdir *f)
5933
+ {
5934
+   u_char *p;
5935
+   
5936
+   U9P_PULLUP(m, sizeof(f->dir_name)+sizeof(f->dir_uid)+sizeof(f->dir_gid));
5937
+   N2HSTRING(f->dir_name, sizeof(f->dir_name));
5938
+   N2HSTRING(f->dir_uid, sizeof(f->dir_uid));
5939
+   N2HSTRING(f->dir_gid, sizeof(f->dir_gid));
5940
+   U9P_ADJ(m, sizeof(f->dir_name)+sizeof(f->dir_uid)+sizeof(f->dir_gid));
5941
+ 
5942
+   U9P_PULLUP(m, sizeof(f->dir_qid)+sizeof(f->dir_mode)
5943
+ 	     +sizeof(f->dir_atime)+sizeof(f->dir_mtime)
5944
+ 	     +sizeof(f->dir_length)+sizeof(f->dir_type)+sizeof(f->dir_dev));
5945
+   N2HLONG(f->dir_qid.path);
5946
+   N2HLONG(f->dir_qid.vers);
5947
+   N2HLONG(f->dir_mode);
5948
+   N2HLONG(f->dir_atime);
5949
+   N2HLONG(f->dir_mtime);
5950
+   N2HQUAD(f->dir_length);
5951
+   N2HSHORT(f->dir_type);
5952
+   N2HSHORT(f->dir_dev);
5953
+   U9P_ADJ(m, sizeof(f->dir_qid)+sizeof(f->dir_mode)
5954
+ 	     +sizeof(f->dir_atime)+sizeof(f->dir_mtime)
5955
+ 	     +sizeof(f->dir_length)+sizeof(f->dir_type)+sizeof(f->dir_dev));
5956
+ 
5957
+   return 0;
5958
+ }
5959
+ 
5960
+ struct mbuf * u9p_m_d2m (struct u9fsdir *f)
5961
+ {
5962
+   char * ap;
5963
+   struct mbuf * m;
5964
+   MGET(m, M_WAIT, MT_DATA);
5965
+   MCLGET(m, M_WAIT);
5966
+   m->m_len = 0;
5967
+ 
5968
+   if ( M_TRAILINGSPACE(m) < sizeof(struct u9fsdir) )
5969
+     panic("u9p_m_d2m");
5970
+ 
5971
+   ap = mtod(m, char *);
5972
+   m->m_len = u9p_d2m(f, ap);  
5973
+ 
5974
+   return m;
5975
+ }
5976
diff -N -c -r /usr/src/sys/9fs/9p.h ./9fs/9p.h
5977
*** /usr/src/sys/9fs/9p.h	Wed Dec 31 19:00:00 1969
5978
--- ./9fs/9p.h	Thu Nov 25 15:45:46 1999
5979
***************
5980
*** 0 ****
5981
--- 1,183 ----
5982
+ #ifndef _9FS_9P_H_
5983
+ #define _9FS_9P_H_
5984
+ 
5985
+ 
5986
+ #define U9FS_AUTHLEN 13
5987
+ #define U9FS_NAMELEN    28
5988
+ #define U9FS_TICKETLEN  72
5989
+ #define U9FS_ERRLEN     64
5990
+ #define U9FS_DOMLEN     48
5991
+ #define U9FS_CHALLEN    8
5992
+ #define U9FS_DIRLEN     116
5993
+ #define U9FS_MAXFDATA  8192
5994
+ #define U9FS_MAXDDATA  (((int)U9FS_MAXFDATA/U9FS_DIRLEN)*U9FS_DIRLEN)
5995
+ 
5996
+ #define U9P_MODE_RD    0x0
5997
+ #define U9P_MODE_WR    0x1
5998
+ #define U9P_MODE_RDWR  0x2
5999
+ #define U9P_MODE_EX    0x3
6000
+ #define U9P_MODE_TRUNC 0x10
6001
+ #define U9P_MODE_CLOSE 0x40
6002
+ 
6003
+ #define U9P_PERM_CHDIR(m) (0x80000000&(m))
6004
+ #define U9P_PERM_OWNER(m) ((m)&0x7)
6005
+ #define U9P_PERM_GROUP(m) (((m)>>3)&0x7)
6006
+ #define U9P_PERM_OTHER(m) (((m)>>6)&0x7)
6007
+ #define U9P_PERM_ALL(m)   ((m)&0777)
6008
+ #define U9P_PERM_EXCL(m)    ((m)&0x20000000)
6009
+ #define U9P_PERM_APPEND(m)  ((m)&0x40000000)
6010
+ #define U9P_PERM_NONPERM(m) ((m)&0xfffffe00)
6011
+ 
6012
+ /* this is too small */
6013
+ typedef u_int32_t u9fsfh_t;
6014
+ 
6015
+ struct u9fs_qid {
6016
+ 	u9fsfh_t	path;
6017
+ 	u_int32_t	vers;
6018
+ };
6019
+ 
6020
+ struct	u9fsreq {
6021
+   TAILQ_ENTRY(u9fsreq) r_chain;
6022
+   struct u9fsreq * r_rep;
6023
+   struct mbuf * r_mrep;
6024
+   struct proc	*r_procp;	/* Proc that did I/O system call */
6025
+   struct u9fsmount *r_nmp;
6026
+ 
6027
+   /* actual content of the 9P message */
6028
+ 	char	r_type;
6029
+ 	short	r_fid;
6030
+ 	u_short	r_tag;
6031
+ 	union {
6032
+ 		struct {
6033
+ 			u_short	oldtag;		/* Tflush */
6034
+ 			struct u9fs_qid qid;		/* Rattach, Rwalk, Ropen, Rcreate */
6035
+ 			char	rauth[U9FS_AUTHLEN];	/* Rattach */
6036
+ 		} u1;
6037
+ 		struct {
6038
+ 			char	uname[U9FS_NAMELEN];		/* Tattach */
6039
+ 			char	aname[U9FS_NAMELEN];		/* Tattach */
6040
+ 			char	ticket[U9FS_TICKETLEN];	/* Tattach */
6041
+ 			char	auth[U9FS_AUTHLEN];	/* Tattach */
6042
+ 		} u2;
6043
+ 		struct {
6044
+ 			char	ename[U9FS_ERRLEN];		/* Rerror */
6045
+ 			char	authid[U9FS_NAMELEN];	/* Rsession */
6046
+ 			char	authdom[U9FS_DOMLEN];	/* Rsession */
6047
+ 			char	chal[U9FS_CHALLEN];		/* Tsession/Rsession */
6048
+ 		} u3;
6049
+ 		struct {
6050
+ 			u_int32_t	perm;		/* Tcreate */ 
6051
+ 			short	newfid;		/* Tclone, Tclwalk */
6052
+ 			char	name[U9FS_NAMELEN];	/* Twalk, Tclwalk, Tcreate */
6053
+ 			char	mode;		/* Tcreate, Topen */
6054
+ 		} u4;
6055
+ 		struct {
6056
+ 			u_int64_t	offset;		/* Tread, Twrite */
6057
+ 			u_short	        count;		/* Tread, Twrite, Rread */
6058
+ 			char	*data;		/* Twrite, Rread */
6059
+ 		} u5;
6060
+ 			char	stat[U9FS_DIRLEN];	/* Twstat, Rstat */
6061
+ 	} u;
6062
+ };
6063
+ 
6064
+ #define r_oldtag u.u1.oldtag
6065
+ #define r_qid u.u1.qid
6066
+ #define r_rauth u.u1.rauth
6067
+ #define r_uname u.u2.uname
6068
+ #define r_aname u.u2.aname
6069
+ #define r_ticket  u.u2.ticket
6070
+ #define r_auth  u.u2.auth
6071
+ #define r_ename  u.u3.ename
6072
+ #define r_authid  u.u3.authid
6073
+ #define r_authdom  u.u3.authdom
6074
+ #define r_chal  u.u3.chal
6075
+ #define r_perm  u.u4.perm
6076
+ #define r_newfid  u.u4.newfid
6077
+ #define r_name  u.u4.name
6078
+ #define r_mode  u.u4.mode
6079
+ #define r_offset  u.u5.offset
6080
+ #define r_count  u.u5.count
6081
+ #define r_data  u.u5.data
6082
+ #define r_stat  u.stat
6083
+ 
6084
+ struct u9fsdir {
6085
+   char	dir_name[U9FS_NAMELEN];
6086
+   char	dir_uid[U9FS_NAMELEN];
6087
+   char	dir_gid[U9FS_NAMELEN];
6088
+   struct u9fs_qid	dir_qid;
6089
+   u_int32_t	dir_mode;
6090
+   u_int32_t	dir_atime;
6091
+   u_int32_t	dir_mtime;
6092
+   union {
6093
+     u_int64_t	length;
6094
+     struct {	/* little endian */
6095
+       u_int32_t	llength;
6096
+       u_int32_t	hlength;
6097
+     } l;
6098
+   } u;
6099
+   u_short	dir_type;
6100
+   u_short	dir_dev;
6101
+ };
6102
+ 
6103
+ #define dir_length u.length
6104
+ #define dir_llength u.l.llength
6105
+ #define dir_hlength u.l.hlength
6106
+ 
6107
+ enum
6108
+ {
6109
+ 	Tnop =		50,
6110
+ 	Rnop,
6111
+ 	Tosession =	52,	/* illegal */
6112
+ 	Rosession,		/* illegal */
6113
+ 	Terror =	54,	/* illegal */
6114
+ 	Rerror,
6115
+ 	Tflush =	56,
6116
+ 	Rflush,
6117
+ 	Toattach =	58,	/* illegal */
6118
+ 	Roattach,		/* illegal */
6119
+ 	Tclone =	60,
6120
+ 	Rclone,
6121
+ 	Twalk =		62,
6122
+ 	Rwalk,
6123
+ 	Topen =		64,
6124
+ 	Ropen,
6125
+ 	Tcreate =	66,
6126
+ 	Rcreate,
6127
+ 	Tread =		68,
6128
+ 	Rread,
6129
+ 	Twrite =	70,
6130
+ 	Rwrite,
6131
+ 	Tclunk =	72,
6132
+ 	Rclunk,
6133
+ 	Tremove =	74,
6134
+ 	Rremove,
6135
+ 	Tstat =		76,
6136
+ 	Rstat,
6137
+ 	Twstat =	78,
6138
+ 	Rwstat,
6139
+ 	Tclwalk =	80,
6140
+ 	Rclwalk,
6141
+ 	Tauth =		82,	/* illegal */
6142
+ 	Rauth,			/* illegal */
6143
+ 	Tsession =	84,
6144
+ 	Rsession,
6145
+ 	Tattach =	86,
6146
+ 	Rattach,
6147
+ 	Ttunnel =	88,
6148
+ 	Rtunnel,
6149
+ 	Tmax
6150
+ };
6151
+ 
6152
+ int u9p_m2s __P((char *ap, int n, struct u9fsreq *f));
6153
+ int u9p_s2m __P((struct u9fsreq *f, char *ap, int copydata));
6154
+ int u9p_m2d __P((char *ap, struct u9fsdir *f));
6155
+ int u9p_d2m __P((struct u9fsdir *f, char *ap));
6156
+ int u9p_type __P((char * t));
6157
+ 
6158
+ int u9p_m_m2s __P((struct mbuf **m, struct u9fsreq *f));
6159
+ struct mbuf * u9p_m_s2m __P((struct u9fsreq *f));
6160
+ int u9p_m_m2d __P((struct mbuf **m, struct u9fsdir *f));
6161
+ struct mbuf * u9p_m_d2m __P((struct u9fsdir *f));
6162
+ u_short u9p_m_tag __P((struct mbuf **m));
6163
+ 
6164
+ #endif
6165
diff -N -c -r /usr/src/sys/9fs/bitstring.h ./9fs/bitstring.h
6166
*** /usr/src/sys/9fs/bitstring.h	Wed Dec 31 19:00:00 1969
6167
--- ./9fs/bitstring.h	Thu Oct 21 12:34:50 1999
6168
***************
6169
*** 0 ****
6170
--- 1,143 ----
6171
+ /*
6172
+  * Copyright (c) 1989, 1993
6173
+  *	The Regents of the University of California.  All rights reserved.
6174
+  *
6175
+  * This code is derived from software contributed to Berkeley by
6176
+  * Paul Vixie.
6177
+  *
6178
+  * Redistribution and use in source and binary forms, with or without
6179
+  * modification, are permitted provided that the following conditions
6180
+  * are met:
6181
+  * 1. Redistributions of source code must retain the above copyright
6182
+  *    notice, this list of conditions and the following disclaimer.
6183
+  * 2. Redistributions in binary form must reproduce the above copyright
6184
+  *    notice, this list of conditions and the following disclaimer in the
6185
+  *    documentation and/or other materials provided with the distribution.
6186
+  * 3. All advertising materials mentioning features or use of this software
6187
+  *    must display the following acknowledgement:
6188
+  *	This product includes software developed by the University of
6189
+  *	California, Berkeley and its contributors.
6190
+  * 4. Neither the name of the University nor the names of its contributors
6191
+  *    may be used to endorse or promote products derived from this software
6192
+  *    without specific prior written permission.
6193
+  *
6194
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
6195
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6196
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6197
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6198
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6199
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6200
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6201
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6202
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6203
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6204
+  * SUCH DAMAGE.
6205
+  *
6206
+  *	@(#)bitstring.h	8.1 (Berkeley) 7/19/93
6207
+  */
6208
+ 
6209
+ #ifndef _BITSTRING_H_
6210
+ #define	_BITSTRING_H_
6211
+ 
6212
+ typedef	unsigned char bitstr_t;
6213
+ 
6214
+ /* internal macros */
6215
+ 				/* byte of the bitstring bit is in */
6216
+ #define	_bit_byte(bit) \
6217
+ 	((bit) >> 3)
6218
+ 
6219
+ 				/* mask for the bit within its byte */
6220
+ #define	_bit_mask(bit) \
6221
+ 	(1 << ((bit)&0x7))
6222
+ 
6223
+ /* external macros */
6224
+ 				/* bytes in a bitstring of nbits bits */
6225
+ #define	bitstr_size(nbits) \
6226
+ 	((((nbits) - 1) >> 3) + 1)
6227
+ 
6228
+ 				/* allocate a bitstring */
6229
+ #define	bit_alloc(space, nbits, type, flags) \
6230
+ 	MALLOC((space), bitstr_t *, \
6231
+         (u_int)bitstr_size(nbits)*sizeof(bitstr_t), (type), (flags))
6232
+ 
6233
+ 				/* allocate a bitstring on the stack */
6234
+ #define	bit_decl(name, nbits) \
6235
+ 	(name)[bitstr_size(nbits)]
6236
+ 
6237
+ 				/* is bit N of bitstring name set? */
6238
+ #define	bit_test(name, bit) \
6239
+ 	((name)[_bit_byte(bit)] & _bit_mask(bit))
6240
+ 
6241
+ 				/* set bit N of bitstring name */
6242
+ #define	bit_set(name, bit) \
6243
+ 	(name)[_bit_byte(bit)] |= _bit_mask(bit)
6244
+ 
6245
+ 				/* clear bit N of bitstring name */
6246
+ #define	bit_clear(name, bit) \
6247
+ 	(name)[_bit_byte(bit)] &= ~_bit_mask(bit)
6248
+ 
6249
+ 				/* clear bits start ... stop in bitstring */
6250
+ #define	bit_nclear(name, start, stop) { \
6251
+ 	register bitstr_t *_name = name; \
6252
+ 	register int _start = start, _stop = stop; \
6253
+ 	register int _startbyte = _bit_byte(_start); \
6254
+ 	register int _stopbyte = _bit_byte(_stop); \
6255
+ 	if (_startbyte == _stopbyte) { \
6256
+ 		_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
6257
+ 				      (0xff << ((_stop&0x7) + 1))); \
6258
+ 	} else { \
6259
+ 		_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
6260
+ 		while (++_startbyte < _stopbyte) \
6261
+ 			_name[_startbyte] = 0; \
6262
+ 		_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
6263
+ 	} \
6264
+ }
6265
+ 
6266
+ 				/* set bits start ... stop in bitstring */
6267
+ #define	bit_nset(name, start, stop) { \
6268
+ 	register bitstr_t *_name = name; \
6269
+ 	register int _start = start, _stop = stop; \
6270
+ 	register int _startbyte = _bit_byte(_start); \
6271
+ 	register int _stopbyte = _bit_byte(_stop); \
6272
+ 	if (_startbyte == _stopbyte) { \
6273
+ 		_name[_startbyte] |= ((0xff << (_start&0x7)) & \
6274
+ 				    (0xff >> (7 - (_stop&0x7)))); \
6275
+ 	} else { \
6276
+ 		_name[_startbyte] |= 0xff << ((_start)&0x7); \
6277
+ 		while (++_startbyte < _stopbyte) \
6278
+ 	    		_name[_startbyte] = 0xff; \
6279
+ 		_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
6280
+ 	} \
6281
+ }
6282
+ 
6283
+ 				/* find first bit clear in name */
6284
+ #define	bit_ffc(name, nbits, value) { \
6285
+ 	register bitstr_t *_name = name; \
6286
+ 	register int _byte, _nbits = nbits; \
6287
+ 	register int _stopbyte = _bit_byte(_nbits), _value = -1; \
6288
+ 	for (_byte = 0; _byte <= _stopbyte; ++_byte) \
6289
+ 		if (_name[_byte] != 0xff) { \
6290
+ 			_value = _byte << 3; \
6291
+ 			for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
6292
+ 			    ++_value, _stopbyte >>= 1); \
6293
+ 			break; \
6294
+ 		} \
6295
+ 	*(value) = _value; \
6296
+ }
6297
+ 
6298
+ 				/* find first bit set in name */
6299
+ #define	bit_ffs(name, nbits, value) { \
6300
+ 	register bitstr_t *_name = name; \
6301
+ 	register int _byte, _nbits = nbits; \
6302
+ 	register int _stopbyte = _bit_byte(_nbits), _value = -1; \
6303
+ 	for (_byte = 0; _byte <= _stopbyte; ++_byte) \
6304
+ 		if (_name[_byte]) { \
6305
+ 			_value = _byte << 3; \
6306
+ 			for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
6307
+ 			    ++_value, _stopbyte >>= 1); \
6308
+ 			break; \
6309
+ 		} \
6310
+ 	*(value) = _value; \
6311
+ }
6312
+ 
6313
+ #endif /* !_BITSTRING_H_ */
6314
diff -N -c -r /usr/src/sys/conf/files ./conf/files
6315
*** /usr/src/sys/conf/files	Fri Apr 30 15:32:40 1999
6316
--- ./conf/files	Thu Nov 25 15:34:34 1999
6317
***************
6318
*** 535,540 ****
6319
--- 535,541 ----
6320
  netinet/tcp_timer.c	optional inet
6321
  netinet/tcp_usrreq.c	optional inet
6322
  netinet/udp_usrreq.c	optional inet
6323
+ netinet/il.c		optional  il
6324
  netipx/ipx.c		optional ipx
6325
  netipx/ipx_cksum.c	optional ipx
6326
  netipx/ipx_input.c	optional ipx
6327
***************
6328
*** 571,576 ****
6329
--- 572,586 ----
6330
  nfs/nfs_syscalls.c	optional nfs
6331
  nfs/nfs_vfsops.c	optional nfs
6332
  nfs/nfs_vnops.c		optional nfs
6333
+ 9fs/9fs_vfsops.c	optional u9fs
6334
+ 9fs/9fs_vnops.c		optional u9fs
6335
+ 9fs/9p.c		optional u9fs
6336
+ 9fs/9auth.c		optional u9fs
6337
+ 9fs/9crypt.c		optional u9fs
6338
+ 9fs/9fs_subr.c		optional u9fs
6339
+ 9fs/9fs_socket.c	optional u9fs
6340
+ 9fs/9fs_bio.c		optional u9fs
6341
+ 9fs/9fs_node.c		optional u9fs
6342
  nfs/bootp_subr.c	optional bootp
6343
  nfs/krpc_subr.c		optional bootp
6344
  pccard/pccard.c		optional card
6345
diff -N -c -r /usr/src/sys/conf/options ./conf/options
6346
*** /usr/src/sys/conf/options	Tue May 11 01:35:28 1999
6347
--- ./conf/options	Mon Oct 11 19:59:14 1999
6348
***************
6349
*** 202,207 ****
6350
--- 202,208 ----
6351
  BRIDGE			opt_bdg.h
6352
  MROUTING		opt_mrouting.h
6353
  INET			opt_inet.h
6354
+ IL			opt_inet.h
6355
  IPDIVERT
6356
  DUMMYNET		opt_ipdn.h
6357
  IPFIREWALL		opt_ipfw.h
6358
***************
6359
*** 314,319 ****
6360
--- 315,322 ----
6361
  NFS_MUIDHASHSIZ		opt_nfs.h
6362
  NFS_NOSERVER		opt_nfs.h
6363
  NFS_DEBUG		opt_nfs.h
6364
+ 
6365
+ U9FS
6366
 
6367
  # give bktr an opt_bktr.h file
6368
  OVERRIDE_CARD		opt_bktr.h
6369
diff -N -c -r /usr/src/sys/i386/conf/IL ./i386/conf/IL
6370
*** /usr/src/sys/i386/conf/IL	Wed Dec 31 19:00:00 1969
6371
--- ./i386/conf/IL	Sat Oct 23 14:01:36 1999
6372
***************
6373
*** 0 ****
6374
--- 1,234 ----
6375
+ #
6376
+ # GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks
6377
+ #
6378
+ # For more information read the handbook part System Administration -> 
6379
+ # Configuring the FreeBSD Kernel -> The Configuration File. 
6380
+ # The handbook is available in /usr/share/doc/handbook or online as
6381
+ # latest version from the FreeBSD World Wide Web server 
6382
+ # <URL:http://www.FreeBSD.ORG/>
6383
+ #
6384
+ # An exhaustive list of options and more detailed explanations of the 
6385
+ # device lines is present in the ./LINT configuration file. If you are 
6386
+ # in doubt as to the purpose or necessity of a line, check first in LINT.
6387
+ #
6388
+ #	$Id: GENERIC,v 1.143.2.2 1999/02/15 02:50:07 des Exp $
6389
+ 
6390
+ machine		"i386"
6391
+ cpu		"I586_CPU"
6392
+ cpu		"I686_CPU"
6393
+ ident		GENERIC
6394
+ maxusers	128
6395
+ 
6396
+ #options		DDB
6397
+ options		IL			# plan9's IL
6398
+ options		"U9FS"			# plan9's 9fs client
6399
+ options		INET			#InterNETworking
6400
+ options		FFS			#Berkeley Fast Filesystem
6401
+ options		FFS_ROOT		#FFS usable as root device [keep this!]
6402
+ options		MFS			#Memory Filesystem
6403
+ options		MFS_ROOT		#MFS usable as root device, "MFS" req'ed
6404
+ options		NFS			#Network Filesystem
6405
+ options		NFS_ROOT		#NFS usable as root device, "NFS" req'ed
6406
+ options		"CD9660"		#ISO 9660 Filesystem
6407
+ options		"CD9660_ROOT"		#CD-ROM usable as root. "CD9660" req'ed
6408
+ options		PROCFS			#Process filesystem
6409
+ options         FDESC                   #File descriptor filesystem
6410
+ options		"COMPAT_43"		#Compatible with BSD 4.3 [KEEP THIS!]
6411
+ options		SCSI_DELAY=15000	#Be pessimistic about Joe SCSI device
6412
+ options		UCONSOLE		#Allow users to grab the console
6413
+ options		FAILSAFE		#Be conservative
6414
+ options		USERCONFIG		#boot -c editor
6415
+ options		VISUAL_USERCONFIG	#visual boot -c editor
6416
+ options		NMBCLUSTERS=4096
6417
+ options		MAXFILES=10000
6418
+ 
6419
+ config		kernel	root on wd0
6420
+ 
6421
+ # To make an SMP kernel, the next two are needed
6422
+ #options	SMP			# Symmetric MultiProcessor Kernel
6423
+ #options	APIC_IO			# Symmetric (APIC) I/O
6424
+ # Optionally these may need tweaked, (defaults shown):
6425
+ #options	NCPU=2			# number of CPUs
6426
+ #options	NBUS=4			# number of busses
6427
+ #options	NAPIC=1			# number of IO APICs
6428
+ #options	NINTR=24		# number of INTs
6429
+ 
6430
+ controller	isa0
6431
+ controller	eisa0
6432
+ controller	pci0
6433
+ 
6434
+ controller	fdc0	at isa? port "IO_FD1" bio irq 6 drq 2
6435
+ disk		fd0	at fdc0 drive 0
6436
+ disk		fd1	at fdc0 drive 1
6437
+ 
6438
+ options		"CMD640"	# work around CMD640 chip deficiency
6439
+ controller	wdc0	at isa? port "IO_WD1" bio irq 14 flags 0xa0ff vector wdintr
6440
+ disk		wd0	at wdc0 drive 0
6441
+ disk		wd1	at wdc0 drive 1
6442
+ 
6443
+ controller	wdc1	at isa? port "IO_WD2" bio irq 15 flags 0xa0ff vector wdintr
6444
+ disk		wd2	at wdc1 drive 0
6445
+ disk		wd3	at wdc1 drive 1
6446
+ 
6447
+ options		ATAPI		#Enable ATAPI support for IDE bus
6448
+ options		ATAPI_STATIC	#Don't do it as an LKM
6449
+ #device		acd0		#IDE CD-ROM
6450
+ #device		wfd0		#IDE Floppy (e.g. LS-120)
6451
+ 
6452
+ # A single entry for any of these controllers (ncr, ahb, ahc) is
6453
+ # sufficient for any number of installed devices.
6454
+ #controller	ncr0
6455
+ #controller	ahb0
6456
+ #controller	ahc0
6457
+ #controller	isp0
6458
+ 
6459
+ # This controller offers a number of configuration options, too many to
6460
+ # document here  - see the LINT file in this directory and look up the
6461
+ # dpt0 entry there for much fuller documentation on this.
6462
+ controller      dpt0
6463
+ 
6464
+ #controller	adv0	at isa? port ? cam irq ?
6465
+ #controller	adw0
6466
+ #controller	bt0	at isa? port ? cam irq ?
6467
+ #controller	aha0	at isa? port ? cam irq ?
6468
+ #controller	aic0	at isa? port 0x340 bio irq 11
6469
+ 
6470
+ controller	scbus0
6471
+ 
6472
+ device		da0
6473
+ 
6474
+ device		sa0
6475
+ 
6476
+ device		pass0
6477
+ 
6478
+ device		cd0	#Only need one of these, the code dynamically grows
6479
+ 
6480
+ #device		wt0	at isa? port 0x300 bio irq 5 drq 1
6481
+ #device		mcd0	at isa? port 0x300 bio irq 10
6482
+ 
6483
+ #controller	matcd0	at isa? port 0x230 bio
6484
+ 
6485
+ #device		scd0	at isa? port 0x230 bio
6486
+ 
6487
+ # atkbdc0 controlls both the keyboard and the PS/2 mouse
6488
+ controller	atkbdc0	at isa? port IO_KBD tty
6489
+ device		atkbd0	at isa? tty irq 1
6490
+ device		psm0	at isa? tty irq 12
6491
+ 
6492
+ device		vga0	at isa? port ? conflicts
6493
+ 
6494
+ # splash screen/screen saver
6495
+ pseudo-device	splash
6496
+ 
6497
+ # syscons is the default console driver, resembling an SCO console
6498
+ device		sc0	at isa? tty
6499
+ # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver
6500
+ #device		vt0	at isa? tty
6501
+ #options		XSERVER			# support for X server
6502
+ #options		FAT_CURSOR		# start with block cursor
6503
+ # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines
6504
+ #options		PCVT_SCANSET=2		# IBM keyboards are non-std
6505
+ 
6506
+ device		npx0	at isa? port IO_NPX irq 13
6507
+ 
6508
+ #
6509
+ # Laptop support (see LINT for more options)
6510
+ #
6511
+ device		apm0    at isa?	disable	flags 0x31 # Advanced Power Management
6512
+ 
6513
+ # PCCARD (PCMCIA) support
6514
+ #controller	card0
6515
+ #device		pcic0	at card?
6516
+ #device		pcic1	at card?
6517
+ 
6518
+ device		sio0	at isa? port "IO_COM1" flags 0x10 tty irq 4
6519
+ device		sio1	at isa? port "IO_COM2" tty irq 3
6520
+ device		sio2	at isa? disable port "IO_COM3" tty irq 5
6521
+ device		sio3	at isa? disable port "IO_COM4" tty irq 9
6522
+ 
6523
+ # Parallel port
6524
+ device		ppc0	at isa? port? net irq 7
6525
+ controller	ppbus0
6526
+ device		nlpt0	at ppbus?
6527
+ device		plip0	at ppbus?
6528
+ device		ppi0	at ppbus?
6529
+ #controller	vpo0	at ppbus?
6530
+ 
6531
+ #
6532
+ # The following Ethernet NICs are all PCI devices.
6533
+ #
6534
+ device ax0		# ASIX AX88140A
6535
+ device de0		# DEC/Intel DC21x4x (``Tulip'')
6536
+ device fxp0		# Intel EtherExpress PRO/100B (82557, 82558)
6537
+ device mx0		# Macronix 98713/98715/98725 (``PMAC'')
6538
+ device pn0		# Lite-On 82c168/82c169 (``PNIC'')
6539
+ device rl0		# RealTek 8129/8139
6540
+ device tl0		# Texas Instruments ThunderLAN
6541
+ device tx0		# SMC 9432TX (83c170 ``EPIC'')
6542
+ device vr0		# VIA Rhine, Rhine II
6543
+ device vx0		# 3Com 3c590, 3c595 (``Vortex'')
6544
+ device wb0		# Winbond W89C840F
6545
+ device xl0		# 3Com 3c90x (``Boomerang'', ``Cyclone'')
6546
+ 
6547
+ # Order is important here due to intrusive probes, do *not* alphabetize
6548
+ # this list of network interfaces until the probes have been fixed.
6549
+ # Right now it appears that the ie0 must be probed before ep0. See
6550
+ # revision 1.20 of this file.
6551
+ 
6552
+ #device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000
6553
+ #device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000
6554
+ #device ep0 at isa? port 0x300 net irq 10
6555
+ #device ex0 at isa? port? net irq?
6556
+ #device fe0 at isa? port 0x300 net irq ?
6557
+ #device le0 at isa? port 0x300 net irq 5 iomem 0xd0000
6558
+ #device lnc0 at isa? port 0x280 net irq 10 drq 0
6559
+ #device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000
6560
+ #device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000
6561
+ #device cs0 at isa? port 0x300 net irq ?
6562
+ 
6563
+ pseudo-device	loop
6564
+ pseudo-device	ether
6565
+ pseudo-device	sl	1
6566
+ pseudo-device	ppp	1
6567
+ pseudo-device	tun	1
6568
+ pseudo-device	pty	32
6569
+ pseudo-device	gzip		# Exec gzipped a.out's
6570
+ 
6571
+ # KTRACE enables the system-call tracing facility ktrace(2).
6572
+ # This adds 4 KB bloat to your kernel, and slightly increases
6573
+ # the costs of each syscall.
6574
+ options		KTRACE		#kernel tracing
6575
+ 
6576
+ # This provides support for System V shared memory and message queues.
6577
+ #
6578
+ options		SYSVSHM
6579
+ options		SYSVMSG
6580
+ 
6581
+ #  The `bpfilter' pseudo-device enables the Berkeley Packet Filter.  Be
6582
+ #  aware of the legal and administrative consequences of enabling this
6583
+ #  option.  The number of devices determines the maximum number of
6584
+ #  simultaneous BPF clients programs runnable.
6585
+ pseudo-device	bpfilter 4	#Berkeley packet filter
6586
+ 
6587
+ 
6588
+ # USB support
6589
+ #controller    uhci0
6590
+ #controller    ohci0
6591
+ #controller    usb0
6592
+ #
6593
+ # for the moment we have to specify the priorities of the device
6594
+ # drivers explicitly by the ordering in the list below. This will
6595
+ # be changed in the future.
6596
+ #
6597
+ #device        ums0
6598
+ #device        ukbd0
6599
+ #device        ulpt0
6600
+ #device        uhub0
6601
+ #device        ucom0
6602
+ #device        umodem0
6603
+ #device        hid0
6604
+ #device        ugen0
6605
+ 
6606
+ #
6607
+ #options       USB_DEBUG
6608
+ #options       USBVERBOSE
6609
diff -N -c -r /usr/src/sys/netinet/il.c ./netinet/il.c
6610
*** /usr/src/sys/netinet/il.c	Wed Dec 31 19:00:00 1969
6611
--- ./netinet/il.c	Tue Nov 23 19:16:13 1999
6612
***************
6613
*** 0 ****
6614
--- 1,1147 ----
6615
+ #include <unistd.h>
6616
+ #include <ctype.h>
6617
+ #include <sys/types.h>
6618
+ #include <sys/param.h>
6619
+ #include <sys/time.h>
6620
+ #include <sys/systm.h>
6621
+ #include <vm/vm_zone.h>
6622
+ 
6623
+ #include <sys/malloc.h>
6624
+ #include <machine/param.h>
6625
+ #include <sys/mbuf.h>
6626
+ #include <sys/protosw.h>
6627
+ #include <sys/socket.h>
6628
+ #include <sys/socketvar.h>
6629
+ #include <sys/proc.h>
6630
+ #include <net/if.h>
6631
+ #include <net/route.h>
6632
+ #include <netinet/in_systm.h>
6633
+ #include <netinet/in.h>
6634
+ #include <netinet/in_var.h>
6635
+ #include <netinet/if_ether.h>
6636
+ #include <netinet/ip.h>
6637
+ #include <netinet/ip_var.h>
6638
+ #include <netinet/in_pcb.h>
6639
+ #include <errno.h>
6640
+ 
6641
+ #include <netinet/il.h>
6642
+ #include <netinet/il_var.h>
6643
+ 
6644
+ struct ilpcb * il_drop(struct ilpcb *ilpcb, int errno0);
6645
+ static struct ilpcb * il_close(struct ilpcb *ilpcb);
6646
+ 
6647
+ /* kernel protocol states needed */
6648
+ static struct inpcbhead ilb;
6649
+ static struct inpcbinfo ilbinfo;
6650
+ 
6651
+ u_long il_sendspace = 1024*64;
6652
+ u_long il_recvspace = 1024*64;
6653
+ 
6654
+ /*
6655
+  * Target size of IL PCB hash tables. Must be a power of two.
6656
+  *
6657
+  * Note that this can be overridden by the kernel environment
6658
+  * variable net.inet.tcp.tcbhashsize
6659
+  */
6660
+ #ifndef ILBHASHSIZE
6661
+ #define ILBHASHSIZE	512
6662
+ #endif
6663
+ 
6664
+ enum				/* Connection state */
6665
+ {
6666
+ 	ILS_CLOSED,
6667
+ 	ILS_SYNCER,
6668
+ 	ILS_SYNCEE,
6669
+ 	ILS_ESTABLISHED,
6670
+ 	ILS_LISTENING,
6671
+ 	ILS_CLOSING,
6672
+ 	ILS_OPENING,		/* only for file server */
6673
+ };
6674
+ 
6675
+ char	*ilstates[] = 
6676
+ { 
6677
+ 	"Closed",
6678
+ 	"Syncer",
6679
+ 	"Syncee",
6680
+ 	"Established",
6681
+ 	"Listening",
6682
+ 	"Closing",
6683
+ 	"Opening",		/* only for file server */
6684
+ };
6685
+ 
6686
+ enum				/* Packet types */
6687
+ {
6688
+ 	ILT_SYNC,
6689
+ 	ILT_DATA,
6690
+ 	ILT_DATAQUERY,
6691
+ 	ILT_ACK,
6692
+ 	ILT_QUERY,
6693
+ 	ILT_STATE,
6694
+ 	ILT_CLOSE
6695
+ };
6696
+ 
6697
+ char	*iltype[] = 
6698
+ {	
6699
+ 	"sync",
6700
+ 	"data",
6701
+ 	"dataquery",
6702
+ 	"ack",
6703
+ 	"query",
6704
+ 	"state",
6705
+ 	"close",
6706
+ };
6707
+ 
6708
+ /*
6709
+  * This is the actual shape of what we allocate using the zone
6710
+  * allocator.  Doing it this way allows us to protect both structures
6711
+  * using the same generation count, and also eliminates the overhead
6712
+  * of allocating tcpcbs separately.  By hiding the structure here,
6713
+  * we avoid changing most of the rest of the code (although it needs
6714
+  * to be changed, eventually, for greater efficiency).
6715
+  */
6716
+ #define	ALIGNMENT	32
6717
+ #define	ALIGNM1		(ALIGNMENT - 1)
6718
+ struct	inp_ilpcb {
6719
+ 	union {
6720
+ 		struct	inpcb inp;
6721
+ 		char	align[(sizeof(struct inpcb) + ALIGNM1) & ~ALIGNM1];
6722
+ 	} inp_tp_u;
6723
+ 	struct	ilpcb ilpcb;
6724
+ };
6725
+ #undef ALIGNMENT
6726
+ #undef ALIGNM1
6727
+ 
6728
+ static __inline struct mbuf * il_segq_top(struct ilpcb * ilpcb)
6729
+ {
6730
+   return (ilpcb->segq);
6731
+ }
6732
+ 
6733
+ static __inline void il_segq_dequeue(struct ilpcb * ilpcb)
6734
+ {
6735
+   struct mbuf * m = ilpcb->segq;
6736
+   ilpcb->segq = m->m_nextpkt;
6737
+   m->m_nextpkt = 0;
6738
+ }
6739
+ 
6740
+ static __inline void il_segq_insert(struct ilpcb * ilpcb, struct mbuf * m, u_long seq, struct ilhdr * il)
6741
+ {
6742
+   u_long pseq;
6743
+   struct mbuf * mp, * mq;
6744
+ 
6745
+   m->m_pkthdr.header = il;
6746
+ 
6747
+   mp = 0;
6748
+   mq = ilpcb->segq;
6749
+   while ( mq ) {
6750
+     il = mq->m_pkthdr.header;
6751
+     pseq = ntohl(*(u_long *)il->ilid);
6752
+     if( pseq > seq )
6753
+       break;
6754
+     if( pseq == seq ) { /* we already got this packet */
6755
+       m_freem(m);
6756
+       return;
6757
+     }
6758
+     mp = mq;
6759
+     mq = mq->m_nextpkt;
6760
+   }
6761
+ 
6762
+   if( mp == 0 ) {
6763
+     m->m_nextpkt = ilpcb->segq;
6764
+     ilpcb->segq = m;
6765
+     return;
6766
+   }
6767
+   mp->m_nextpkt = m;
6768
+   m->m_nextpkt = mq;
6769
+ }
6770
+ 
6771
+ void il_init()
6772
+ {  
6773
+   LIST_INIT(&ilb);
6774
+   ilbinfo.listhead = &ilb;
6775
+   ilbinfo.hashbase = hashinit(ILBHASHSIZE, M_PCB, &ilbinfo.hashmask);
6776
+   ilbinfo.porthashbase = hashinit(ILBHASHSIZE, M_PCB,
6777
+ 				  &ilbinfo.porthashmask);
6778
+   ilbinfo.ipi_zone = zinit("ilpcb", sizeof(struct inp_ilpcb), maxsockets,
6779
+ 			   ZONE_INTERRUPT, 0);
6780
+ }
6781
+ 
6782
+ /* fill in il header and cksum, ip src/dst addresses */
6783
+ static int il_output(struct ilpcb * ilpcb, struct mbuf *m, int type, u_long seq, u_char spec)
6784
+ {
6785
+   struct ilhdr * il;
6786
+   struct ip * ip;
6787
+   int illen;
6788
+   struct inpcb * inp;
6789
+   struct socket * so;
6790
+ 
6791
+   /* XXX: check total size is less than IP_MAXPACKET */
6792
+ 
6793
+   if( m == 0 ) {
6794
+     inp = ilpcb->inpcb;
6795
+     so = inp->inp_socket;
6796
+     m = m_copypacket(so->so_snd.sb_mb, M_DONTWAIT);
6797
+   } 
6798
+ 
6799
+   /*
6800
+    * Calculate data length and get a mbuf
6801
+    * for IL and IP headers.
6802
+    */
6803
+   illen = m->m_pkthdr.len; /* size of il payload */
6804
+   M_PREPEND(m, sizeof(struct ip) + sizeof(struct ilhdr), M_DONTWAIT);
6805
+   if( m == 0 )
6806
+     return ENOBUFS;
6807
+ 
6808
+   ip = mtod(m, struct ip *);
6809
+   il = (struct ilhdr *) (ip+1);
6810
+   bzero(ip, sizeof(*ip));
6811
+ 
6812
+   ip->ip_p = IPPROTO_IL;
6813
+   ip->ip_src = ilpcb->inpcb->inp_laddr;
6814
+   ip->ip_dst = ilpcb->inpcb->inp_faddr;
6815
+   ip->ip_len = m->m_pkthdr.len;
6816
+   ip->ip_ttl = ilpcb->inpcb->inp_ip_ttl;	/* XXX */
6817
+   ip->ip_tos = ilpcb->inpcb->inp_ip_tos;	/* XXX */
6818
+ 
6819
+   *(u_short *)il->illen = htons(illen + sizeof(struct ilhdr));
6820
+   il->iltype = type;
6821
+   il->ilspec = spec;
6822
+   *(u_short *)il->ilsrc = ilpcb->inpcb->inp_lport;
6823
+   *(u_short *)il->ildst = ilpcb->inpcb->inp_fport;
6824
+   if ( type != ILT_SYNC )
6825
+     *(u_long *)il->ilid = htonl(seq);
6826
+   else
6827
+     *(u_long *)il->ilid = htonl(ilpcb->start);
6828
+ 
6829
+   if( type != ILT_ACK && type != ILT_STATE) {
6830
+     if( ilpcb->rxt_timer == 0 )
6831
+       ilpcb->rxt_timer = ilpcb->rxt_timer_cur;
6832
+     if( ilpcb->death_timer == 0 )
6833
+       ilpcb->death_timer = ilpcb->death_timer_cur;
6834
+   }
6835
+ 
6836
+   *(u_long *)il->ilack = htonl(ilpcb->recvd);
6837
+   il->ilsum[0] = il->ilsum[1] = 0;
6838
+ 
6839
+   /* IL checksum does not cover IP header */
6840
+   m->m_data += sizeof(struct ip);
6841
+   m->m_len  -= sizeof(struct ip);
6842
+   *(u_short *)il->ilsum = in_cksum(m, illen + sizeof(struct ilhdr));
6843
+   m->m_data -= sizeof(struct ip);
6844
+   m->m_len  += sizeof(struct ip);
6845
+ 
6846
+   return ip_output(m, ilpcb->inpcb->inp_options, &ilpcb->inpcb->inp_route, 
6847
+ 		   ilpcb->inpcb->inp_socket->so_options & SO_DONTROUTE ,0);
6848
+ }
6849
+ 
6850
+ static int il_send_empty(struct ilpcb * ilpcb, int type, u_char spec)
6851
+ {
6852
+   struct mbuf * m0;
6853
+ 
6854
+   MGETHDR(m0, M_DONTWAIT, MT_DATA);
6855
+   m0->m_len = 0;
6856
+   m0->m_pkthdr.len = 0;
6857
+   MH_ALIGN(m0, 0); /* leave space for the packet header */
6858
+ 
6859
+   return il_output(ilpcb, m0, type, ilpcb->next, spec);
6860
+ }
6861
+ 
6862
+ static int il_respond(struct ilpcb * ilpcb, struct ip * ip, struct ilhdr *il, int type, u_char spec)
6863
+ {
6864
+   struct mbuf * m;
6865
+   int illen;
6866
+   struct ip * ip0;
6867
+   struct ilhdr *il0;
6868
+   struct route * ro;
6869
+   struct route sro;
6870
+ 
6871
+   if( ilpcb ) {
6872
+     ro = & ilpcb->inpcb->inp_route;
6873
+   } else {
6874
+     ro = &sro;
6875
+     bzero(ro, sizeof *ro);
6876
+   }
6877
+ 	      
6878
+   MGETHDR(m, M_DONTWAIT, MT_DATA);
6879
+   m->m_len = 0;
6880
+   m->m_pkthdr.len = 0;
6881
+   MH_ALIGN(m, 0); /* leave space for the packet header */
6882
+   illen = m->m_pkthdr.len; /* size of il payload */
6883
+   M_PREPEND(m, sizeof(struct ip) + sizeof(struct ilhdr), M_DONTWAIT);
6884
+   if( m == 0 )
6885
+     return ENOBUFS;
6886
+ 
6887
+   ip0 = mtod(m, struct ip *);
6888
+   il0 = (struct ilhdr *) (ip0+1);
6889
+   bzero(ip0, sizeof(*ip0));
6890
+ 
6891
+   ip0->ip_p = IPPROTO_IL;
6892
+   ip0->ip_src = ip->ip_dst;
6893
+   ip0->ip_dst = ip->ip_src;
6894
+   ip0->ip_ttl = ip_defttl;
6895
+   ip0->ip_len = sizeof(struct ip) + sizeof(struct ilhdr);
6896
+   *(u_short *)il0->illen = htons(illen + sizeof(struct ilhdr));
6897
+   il0->iltype = type;
6898
+   il0->ilspec = spec;
6899
+   bcopy(il->ilsrc, il0->ildst, 2);
6900
+   bcopy(il->ildst, il0->ilsrc, 2);
6901
+   *(u_long *)il0->ilid = 0;
6902
+   bcopy(il->ilid, il0->ilack, 4);
6903
+   il0->ilsum[0] = il0->ilsum[1] = 0;
6904
+ 
6905
+   /* IL checksum does not cover IP header */
6906
+   m->m_data += sizeof(struct ip);
6907
+   m->m_len  -= sizeof(struct ip);
6908
+   *(u_short *)il0->ilsum = in_cksum(m, illen + sizeof(struct ilhdr));
6909
+   m->m_data -= sizeof(struct ip);
6910
+   m->m_len  += sizeof(struct ip);
6911
+ 
6912
+   return ip_output(m, 0, ro, 0 ,0);
6913
+ }
6914
+ 
6915
+ static struct ilpcb *
6916
+ il_newconn(struct ilpcb * ilpcb, struct in_addr ti_dst, u_short ti_dport,
6917
+ 	   struct in_addr ti_src, u_short ti_sport)
6918
+ {
6919
+   register struct ilpcb * ilpcb0;
6920
+   struct socket *so2, * so;
6921
+   struct inpcb * inp;
6922
+   struct sockaddr_in sin;
6923
+ 
6924
+   so = ilpcb->inpcb->inp_socket;
6925
+   so2 = sonewconn(so, 0);
6926
+   if (so2 == 0) {
6927
+     so2 = sodropablereq(so);
6928
+     if (so2) {
6929
+       il_drop(sotoilpcb(so2), ETIMEDOUT);
6930
+       so2 = sonewconn(so, 0);
6931
+     }
6932
+     if (!so2)
6933
+       return 0;
6934
+   }
6935
+   so = so2;
6936
+ 
6937
+   inp = (struct inpcb *)so->so_pcb;
6938
+   inp->inp_laddr = ti_dst;
6939
+   inp->inp_lport = ti_dport;
6940
+   if (in_pcbinshash(inp) != 0) {
6941
+ 				/*
6942
+ 				 * Undo the assignments above if we failed to put
6943
+ 				 * the PCB on the hash lists.
6944
+ 				 */
6945
+     inp->inp_laddr.s_addr = INADDR_ANY;
6946
+     inp->inp_lport = 0;
6947
+ 
6948
+     soabort(so);
6949
+     return 0;
6950
+   }
6951
+ 
6952
+   bzero((char *)&sin, sizeof(sin));
6953
+   sin.sin_family = AF_INET;
6954
+   sin.sin_len = sizeof(sin);
6955
+   sin.sin_addr = ti_src;
6956
+   sin.sin_port = ti_sport;
6957
+   if (in_pcbconnect(inp, (struct sockaddr *)&sin, &proc0)) {
6958
+     inp->inp_laddr.s_addr = INADDR_ANY;
6959
+     soabort(so);
6960
+     return 0;
6961
+   }
6962
+ 
6963
+   ilpcb0 = intoilpcb(inp);
6964
+   ilpcb0->state = ILS_LISTENING;
6965
+ 
6966
+   return ilpcb0;
6967
+ }
6968
+ 
6969
+ /* ack processing */
6970
+ static void il_proc_ack(struct ilpcb * ilpcb, struct socket * so, u_long ack)
6971
+ {
6972
+   if( ack >= ilpcb->unacked ) {
6973
+     ilpcb->rxt_timer = 0;
6974
+     ilpcb->death_timer = 0;
6975
+ 
6976
+     /* the rxt timer is not prop. to RTT */
6977
+     /* reset it so that the first rxt is always 1 second */
6978
+     ilpcb->rxt_timer_cur = 2;
6979
+ 
6980
+     if( ack >= ilpcb->next )
6981
+       ack = ilpcb->next - 1;
6982
+     while (ilpcb->unacked <= ack ) {
6983
+       sbdroprecord(&so->so_snd);
6984
+       ilpcb->unacked++;
6985
+     }
6986
+     if( ilpcb->unacked != ilpcb->next ) {
6987
+       ilpcb->rxt_timer = ilpcb->rxt_timer_cur;
6988
+       ilpcb->death_timer = ilpcb->death_timer_cur; /* do we need this here? */
6989
+     }
6990
+     sowwakeup(so);
6991
+   }
6992
+ }
6993
+ 
6994
+ static int il_proc_data(struct ilpcb * ilpcb, struct socket * so, struct mbuf * m, u_long seq, int spec)
6995
+ {
6996
+   struct mbuf * m0;
6997
+   struct ip * ip;
6998
+   int hlen = sizeof(struct ip) + sizeof(struct ilhdr);
6999
+   struct ilhdr * il;
7000
+   int needack = 0;
7001
+ 
7002
+   ip = mtod(m, struct ip *);
7003
+   il = (struct ilhdr *)(ip+1);
7004
+   if( seq == ilpcb->recvd + 1 ) {
7005
+     needack = 1;
7006
+     while(1) {
7007
+       ilpcb->recvd = seq;
7008
+       
7009
+       m->m_len -= hlen;
7010
+       m->m_pkthdr.len -= hlen;
7011
+       m->m_data += hlen;
7012
+       sbappendrecord(&so->so_rcv, m);
7013
+ 
7014
+       if( (m0 = il_segq_top(ilpcb)) == 0 )
7015
+ 	break;
7016
+       ip = mtod(m0, struct ip *);
7017
+       il = (struct ilhdr *)(ip+1);
7018
+       seq = ntohl(*(u_long *)il->ilid);
7019
+       if( seq != ilpcb->recvd + 1 )
7020
+ 	break;
7021
+       il_segq_dequeue(ilpcb);
7022
+       m = m0;
7023
+     };      
7024
+     sorwakeup(so);
7025
+   } else {
7026
+     if( seq > ilpcb->recvd ) 
7027
+       il_segq_insert(ilpcb, m, seq, il);
7028
+     else
7029
+       m_freem(m);
7030
+   }
7031
+ 
7032
+   return needack;
7033
+ }
7034
+ 
7035
+ /* assume we only have one connection */
7036
+ void il_input(struct mbuf * m, int iphlen)
7037
+ {
7038
+   struct ilhdr * il;
7039
+   struct ilpcb * ilpcb = 0;
7040
+   int len, type;
7041
+   u_long seq, ack;
7042
+   struct ip * ip;
7043
+   struct inpcb * inp;
7044
+   u_short sport, dport;
7045
+   struct socket * so;
7046
+   u_char spec;
7047
+ 
7048
+   /*
7049
+    * Strip IP options, if any; should skip this,
7050
+    * make available to user, and use on returned packets,
7051
+    * but we don't yet have a way to check the checksum
7052
+    * with options still present.
7053
+    */
7054
+   if (iphlen > sizeof (struct ip)) {
7055
+     ip_stripoptions(m, (struct mbuf *)0);
7056
+     iphlen = sizeof(struct ip);
7057
+   }
7058
+ 
7059
+   /*
7060
+    * Get IP and IL header together in first mbuf.
7061
+    */
7062
+   ip = mtod(m, struct ip *);
7063
+   if (m->m_len < iphlen + sizeof(struct ilhdr)) {
7064
+     if ((m = m_pullup(m, iphlen + sizeof(struct ilhdr))) == 0) {
7065
+       return;
7066
+     }
7067
+     ip = mtod(m, struct ip *);
7068
+   }
7069
+   il = (struct ilhdr *)((caddr_t)ip + iphlen);
7070
+ 
7071
+   len = ntohs(*(u_short *)il->illen);
7072
+   seq = ntohl(*(u_long *)il->ilid);
7073
+   ack = ntohl(*(u_long *)il->ilack);
7074
+   sport = *(u_short *)il->ilsrc;
7075
+   dport = *(u_short *)il->ildst;  
7076
+   type = il->iltype;
7077
+   spec = il->ilspec;
7078
+ 
7079
+   inp = in_pcblookup_hash(&ilbinfo, ip->ip_src, sport, ip->ip_dst, dport, 1);
7080
+   if ( inp == 0 && type == ILT_SYNC )
7081
+     goto dropwithrest;
7082
+   if( inp == 0 )
7083
+     goto drop;
7084
+ 
7085
+   ilpcb = intoilpcb(inp);
7086
+   if( ilpcb == 0 )
7087
+     goto drop;
7088
+ 
7089
+   so = inp->inp_socket;
7090
+   if( type == ILT_QUERY ) { /* XXX: can we use the same mbuf to send? */
7091
+     il_send_empty(ilpcb, ILT_STATE, il->ilspec);
7092
+     goto drop;
7093
+   }  
7094
+ 
7095
+  again:
7096
+   /* FSM transition */
7097
+   switch( ilpcb->state ) {
7098
+   case ILS_SYNCER:
7099
+     if( ack != ilpcb->start )
7100
+       goto drop;
7101
+     switch( type ) {
7102
+     case ILT_SYNC:
7103
+       ilpcb->unacked++;
7104
+       ilpcb->recvd = seq;
7105
+       il_send_empty(ilpcb, ILT_ACK, 0);
7106
+       ilpcb->state = ILS_ESTABLISHED;
7107
+       ilpcb->rxt_timer = 0;
7108
+       ilpcb->death_timer = 0;
7109
+       soisconnected(inp->inp_socket);
7110
+       break;
7111
+     case ILT_CLOSE:
7112
+       il_drop(ilpcb, ECONNREFUSED);
7113
+       break;
7114
+     }
7115
+     break;
7116
+ 
7117
+   case ILS_LISTENING:
7118
+     if( type == ILT_SYNC && ack == 0 && so->so_options & SO_ACCEPTCONN ) {
7119
+       ilpcb = il_newconn(ilpcb, ip->ip_dst, dport, ip->ip_src, sport);
7120
+ 
7121
+       ilpcb->next = ilpcb->start = random();
7122
+       ilpcb->unacked = ilpcb->next;
7123
+       ilpcb->rstart = ilpcb->recvd = seq;
7124
+       ilpcb->state = ILS_SYNCEE;
7125
+       il_send_empty(ilpcb, ILT_SYNC, 0);
7126
+       ilpcb->next++;
7127
+     } else
7128
+       il_respond(ilpcb, ip, il, ILT_CLOSE, 0);
7129
+     break;
7130
+ 
7131
+   case ILS_SYNCEE:
7132
+     if( ack == ilpcb->start ) {      
7133
+       ilpcb->rxt_timer = 0;
7134
+       ilpcb->unacked++;
7135
+       ilpcb->state = ILS_ESTABLISHED;
7136
+       soisconnected(so);
7137
+       goto again;
7138
+       break;
7139
+     }
7140
+     if( type == ILT_SYNC && seq == ilpcb->recvd && ack == 0 )
7141
+       il_send_empty(ilpcb, ILT_SYNC, 0);
7142
+     break;
7143
+ 
7144
+   case ILS_ESTABLISHED:
7145
+     il_proc_ack(ilpcb, so, ack);
7146
+     switch( type ) {
7147
+     case ILT_DATA:
7148
+       if( il_proc_data(ilpcb, so, m, seq, spec) ) 
7149
+ 	ilpcb->flags |= ILF_NEEDACK;
7150
+       goto done;
7151
+       break;
7152
+     case ILT_DATAQUERY:
7153
+       il_proc_data(ilpcb, so, m, seq, spec);
7154
+       il_send_empty(ilpcb, ILT_STATE, spec);
7155
+       goto done;
7156
+       break;
7157
+     case ILT_CLOSE:
7158
+       if( ack < ilpcb->next && ack >= ilpcb->start ) {
7159
+ 	if( ilpcb->recvd+1 == seq )
7160
+ 	  ilpcb->recvd = seq;
7161
+ 	il_send_empty(ilpcb, ILT_CLOSE, 0);
7162
+ 	ilpcb->state = ILS_CLOSING;
7163
+       }
7164
+       break;
7165
+     case ILT_STATE:
7166
+       if( ack < ilpcb->rxt_max ) {
7167
+ 	ilpcb->rxt_max = ilpcb->next;
7168
+ 	il_output(ilpcb, 0, ILT_DATAQUERY, ilpcb->unacked, 1);
7169
+       }
7170
+       break;
7171
+     case ILT_SYNC:
7172
+       il_send_empty(ilpcb, ILT_ACK, 0);
7173
+       break;
7174
+     }
7175
+     break;
7176
+ 
7177
+   case	ILS_CLOSED:
7178
+     goto drop;
7179
+     break;
7180
+ 
7181
+   case ILS_CLOSING:
7182
+     if( type == ILT_CLOSE ) {
7183
+       if( ilpcb->recvd+1 == seq )
7184
+ 	ilpcb->recvd = seq;
7185
+       il_send_empty(ilpcb, ILT_CLOSE, 0);
7186
+       ilpcb->state = ILS_CLOSED;
7187
+       il_close(ilpcb);
7188
+     }
7189
+     break;
7190
+   }
7191
+ 
7192
+   m_freem(m);
7193
+  done:
7194
+   return;
7195
+ 
7196
+  dropwithrest:
7197
+   il_respond(ilpcb, ip, il, ILT_CLOSE, 0);
7198
+  drop:
7199
+   m_freem(m);
7200
+ }
7201
+ 
7202
+ static void il_sendseqinit(struct ilpcb * ilpcb)
7203
+ {
7204
+   ilpcb->start = ilpcb->next = random();
7205
+   ilpcb->unacked = ilpcb->next;
7206
+   ilpcb->state = ILS_SYNCER;
7207
+   ilpcb->next++;
7208
+ }
7209
+ 
7210
+ static void il_rxt_timeout(struct ilpcb * ilpcb)
7211
+ {
7212
+   switch ( ilpcb->state ) {
7213
+   case ILS_ESTABLISHED:
7214
+     il_output(ilpcb, 0, ILT_DATAQUERY, ilpcb->unacked, 1);
7215
+     ilpcb->rxtot++;
7216
+     break;
7217
+   case ILS_SYNCER:
7218
+   case ILS_SYNCEE:
7219
+     il_send_empty(ilpcb, ILT_SYNC, 0);
7220
+     break;
7221
+   case ILS_CLOSING:
7222
+     il_send_empty(ilpcb, ILT_CLOSE, 0);
7223
+     break;
7224
+   }
7225
+   ilpcb->rxt_timer = ilpcb->rxt_timer_cur;
7226
+ }
7227
+ 
7228
+ void il_ctlinput(int cmd, struct sockaddr *sa, void *vip)
7229
+ {}
7230
+ 
7231
+ int  il_ctloutput(struct socket *so, struct sockopt *sopt)
7232
+ { return 0; }
7233
+ 
7234
+ void il_drain()
7235
+ {}
7236
+ 
7237
+ void il_slowtimo()
7238
+ {
7239
+   struct ilpcb * ilpcb;
7240
+   struct inpcb * inp;
7241
+   int s;
7242
+ 
7243
+   s = splnet();
7244
+   for(inp = ilb.lh_first; inp; inp = inp->inp_list.le_next) {
7245
+     ilpcb = intoilpcb(inp);
7246
+     if(ilpcb->death_timer &&  --ilpcb->death_timer == 0 )
7247
+       il_drop(ilpcb, ETIMEDOUT);
7248
+     
7249
+     if(ilpcb->rxt_timer &&  --ilpcb->rxt_timer == 0 ) {
7250
+       ilpcb->rxt_timer_cur <<= 1;
7251
+       il_rxt_timeout(ilpcb);
7252
+     }
7253
+   }
7254
+   splx(s);
7255
+ }
7256
+ 
7257
+ void il_fasttimo()
7258
+ {
7259
+   struct ilpcb * ilpcb;
7260
+   struct inpcb * inp;
7261
+   int s;
7262
+ 
7263
+   s = splnet();
7264
+   for(inp = ilb.lh_first; inp; inp = inp->inp_list.le_next) {
7265
+     ilpcb = intoilpcb(inp);
7266
+     if(ilpcb->flags & ILF_NEEDACK) {
7267
+       ilpcb->flags &= ~ILF_NEEDACK;
7268
+       il_send_empty(ilpcb, ILT_ACK, 0);
7269
+     }
7270
+   }
7271
+   splx(s);
7272
+ }
7273
+ 
7274
+ static struct ilpcb * il_newilpcb(struct inpcb * inp)
7275
+ {
7276
+   struct inp_ilpcb *it;
7277
+   register struct ilpcb *ilpcb;
7278
+   
7279
+   it = (struct inp_ilpcb *)inp;
7280
+   ilpcb = &it->ilpcb;
7281
+   bzero((char *) ilpcb, sizeof(struct ilpcb));
7282
+   
7283
+   ilpcb->state = ILS_CLOSED;
7284
+   ilpcb->inpcb = inp;
7285
+   ilpcb->rxt_timer_cur = 2;
7286
+   ilpcb->death_timer_cur = 20;
7287
+   
7288
+   ilpcb->inpcb = inp;	/* XXX */
7289
+   inp->inp_ip_ttl = ip_defttl;
7290
+   inp->inp_ppcb = (caddr_t)ilpcb;
7291
+   return (ilpcb);		/* XXX */
7292
+ }
7293
+ 
7294
+ /*
7295
+  * Common subroutine to open a TCP connection to remote host specified
7296
+  * by struct sockaddr_in in mbuf *nam.  Call in_pcbbind to assign a local
7297
+  * port number if needed.  Call in_pcbladdr to do the routing and to choose
7298
+  * a local host address (interface).  If there is an existing incarnation
7299
+  * of the same connection in TIME-WAIT state and if the remote host was
7300
+  * sending CC options and if the connection duration was < MSL, then
7301
+  * truncate the previous TIME-WAIT state and proceed.
7302
+  * Initialize connection parameters and enter SYN-SENT state.
7303
+  */
7304
+ static int
7305
+ il_connect(struct ilpcb *ilpcb, struct sockaddr *nam, struct proc *p)
7306
+ {
7307
+ 	struct inpcb *inp = ilpcb->inpcb, *oinp;
7308
+ 	struct socket *so = inp->inp_socket;
7309
+ 	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
7310
+ 	struct sockaddr_in *ifaddr;
7311
+ 	int error;
7312
+ 
7313
+ 	if (inp->inp_lport == 0) {
7314
+ 		error = in_pcbbind(inp, (struct sockaddr *)0, p);
7315
+ 		if (error)
7316
+ 			return error;
7317
+ 	}
7318
+ 
7319
+ 	/*
7320
+ 	 * Cannot simply call in_pcbconnect, because there might be an
7321
+ 	 * earlier incarnation of this same connection still in
7322
+ 	 * TIME_WAIT state, creating an ADDRINUSE error.
7323
+ 	 */
7324
+ 	error = in_pcbladdr(inp, nam, &ifaddr);
7325
+ 	if (error)
7326
+ 		return error;
7327
+ 	oinp = in_pcblookup_hash(inp->inp_pcbinfo,
7328
+ 	    sin->sin_addr, sin->sin_port,
7329
+ 	    inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
7330
+ 						: ifaddr->sin_addr,
7331
+ 	    inp->inp_lport,  0);
7332
+ 	if (oinp) {
7333
+ 			return EADDRINUSE;
7334
+ 	}
7335
+ 	if (inp->inp_laddr.s_addr == INADDR_ANY)
7336
+ 		inp->inp_laddr = ifaddr->sin_addr;
7337
+ 	inp->inp_faddr = sin->sin_addr;
7338
+ 	inp->inp_fport = sin->sin_port;
7339
+ 	in_pcbrehash(inp);
7340
+ 
7341
+ #if 0
7342
+ 	ilpcb->t_template = tcp_template(tp);
7343
+ 	if (ilpcb->t_template == 0) {
7344
+ 		in_pcbdisconnect(inp);
7345
+ 		return ENOBUFS;
7346
+ 	}
7347
+ #endif
7348
+ 
7349
+ 	soisconnecting(so);
7350
+ 	il_sendseqinit(ilpcb);
7351
+ 
7352
+ 	return 0;
7353
+ }
7354
+ 
7355
+ static int il_usr_send(struct socket *so, int flags, struct mbuf * m, struct sockaddr *addr, struct mbuf *control, struct proc *p)
7356
+ {
7357
+   struct ilpcb * ilpcb;
7358
+   struct inpcb * inp = sotoinpcb(so);
7359
+   int error;
7360
+   struct mbuf * m0;
7361
+ 
7362
+   if (inp == 0) {
7363
+     m_freem(m);
7364
+     return EINVAL;
7365
+   }
7366
+   ilpcb = intoilpcb(inp);
7367
+ 
7368
+   if (sbspace(&so->so_snd) < -512) {
7369
+     m_freem(m);
7370
+     error = ENOBUFS;
7371
+     goto out;
7372
+   }
7373
+ 
7374
+   sbappendrecord(&so->so_snd, m);
7375
+   m0 = m_copypacket(m, M_DONTWAIT);
7376
+   error = il_output(ilpcb, m0, ILT_DATA, ilpcb->next++, 0); 
7377
+ 
7378
+  out:
7379
+   return error;
7380
+ }
7381
+ 
7382
+ static int il_usr_attach(struct socket *so, int proto, struct proc *p)
7383
+ {
7384
+   int s = splnet();
7385
+   int error = 0;
7386
+   struct inpcb *inp = sotoinpcb(so);
7387
+   struct ilpcb *ilpcb = 0;
7388
+ 
7389
+   if (inp) {
7390
+     error = EISCONN;
7391
+     goto out;
7392
+   }
7393
+   
7394
+   if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
7395
+     error = soreserve(so, il_sendspace, il_recvspace);
7396
+     if (error)
7397
+       goto out;
7398
+   }
7399
+ 
7400
+   error = in_pcballoc(so, &ilbinfo, p);
7401
+ 
7402
+   if (error)
7403
+     goto out;
7404
+ 
7405
+   inp = sotoinpcb(so);
7406
+   ilpcb = il_newilpcb(inp);
7407
+   if (ilpcb == 0) {
7408
+     int nofd = so->so_state & SS_NOFDREF;	/* XXX */
7409
+     
7410
+     so->so_state &= ~SS_NOFDREF;	/* don't free the socket yet */
7411
+     in_pcbdetach(inp);
7412
+     so->so_state |= nofd;
7413
+     error = ENOBUFS;
7414
+     goto out;
7415
+   }
7416
+   ilpcb->state = ILS_CLOSED;
7417
+   ilpcb->segq = 0;
7418
+   
7419
+  out:
7420
+   splx(s);
7421
+   return error;
7422
+ 
7423
+ }
7424
+ 
7425
+ static int il_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
7426
+ {
7427
+   int s = splnet();
7428
+   int error = 0;
7429
+   struct inpcb *inp = sotoinpcb(so);
7430
+   struct ilpcb *ilpcb;
7431
+   struct sockaddr_in *sinp;
7432
+ 
7433
+   if (inp == 0) {
7434
+     splx(s);
7435
+     return EINVAL;
7436
+   }
7437
+   ilpcb = intoilpcb(inp);
7438
+ 
7439
+ 	/*
7440
+ 	 * Must check for multicast addresses and disallow binding
7441
+ 	 * to them.
7442
+ 	 */
7443
+   sinp = (struct sockaddr_in *)nam;
7444
+   if (sinp->sin_family == AF_INET &&
7445
+       IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
7446
+     error = EAFNOSUPPORT;
7447
+     goto out;
7448
+   }
7449
+   error = in_pcbbind(inp, nam, p);
7450
+  out: splx(s); 
7451
+   return error; 
7452
+ }
7453
+ 
7454
+ /*
7455
+  * Initiate connection to peer.
7456
+  * Create a template for use in transmissions on this connection.
7457
+  * Enter SYN_SENT state, and mark socket as connecting.
7458
+  * Start keep-alive timer, and seed output sequence space.
7459
+  * Send initial segment on connection.
7460
+  */
7461
+ static int
7462
+ il_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
7463
+ {
7464
+   int s = splnet();
7465
+   int error = 0;
7466
+   struct inpcb *inp = sotoinpcb(so);
7467
+   struct ilpcb *ilpcb;
7468
+   struct sockaddr_in *sinp;
7469
+   
7470
+   if (inp == 0) {
7471
+     splx(s);
7472
+     return EINVAL;
7473
+   }
7474
+   ilpcb = intoilpcb(inp);
7475
+     
7476
+   /*
7477
+    * Must disallow TCP ``connections'' to multicast addresses.
7478
+    */
7479
+   sinp = (struct sockaddr_in *)nam;
7480
+   if (sinp->sin_family == AF_INET
7481
+       && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
7482
+     error = EAFNOSUPPORT;
7483
+     goto out;
7484
+   }
7485
+   
7486
+   if ((error = il_connect(ilpcb, nam, p)) != 0)
7487
+     goto out;
7488
+ 
7489
+   error = il_send_empty(ilpcb, ILT_SYNC, 0);
7490
+ 
7491
+  out: splx(s); 
7492
+   return error; 
7493
+ }
7494
+ 
7495
+ /*
7496
+  * Close a TCP control block:
7497
+  *	discard all space held by the tcp
7498
+  *	discard internet protocol block
7499
+  *	wake up any sleepers
7500
+  */
7501
+ static struct ilpcb *
7502
+ il_close(struct ilpcb *ilpcb)
7503
+ {
7504
+ 	register struct mbuf *q;
7505
+ 	register struct mbuf *nq;
7506
+ 	struct inpcb *inp = ilpcb->inpcb;
7507
+ 	struct socket *so = inp->inp_socket;
7508
+ 
7509
+ 	/* free the reassembly queue, if any */
7510
+ 	for (q = ilpcb->segq; q; q = nq) {
7511
+ 		nq = q->m_nextpkt;
7512
+ 		ilpcb->segq = nq;
7513
+ 		m_freem(q);
7514
+ 	}
7515
+ 	inp->inp_ppcb = NULL;
7516
+ 	soisdisconnected(so);
7517
+ 	in_pcbdetach(inp);
7518
+ 	return ((struct ilpcb *)0);
7519
+ }
7520
+ 
7521
+ /*
7522
+  * User issued close, and wish to trail through shutdown states:
7523
+  * if never received SYN, just forget it.  If got a SYN from peer,
7524
+  * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
7525
+  * If already got a FIN from peer, then almost done; go to LAST_ACK
7526
+  * state.  In all other cases, have already sent FIN to peer (e.g.
7527
+  * after PRU_SHUTDOWN), and just have to play tedious game waiting
7528
+  * for peer to send FIN or not respond to keep-alives, etc.
7529
+  * We can let the user exit from the close as soon as the FIN is acked.
7530
+  */
7531
+ static struct ilpcb *
7532
+ il_usrclosed(struct ilpcb *ilpcb)
7533
+ {
7534
+ 
7535
+ 	switch (ilpcb->state) {
7536
+ 	case ILS_CLOSED:
7537
+ 	case ILS_LISTENING:
7538
+ 		ilpcb->state = ILS_CLOSED;
7539
+ 		ilpcb = il_close(ilpcb);
7540
+ 		break;
7541
+ 
7542
+ 	case ILS_SYNCER:
7543
+ 	case ILS_SYNCEE:
7544
+ 	case ILS_ESTABLISHED:
7545
+ 	  il_send_empty(ilpcb, ILT_CLOSE, 0);
7546
+ 	  ilpcb->state = ILS_CLOSING;
7547
+ 	  break;
7548
+ 
7549
+ 	case ILS_CLOSING:
7550
+ 		break;
7551
+ 	}
7552
+ 	return (ilpcb);
7553
+ }
7554
+ 
7555
+ /*
7556
+  * Drop a TCP connection, reporting
7557
+  * the specified error.  If connection is synchronized,
7558
+  * then send a RST to peer.
7559
+  */
7560
+ struct ilpcb *
7561
+ il_drop(ilpcb, errno0)
7562
+      register struct ilpcb *ilpcb;
7563
+      int errno0;
7564
+ {
7565
+   struct socket *so = ilpcb->inpcb->inp_socket;
7566
+ 
7567
+   panic("il_drop");
7568
+   
7569
+   switch(ilpcb->state) {
7570
+   case ILS_SYNCEE:
7571
+   case ILS_ESTABLISHED:
7572
+   case ILS_CLOSING:
7573
+     il_send_empty(ilpcb, ILT_CLOSE, 0);
7574
+   default:
7575
+     break;
7576
+   }
7577
+   ilpcb->state = ILS_CLOSED;
7578
+   so->so_error = errno0;
7579
+   return (il_close(ilpcb));
7580
+ }
7581
+ 
7582
+ /*
7583
+  * Initiate (or continue) disconnect.
7584
+  * If embryonic state, just send reset (once).
7585
+  * If in ``let data drain'' option and linger null, just drop.
7586
+  * Otherwise (hard), mark socket disconnecting and drop
7587
+  * current input data; switch states based on user close, and
7588
+  * send segment to peer (with FIN).
7589
+  */
7590
+ static struct ilpcb *
7591
+ il_disconnect(struct ilpcb *ilpcb)
7592
+ {
7593
+   struct socket *so = ilpcb->inpcb->inp_socket;
7594
+   
7595
+   soisdisconnecting(so);
7596
+   sbflush(&so->so_rcv);
7597
+   ilpcb = il_usrclosed(ilpcb);
7598
+   
7599
+   return (ilpcb);
7600
+ }
7601
+ 
7602
+ 
7603
+ /*
7604
+  * pru_detach() detaches the IL protocol from the socket.
7605
+  * If the protocol state is non-embryonic, then can't
7606
+  * do this directly: have to initiate a pru_disconnect(),
7607
+  * which may finish later; embryonic TCB's can just
7608
+  * be discarded here.
7609
+  */
7610
+ static int
7611
+ il_usr_detach(struct socket *so)
7612
+ {
7613
+ 	int s = splnet();
7614
+ 	int error = 0;
7615
+ 	struct inpcb *inp = sotoinpcb(so);
7616
+ 	struct ilpcb *ilpcb;
7617
+ 
7618
+ 	if (inp == 0) {
7619
+ 		splx(s);
7620
+ 		return EINVAL;	/* XXX */
7621
+ 	}
7622
+ 	ilpcb = intoilpcb(inp);
7623
+ 	ilpcb = il_disconnect(ilpcb);
7624
+ 	splx(s);
7625
+ 	return error;
7626
+ }
7627
+ 
7628
+ /*
7629
+  * Mark the connection as being incapable of further output.
7630
+  */
7631
+ static int
7632
+ il_usr_shutdown(struct socket *so)
7633
+ {
7634
+ 	int s = splnet();
7635
+ 	int error = 0;
7636
+ 	struct inpcb *inp = sotoinpcb(so);
7637
+ 	struct ilpcb *ilpcb;
7638
+ 
7639
+   if (inp == 0) {
7640
+     splx(s);
7641
+     return EINVAL;
7642
+   }
7643
+   ilpcb = intoilpcb(inp);
7644
+   
7645
+   socantsendmore(so);
7646
+   ilpcb = il_usrclosed(ilpcb);
7647
+   splx(s); 
7648
+   return error;
7649
+ }
7650
+ 
7651
+ /*
7652
+  * Initiate disconnect from peer.
7653
+  * If connection never passed embryonic stage, just drop;
7654
+  * else if don't need to let data drain, then can just drop anyways,
7655
+  * else have to begin TCP shutdown process: mark socket disconnecting,
7656
+  * drain unread data, state switch to reflect user close, and
7657
+  * send segment (e.g. FIN) to peer.  Socket will be really disconnected
7658
+  * when peer sends FIN and acks ours.
7659
+  *
7660
+  * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
7661
+  */
7662
+ static int
7663
+ il_usr_disconnect(struct socket *so)
7664
+ {
7665
+   int s = splnet();
7666
+   int error = 0;
7667
+   struct inpcb *inp = sotoinpcb(so);
7668
+   struct ilpcb * ilpcb;
7669
+ 
7670
+   if (inp == 0) {
7671
+     splx(s);
7672
+     return EINVAL;
7673
+   }
7674
+   ilpcb = intoilpcb(inp);
7675
+     
7676
+   il_disconnect(ilpcb);
7677
+   splx(s); 
7678
+   return error;
7679
+ }
7680
+ 
7681
+ /*
7682
+  * Abort the TCP.
7683
+  */
7684
+ static int
7685
+ il_usr_abort(struct socket *so)
7686
+ {
7687
+ 	int s = splnet();
7688
+ 	int error = 0;
7689
+ 	struct inpcb *inp = sotoinpcb(so);
7690
+ 	struct ilpcb * ilpcb;
7691
+ 
7692
+   if (inp == 0) {
7693
+     splx(s);
7694
+     return EINVAL;
7695
+   }
7696
+   ilpcb = intoilpcb(inp);
7697
+     
7698
+   ilpcb = il_drop(ilpcb, ECONNABORTED);
7699
+   splx(s); 
7700
+   return error;
7701
+ 
7702
+ }
7703
+ 
7704
+ /*
7705
+  * Prepare to accept connections.
7706
+  */
7707
+ static int
7708
+ il_usr_listen(struct socket *so, struct proc *p)
7709
+ {
7710
+   int s = splnet();
7711
+   int error = 0;
7712
+   struct inpcb *inp = sotoinpcb(so);
7713
+   struct ilpcb *ilpcb;
7714
+   
7715
+   if (inp == 0) {
7716
+     splx(s);
7717
+     return EINVAL;
7718
+   }
7719
+   ilpcb = intoilpcb(inp);
7720
+   
7721
+   if (inp->inp_lport == 0)
7722
+     error = in_pcbbind(inp, (struct sockaddr *)0, p);
7723
+   if (error == 0)
7724
+     ilpcb->state = ILS_LISTENING;
7725
+ 
7726
+   splx(s); 
7727
+   return error;
7728
+ }
7729
+ 
7730
+ /*
7731
+  * Accept a connection.  Essentially all the work is
7732
+  * done at higher levels; just return the address
7733
+  * of the peer, storing through addr.
7734
+  */
7735
+ static int
7736
+ il_usr_accept(struct socket *so, struct sockaddr **nam)
7737
+ {
7738
+   int s = splnet();
7739
+   int error = 0;
7740
+   struct inpcb *inp = sotoinpcb(so);
7741
+   struct ilpcb * ilpcb;
7742
+   
7743
+   if (inp == 0) {
7744
+     splx(s);
7745
+     return EINVAL;
7746
+   }
7747
+   ilpcb = intoilpcb(inp);
7748
+   
7749
+   in_setpeeraddr(so, nam);
7750
+   splx(s); 
7751
+   return error;
7752
+ }
7753
+ 
7754
+ /* xxx - should be const */
7755
+ struct pr_usrreqs il_usrreqs = {
7756
+ 	il_usr_abort, il_usr_accept, il_usr_attach, il_usr_bind,
7757
+ 	il_usr_connect, pru_connect2_notsupp, in_control, il_usr_detach,
7758
+ 	il_usr_disconnect, il_usr_listen, in_setpeeraddr, pru_rcvd_notsupp,
7759
+ 	pru_rcvoob_notsupp, il_usr_send, pru_sense_null, il_usr_shutdown,
7760
+ 	in_setsockaddr, sosend, soreceive, sopoll
7761
+ };
7762
diff -N -c -r /usr/src/sys/netinet/il.h ./netinet/il.h
7763
*** /usr/src/sys/netinet/il.h	Wed Dec 31 19:00:00 1969
7764
--- ./netinet/il.h	Thu Sep 30 11:24:51 1999
7765
***************
7766
*** 0 ****
7767
--- 1,17 ----
7768
+ 
7769
+ #ifndef NETINET_IL_H_
7770
+ #define NETINET_IL_H_
7771
+ 
7772
+ struct ilhdr
7773
+ {
7774
+ 	u_char	ilsum[2];	/* Checksum including header */
7775
+ 	u_char	illen[2];	/* Packet length */
7776
+ 	u_char	iltype;		/* Packet type */
7777
+ 	u_char	ilspec;		/* Special */
7778
+ 	u_char	ilsrc[2];	/* Src port */
7779
+ 	u_char	ildst[2];	/* Dst port */
7780
+ 	u_char	ilid[4];	/* Sequence id */
7781
+ 	u_char	ilack[4];	/* Acked sequence */
7782
+ };
7783
+ 
7784
+ #endif
7785
diff -N -c -r /usr/src/sys/netinet/il_var.h ./netinet/il_var.h
7786
*** /usr/src/sys/netinet/il_var.h	Wed Dec 31 19:00:00 1969
7787
--- ./netinet/il_var.h	Thu Oct  7 10:45:05 1999
7788
***************
7789
*** 0 ****
7790
--- 1,46 ----
7791
+ #ifndef NETINET_IL_VAR_H_
7792
+ #define NETINET_IL_VAR_H_
7793
+ 
7794
+ struct ilpcb			/* Control block */
7795
+ {
7796
+   int	state;		/* Connection state */
7797
+   struct inpcb * inpcb;  /* back pointer to internet pcb */
7798
+   u_long unacked;
7799
+ 
7800
+ #define ILF_NEEDACK 1
7801
+   u_long flags;
7802
+ 
7803
+   u_long rxt_max;
7804
+   int rxt_timer;  /* number of ticks to the next timeout */
7805
+   int rxt_timer_cur;  /* current rxt timer period */
7806
+ 
7807
+   int death_timer;
7808
+   int death_timer_cur;
7809
+   
7810
+   u_long	next;		/* Id of next to send */
7811
+   u_long	recvd;		/* Last packet received */
7812
+   
7813
+   u_long	start;		/* Local start id */
7814
+   u_long	rstart;		/* Remote start id */
7815
+   int	rxtot;		/* number of retransmits on this connection */
7816
+ 
7817
+   struct mbuf * segq;
7818
+ };
7819
+ 
7820
+ #define	intoilpcb(ip)	((struct ilpcb *)(ip)->inp_ppcb)
7821
+ #define	sotoilpcb(so)	(intoilpcb(sotoinpcb(so)))
7822
+ 
7823
+ #ifdef KERNEL
7824
+ void il_init __P((void));
7825
+ void il_input __P((struct mbuf * m, int iphlen));
7826
+ void il_slowtimo __P((void));
7827
+ void il_fasttimo __P((void));
7828
+ void il_ctlinput __P((int cmd, struct sockaddr *sa, void *vip));
7829
+ int  il_ctloutput __P((struct socket *so, struct sockopt *sopt));
7830
+ void il_drain __P((void));
7831
+ 
7832
+ extern struct pr_usrreqs il_usrreqs;
7833
+ 
7834
+ #endif
7835
+ 
7836
+ #endif
7837
diff -N -c -r /usr/src/sys/netinet/in_proto.c ./netinet/in_proto.c
7838
*** /usr/src/sys/netinet/in_proto.c	Sat Aug 22 23:07:14 1998
7839
--- ./netinet/in_proto.c	Wed Oct  6 17:55:12 1999
7840
***************
7841
*** 36,41 ****
7842
--- 36,42 ----
7843
 
7844
  #include "opt_ipdivert.h"
7845
  #include "opt_ipx.h"
7846
+ #include "opt_inet.h"
7847
 
7848
  #include <sys/param.h>
7849
  #include <sys/kernel.h>
7850
***************
7851
*** 71,76 ****
7852
--- 72,82 ----
7853
  #include <netns/ns_if.h>
7854
  #endif
7855
 
7856
+ #ifdef IL
7857
+ #include <netinet/il.h>
7858
+ #include <netinet/il_var.h>
7859
+ #endif
7860
+ 
7861
  extern	struct domain inetdomain;
7862
  static	struct pr_usrreqs nousrreqs;
7863
 
7864
***************
7865
*** 161,166 ****
7866
--- 167,181 ----
7867
    0,
7868
    0,		0,		0,		0,
7869
    &rip_usrreqs
7870
+ },
7871
+ #endif
7872
+ #ifdef IL
7873
+ { SOCK_SEQPACKET,	&inetdomain,	IPPROTO_IL,
7874
+ 	PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD|PR_ATOMIC,
7875
+   il_input,	0,		il_ctlinput,	il_ctloutput,
7876
+   0,
7877
+   il_init,	il_fasttimo,	il_slowtimo,	il_drain,
7878
+   &il_usrreqs
7879
  },
7880
  #endif
7881
  	/* raw wildcard */
7882
diff -N -c -r /usr/src/sys/sys/vnode.h ./sys/vnode.h
7883
*** /usr/src/sys/sys/vnode.h	Sat Mar 20 04:37:49 1999
7884
--- ./sys/vnode.h	Fri Oct 15 17:44:42 1999
7885
***************
7886
*** 62,68 ****
7887
  enum vtagtype	{
7888
  	VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PC, VT_LFS, VT_LOFS, VT_FDESC,
7889
  	VT_PORTAL, VT_NULL, VT_UMAP, VT_KERNFS, VT_PROCFS, VT_AFS, VT_ISOFS,
7890
! 	VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS, VT_VFS, VT_CODA, VT_NTFS
7891
  };
7892
 
7893
  /*
7894
--- 62,68 ----
7895
  enum vtagtype	{
7896
  	VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PC, VT_LFS, VT_LOFS, VT_FDESC,
7897
  	VT_PORTAL, VT_NULL, VT_UMAP, VT_KERNFS, VT_PROCFS, VT_AFS, VT_ISOFS,
7898
! 	VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS, VT_VFS, VT_CODA, VT_NTFS, VT_U9FS
7899
  };
7900
 
7901
  /*