1diff -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+ 245diff -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 380diff -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+ } 802diff -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 1102diff -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+ 1658diff -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+ } 1796diff -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+ 2305diff -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+ 2551diff -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+ } 3196diff -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+ } 4996diff -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+ } 5976diff -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 6165diff -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_ */ 6314diff -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 6345diff -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 6369diff -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 6609diff -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+ }; 7762diff -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 7785diff -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 7837diff -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 */ 7882diff -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 /* 7902