1*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9auth.c ./9fs/9auth.c 2*14414594SDavid du Colombier*** /usr/src/sys/9fs/9auth.c Wed Dec 31 19:00:00 1969 3*14414594SDavid du Colombier--- ./9fs/9auth.c Mon May 22 17:11:29 2000 4*14414594SDavid du Colombier*************** 5*14414594SDavid du Colombier*** 0 **** 6*14414594SDavid du Colombier--- 1,238 ---- 7*14414594SDavid du Colombier+ #include <sys/param.h> 8*14414594SDavid du Colombier+ #include <sys/systm.h> 9*14414594SDavid du Colombier+ #include <sys/socket.h> 10*14414594SDavid du Colombier+ #include <sys/socketvar.h> 11*14414594SDavid du Colombier+ #include <sys/protosw.h> 12*14414594SDavid du Colombier+ #include <sys/malloc.h> 13*14414594SDavid du Colombier+ #include <sys/mbuf.h> 14*14414594SDavid du Colombier+ #include <sys/uio.h> 15*14414594SDavid du Colombier+ 16*14414594SDavid du Colombier+ #include <9fs/9p.h> 17*14414594SDavid du Colombier+ #include <9fs/9auth.h> 18*14414594SDavid du Colombier+ 19*14414594SDavid du Colombier+ #define N2HCHAR(x) x = *p++ 20*14414594SDavid du Colombier+ #define N2HSHORT(x) x = (p[0] | (p[1]<<8)); p += 2 21*14414594SDavid du Colombier+ #define N2HLONG(x) x = (p[0] | (p[1]<<8) |\ 22*14414594SDavid du Colombier+ (p[2]<<16) | (p[3]<<24)); p += 4 23*14414594SDavid du Colombier+ #define N2HQUAD(x) x = (u_int64_t)(p[0] | (p[1]<<8) |\ 24*14414594SDavid du Colombier+ (p[2]<<16) | (p[3]<<24)) |\ 25*14414594SDavid du Colombier+ ((u_int64_t)(p[4] | (p[5]<<8) |\ 26*14414594SDavid du Colombier+ (p[6]<<16) | (p[7]<<24)) << 32); p += 8 27*14414594SDavid du Colombier+ #define N2HSTRING(x,n) bcopy(p, x, n); p += n 28*14414594SDavid du Colombier+ 29*14414594SDavid du Colombier+ #define H2NCHAR(x) *p++ = x 30*14414594SDavid du Colombier+ #define H2NSHORT(x) p[0]=x; p[1]=x>>8; p += 2 31*14414594SDavid du Colombier+ #define H2NLONG(x) p[0]=x; p[1]=x>>8; p[2]=x>>16; p[3]=x>>24; p += 4 32*14414594SDavid du Colombier+ #define H2NQUAD(x) p[0]=x; p[1]=x>>8;\ 33*14414594SDavid du Colombier+ p[2]=x>>16; p[3]=x>>24;\ 34*14414594SDavid du Colombier+ p[4]=x>>32; p[5]=x>>40;\ 35*14414594SDavid du Colombier+ p[6]=x>>48; p[7]=x>>56;\ 36*14414594SDavid du Colombier+ p += 8 37*14414594SDavid du Colombier+ #define H2NSTRING(x,n) bcopy(x, p, n); p += n 38*14414594SDavid du Colombier+ 39*14414594SDavid du Colombier+ static int u9auth_send __P((struct socket *so, struct mbuf *top, struct proc *p)); 40*14414594SDavid du Colombier+ static int u9auth_recv __P((struct socket *so, struct mbuf **mp, struct proc *p)); 41*14414594SDavid du Colombier+ 42*14414594SDavid du Colombier+ static int u9auth_count = 0; 43*14414594SDavid du Colombier+ 44*14414594SDavid du Colombier+ static int u9auth_tr2m(struct u9auth_ticketreq *f, char *ap) 45*14414594SDavid du Colombier+ { 46*14414594SDavid du Colombier+ int n; 47*14414594SDavid du Colombier+ u_char *p; 48*14414594SDavid du Colombier+ 49*14414594SDavid du Colombier+ p = (u_char*)ap; 50*14414594SDavid du Colombier+ H2NCHAR(f->type); 51*14414594SDavid du Colombier+ H2NSTRING(f->authid, U9FS_NAMELEN); 52*14414594SDavid du Colombier+ H2NSTRING(f->authdom, U9FS_DOMLEN); 53*14414594SDavid du Colombier+ H2NSTRING(f->chal, U9FS_CHALLEN); 54*14414594SDavid du Colombier+ H2NSTRING(f->hostid, U9FS_NAMELEN); 55*14414594SDavid du Colombier+ H2NSTRING(f->uid, U9FS_NAMELEN); 56*14414594SDavid du Colombier+ n = p - (u_char*)ap; 57*14414594SDavid du Colombier+ return n; 58*14414594SDavid du Colombier+ } 59*14414594SDavid du Colombier+ 60*14414594SDavid du Colombier+ static struct mbuf * u9auth_m_tr2m(struct u9auth_ticketreq * tktq) 61*14414594SDavid du Colombier+ { 62*14414594SDavid du Colombier+ register struct mbuf *m; 63*14414594SDavid du Colombier+ char * ap; 64*14414594SDavid du Colombier+ int sz = 141; 65*14414594SDavid du Colombier+ 66*14414594SDavid du Colombier+ MGETHDR(m, M_WAIT, MT_DATA); 67*14414594SDavid du Colombier+ if( sz > MHLEN ) 68*14414594SDavid du Colombier+ MCLGET(m, M_WAIT); 69*14414594SDavid du Colombier+ m->m_len = 0; 70*14414594SDavid du Colombier+ 71*14414594SDavid du Colombier+ if ( M_TRAILINGSPACE(m) < sz ) 72*14414594SDavid du Colombier+ panic("u9auth_m_tr2m"); 73*14414594SDavid du Colombier+ 74*14414594SDavid du Colombier+ ap = mtod(m, char *); 75*14414594SDavid du Colombier+ m->m_len = u9auth_tr2m(tktq, ap); 76*14414594SDavid du Colombier+ m->m_pkthdr.len = m->m_len; 77*14414594SDavid du Colombier+ 78*14414594SDavid du Colombier+ return (m); 79*14414594SDavid du Colombier+ } 80*14414594SDavid du Colombier+ 81*14414594SDavid du Colombier+ static int 82*14414594SDavid du Colombier+ u9auth_send(so, top, p) 83*14414594SDavid du Colombier+ register struct socket *so; 84*14414594SDavid du Colombier+ register struct mbuf *top; 85*14414594SDavid du Colombier+ register struct proc *p; 86*14414594SDavid du Colombier+ 87*14414594SDavid du Colombier+ { 88*14414594SDavid du Colombier+ int error, soflags, flags; 89*14414594SDavid du Colombier+ 90*14414594SDavid du Colombier+ soflags = so->so_proto->pr_flags; 91*14414594SDavid du Colombier+ if (so->so_type == SOCK_SEQPACKET) 92*14414594SDavid du Colombier+ flags = MSG_EOR; 93*14414594SDavid du Colombier+ else 94*14414594SDavid du Colombier+ flags = 0; 95*14414594SDavid du Colombier+ 96*14414594SDavid du Colombier+ error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 0, top, 0, flags, p); 97*14414594SDavid du Colombier+ 98*14414594SDavid du Colombier+ return (error); 99*14414594SDavid du Colombier+ } 100*14414594SDavid du Colombier+ 101*14414594SDavid du Colombier+ static int 102*14414594SDavid du Colombier+ u9auth_recv(so, mp, p) 103*14414594SDavid du Colombier+ register struct socket * so; 104*14414594SDavid du Colombier+ register struct mbuf **mp; 105*14414594SDavid du Colombier+ struct proc *p; 106*14414594SDavid du Colombier+ { 107*14414594SDavid du Colombier+ struct uio auio; 108*14414594SDavid du Colombier+ u_int32_t len; 109*14414594SDavid du Colombier+ int error = 0, sotype, rcvflg; 110*14414594SDavid du Colombier+ 111*14414594SDavid du Colombier+ *mp = 0; 112*14414594SDavid du Colombier+ sotype = so->so_type; 113*14414594SDavid du Colombier+ 114*14414594SDavid du Colombier+ /* 115*14414594SDavid du Colombier+ * For reliable protocols, lock against other senders/receivers 116*14414594SDavid du Colombier+ * in case a reconnect is necessary. 117*14414594SDavid du Colombier+ * For SOCK_STREAM, first get the Record Mark to find out how much 118*14414594SDavid du Colombier+ * more there is to get. 119*14414594SDavid du Colombier+ * We must lock the socket against other receivers 120*14414594SDavid du Colombier+ * until we have an entire rpc request/reply. 121*14414594SDavid du Colombier+ */ 122*14414594SDavid du Colombier+ if (sotype == SOCK_SEQPACKET ) { 123*14414594SDavid du Colombier+ if( (so->so_state & SS_ISCONNECTED) == 0 ) 124*14414594SDavid du Colombier+ return (EACCES); 125*14414594SDavid du Colombier+ auio.uio_resid = len = 1000000; 126*14414594SDavid du Colombier+ auio.uio_procp = p; 127*14414594SDavid du Colombier+ do { 128*14414594SDavid du Colombier+ rcvflg = 0; 129*14414594SDavid du Colombier+ error = so->so_proto->pr_usrreqs->pru_soreceive 130*14414594SDavid du Colombier+ (so, 0, &auio, mp, 131*14414594SDavid du Colombier+ (struct mbuf **)0, &rcvflg); 132*14414594SDavid du Colombier+ } while (error == EWOULDBLOCK); 133*14414594SDavid du Colombier+ len -= auio.uio_resid; 134*14414594SDavid du Colombier+ } 135*14414594SDavid du Colombier+ if (error) { 136*14414594SDavid du Colombier+ m_freem(*mp); 137*14414594SDavid du Colombier+ *mp = 0; 138*14414594SDavid du Colombier+ } 139*14414594SDavid du Colombier+ return (error); 140*14414594SDavid du Colombier+ } 141*14414594SDavid du Colombier+ 142*14414594SDavid du Colombier+ static void 143*14414594SDavid du Colombier+ u9auth_m2t(char *ap, struct u9auth_ticket *f, char *key) 144*14414594SDavid du Colombier+ { 145*14414594SDavid du Colombier+ u_char *p; 146*14414594SDavid du Colombier+ 147*14414594SDavid du Colombier+ if(key) 148*14414594SDavid du Colombier+ decrypt9(key, ap, U9AUTH_TICKETLEN); 149*14414594SDavid du Colombier+ p = (u_char*)ap; 150*14414594SDavid du Colombier+ N2HCHAR(f->num); 151*14414594SDavid du Colombier+ N2HSTRING(f->chal, U9FS_CHALLEN); 152*14414594SDavid du Colombier+ N2HSTRING(f->cuid, U9FS_NAMELEN); 153*14414594SDavid du Colombier+ f->cuid[U9FS_NAMELEN-1] = 0; 154*14414594SDavid du Colombier+ N2HSTRING(f->suid, U9FS_NAMELEN); 155*14414594SDavid du Colombier+ f->suid[U9FS_NAMELEN-1] = 0; 156*14414594SDavid du Colombier+ N2HSTRING(f->key, U9AUTH_DESKEYLEN); 157*14414594SDavid du Colombier+ }; 158*14414594SDavid du Colombier+ 159*14414594SDavid du Colombier+ static int 160*14414594SDavid du Colombier+ u9auth_a2m(struct u9auth_authenticator *f, char *ap, char *key) 161*14414594SDavid du Colombier+ { 162*14414594SDavid du Colombier+ int n; 163*14414594SDavid du Colombier+ u_char *p; 164*14414594SDavid du Colombier+ 165*14414594SDavid du Colombier+ p = (u_char*)ap; 166*14414594SDavid du Colombier+ H2NCHAR(f->num); 167*14414594SDavid du Colombier+ H2NSTRING(f->chal, U9FS_CHALLEN); 168*14414594SDavid du Colombier+ H2NLONG(f->id); 169*14414594SDavid du Colombier+ n = p - (u_char*)ap; 170*14414594SDavid du Colombier+ if(key) 171*14414594SDavid du Colombier+ encrypt9(key, ap, n); 172*14414594SDavid du Colombier+ return n; 173*14414594SDavid du Colombier+ } 174*14414594SDavid du Colombier+ 175*14414594SDavid du Colombier+ void u9auth_genchal (char * chal) 176*14414594SDavid du Colombier+ { 177*14414594SDavid du Colombier+ u_long * lp = (u_long *)chal; 178*14414594SDavid du Colombier+ 179*14414594SDavid du Colombier+ *lp++ = random(); 180*14414594SDavid du Colombier+ *lp = random(); 181*14414594SDavid du Colombier+ } 182*14414594SDavid du Colombier+ 183*14414594SDavid du Colombier+ int u9auth_gettickets (struct socket * so, struct u9fsreq * rep, 184*14414594SDavid du Colombier+ char * user, char * ckey, char * ts, char * authc, 185*14414594SDavid du Colombier+ struct proc *p) 186*14414594SDavid du Colombier+ { 187*14414594SDavid du Colombier+ char * cp; 188*14414594SDavid du Colombier+ struct u9auth_ticketreq tktq; 189*14414594SDavid du Colombier+ struct u9auth_ticket tc; 190*14414594SDavid du Colombier+ struct u9auth_authenticator auth; 191*14414594SDavid du Colombier+ struct mbuf * m; 192*14414594SDavid du Colombier+ int error, len; 193*14414594SDavid du Colombier+ 194*14414594SDavid du Colombier+ bzero(&tktq, sizeof(tktq)); 195*14414594SDavid du Colombier+ tktq.type = AuthTreq; 196*14414594SDavid du Colombier+ bcopy(rep->r_authid, tktq.authid, U9FS_NAMELEN); 197*14414594SDavid du Colombier+ bcopy(rep->r_authdom, tktq.authdom, U9FS_DOMLEN); 198*14414594SDavid du Colombier+ bcopy(rep->r_chal, tktq.chal, U9FS_CHALLEN); 199*14414594SDavid du Colombier+ strncpy(tktq.hostid, user, U9FS_NAMELEN); 200*14414594SDavid du Colombier+ strncpy(tktq.uid, user, U9FS_NAMELEN); 201*14414594SDavid du Colombier+ 202*14414594SDavid du Colombier+ m = u9auth_m_tr2m(&tktq); 203*14414594SDavid du Colombier+ error = u9auth_send(so, m, p); 204*14414594SDavid du Colombier+ if( error ) 205*14414594SDavid du Colombier+ goto bad; 206*14414594SDavid du Colombier+ error = u9auth_recv(so, &m, p); 207*14414594SDavid du Colombier+ if( error ) 208*14414594SDavid du Colombier+ goto bad; 209*14414594SDavid du Colombier+ 210*14414594SDavid du Colombier+ len = U9AUTH_TICKETLEN+1; 211*14414594SDavid du Colombier+ if( m->m_len < len && (m = m_pullup(m, len)) == 0 ) 212*14414594SDavid du Colombier+ goto bad; 213*14414594SDavid du Colombier+ 214*14414594SDavid du Colombier+ cp = mtod(m, char *); 215*14414594SDavid du Colombier+ switch( cp[0] ) { 216*14414594SDavid du Colombier+ case AuthOK: 217*14414594SDavid du Colombier+ u9auth_m2t(&cp[1], & tc, ckey); 218*14414594SDavid du Colombier+ bzero(&auth, sizeof(auth)); 219*14414594SDavid du Colombier+ auth.num = AuthAc; 220*14414594SDavid du Colombier+ bcopy(tc.chal, auth.chal, sizeof(auth.chal)); 221*14414594SDavid du Colombier+ auth.id = u9auth_count++; 222*14414594SDavid du Colombier+ 223*14414594SDavid du Colombier+ m->m_len -= len; 224*14414594SDavid du Colombier+ m->m_data += len; 225*14414594SDavid du Colombier+ 226*14414594SDavid du Colombier+ len = U9AUTH_TICKETLEN; 227*14414594SDavid du Colombier+ if( m->m_len < len && (m = m_pullup(m, len)) == 0 ) 228*14414594SDavid du Colombier+ goto bad; 229*14414594SDavid du Colombier+ cp = mtod(m, char *); 230*14414594SDavid du Colombier+ bcopy(cp, ts, len); 231*14414594SDavid du Colombier+ break; 232*14414594SDavid du Colombier+ case AuthErr: 233*14414594SDavid du Colombier+ case AuthOKvar: 234*14414594SDavid du Colombier+ m_freem(m); 235*14414594SDavid du Colombier+ goto bad; 236*14414594SDavid du Colombier+ break; 237*14414594SDavid du Colombier+ } 238*14414594SDavid du Colombier+ 239*14414594SDavid du Colombier+ u9auth_a2m(&auth, authc, tc.key); 240*14414594SDavid du Colombier+ return 0; 241*14414594SDavid du Colombier+ bad: 242*14414594SDavid du Colombier+ return error; 243*14414594SDavid du Colombier+ } 244*14414594SDavid du Colombier+ 245*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9auth.h ./9fs/9auth.h 246*14414594SDavid du Colombier*** /usr/src/sys/9fs/9auth.h Wed Dec 31 19:00:00 1969 247*14414594SDavid du Colombier--- ./9fs/9auth.h Thu Nov 11 15:00:29 1999 248*14414594SDavid du Colombier*************** 249*14414594SDavid du Colombier*** 0 **** 250*14414594SDavid du Colombier--- 1,129 ---- 251*14414594SDavid du Colombier+ #ifndef P9AUTH_H 252*14414594SDavid du Colombier+ #define P9AUTH_H 253*14414594SDavid du Colombier+ 254*14414594SDavid du Colombier+ #define U9AUTH_DOMLEN 48 /* length of an authentication domain name */ 255*14414594SDavid du Colombier+ #define U9AUTH_DESKEYLEN 7 /* length of a des key for encrypt/decrypt */ 256*14414594SDavid du Colombier+ #define U9AUTH_CHALLEN 8 /* length of a challenge */ 257*14414594SDavid du Colombier+ #define U9AUTH_NETCHLEN 16 /* max network challenge length */ 258*14414594SDavid du Colombier+ #define U9AUTH_CONFIGLEN 14 259*14414594SDavid du Colombier+ #define U9AUTH_SECRETLEN 32 /* max length of a secret */ 260*14414594SDavid du Colombier+ #define U9AUTH_APOPCHLEN 256 261*14414594SDavid du Colombier+ #define U9AUTH_MD5LEN 16 262*14414594SDavid du Colombier+ #define U9AUTH_KEYDBOFF 8 /* length of random data at the start of key file */ 263*14414594SDavid du Colombier+ #define U9AUTH_OKEYDBLEN U9FSNAMELEN+U9AUTH_DESKEYLEN+4+2, /* length of an entry in old key file */ 264*14414594SDavid du Colombier+ #define U9AUTH_KEYDBLEN OKEYDBLENSECRETLEN, /* length of an entry in key file */ 265*14414594SDavid du Colombier+ 266*14414594SDavid du Colombier+ /* encryption numberings (anti-replay) */ 267*14414594SDavid du Colombier+ enum 268*14414594SDavid du Colombier+ { 269*14414594SDavid du Colombier+ AuthTreq=1, /* ticket request */ 270*14414594SDavid du Colombier+ AuthChal=2, /* challenge box request */ 271*14414594SDavid du Colombier+ AuthPass=3, /* change password */ 272*14414594SDavid du Colombier+ AuthOK=4, /* fixed length reply follows */ 273*14414594SDavid du Colombier+ AuthErr=5, /* error follows */ 274*14414594SDavid du Colombier+ AuthMod=6, /* modify user */ 275*14414594SDavid du Colombier+ AuthApop=7, /* apop authentication for pop3 */ 276*14414594SDavid du Colombier+ AuthOKvar=9, /* variable length reply follows */ 277*14414594SDavid du Colombier+ AuthChap=10, /* chap authentication for ppp */ 278*14414594SDavid du Colombier+ AuthMSchap=11, /* MS chap authentication for ppp */ 279*14414594SDavid du Colombier+ 280*14414594SDavid du Colombier+ 281*14414594SDavid du Colombier+ AuthTs=64, /* ticket encrypted with server's key */ 282*14414594SDavid du Colombier+ AuthTc, /* ticket encrypted with client's key */ 283*14414594SDavid du Colombier+ AuthAs, /* server generated authenticator */ 284*14414594SDavid du Colombier+ AuthAc, /* client generated authenticator */ 285*14414594SDavid du Colombier+ AuthTp, /* ticket encrypted with clien's key for password change */ 286*14414594SDavid du Colombier+ }; 287*14414594SDavid du Colombier+ 288*14414594SDavid du Colombier+ struct u9auth_ticketreq 289*14414594SDavid du Colombier+ { 290*14414594SDavid du Colombier+ char type; 291*14414594SDavid du Colombier+ char authid[U9FS_NAMELEN]; /* server's encryption id */ 292*14414594SDavid du Colombier+ char authdom[U9AUTH_DOMLEN]; /* server's authentication domain */ 293*14414594SDavid du Colombier+ char chal[U9AUTH_CHALLEN]; /* challenge from server */ 294*14414594SDavid du Colombier+ char hostid[U9FS_NAMELEN]; /* host's encryption id */ 295*14414594SDavid du Colombier+ char uid[U9FS_NAMELEN]; /* uid of requesting user on host */ 296*14414594SDavid du Colombier+ }; 297*14414594SDavid du Colombier+ #define U9AUTH_TICKREQLEN (3*U9FS_NAMELEN+U9AUTH_CHALLEN+U9AUTH_DOMLEN+1) 298*14414594SDavid du Colombier+ 299*14414594SDavid du Colombier+ struct u9auth_ticket 300*14414594SDavid du Colombier+ { 301*14414594SDavid du Colombier+ char num; /* replay protection */ 302*14414594SDavid du Colombier+ char chal[U9AUTH_CHALLEN]; /* server challenge */ 303*14414594SDavid du Colombier+ char cuid[U9FS_NAMELEN]; /* uid on client */ 304*14414594SDavid du Colombier+ char suid[U9FS_NAMELEN]; /* uid on server */ 305*14414594SDavid du Colombier+ char key[U9AUTH_DESKEYLEN]; /* nonce DES key */ 306*14414594SDavid du Colombier+ }; 307*14414594SDavid du Colombier+ #define U9AUTH_TICKETLEN (U9AUTH_CHALLEN+2*U9FS_NAMELEN+U9AUTH_DESKEYLEN+1) 308*14414594SDavid du Colombier+ 309*14414594SDavid du Colombier+ struct u9auth_authenticator 310*14414594SDavid du Colombier+ { 311*14414594SDavid du Colombier+ char num; /* replay protection */ 312*14414594SDavid du Colombier+ char chal[U9AUTH_CHALLEN]; 313*14414594SDavid du Colombier+ u_long id; /* authenticator id, ++'d with each auth */ 314*14414594SDavid du Colombier+ }; 315*14414594SDavid du Colombier+ #define U9AUTH_AUTHENTLEN (U9AUTH_CHALLEN+4+1) 316*14414594SDavid du Colombier+ 317*14414594SDavid du Colombier+ struct u9auth_passwordreq 318*14414594SDavid du Colombier+ { 319*14414594SDavid du Colombier+ char num; 320*14414594SDavid du Colombier+ char old[U9FS_NAMELEN]; 321*14414594SDavid du Colombier+ char new[U9FS_NAMELEN]; 322*14414594SDavid du Colombier+ char changesecret; 323*14414594SDavid du Colombier+ char secret[U9AUTH_SECRETLEN]; /* new secret */ 324*14414594SDavid du Colombier+ }; 325*14414594SDavid du Colombier+ #define U9AUTH_PASSREQLEN (2*U9FS_NAMELEN+1+1+U9AUTH_SECRETLEN) 326*14414594SDavid du Colombier+ 327*14414594SDavid du Colombier+ struct u9auth_nvrsafe 328*14414594SDavid du Colombier+ { 329*14414594SDavid du Colombier+ char machkey[U9AUTH_DESKEYLEN]; 330*14414594SDavid du Colombier+ u_char machsum; 331*14414594SDavid du Colombier+ char authkey[U9AUTH_DESKEYLEN]; 332*14414594SDavid du Colombier+ u_char authsum; 333*14414594SDavid du Colombier+ char config[U9AUTH_CONFIGLEN]; 334*14414594SDavid du Colombier+ u_char configsum; 335*14414594SDavid du Colombier+ char authid[U9FS_NAMELEN]; 336*14414594SDavid du Colombier+ u_char authidsum; 337*14414594SDavid du Colombier+ char authdom[U9AUTH_DOMLEN]; 338*14414594SDavid du Colombier+ u_char authdomsum; 339*14414594SDavid du Colombier+ }; 340*14414594SDavid du Colombier+ 341*14414594SDavid du Colombier+ struct u9auth_chalstate 342*14414594SDavid du Colombier+ { 343*14414594SDavid du Colombier+ int afd; /* /dev/authenticate */ 344*14414594SDavid du Colombier+ int asfd; /* authdial() */ 345*14414594SDavid du Colombier+ char chal[U9AUTH_NETCHLEN]; /* challenge/response */ 346*14414594SDavid du Colombier+ }; 347*14414594SDavid du Colombier+ 348*14414594SDavid du Colombier+ struct u9auth_apopchalstate 349*14414594SDavid du Colombier+ { 350*14414594SDavid du Colombier+ int afd; /* /dev/authenticate */ 351*14414594SDavid du Colombier+ int asfd; /* authdial() */ 352*14414594SDavid du Colombier+ char chal[U9AUTH_APOPCHLEN]; /* challenge/response */ 353*14414594SDavid du Colombier+ }; 354*14414594SDavid du Colombier+ 355*14414594SDavid du Colombier+ struct u9auth_chapreply 356*14414594SDavid du Colombier+ { 357*14414594SDavid du Colombier+ u_char id; 358*14414594SDavid du Colombier+ char uid[U9FS_NAMELEN]; 359*14414594SDavid du Colombier+ char resp[U9AUTH_MD5LEN]; 360*14414594SDavid du Colombier+ }; 361*14414594SDavid du Colombier+ 362*14414594SDavid du Colombier+ struct u9auth_mSchapreply 363*14414594SDavid du Colombier+ { 364*14414594SDavid du Colombier+ char uid[U9FS_NAMELEN]; 365*14414594SDavid du Colombier+ char LMresp[24]; /* Lan Manager response */ 366*14414594SDavid du Colombier+ char NTresp[24]; /* NT response */ 367*14414594SDavid du Colombier+ }; 368*14414594SDavid du Colombier+ 369*14414594SDavid du Colombier+ #ifdef KERNEL 370*14414594SDavid du Colombier+ void u9auth_genchal __P((char *)); 371*14414594SDavid du Colombier+ int u9auth_gettickets __P((struct socket * so, struct u9fsreq * rep, 372*14414594SDavid du Colombier+ char * user, char * ckey, char * ts, char * authc, 373*14414594SDavid du Colombier+ struct proc * p)); 374*14414594SDavid du Colombier+ int encrypt9 __P((void *key, void * vbuf, int n)); 375*14414594SDavid du Colombier+ int decrypt9 __P((void *key, void * vbuf, int n)); 376*14414594SDavid du Colombier+ 377*14414594SDavid du Colombier+ #endif 378*14414594SDavid du Colombier+ 379*14414594SDavid du Colombier+ #endif 380*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9crypt.c ./9fs/9crypt.c 381*14414594SDavid du Colombier*** /usr/src/sys/9fs/9crypt.c Wed Dec 31 19:00:00 1969 382*14414594SDavid du Colombier--- ./9fs/9crypt.c Thu Nov 11 12:23:02 1999 383*14414594SDavid du Colombier*************** 384*14414594SDavid du Colombier*** 0 **** 385*14414594SDavid du Colombier--- 1,416 ---- 386*14414594SDavid du Colombier+ /* 387*14414594SDavid du Colombier+ * Data Encryption Standard 388*14414594SDavid du Colombier+ * D.P.Mitchell 83/06/08. 389*14414594SDavid du Colombier+ * 390*14414594SDavid du Colombier+ * block_cipher(key, block, decrypting) 391*14414594SDavid du Colombier+ */ 392*14414594SDavid du Colombier+ #include <sys/param.h> 393*14414594SDavid du Colombier+ #include <sys/systm.h> 394*14414594SDavid du Colombier+ #include <sys/socket.h> 395*14414594SDavid du Colombier+ #include <sys/socketvar.h> 396*14414594SDavid du Colombier+ 397*14414594SDavid du Colombier+ typedef unsigned char uchar; 398*14414594SDavid du Colombier+ typedef unsigned long ulong; 399*14414594SDavid du Colombier+ #define NAMELEN 28 /* length of path element, including '\0' */ 400*14414594SDavid du Colombier+ #include <9fs/9p.h> 401*14414594SDavid du Colombier+ #include <9fs/9auth.h> 402*14414594SDavid du Colombier+ 403*14414594SDavid du Colombier+ static long ip_low(char [8]); 404*14414594SDavid du Colombier+ static long ip_high(char [8]); 405*14414594SDavid du Colombier+ static void fp(long, long, char[8]); 406*14414594SDavid du Colombier+ static void key_setup(char[U9AUTH_DESKEYLEN], char[128]); 407*14414594SDavid du Colombier+ static void block_cipher(char[128], char[8], int); 408*14414594SDavid du Colombier+ 409*14414594SDavid du Colombier+ /* 410*14414594SDavid du Colombier+ * destructively encrypt the buffer, which 411*14414594SDavid du Colombier+ * must be at least 8 characters long. 412*14414594SDavid du Colombier+ */ 413*14414594SDavid du Colombier+ int 414*14414594SDavid du Colombier+ encrypt9(void *key, void *vbuf, int n) 415*14414594SDavid du Colombier+ { 416*14414594SDavid du Colombier+ char ekey[128], *buf; 417*14414594SDavid du Colombier+ int i, r; 418*14414594SDavid du Colombier+ 419*14414594SDavid du Colombier+ if(n < 8) 420*14414594SDavid du Colombier+ return 0; 421*14414594SDavid du Colombier+ key_setup(key, ekey); 422*14414594SDavid du Colombier+ buf = vbuf; 423*14414594SDavid du Colombier+ n--; 424*14414594SDavid du Colombier+ r = n % 7; 425*14414594SDavid du Colombier+ n /= 7; 426*14414594SDavid du Colombier+ for(i = 0; i < n; i++){ 427*14414594SDavid du Colombier+ block_cipher(ekey, buf, 0); 428*14414594SDavid du Colombier+ buf += 7; 429*14414594SDavid du Colombier+ } 430*14414594SDavid du Colombier+ if(r) 431*14414594SDavid du Colombier+ block_cipher(ekey, buf - 7 + r, 0); 432*14414594SDavid du Colombier+ return 1; 433*14414594SDavid du Colombier+ } 434*14414594SDavid du Colombier+ 435*14414594SDavid du Colombier+ /* 436*14414594SDavid du Colombier+ * destructively decrypt the buffer, which 437*14414594SDavid du Colombier+ * must be at least 8 characters long. 438*14414594SDavid du Colombier+ */ 439*14414594SDavid du Colombier+ int 440*14414594SDavid du Colombier+ decrypt9(void *key, void *vbuf, int n) 441*14414594SDavid du Colombier+ { 442*14414594SDavid du Colombier+ char ekey[128], *buf; 443*14414594SDavid du Colombier+ int i, r; 444*14414594SDavid du Colombier+ 445*14414594SDavid du Colombier+ if(n < 8) 446*14414594SDavid du Colombier+ return 0; 447*14414594SDavid du Colombier+ key_setup(key, ekey); 448*14414594SDavid du Colombier+ buf = vbuf; 449*14414594SDavid du Colombier+ n--; 450*14414594SDavid du Colombier+ r = n % 7; 451*14414594SDavid du Colombier+ n /= 7; 452*14414594SDavid du Colombier+ buf += n * 7; 453*14414594SDavid du Colombier+ if(r) 454*14414594SDavid du Colombier+ block_cipher(ekey, buf - 7 + r, 1); 455*14414594SDavid du Colombier+ for(i = 0; i < n; i++){ 456*14414594SDavid du Colombier+ buf -= 7; 457*14414594SDavid du Colombier+ block_cipher(ekey, buf, 1); 458*14414594SDavid du Colombier+ } 459*14414594SDavid du Colombier+ return 1; 460*14414594SDavid du Colombier+ } 461*14414594SDavid du Colombier+ 462*14414594SDavid du Colombier+ /* 463*14414594SDavid du Colombier+ * Tables for Combined S and P Boxes 464*14414594SDavid du Colombier+ */ 465*14414594SDavid du Colombier+ 466*14414594SDavid du Colombier+ static long s0p[] = { 467*14414594SDavid du Colombier+ 0x00410100,0x00010000,0x40400000,0x40410100,0x00400000,0x40010100,0x40010000,0x40400000, 468*14414594SDavid du Colombier+ 0x40010100,0x00410100,0x00410000,0x40000100,0x40400100,0x00400000,0x00000000,0x40010000, 469*14414594SDavid du Colombier+ 0x00010000,0x40000000,0x00400100,0x00010100,0x40410100,0x00410000,0x40000100,0x00400100, 470*14414594SDavid du Colombier+ 0x40000000,0x00000100,0x00010100,0x40410000,0x00000100,0x40400100,0x40410000,0x00000000, 471*14414594SDavid du Colombier+ 0x00000000,0x40410100,0x00400100,0x40010000,0x00410100,0x00010000,0x40000100,0x00400100, 472*14414594SDavid du Colombier+ 0x40410000,0x00000100,0x00010100,0x40400000,0x40010100,0x40000000,0x40400000,0x00410000, 473*14414594SDavid du Colombier+ 0x40410100,0x00010100,0x00410000,0x40400100,0x00400000,0x40000100,0x40010000,0x00000000, 474*14414594SDavid du Colombier+ 0x00010000,0x00400000,0x40400100,0x00410100,0x40000000,0x40410000,0x00000100,0x40010100, 475*14414594SDavid du Colombier+ }; 476*14414594SDavid du Colombier+ 477*14414594SDavid du Colombier+ static long s1p[] = { 478*14414594SDavid du Colombier+ 0x08021002,0x00000000,0x00021000,0x08020000,0x08000002,0x00001002,0x08001000,0x00021000, 479*14414594SDavid du Colombier+ 0x00001000,0x08020002,0x00000002,0x08001000,0x00020002,0x08021000,0x08020000,0x00000002, 480*14414594SDavid du Colombier+ 0x00020000,0x08001002,0x08020002,0x00001000,0x00021002,0x08000000,0x00000000,0x00020002, 481*14414594SDavid du Colombier+ 0x08001002,0x00021002,0x08021000,0x08000002,0x08000000,0x00020000,0x00001002,0x08021002, 482*14414594SDavid du Colombier+ 0x00020002,0x08021000,0x08001000,0x00021002,0x08021002,0x00020002,0x08000002,0x00000000, 483*14414594SDavid du Colombier+ 0x08000000,0x00001002,0x00020000,0x08020002,0x00001000,0x08000000,0x00021002,0x08001002, 484*14414594SDavid du Colombier+ 0x08021000,0x00001000,0x00000000,0x08000002,0x00000002,0x08021002,0x00021000,0x08020000, 485*14414594SDavid du Colombier+ 0x08020002,0x00020000,0x00001002,0x08001000,0x08001002,0x00000002,0x08020000,0x00021000, 486*14414594SDavid du Colombier+ }; 487*14414594SDavid du Colombier+ 488*14414594SDavid du Colombier+ static long s2p[] = { 489*14414594SDavid du Colombier+ 0x20800000,0x00808020,0x00000020,0x20800020,0x20008000,0x00800000,0x20800020,0x00008020, 490*14414594SDavid du Colombier+ 0x00800020,0x00008000,0x00808000,0x20000000,0x20808020,0x20000020,0x20000000,0x20808000, 491*14414594SDavid du Colombier+ 0x00000000,0x20008000,0x00808020,0x00000020,0x20000020,0x20808020,0x00008000,0x20800000, 492*14414594SDavid du Colombier+ 0x20808000,0x00800020,0x20008020,0x00808000,0x00008020,0x00000000,0x00800000,0x20008020, 493*14414594SDavid du Colombier+ 0x00808020,0x00000020,0x20000000,0x00008000,0x20000020,0x20008000,0x00808000,0x20800020, 494*14414594SDavid du Colombier+ 0x00000000,0x00808020,0x00008020,0x20808000,0x20008000,0x00800000,0x20808020,0x20000000, 495*14414594SDavid du Colombier+ 0x20008020,0x20800000,0x00800000,0x20808020,0x00008000,0x00800020,0x20800020,0x00008020, 496*14414594SDavid du Colombier+ 0x00800020,0x00000000,0x20808000,0x20000020,0x20800000,0x20008020,0x00000020,0x00808000, 497*14414594SDavid du Colombier+ }; 498*14414594SDavid du Colombier+ 499*14414594SDavid du Colombier+ static long s3p[] = { 500*14414594SDavid du Colombier+ 0x00080201,0x02000200,0x00000001,0x02080201,0x00000000,0x02080000,0x02000201,0x00080001, 501*14414594SDavid du Colombier+ 0x02080200,0x02000001,0x02000000,0x00000201,0x02000001,0x00080201,0x00080000,0x02000000, 502*14414594SDavid du Colombier+ 0x02080001,0x00080200,0x00000200,0x00000001,0x00080200,0x02000201,0x02080000,0x00000200, 503*14414594SDavid du Colombier+ 0x00000201,0x00000000,0x00080001,0x02080200,0x02000200,0x02080001,0x02080201,0x00080000, 504*14414594SDavid du Colombier+ 0x02080001,0x00000201,0x00080000,0x02000001,0x00080200,0x02000200,0x00000001,0x02080000, 505*14414594SDavid du Colombier+ 0x02000201,0x00000000,0x00000200,0x00080001,0x00000000,0x02080001,0x02080200,0x00000200, 506*14414594SDavid du Colombier+ 0x02000000,0x02080201,0x00080201,0x00080000,0x02080201,0x00000001,0x02000200,0x00080201, 507*14414594SDavid du Colombier+ 0x00080001,0x00080200,0x02080000,0x02000201,0x00000201,0x02000000,0x02000001,0x02080200, 508*14414594SDavid du Colombier+ }; 509*14414594SDavid du Colombier+ 510*14414594SDavid du Colombier+ static long s4p[] = { 511*14414594SDavid du Colombier+ 0x01000000,0x00002000,0x00000080,0x01002084,0x01002004,0x01000080,0x00002084,0x01002000, 512*14414594SDavid du Colombier+ 0x00002000,0x00000004,0x01000004,0x00002080,0x01000084,0x01002004,0x01002080,0x00000000, 513*14414594SDavid du Colombier+ 0x00002080,0x01000000,0x00002004,0x00000084,0x01000080,0x00002084,0x00000000,0x01000004, 514*14414594SDavid du Colombier+ 0x00000004,0x01000084,0x01002084,0x00002004,0x01002000,0x00000080,0x00000084,0x01002080, 515*14414594SDavid du Colombier+ 0x01002080,0x01000084,0x00002004,0x01002000,0x00002000,0x00000004,0x01000004,0x01000080, 516*14414594SDavid du Colombier+ 0x01000000,0x00002080,0x01002084,0x00000000,0x00002084,0x01000000,0x00000080,0x00002004, 517*14414594SDavid du Colombier+ 0x01000084,0x00000080,0x00000000,0x01002084,0x01002004,0x01002080,0x00000084,0x00002000, 518*14414594SDavid du Colombier+ 0x00002080,0x01002004,0x01000080,0x00000084,0x00000004,0x00002084,0x01002000,0x01000004, 519*14414594SDavid du Colombier+ }; 520*14414594SDavid du Colombier+ 521*14414594SDavid du Colombier+ static long s5p[] = { 522*14414594SDavid du Colombier+ 0x10000008,0x00040008,0x00000000,0x10040400,0x00040008,0x00000400,0x10000408,0x00040000, 523*14414594SDavid du Colombier+ 0x00000408,0x10040408,0x00040400,0x10000000,0x10000400,0x10000008,0x10040000,0x00040408, 524*14414594SDavid du Colombier+ 0x00040000,0x10000408,0x10040008,0x00000000,0x00000400,0x00000008,0x10040400,0x10040008, 525*14414594SDavid du Colombier+ 0x10040408,0x10040000,0x10000000,0x00000408,0x00000008,0x00040400,0x00040408,0x10000400, 526*14414594SDavid du Colombier+ 0x00000408,0x10000000,0x10000400,0x00040408,0x10040400,0x00040008,0x00000000,0x10000400, 527*14414594SDavid du Colombier+ 0x10000000,0x00000400,0x10040008,0x00040000,0x00040008,0x10040408,0x00040400,0x00000008, 528*14414594SDavid du Colombier+ 0x10040408,0x00040400,0x00040000,0x10000408,0x10000008,0x10040000,0x00040408,0x00000000, 529*14414594SDavid du Colombier+ 0x00000400,0x10000008,0x10000408,0x10040400,0x10040000,0x00000408,0x00000008,0x10040008, 530*14414594SDavid du Colombier+ }; 531*14414594SDavid du Colombier+ 532*14414594SDavid du Colombier+ static long s6p[] = { 533*14414594SDavid du Colombier+ 0x00000800,0x00000040,0x00200040,0x80200000,0x80200840,0x80000800,0x00000840,0x00000000, 534*14414594SDavid du Colombier+ 0x00200000,0x80200040,0x80000040,0x00200800,0x80000000,0x00200840,0x00200800,0x80000040, 535*14414594SDavid du Colombier+ 0x80200040,0x00000800,0x80000800,0x80200840,0x00000000,0x00200040,0x80200000,0x00000840, 536*14414594SDavid du Colombier+ 0x80200800,0x80000840,0x00200840,0x80000000,0x80000840,0x80200800,0x00000040,0x00200000, 537*14414594SDavid du Colombier+ 0x80000840,0x00200800,0x80200800,0x80000040,0x00000800,0x00000040,0x00200000,0x80200800, 538*14414594SDavid du Colombier+ 0x80200040,0x80000840,0x00000840,0x00000000,0x00000040,0x80200000,0x80000000,0x00200040, 539*14414594SDavid du Colombier+ 0x00000000,0x80200040,0x00200040,0x00000840,0x80000040,0x00000800,0x80200840,0x00200000, 540*14414594SDavid du Colombier+ 0x00200840,0x80000000,0x80000800,0x80200840,0x80200000,0x00200840,0x00200800,0x80000800, 541*14414594SDavid du Colombier+ }; 542*14414594SDavid du Colombier+ 543*14414594SDavid du Colombier+ static long s7p[] = { 544*14414594SDavid du Colombier+ 0x04100010,0x04104000,0x00004010,0x00000000,0x04004000,0x00100010,0x04100000,0x04104010, 545*14414594SDavid du Colombier+ 0x00000010,0x04000000,0x00104000,0x00004010,0x00104010,0x04004010,0x04000010,0x04100000, 546*14414594SDavid du Colombier+ 0x00004000,0x00104010,0x00100010,0x04004000,0x04104010,0x04000010,0x00000000,0x00104000, 547*14414594SDavid du Colombier+ 0x04000000,0x00100000,0x04004010,0x04100010,0x00100000,0x00004000,0x04104000,0x00000010, 548*14414594SDavid du Colombier+ 0x00100000,0x00004000,0x04000010,0x04104010,0x00004010,0x04000000,0x00000000,0x00104000, 549*14414594SDavid du Colombier+ 0x04100010,0x04004010,0x04004000,0x00100010,0x04104000,0x00000010,0x00100010,0x04004000, 550*14414594SDavid du Colombier+ 0x04104010,0x00100000,0x04100000,0x04000010,0x00104000,0x00004010,0x04004010,0x04100000, 551*14414594SDavid du Colombier+ 0x00000010,0x04104000,0x00104010,0x00000000,0x04000000,0x04100010,0x00004000,0x00104010, 552*14414594SDavid du Colombier+ }; 553*14414594SDavid du Colombier+ 554*14414594SDavid du Colombier+ /* 555*14414594SDavid du Colombier+ * DES electronic codebook encryption of one block 556*14414594SDavid du Colombier+ */ 557*14414594SDavid du Colombier+ static void 558*14414594SDavid du Colombier+ block_cipher(char expanded_key[128], char text[8], int decrypting) 559*14414594SDavid du Colombier+ { 560*14414594SDavid du Colombier+ char *key; 561*14414594SDavid du Colombier+ long crypto, temp, right, left; 562*14414594SDavid du Colombier+ int i, key_offset; 563*14414594SDavid du Colombier+ 564*14414594SDavid du Colombier+ key = expanded_key; 565*14414594SDavid du Colombier+ left = ip_low(text); 566*14414594SDavid du Colombier+ right = ip_high(text); 567*14414594SDavid du Colombier+ if (decrypting) { 568*14414594SDavid du Colombier+ key_offset = 16; 569*14414594SDavid du Colombier+ key = key + 128 - 8; 570*14414594SDavid du Colombier+ } else 571*14414594SDavid du Colombier+ key_offset = 0; 572*14414594SDavid du Colombier+ for (i = 0; i < 16; i++) { 573*14414594SDavid du Colombier+ temp = (right << 1) | ((right >> 31) & 1); 574*14414594SDavid du Colombier+ crypto = s0p[(temp & 0x3f) ^ *key++]; 575*14414594SDavid du Colombier+ crypto |= s1p[((temp >> 4) & 0x3f) ^ *key++]; 576*14414594SDavid du Colombier+ crypto |= s2p[((temp >> 8) & 0x3f) ^ *key++]; 577*14414594SDavid du Colombier+ crypto |= s3p[((temp >> 12) & 0x3f) ^ *key++]; 578*14414594SDavid du Colombier+ crypto |= s4p[((temp >> 16) & 0x3f) ^ *key++]; 579*14414594SDavid du Colombier+ crypto |= s5p[((temp >> 20) & 0x3f) ^ *key++]; 580*14414594SDavid du Colombier+ crypto |= s6p[((temp >> 24) & 0x3f) ^ *key++]; 581*14414594SDavid du Colombier+ temp = ((right & 1) << 5) | ((right >> 27) & 0x1f); 582*14414594SDavid du Colombier+ crypto |= s7p[temp ^ *key++]; 583*14414594SDavid du Colombier+ temp = left; 584*14414594SDavid du Colombier+ left = right; 585*14414594SDavid du Colombier+ right = temp ^ crypto; 586*14414594SDavid du Colombier+ key -= key_offset; 587*14414594SDavid du Colombier+ } 588*14414594SDavid du Colombier+ /* 589*14414594SDavid du Colombier+ * standard final permutation (IPI) 590*14414594SDavid du Colombier+ * left and right are reversed here 591*14414594SDavid du Colombier+ */ 592*14414594SDavid du Colombier+ fp(right, left, text); 593*14414594SDavid du Colombier+ } 594*14414594SDavid du Colombier+ 595*14414594SDavid du Colombier+ /* 596*14414594SDavid du Colombier+ * Initial Permutation 597*14414594SDavid du Colombier+ */ 598*14414594SDavid du Colombier+ static long iptab[] = { 599*14414594SDavid du Colombier+ 0x00000000, 0x00008000, 0x00000000, 0x00008000, 600*14414594SDavid du Colombier+ 0x00000080, 0x00008080, 0x00000080, 0x00008080 601*14414594SDavid du Colombier+ }; 602*14414594SDavid du Colombier+ 603*14414594SDavid du Colombier+ static long 604*14414594SDavid du Colombier+ ip_low(char block[8]) 605*14414594SDavid du Colombier+ { 606*14414594SDavid du Colombier+ int i; 607*14414594SDavid du Colombier+ long l; 608*14414594SDavid du Colombier+ 609*14414594SDavid du Colombier+ l = 0; 610*14414594SDavid du Colombier+ for(i = 0; i < 8; i++){ 611*14414594SDavid du Colombier+ l |= iptab[(block[i] >> 4) & 7] >> i; 612*14414594SDavid du Colombier+ l |= iptab[block[i] & 7] << (16 - i); 613*14414594SDavid du Colombier+ } 614*14414594SDavid du Colombier+ return l; 615*14414594SDavid du Colombier+ } 616*14414594SDavid du Colombier+ 617*14414594SDavid du Colombier+ static long 618*14414594SDavid du Colombier+ ip_high(char block[8]) 619*14414594SDavid du Colombier+ { 620*14414594SDavid du Colombier+ int i; 621*14414594SDavid du Colombier+ long l; 622*14414594SDavid du Colombier+ 623*14414594SDavid du Colombier+ l = 0; 624*14414594SDavid du Colombier+ for(i = 0; i < 8; i++){ 625*14414594SDavid du Colombier+ l |= iptab[(block[i] >> 5) & 7] >> i; 626*14414594SDavid du Colombier+ l |= iptab[(block[i] >> 1) & 7] << (16 - i); 627*14414594SDavid du Colombier+ } 628*14414594SDavid du Colombier+ return l; 629*14414594SDavid du Colombier+ } 630*14414594SDavid du Colombier+ 631*14414594SDavid du Colombier+ /* 632*14414594SDavid du Colombier+ * Final Permutation 633*14414594SDavid du Colombier+ */ 634*14414594SDavid du Colombier+ static unsigned long fptab[] = { 635*14414594SDavid du Colombier+ 0x00000000,0x80000000,0x00800000,0x80800000,0x00008000,0x80008000,0x00808000,0x80808000, 636*14414594SDavid du Colombier+ 0x00000080,0x80000080,0x00800080,0x80800080,0x00008080,0x80008080,0x00808080,0x80808080, 637*14414594SDavid du Colombier+ }; 638*14414594SDavid du Colombier+ 639*14414594SDavid du Colombier+ static void 640*14414594SDavid du Colombier+ fp(long left, long right, char text[8]) 641*14414594SDavid du Colombier+ { 642*14414594SDavid du Colombier+ unsigned long ta[2], t, v[2]; 643*14414594SDavid du Colombier+ int i, j, sh; 644*14414594SDavid du Colombier+ 645*14414594SDavid du Colombier+ ta[0] = right; 646*14414594SDavid du Colombier+ ta[1] = left; 647*14414594SDavid du Colombier+ v[0] = v[1] = 0; 648*14414594SDavid du Colombier+ for(i = 0; i < 2; i++){ 649*14414594SDavid du Colombier+ t = ta[i]; 650*14414594SDavid du Colombier+ sh = i; 651*14414594SDavid du Colombier+ for(j = 0; j < 4; j++){ 652*14414594SDavid du Colombier+ v[1] |= fptab[t & 0xf] >> sh; 653*14414594SDavid du Colombier+ t >>= 4; 654*14414594SDavid du Colombier+ v[0] |= fptab[t & 0xf] >> sh; 655*14414594SDavid du Colombier+ t >>= 4; 656*14414594SDavid du Colombier+ sh += 2; 657*14414594SDavid du Colombier+ } 658*14414594SDavid du Colombier+ } 659*14414594SDavid du Colombier+ for(i = 0; i < 2; i++) 660*14414594SDavid du Colombier+ for(j = 0; j < 4; j++){ 661*14414594SDavid du Colombier+ *text++ = v[i]; 662*14414594SDavid du Colombier+ v[i] >>= 8; 663*14414594SDavid du Colombier+ } 664*14414594SDavid du Colombier+ } 665*14414594SDavid du Colombier+ 666*14414594SDavid du Colombier+ /* 667*14414594SDavid du Colombier+ * Key set-up 668*14414594SDavid du Colombier+ */ 669*14414594SDavid du Colombier+ static uchar keyexpand[][15][2] = { 670*14414594SDavid du Colombier+ { 3, 2, 9, 8, 18, 8, 27, 32, 33, 2, 42, 16, 48, 8, 65, 16, 671*14414594SDavid du Colombier+ 74, 2, 80, 2, 89, 4, 99, 16, 104, 4, 122, 32, 0, 0, }, 672*14414594SDavid du Colombier+ { 1, 4, 8, 1, 18, 4, 25, 32, 34, 32, 41, 8, 50, 8, 59, 32, 673*14414594SDavid du Colombier+ 64, 16, 75, 4, 90, 1, 97, 16, 106, 2, 112, 2, 123, 1, }, 674*14414594SDavid du Colombier+ { 2, 1, 19, 8, 35, 1, 40, 1, 50, 4, 57, 32, 75, 2, 80, 32, 675*14414594SDavid du Colombier+ 89, 1, 96, 16, 107, 4, 120, 8, 0, 0, 0, 0, 0, 0, }, 676*14414594SDavid du Colombier+ { 4, 32, 20, 2, 31, 4, 37, 32, 47, 1, 54, 1, 63, 2, 68, 1, 677*14414594SDavid du Colombier+ 78, 4, 84, 8, 101, 16, 108, 4, 119, 16, 126, 8, 0, 0, }, 678*14414594SDavid du Colombier+ { 5, 4, 15, 4, 21, 32, 31, 1, 38, 1, 47, 2, 53, 2, 68, 8, 679*14414594SDavid du Colombier+ 85, 16, 92, 4, 103, 16, 108, 32, 118, 32, 124, 2, 0, 0, }, 680*14414594SDavid du Colombier+ { 15, 2, 21, 2, 39, 8, 46, 16, 55, 32, 61, 1, 71, 16, 76, 32, 681*14414594SDavid du Colombier+ 86, 32, 93, 4, 102, 2, 108, 16, 117, 8, 126, 1, 0, 0, }, 682*14414594SDavid du Colombier+ { 14, 16, 23, 32, 29, 1, 38, 8, 52, 2, 63, 4, 70, 2, 76, 16, 683*14414594SDavid du Colombier+ 85, 8, 100, 1, 110, 4, 116, 8, 127, 8, 0, 0, 0, 0, }, 684*14414594SDavid du Colombier+ { 1, 8, 8, 32, 17, 1, 24, 16, 35, 4, 50, 1, 57, 16, 67, 8, 685*14414594SDavid du Colombier+ 83, 1, 88, 1, 98, 4, 105, 32, 114, 32, 123, 2, 0, 0, }, 686*14414594SDavid du Colombier+ { 0, 1, 11, 16, 16, 4, 35, 2, 40, 32, 49, 1, 56, 16, 65, 2, 687*14414594SDavid du Colombier+ 74, 16, 80, 8, 99, 8, 115, 1, 121, 4, 0, 0, 0, 0, }, 688*14414594SDavid du Colombier+ { 9, 16, 18, 2, 24, 2, 33, 4, 43, 16, 48, 4, 66, 32, 73, 8, 689*14414594SDavid du Colombier+ 82, 8, 91, 32, 97, 2, 106, 16, 112, 8, 122, 1, 0, 0, }, 690*14414594SDavid du Colombier+ { 14, 32, 21, 4, 30, 2, 36, 16, 45, 8, 60, 1, 69, 2, 87, 8, 691*14414594SDavid du Colombier+ 94, 16, 103, 32, 109, 1, 118, 8, 124, 32, 0, 0, 0, 0, }, 692*14414594SDavid du Colombier+ { 7, 4, 14, 2, 20, 16, 29, 8, 44, 1, 54, 4, 60, 8, 71, 8, 693*14414594SDavid du Colombier+ 78, 16, 87, 32, 93, 1, 102, 8, 116, 2, 125, 4, 0, 0, }, 694*14414594SDavid du Colombier+ { 7, 2, 12, 1, 22, 4, 28, 8, 45, 16, 52, 4, 63, 16, 70, 8, 695*14414594SDavid du Colombier+ 84, 2, 95, 4, 101, 32, 111, 1, 118, 1, 0, 0, 0, 0, }, 696*14414594SDavid du Colombier+ { 6, 16, 13, 16, 20, 4, 31, 16, 36, 32, 46, 32, 53, 4, 62, 2, 697*14414594SDavid du Colombier+ 69, 32, 79, 1, 86, 1, 95, 2, 101, 2, 119, 8, 0, 0, }, 698*14414594SDavid du Colombier+ { 0, 32, 10, 8, 19, 32, 25, 2, 34, 16, 40, 8, 59, 8, 66, 2, 699*14414594SDavid du Colombier+ 72, 2, 81, 4, 91, 16, 96, 4, 115, 2, 121, 8, 0, 0, }, 700*14414594SDavid du Colombier+ { 3, 16, 10, 4, 17, 32, 26, 32, 33, 8, 42, 8, 51, 32, 57, 2, 701*14414594SDavid du Colombier+ 67, 4, 82, 1, 89, 16, 98, 2, 104, 2, 113, 4, 120, 1, }, 702*14414594SDavid du Colombier+ { 1, 16, 11, 8, 27, 1, 32, 1, 42, 4, 49, 32, 58, 32, 67, 2, 703*14414594SDavid du Colombier+ 72, 32, 81, 1, 88, 16, 99, 4, 114, 1, 0, 0, 0, 0, }, 704*14414594SDavid du Colombier+ { 6, 32, 12, 2, 23, 4, 29, 32, 39, 1, 46, 1, 55, 2, 61, 2, 705*14414594SDavid du Colombier+ 70, 4, 76, 8, 93, 16, 100, 4, 111, 16, 116, 32, 0, 0, }, 706*14414594SDavid du Colombier+ { 6, 2, 13, 32, 23, 1, 30, 1, 39, 2, 45, 2, 63, 8, 77, 16, 707*14414594SDavid du Colombier+ 84, 4, 95, 16, 100, 32, 110, 32, 117, 4, 127, 4, 0, 0, }, 708*14414594SDavid du Colombier+ { 4, 1, 13, 2, 31, 8, 38, 16, 47, 32, 53, 1, 62, 8, 68, 32, 709*14414594SDavid du Colombier+ 78, 32, 85, 4, 94, 2, 100, 16, 109, 8, 127, 2, 0, 0, }, 710*14414594SDavid du Colombier+ { 5, 16, 15, 32, 21, 1, 30, 8, 44, 2, 55, 4, 61, 32, 68, 16, 711*14414594SDavid du Colombier+ 77, 8, 92, 1, 102, 4, 108, 8, 126, 16, 0, 0, 0, 0, }, 712*14414594SDavid du Colombier+ { 2, 8, 9, 1, 16, 16, 27, 4, 42, 1, 49, 16, 58, 2, 75, 1, 713*14414594SDavid du Colombier+ 80, 1, 90, 4, 97, 32, 106, 32, 113, 8, 120, 32, 0, 0, }, 714*14414594SDavid du Colombier+ { 2, 4, 8, 4, 27, 2, 32, 32, 41, 1, 48, 16, 59, 4, 66, 16, 715*14414594SDavid du Colombier+ 72, 8, 91, 8, 107, 1, 112, 1, 123, 16, 0, 0, 0, 0, }, 716*14414594SDavid du Colombier+ { 3, 8, 10, 2, 16, 2, 25, 4, 35, 16, 40, 4, 59, 2, 65, 8, 717*14414594SDavid du Colombier+ 74, 8, 83, 32, 89, 2, 98, 16, 104, 8, 121, 16, 0, 0, }, 718*14414594SDavid du Colombier+ { 4, 2, 13, 4, 22, 2, 28, 16, 37, 8, 52, 1, 62, 4, 79, 8, 719*14414594SDavid du Colombier+ 86, 16, 95, 32, 101, 1, 110, 8, 126, 32, 0, 0, 0, 0, }, 720*14414594SDavid du Colombier+ { 5, 32, 12, 16, 21, 8, 36, 1, 46, 4, 52, 8, 70, 16, 79, 32, 721*14414594SDavid du Colombier+ 85, 1, 94, 8, 108, 2, 119, 4, 126, 2, 0, 0, 0, 0, }, 722*14414594SDavid du Colombier+ { 5, 2, 14, 4, 20, 8, 37, 16, 44, 4, 55, 16, 60, 32, 76, 2, 723*14414594SDavid du Colombier+ 87, 4, 93, 32, 103, 1, 110, 1, 119, 2, 124, 1, 0, 0, }, 724*14414594SDavid du Colombier+ { 7, 32, 12, 4, 23, 16, 28, 32, 38, 32, 45, 4, 54, 2, 60, 16, 725*14414594SDavid du Colombier+ 71, 1, 78, 1, 87, 2, 93, 2, 111, 8, 118, 16, 125, 16, }, 726*14414594SDavid du Colombier+ { 1, 1, 11, 32, 17, 2, 26, 16, 32, 8, 51, 8, 64, 2, 73, 4, 727*14414594SDavid du Colombier+ 83, 16, 88, 4, 107, 2, 112, 32, 122, 8, 0, 0, 0, 0, }, 728*14414594SDavid du Colombier+ { 0, 4, 9, 32, 18, 32, 25, 8, 34, 8, 43, 32, 49, 2, 58, 16, 729*14414594SDavid du Colombier+ 74, 1, 81, 16, 90, 2, 96, 2, 105, 4, 115, 16, 122, 4, }, 730*14414594SDavid du Colombier+ { 2, 2, 19, 1, 24, 1, 34, 4, 41, 32, 50, 32, 57, 8, 64, 32, 731*14414594SDavid du Colombier+ 73, 1, 80, 16, 91, 4, 106, 1, 113, 16, 123, 8, 0, 0, }, 732*14414594SDavid du Colombier+ { 3, 4, 10, 16, 16, 8, 35, 8, 51, 1, 56, 1, 67, 16, 72, 4, 733*14414594SDavid du Colombier+ 91, 2, 96, 32, 105, 1, 112, 16, 121, 2, 0, 0, 0, 0, }, 734*14414594SDavid du Colombier+ { 4, 16, 15, 1, 22, 1, 31, 2, 37, 2, 55, 8, 62, 16, 69, 16, 735*14414594SDavid du Colombier+ 76, 4, 87, 16, 92, 32, 102, 32, 109, 4, 118, 2, 125, 32, }, 736*14414594SDavid du Colombier+ { 6, 4, 23, 8, 30, 16, 39, 32, 45, 1, 54, 8, 70, 32, 77, 4, 737*14414594SDavid du Colombier+ 86, 2, 92, 16, 101, 8, 116, 1, 125, 2, 0, 0, 0, 0, }, 738*14414594SDavid du Colombier+ { 4, 4, 13, 1, 22, 8, 36, 2, 47, 4, 53, 32, 63, 1, 69, 8, 739*14414594SDavid du Colombier+ 84, 1, 94, 4, 100, 8, 117, 16, 127, 32, 0, 0, 0, 0, }, 740*14414594SDavid du Colombier+ { 3, 32, 8, 16, 19, 4, 34, 1, 41, 16, 50, 2, 56, 2, 67, 1, 741*14414594SDavid du Colombier+ 72, 1, 82, 4, 89, 32, 98, 32, 105, 8, 114, 8, 121, 1, }, 742*14414594SDavid du Colombier+ { 1, 32, 19, 2, 24, 32, 33, 1, 40, 16, 51, 4, 64, 8, 83, 8, 743*14414594SDavid du Colombier+ 99, 1, 104, 1, 114, 4, 120, 4, 0, 0, 0, 0, 0, 0, }, 744*14414594SDavid du Colombier+ { 8, 2, 17, 4, 27, 16, 32, 4, 51, 2, 56, 32, 66, 8, 75, 32, 745*14414594SDavid du Colombier+ 81, 2, 90, 16, 96, 8, 115, 8, 122, 2, 0, 0, 0, 0, }, 746*14414594SDavid du Colombier+ { 2, 16, 18, 1, 25, 16, 34, 2, 40, 2, 49, 4, 59, 16, 66, 4, 747*14414594SDavid du Colombier+ 73, 32, 82, 32, 89, 8, 98, 8, 107, 32, 113, 2, 123, 4, }, 748*14414594SDavid du Colombier+ { 7, 1, 13, 8, 28, 1, 38, 4, 44, 8, 61, 16, 71, 32, 77, 1, 749*14414594SDavid du Colombier+ 86, 8, 100, 2, 111, 4, 117, 32, 124, 16, 0, 0, 0, 0, }, 750*14414594SDavid du Colombier+ { 12, 8, 29, 16, 36, 4, 47, 16, 52, 32, 62, 32, 68, 2, 79, 4, 751*14414594SDavid du Colombier+ 85, 32, 95, 1, 102, 1, 111, 2, 117, 2, 126, 4, 0, 0, }, 752*14414594SDavid du Colombier+ { 5, 1, 15, 16, 20, 32, 30, 32, 37, 4, 46, 2, 52, 16, 61, 8, 753*14414594SDavid du Colombier+ 70, 1, 79, 2, 85, 2, 103, 8, 110, 16, 119, 32, 124, 4, }, 754*14414594SDavid du Colombier+ { 0, 16, 9, 2, 18, 16, 24, 8, 43, 8, 59, 1, 65, 4, 75, 16, 755*14414594SDavid du Colombier+ 80, 4, 99, 2, 104, 32, 113, 1, 123, 32, 0, 0, 0, 0, }, 756*14414594SDavid du Colombier+ { 10, 32, 17, 8, 26, 8, 35, 32, 41, 2, 50, 16, 56, 8, 66, 1, 757*14414594SDavid du Colombier+ 73, 16, 82, 2, 88, 2, 97, 4, 107, 16, 112, 4, 121, 32, }, 758*14414594SDavid du Colombier+ { 0, 2, 11, 1, 16, 1, 26, 4, 33, 32, 42, 32, 49, 8, 58, 8, 759*14414594SDavid du Colombier+ 65, 1, 72, 16, 83, 4, 98, 1, 105, 16, 114, 2, 0, 0, }, 760*14414594SDavid du Colombier+ { 8, 8, 27, 8, 43, 1, 48, 1, 58, 4, 64, 4, 83, 2, 88, 32, 761*14414594SDavid du Colombier+ 97, 1, 104, 16, 115, 4, 122, 16, 0, 0, 0, 0, 0, 0, }, 762*14414594SDavid du Colombier+ { 5, 8, 14, 1, 23, 2, 29, 2, 47, 8, 54, 16, 63, 32, 68, 4, 763*14414594SDavid du Colombier+ 79, 16, 84, 32, 94, 32, 101, 4, 110, 2, 116, 16, 127, 1, }, 764*14414594SDavid du Colombier+ { 4, 8, 15, 8, 22, 16, 31, 32, 37, 1, 46, 8, 60, 2, 69, 4, 765*14414594SDavid du Colombier+ 78, 2, 84, 16, 93, 8, 108, 1, 118, 4, 0, 0, 0, 0, }, 766*14414594SDavid du Colombier+ { 7, 16, 14, 8, 28, 2, 39, 4, 45, 32, 55, 1, 62, 1, 76, 1, 767*14414594SDavid du Colombier+ 86, 4, 92, 8, 109, 16, 116, 4, 125, 1, 0, 0, 0, 0, }, 768*14414594SDavid du Colombier+ { 1, 2, 11, 4, 26, 1, 33, 16, 42, 2, 48, 2, 57, 4, 64, 1, 769*14414594SDavid du Colombier+ 74, 4, 81, 32, 90, 32, 97, 8, 106, 8, 115, 32, 120, 16, }, 770*14414594SDavid du Colombier+ { 2, 32, 11, 2, 16, 32, 25, 1, 32, 16, 43, 4, 58, 1, 75, 8, 771*14414594SDavid du Colombier+ 91, 1, 96, 1, 106, 4, 113, 32, 0, 0, 0, 0, 0, 0, }, 772*14414594SDavid du Colombier+ { 3, 1, 9, 4, 19, 16, 24, 4, 43, 2, 48, 32, 57, 1, 67, 32, 773*14414594SDavid du Colombier+ 73, 2, 82, 16, 88, 8, 107, 8, 120, 2, 0, 0, 0, 0, }, 774*14414594SDavid du Colombier+ { 0, 8, 10, 1, 17, 16, 26, 2, 32, 2, 41, 4, 51, 16, 56, 4, 775*14414594SDavid du Colombier+ 65, 32, 74, 32, 81, 8, 90, 8, 99, 32, 105, 2, 114, 16, }, 776*14414594SDavid du Colombier+ { 6, 1, 20, 1, 30, 4, 36, 8, 53, 16, 60, 4, 69, 1, 78, 8, 777*14414594SDavid du Colombier+ 92, 2, 103, 4, 109, 32, 119, 1, 125, 8, 0, 0, 0, 0, }, 778*14414594SDavid du Colombier+ { 7, 8, 21, 16, 28, 4, 39, 16, 44, 32, 54, 32, 61, 4, 71, 4, 779*14414594SDavid du Colombier+ 77, 32, 87, 1, 94, 1, 103, 2, 109, 2, 124, 8, 0, 0, }, 780*14414594SDavid du Colombier+ { 6, 8, 12, 32, 22, 32, 29, 4, 38, 2, 44, 16, 53, 8, 71, 2, 781*14414594SDavid du Colombier+ 77, 2, 95, 8, 102, 16, 111, 32, 117, 1, 127, 16, 0, 0, } 782*14414594SDavid du Colombier+ }; 783*14414594SDavid du Colombier+ 784*14414594SDavid du Colombier+ static void 785*14414594SDavid du Colombier+ key_setup(char key[U9AUTH_DESKEYLEN], char *ek) 786*14414594SDavid du Colombier+ { 787*14414594SDavid du Colombier+ int i, j, k, mask; 788*14414594SDavid du Colombier+ uchar (*x)[2]; 789*14414594SDavid du Colombier+ 790*14414594SDavid du Colombier+ bzero(ek, 128); 791*14414594SDavid du Colombier+ x = keyexpand[0]; 792*14414594SDavid du Colombier+ for(i = 0; i < 7; i++){ 793*14414594SDavid du Colombier+ k = key[i]; 794*14414594SDavid du Colombier+ for(mask = 0x80; mask; mask >>= 1){ 795*14414594SDavid du Colombier+ if(k & mask) 796*14414594SDavid du Colombier+ for(j = 0; j < 15; j++) 797*14414594SDavid du Colombier+ ek[x[j][0]] |= x[j][1]; 798*14414594SDavid du Colombier+ x += 15; 799*14414594SDavid du Colombier+ } 800*14414594SDavid du Colombier+ } 801*14414594SDavid du Colombier+ } 802*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs.h ./9fs/9fs.h 803*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs.h Wed Dec 31 19:00:00 1969 804*14414594SDavid du Colombier--- ./9fs/9fs.h Mon May 22 11:31:29 2000 805*14414594SDavid du Colombier*************** 806*14414594SDavid du Colombier*** 0 **** 807*14414594SDavid du Colombier--- 1,294 ---- 808*14414594SDavid du Colombier+ /* 809*14414594SDavid du Colombier+ * Copyright (c) 1989, 1993, 1995 810*14414594SDavid du Colombier+ * The Regents of the University of California. All rights reserved. 811*14414594SDavid du Colombier+ * 812*14414594SDavid du Colombier+ * This code is derived from software contributed to Berkeley by 813*14414594SDavid du Colombier+ * Rick Macklem at The University of Guelph. 814*14414594SDavid du Colombier+ * 815*14414594SDavid du Colombier+ * Redistribution and use in source and binary forms, with or without 816*14414594SDavid du Colombier+ * modification, are permitted provided that the following conditions 817*14414594SDavid du Colombier+ * are met: 818*14414594SDavid du Colombier+ * 1. Redistributions of source code must retain the above copyright 819*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer. 820*14414594SDavid du Colombier+ * 2. Redistributions in binary form must reproduce the above copyright 821*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer in the 822*14414594SDavid du Colombier+ * documentation and/or other materials provided with the distribution. 823*14414594SDavid du Colombier+ * 3. All advertising materials mentioning features or use of this software 824*14414594SDavid du Colombier+ * must display the following acknowledgement: 825*14414594SDavid du Colombier+ * This product includes software developed by the University of 826*14414594SDavid du Colombier+ * California, Berkeley and its contributors. 827*14414594SDavid du Colombier+ * 4. Neither the name of the University nor the names of its contributors 828*14414594SDavid du Colombier+ * may be used to endorse or promote products derived from this software 829*14414594SDavid du Colombier+ * without specific prior written permission. 830*14414594SDavid du Colombier+ * 831*14414594SDavid du Colombier+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 832*14414594SDavid du Colombier+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 833*14414594SDavid du Colombier+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 834*14414594SDavid du Colombier+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 835*14414594SDavid du Colombier+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 836*14414594SDavid du Colombier+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 837*14414594SDavid du Colombier+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 838*14414594SDavid du Colombier+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 839*14414594SDavid du Colombier+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 840*14414594SDavid du Colombier+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 841*14414594SDavid du Colombier+ * SUCH DAMAGE. 842*14414594SDavid du Colombier+ * 843*14414594SDavid du Colombier+ * @(#)nfs.h 8.4 (Berkeley) 5/1/95 844*14414594SDavid du Colombier+ * $Id: nfs.h,v 1.44 1998/09/07 05:42:15 bde Exp $ 845*14414594SDavid du Colombier+ */ 846*14414594SDavid du Colombier+ 847*14414594SDavid du Colombier+ #ifndef _9FS_H_ 848*14414594SDavid du Colombier+ #define _9FS_H_ 849*14414594SDavid du Colombier+ 850*14414594SDavid du Colombier+ #ifdef KERNEL 851*14414594SDavid du Colombier+ #include "opt_u9fs.h" 852*14414594SDavid du Colombier+ #endif 853*14414594SDavid du Colombier+ 854*14414594SDavid du Colombier+ #define U9FS_FABLKSIZE 512 855*14414594SDavid du Colombier+ #define U9FS_PORT 17008 856*14414594SDavid du Colombier+ 857*14414594SDavid du Colombier+ /* 858*14414594SDavid du Colombier+ * The set of signals the interrupt an I/O in progress for U9FSMNT_INT mounts. 859*14414594SDavid du Colombier+ * What should be in this set is open to debate, but I believe that since 860*14414594SDavid du Colombier+ * I/O system calls on ufs are never interrupted by signals the set should 861*14414594SDavid du Colombier+ * be minimal. My reasoning is that many current programs that use signals 862*14414594SDavid du Colombier+ * such as SIGALRM will not expect file I/O system calls to be interrupted 863*14414594SDavid du Colombier+ * by them and break. 864*14414594SDavid du Colombier+ */ 865*14414594SDavid du Colombier+ #define U9FSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \ 866*14414594SDavid du Colombier+ sigmask(SIGHUP)|sigmask(SIGQUIT)) 867*14414594SDavid du Colombier+ 868*14414594SDavid du Colombier+ /* 869*14414594SDavid du Colombier+ * U9FS mount option flags 870*14414594SDavid du Colombier+ */ 871*14414594SDavid du Colombier+ #define U9FSMNT_SOFT 0x00000001 /* soft mount (hard is default) */ 872*14414594SDavid du Colombier+ #define U9FSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */ 873*14414594SDavid du Colombier+ #define U9FSMNT_INT 0x00000040 /* allow interrupts on hard mount */ 874*14414594SDavid du Colombier+ #define U9FSMNT_KERB 0x00000400 /* Use Kerberos authentication */ 875*14414594SDavid du Colombier+ #define U9FSMNT_READAHEAD 0x00002000 /* set read ahead */ 876*14414594SDavid du Colombier+ 877*14414594SDavid du Colombier+ #define U9FSSTA_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */ 878*14414594SDavid du Colombier+ #define U9FSSTA_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */ 879*14414594SDavid du Colombier+ #define U9FSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */ 880*14414594SDavid du Colombier+ #define U9FSSTA_MNTD 0x00200000 /* Mnt server for mnt point */ 881*14414594SDavid du Colombier+ #define U9FSSTA_DISMINPROG 0x00400000 /* Dismount in progress */ 882*14414594SDavid du Colombier+ #define U9FSSTA_DISMNT 0x00800000 /* Dismounted */ 883*14414594SDavid du Colombier+ #define U9FSSTA_SNDLOCK 0x01000000 /* Send socket lock */ 884*14414594SDavid du Colombier+ #define U9FSSTA_WANTSND 0x02000000 /* Want above */ 885*14414594SDavid du Colombier+ #define U9FSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */ 886*14414594SDavid du Colombier+ #define U9FSSTA_WANTRCV 0x08000000 /* Want above */ 887*14414594SDavid du Colombier+ #define U9FSSTA_WAITAUTH 0x10000000 /* Wait for authentication */ 888*14414594SDavid du Colombier+ #define U9FSSTA_HASAUTH 0x20000000 /* Has authenticator */ 889*14414594SDavid du Colombier+ #define U9FSSTA_WANTAUTH 0x40000000 /* Wants an authenticator */ 890*14414594SDavid du Colombier+ #define U9FSSTA_AUTHERR 0x80000000 /* Authentication error */ 891*14414594SDavid du Colombier+ 892*14414594SDavid du Colombier+ #define U9FSNOHASH(fhsum) (&u9fsnodehashtbl[(fhsum) % u9fsnodehash]) 893*14414594SDavid du Colombier+ 894*14414594SDavid du Colombier+ /* 895*14414594SDavid du Colombier+ * Arguments to mount 9FS 896*14414594SDavid du Colombier+ */ 897*14414594SDavid du Colombier+ #define U9FS_ARGSVERSION 1 /* change when nfs_args changes */ 898*14414594SDavid du Colombier+ struct u9fs_args { 899*14414594SDavid du Colombier+ int version; /* args structure version number */ 900*14414594SDavid du Colombier+ struct sockaddr *addr; /* file server address */ 901*14414594SDavid du Colombier+ int addrlen; /* length of address */ 902*14414594SDavid du Colombier+ int sotype; /* Socket type */ 903*14414594SDavid du Colombier+ int proto; /* and Protocol */ 904*14414594SDavid du Colombier+ int fhsize; /* Size, in bytes, of fh */ 905*14414594SDavid du Colombier+ int flags; /* flags */ 906*14414594SDavid du Colombier+ int wsize; /* write size in bytes */ 907*14414594SDavid du Colombier+ int rsize; /* read size in bytes */ 908*14414594SDavid du Colombier+ int readdirsize; /* readdir size in bytes */ 909*14414594SDavid du Colombier+ char *hostname; /* server's name */ 910*14414594SDavid du Colombier+ 911*14414594SDavid du Colombier+ struct sockaddr * authaddr; 912*14414594SDavid du Colombier+ int authaddrlen; 913*14414594SDavid du Colombier+ int authsotype; 914*14414594SDavid du Colombier+ int authsoproto; 915*14414594SDavid du Colombier+ 916*14414594SDavid du Colombier+ int nusers; 917*14414594SDavid du Colombier+ char user[U9FS_NAMELEN]; 918*14414594SDavid du Colombier+ char key[U9AUTH_DESKEYLEN]; 919*14414594SDavid du Colombier+ struct p9user { 920*14414594SDavid du Colombier+ uid_t p9_uid; 921*14414594SDavid du Colombier+ char p9_name[U9FS_NAMELEN]; 922*14414594SDavid du Colombier+ } * users; 923*14414594SDavid du Colombier+ }; 924*14414594SDavid du Colombier+ 925*14414594SDavid du Colombier+ #define U9FS_USER_HASHSIZE 512 926*14414594SDavid du Colombier+ 927*14414594SDavid du Colombier+ struct u9fsuser { 928*14414594SDavid du Colombier+ LIST_ENTRY(u9fsuser) u_hash; 929*14414594SDavid du Colombier+ uid_t u_uid; 930*14414594SDavid du Colombier+ char u_name[U9FS_NAMELEN]; 931*14414594SDavid du Colombier+ char u_ckey[U9AUTH_DESKEYLEN]; /* user key */ 932*14414594SDavid du Colombier+ char u_skey[U9AUTH_DESKEYLEN]; /* session key */ 933*14414594SDavid du Colombier+ }; 934*14414594SDavid du Colombier+ 935*14414594SDavid du Colombier+ /* 936*14414594SDavid du Colombier+ * The u9fsnode is the u9fs equivalent to ufs's inode. Any similarity 937*14414594SDavid du Colombier+ * is purely coincidental. 938*14414594SDavid du Colombier+ * There is a unique u9fsnode allocated for each active file, 939*14414594SDavid du Colombier+ * each current directory, each mounted-on file, text file, and the root. 940*14414594SDavid du Colombier+ * An u9fsnode is 'named' by its file handle. (nget/u9fs_node.c) 941*14414594SDavid du Colombier+ * If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite 942*14414594SDavid du Colombier+ * type definitions), file handles of > 32 bytes should probably be split out 943*14414594SDavid du Colombier+ * into a separate MALLOC()'d data structure. (Reduce the size of u9fsfh_t by 944*14414594SDavid du Colombier+ * changing the definition in u9fsproto.h of U9FS_SMALLFH.) 945*14414594SDavid du Colombier+ * NB: Hopefully the current order of the fields is such that everything will 946*14414594SDavid du Colombier+ * be well aligned and, therefore, tightly packed. 947*14414594SDavid du Colombier+ */ 948*14414594SDavid du Colombier+ struct u9fsnode { 949*14414594SDavid du Colombier+ LIST_ENTRY(u9fsnode) n_hash; /* Hash chain */ 950*14414594SDavid du Colombier+ u_quad_t n_size; /* Current size of file */ 951*14414594SDavid du Colombier+ struct vattr n_vattr; /* Vnode attribute cache */ 952*14414594SDavid du Colombier+ time_t n_attrstamp; /* Attr. cache timestamp */ 953*14414594SDavid du Colombier+ u_int32_t n_mode; /* ACCESS mode cache */ 954*14414594SDavid du Colombier+ uid_t n_modeuid; /* credentials having mode */ 955*14414594SDavid du Colombier+ time_t n_modestamp; /* mode cache timestamp */ 956*14414594SDavid du Colombier+ time_t n_mtime; /* Prev modify time. */ 957*14414594SDavid du Colombier+ time_t n_ctime; /* Prev create time. */ 958*14414594SDavid du Colombier+ struct u9fs_qid n_qid; 959*14414594SDavid du Colombier+ u_short n_fid; /* U9FS FID */ 960*14414594SDavid du Colombier+ u_short n_rdfid; 961*14414594SDavid du Colombier+ u_short n_wrfid; 962*14414594SDavid du Colombier+ struct vnode *n_vnode; /* associated vnode */ 963*14414594SDavid du Colombier+ struct lockf *n_lockf; /* Locking record of file */ 964*14414594SDavid du Colombier+ int n_error; /* Save write error value */ 965*14414594SDavid du Colombier+ struct u9fsdir n_dir; 966*14414594SDavid du Colombier+ short n_flag; /* Flag for locking.. */ 967*14414594SDavid du Colombier+ int n_opens; /* number of opens */ 968*14414594SDavid du Colombier+ }; 969*14414594SDavid du Colombier+ 970*14414594SDavid du Colombier+ #define n_atim n_un1.nf_atim 971*14414594SDavid du Colombier+ #define n_mtim n_un2.nf_mtim 972*14414594SDavid du Colombier+ #define n_sillyrename n_un3.nf_silly 973*14414594SDavid du Colombier+ #define n_cookieverf n_un1.nd_cookieverf 974*14414594SDavid du Colombier+ #define n_direofoffset n_un2.nd_direof 975*14414594SDavid du Colombier+ #define n_cookies n_un3.nd_cook 976*14414594SDavid du Colombier+ 977*14414594SDavid du Colombier+ /* 978*14414594SDavid du Colombier+ * Flags for n_flag 979*14414594SDavid du Colombier+ */ 980*14414594SDavid du Colombier+ #define NFLUSHWANT 0x0001 /* Want wakeup from a flush in prog. */ 981*14414594SDavid du Colombier+ #define NFLUSHINPROG 0x0002 /* Avoid multiple calls to vinvalbuf() */ 982*14414594SDavid du Colombier+ #define NMODIFIED 0x0004 /* Might have a modified buffer in bio */ 983*14414594SDavid du Colombier+ #define NWRITEERR 0x0008 /* Flag write errors so close will know */ 984*14414594SDavid du Colombier+ #define NQU9FSNONCACHE 0x0020 /* Non-cachable lease */ 985*14414594SDavid du Colombier+ #define NQU9FSWRITE 0x0040 /* Write lease */ 986*14414594SDavid du Colombier+ #define NQU9FSEVICTED 0x0080 /* Has been evicted */ 987*14414594SDavid du Colombier+ #define NACC 0x0100 /* Special file accessed */ 988*14414594SDavid du Colombier+ #define NUPD 0x0200 /* Special file updated */ 989*14414594SDavid du Colombier+ #define NCHG 0x0400 /* Special file times changed */ 990*14414594SDavid du Colombier+ #define NLOCKED 0x0800 /* node is locked */ 991*14414594SDavid du Colombier+ #define NWANTED 0x0100 /* someone wants to lock */ 992*14414594SDavid du Colombier+ 993*14414594SDavid du Colombier+ /* 994*14414594SDavid du Colombier+ * Convert between u9fsnode pointers and vnode pointers 995*14414594SDavid du Colombier+ */ 996*14414594SDavid du Colombier+ #define VTOU9FS(vp) ((struct u9fsnode *)(vp)->v_data) 997*14414594SDavid du Colombier+ #define U9FSTOV(np) ((struct vnode *)(np)->n_vnode) 998*14414594SDavid du Colombier+ 999*14414594SDavid du Colombier+ /* 1000*14414594SDavid du Colombier+ * Mount structure. 1001*14414594SDavid du Colombier+ * One allocated on every U9FS mount. 1002*14414594SDavid du Colombier+ * Holds U9FS specific information for mount. 1003*14414594SDavid du Colombier+ */ 1004*14414594SDavid du Colombier+ struct u9fsmount { 1005*14414594SDavid du Colombier+ int nm_flag; /* Flags for soft/hard... */ 1006*14414594SDavid du Colombier+ int nm_state; /* Internal state flags */ 1007*14414594SDavid du Colombier+ struct mount *nm_mountp; /* Vfs structure for this filesystem */ 1008*14414594SDavid du Colombier+ int nm_numgrps; /* Max. size of groupslist */ 1009*14414594SDavid du Colombier+ u9fsfh_t nm_fh; /* qid.path */ 1010*14414594SDavid du Colombier+ u_short nm_fid; /* fid of root dir */ 1011*14414594SDavid du Colombier+ struct socket *nm_so; /* Rpc socket */ 1012*14414594SDavid du Colombier+ int nm_sotype; /* Type of socket */ 1013*14414594SDavid du Colombier+ int nm_soproto; /* and protocol */ 1014*14414594SDavid du Colombier+ int nm_soflags; /* pr_flags for socket protocol */ 1015*14414594SDavid du Colombier+ struct sockaddr *nm_nam; /* Addr of server */ 1016*14414594SDavid du Colombier+ int nm_sent; /* Request send count */ 1017*14414594SDavid du Colombier+ int nm_cwnd; /* Request send window */ 1018*14414594SDavid du Colombier+ int nm_rsize; /* Max size of read rpc */ 1019*14414594SDavid du Colombier+ int nm_wsize; /* Max size of write rpc */ 1020*14414594SDavid du Colombier+ int nm_readdirsize; /* Size of a readdir rpc */ 1021*14414594SDavid du Colombier+ 1022*14414594SDavid du Colombier+ struct lock nm_lock; /* lock for tag/fid freelist */ 1023*14414594SDavid du Colombier+ bitstr_t * nm_tags; 1024*14414594SDavid du Colombier+ bitstr_t * nm_fids; 1025*14414594SDavid du Colombier+ TAILQ_HEAD(u9fs_reqq, u9fsreq) nm_reqq; 1026*14414594SDavid du Colombier+ 1027*14414594SDavid du Colombier+ uid_t nm_authuid; /* Uid for authenticator */ 1028*14414594SDavid du Colombier+ #if 0 1029*14414594SDavid du Colombier+ struct vnode *nm_inprog; /* Vnode in prog by nqu9fs_clientd() */ 1030*14414594SDavid du Colombier+ uid_t nm_authuid; /* Uid for authenticator */ 1031*14414594SDavid du Colombier+ int nm_authtype; /* Authenticator type */ 1032*14414594SDavid du Colombier+ int nm_authlen; /* and length */ 1033*14414594SDavid du Colombier+ char *nm_authstr; /* Authenticator string */ 1034*14414594SDavid du Colombier+ char *nm_verfstr; /* and the verifier */ 1035*14414594SDavid du Colombier+ int nm_verflen; 1036*14414594SDavid du Colombier+ u_char nm_verf[U9FSX_V3WRITEVERF]; /* V3 write verifier */ 1037*14414594SDavid du Colombier+ U9FSKERBKEY_T nm_key; /* and the session key */ 1038*14414594SDavid du Colombier+ int nm_numuids; /* Number of u9fsuid mappings */ 1039*14414594SDavid du Colombier+ TAILQ_HEAD(, u9fsuid) nm_uidlruhead; /* Lists of u9fsuid mappings */ 1040*14414594SDavid du Colombier+ LIST_HEAD(, u9fsuid) nm_uidhashtbl[U9FS_MUIDHASHSIZ]; 1041*14414594SDavid du Colombier+ TAILQ_HEAD(, buf) nm_bufq; /* async io buffer queue */ 1042*14414594SDavid du Colombier+ short nm_bufqlen; /* number of buffers in queue */ 1043*14414594SDavid du Colombier+ short nm_bufqwant; /* process wants to add to the queue */ 1044*14414594SDavid du Colombier+ int nm_bufqiods; /* number of iods processing queue */ 1045*14414594SDavid du Colombier+ #endif 1046*14414594SDavid du Colombier+ u_int64_t nm_maxfilesize; /* maximum file size */ 1047*14414594SDavid du Colombier+ }; 1048*14414594SDavid du Colombier+ 1049*14414594SDavid du Colombier+ #ifdef KERNEL 1050*14414594SDavid du Colombier+ 1051*14414594SDavid du Colombier+ #ifdef MALLOC_DECLARE 1052*14414594SDavid du Colombier+ MALLOC_DECLARE(M_U9FSHASH); 1053*14414594SDavid du Colombier+ MALLOC_DECLARE(M_U9FSBITS); 1054*14414594SDavid du Colombier+ 1055*14414594SDavid du Colombier+ extern vop_t **u9fs_vnodeop_p; 1056*14414594SDavid du Colombier+ 1057*14414594SDavid du Colombier+ /* u9fs_node.c */ 1058*14414594SDavid du Colombier+ void u9fs_nhinit __P((void)); 1059*14414594SDavid du Colombier+ int u9fs_nget __P((struct mount *mntp, u9fsfh_t fh, struct u9fsnode **npp, struct proc * p)); 1060*14414594SDavid du Colombier+ 1061*14414594SDavid du Colombier+ /* u9fs_subr.c */ 1062*14414594SDavid du Colombier+ void u9fs_id_init __P((bitstr_t ** bits)); 1063*14414594SDavid du Colombier+ u_short u9fs_id_new __P((bitstr_t * bits)); 1064*14414594SDavid du Colombier+ void u9fs_id_free __P((bitstr_t * bits, u_short v)); 1065*14414594SDavid du Colombier+ void u9fs_uhinit __P((void)); 1066*14414594SDavid du Colombier+ uid_t u9fs_name2uid __P((char * name)); 1067*14414594SDavid du Colombier+ struct u9fsuser * u9fs_finduser __P((uid_t uid)); 1068*14414594SDavid du Colombier+ void u9fs_hashuser __P((uid_t uid, char *name)); 1069*14414594SDavid du Colombier+ int u9fs_mbuftouio __P((struct mbuf *m, struct uio *uiop, int siz)); 1070*14414594SDavid du Colombier+ int u9fs_uiotombuf __P((struct uio *uiop, struct mbuf **mq, int siz)); 1071*14414594SDavid du Colombier+ 1072*14414594SDavid du Colombier+ /* u9fs_vnopes.c */ 1073*14414594SDavid du Colombier+ int u9fs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *)); 1074*14414594SDavid du Colombier+ int u9fs_readrpc __P((struct vnode *vp, struct uio *uiop, struct ucred *cred)); 1075*14414594SDavid du Colombier+ int u9fs_writerpc __P((struct vnode *vp, struct uio *uiop, struct ucred *cred)); 1076*14414594SDavid du Colombier+ 1077*14414594SDavid du Colombier+ /* u9fs_bio.c */ 1078*14414594SDavid du Colombier+ int u9fs_bioread __P((struct vnode *, struct uio *, int, struct ucred *,int)); 1079*14414594SDavid du Colombier+ int u9fs_biowrite __P((struct vnode *, struct uio *, int ioflag, struct ucred *)); 1080*14414594SDavid du Colombier+ int u9fs_doio __P((struct buf *, struct ucred *, struct proc *)); 1081*14414594SDavid du Colombier+ int u9fs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct proc *, int)); 1082*14414594SDavid du Colombier+ 1083*14414594SDavid du Colombier+ 1084*14414594SDavid du Colombier+ /* u9fs_socket.c */ 1085*14414594SDavid du Colombier+ int u9fs_sigintr __P((struct u9fsmount *nmp, struct proc *p)); 1086*14414594SDavid du Colombier+ void u9fs_disconnect __P((struct socket *)); 1087*14414594SDavid du Colombier+ int u9fs_connect __P((struct socket ** sop, struct sockaddr * saddr, int sotype, int soproto, struct proc * p)); 1088*14414594SDavid du Colombier+ int u9fs_connect_9fs __P((struct u9fsmount *)); 1089*14414594SDavid du Colombier+ int u9fs_connect_9auth __P((struct u9fsmount *, struct u9fs_args *, struct socket **)); 1090*14414594SDavid du Colombier+ int u9fs_request __P((struct u9fsreq * req, struct u9fsreq * rep, int relm)); 1091*14414594SDavid du Colombier+ 1092*14414594SDavid du Colombier+ #endif 1093*14414594SDavid du Colombier+ 1094*14414594SDavid du Colombier+ /* 1095*14414594SDavid du Colombier+ * Convert mount ptr to u9fsmount ptr. 1096*14414594SDavid du Colombier+ */ 1097*14414594SDavid du Colombier+ #define VFSTOU9FS(mp) ((struct u9fsmount *)((mp)->mnt_data)) 1098*14414594SDavid du Colombier+ 1099*14414594SDavid du Colombier+ #endif /* KERNEL */ 1100*14414594SDavid du Colombier+ 1101*14414594SDavid du Colombier+ #endif 1102*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_bio.c ./9fs/9fs_bio.c 1103*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_bio.c Wed Dec 31 19:00:00 1969 1104*14414594SDavid du Colombier--- ./9fs/9fs_bio.c Fri Nov 26 12:28:50 1999 1105*14414594SDavid du Colombier*************** 1106*14414594SDavid du Colombier*** 0 **** 1107*14414594SDavid du Colombier--- 1,550 ---- 1108*14414594SDavid du Colombier+ #include <sys/param.h> 1109*14414594SDavid du Colombier+ #include <sys/sockio.h> 1110*14414594SDavid du Colombier+ #include <sys/proc.h> 1111*14414594SDavid du Colombier+ #include <sys/vnode.h> 1112*14414594SDavid du Colombier+ #include <sys/kernel.h> 1113*14414594SDavid du Colombier+ #include <sys/sysctl.h> 1114*14414594SDavid du Colombier+ #include <sys/malloc.h> 1115*14414594SDavid du Colombier+ #include <sys/mount.h> 1116*14414594SDavid du Colombier+ #include <sys/mbuf.h> 1117*14414594SDavid du Colombier+ #include <sys/socket.h> 1118*14414594SDavid du Colombier+ #include <sys/socketvar.h> 1119*14414594SDavid du Colombier+ #include <sys/systm.h> 1120*14414594SDavid du Colombier+ #include <sys/protosw.h> 1121*14414594SDavid du Colombier+ #include <sys/syslog.h> 1122*14414594SDavid du Colombier+ 1123*14414594SDavid du Colombier+ #include <netinet/in.h> 1124*14414594SDavid du Colombier+ #include <netinet/tcp.h> 1125*14414594SDavid du Colombier+ 1126*14414594SDavid du Colombier+ #include <vm/vm.h> 1127*14414594SDavid du Colombier+ #include <vm/vm_extern.h> 1128*14414594SDavid du Colombier+ #include <vm/vm_zone.h> 1129*14414594SDavid du Colombier+ #include <vm/vm_prot.h> 1130*14414594SDavid du Colombier+ #include <vm/vm_page.h> 1131*14414594SDavid du Colombier+ #include <vm/vm_object.h> 1132*14414594SDavid du Colombier+ #include <vm/vm_pager.h> 1133*14414594SDavid du Colombier+ #include <vm/vnode_pager.h> 1134*14414594SDavid du Colombier+ 1135*14414594SDavid du Colombier+ #include <net/if.h> 1136*14414594SDavid du Colombier+ #include <net/route.h> 1137*14414594SDavid du Colombier+ #include <netinet/in.h> 1138*14414594SDavid du Colombier+ 1139*14414594SDavid du Colombier+ #include <9fs/bitstring.h> 1140*14414594SDavid du Colombier+ #include <9fs/9p.h> 1141*14414594SDavid du Colombier+ #include <9fs/9auth.h> 1142*14414594SDavid du Colombier+ #include <9fs/9fs.h> 1143*14414594SDavid du Colombier+ 1144*14414594SDavid du Colombier+ static struct buf *u9fs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size, struct proc *p)); 1145*14414594SDavid du Colombier+ static void u9fs_prot_buf __P((struct buf *bp, int off, int n)); 1146*14414594SDavid du Colombier+ 1147*14414594SDavid du Colombier+ /* 1148*14414594SDavid du Colombier+ * Vnode op for read using bio 1149*14414594SDavid du Colombier+ */ 1150*14414594SDavid du Colombier+ int 1151*14414594SDavid du Colombier+ u9fs_bioread(vp, uio, ioflag, cred, getpages) 1152*14414594SDavid du Colombier+ register struct vnode *vp; 1153*14414594SDavid du Colombier+ register struct uio *uio; 1154*14414594SDavid du Colombier+ int ioflag; 1155*14414594SDavid du Colombier+ struct ucred *cred; 1156*14414594SDavid du Colombier+ int getpages; 1157*14414594SDavid du Colombier+ { 1158*14414594SDavid du Colombier+ register struct u9fsnode *np = VTOU9FS(vp); 1159*14414594SDavid du Colombier+ register int biosize; 1160*14414594SDavid du Colombier+ off_t diff; 1161*14414594SDavid du Colombier+ struct buf *bp = 0; 1162*14414594SDavid du Colombier+ struct proc *p; 1163*14414594SDavid du Colombier+ struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount); 1164*14414594SDavid du Colombier+ daddr_t lbn; 1165*14414594SDavid du Colombier+ int error = 0, n = 0, on = 0, bufsize, not_readin; 1166*14414594SDavid du Colombier+ 1167*14414594SDavid du Colombier+ if (uio->uio_resid == 0) 1168*14414594SDavid du Colombier+ return (0); 1169*14414594SDavid du Colombier+ if (uio->uio_offset < 0) 1170*14414594SDavid du Colombier+ return (EINVAL); 1171*14414594SDavid du Colombier+ p = uio->uio_procp; 1172*14414594SDavid du Colombier+ if (vp->v_type != VDIR && 1173*14414594SDavid du Colombier+ (uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize) 1174*14414594SDavid du Colombier+ return (EFBIG); 1175*14414594SDavid du Colombier+ biosize = vp->v_mount->mnt_stat.f_iosize; 1176*14414594SDavid du Colombier+ #if 0 1177*14414594SDavid du Colombier+ if( np->n_qid.vers ) { /* in cache, check revision */ 1178*14414594SDavid du Colombier+ error = VOP_GETATTR(vp, &vattr, cred, p); 1179*14414594SDavid du Colombier+ if( error ) 1180*14414594SDavid du Colombier+ return error; 1181*14414594SDavid du Colombier+ if( np->n_qid.vers != np->n_dir.dir_qid.vers ) { 1182*14414594SDavid du Colombier+ /* content changed */ 1183*14414594SDavid du Colombier+ u9fs_vinvalbuf(vp, V_SAVE, cred, p, 1); 1184*14414594SDavid du Colombier+ } 1185*14414594SDavid du Colombier+ } 1186*14414594SDavid du Colombier+ #endif 1187*14414594SDavid du Colombier+ do { 1188*14414594SDavid du Colombier+ switch (vp->v_type) { 1189*14414594SDavid du Colombier+ case VREG: 1190*14414594SDavid du Colombier+ lbn = uio->uio_offset / biosize; 1191*14414594SDavid du Colombier+ on = uio->uio_offset & (biosize - 1); 1192*14414594SDavid du Colombier+ not_readin = 1; 1193*14414594SDavid du Colombier+ 1194*14414594SDavid du Colombier+ #if 0 1195*14414594SDavid du Colombier+ /* 1196*14414594SDavid du Colombier+ * Start the read ahead(s), as required. 1197*14414594SDavid du Colombier+ */ 1198*14414594SDavid du Colombier+ if (u9fs_numasync > 0 && nmp->nm_readahead > 0) { 1199*14414594SDavid du Colombier+ for (nra = 0; nra < nmp->nm_readahead && 1200*14414594SDavid du Colombier+ (off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) { 1201*14414594SDavid du Colombier+ rabn = lbn + 1 + nra; 1202*14414594SDavid du Colombier+ if (!incore(vp, rabn)) { 1203*14414594SDavid du Colombier+ rabp = u9fs_getcacheblk(vp, rabn, biosize, p); 1204*14414594SDavid du Colombier+ if (!rabp) 1205*14414594SDavid du Colombier+ return (EINTR); 1206*14414594SDavid du Colombier+ if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) { 1207*14414594SDavid du Colombier+ rabp->b_flags |= (B_READ | B_ASYNC); 1208*14414594SDavid du Colombier+ vfs_busy_pages(rabp, 0); 1209*14414594SDavid du Colombier+ if (u9fs_asyncio(rabp, cred)) { 1210*14414594SDavid du Colombier+ rabp->b_flags |= B_INVAL|B_ERROR; 1211*14414594SDavid du Colombier+ vfs_unbusy_pages(rabp); 1212*14414594SDavid du Colombier+ brelse(rabp); 1213*14414594SDavid du Colombier+ } 1214*14414594SDavid du Colombier+ } else 1215*14414594SDavid du Colombier+ brelse(rabp); 1216*14414594SDavid du Colombier+ } 1217*14414594SDavid du Colombier+ } 1218*14414594SDavid du Colombier+ } 1219*14414594SDavid du Colombier+ #endif 1220*14414594SDavid du Colombier+ 1221*14414594SDavid du Colombier+ /* 1222*14414594SDavid du Colombier+ * If the block is in the cache and has the required data 1223*14414594SDavid du Colombier+ * in a valid region, just copy it out. 1224*14414594SDavid du Colombier+ * Otherwise, get the block and write back/read in, 1225*14414594SDavid du Colombier+ * as required. 1226*14414594SDavid du Colombier+ */ 1227*14414594SDavid du Colombier+ again: 1228*14414594SDavid du Colombier+ bufsize = biosize; 1229*14414594SDavid du Colombier+ if ((off_t)(lbn + 1) * biosize > np->n_size && 1230*14414594SDavid du Colombier+ (off_t)(lbn + 1) * biosize - np->n_size < biosize) { 1231*14414594SDavid du Colombier+ bufsize = np->n_size - (off_t)lbn * biosize; 1232*14414594SDavid du Colombier+ bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 1233*14414594SDavid du Colombier+ } 1234*14414594SDavid du Colombier+ bp = u9fs_getcacheblk(vp, lbn, bufsize, p); 1235*14414594SDavid du Colombier+ if (!bp) 1236*14414594SDavid du Colombier+ return (EINTR); 1237*14414594SDavid du Colombier+ /* 1238*14414594SDavid du Colombier+ * If we are being called from u9fs_getpages, we must 1239*14414594SDavid du Colombier+ * make sure the buffer is a vmio buffer. The vp will 1240*14414594SDavid du Colombier+ * already be setup for vmio but there may be some old 1241*14414594SDavid du Colombier+ * non-vmio buffers attached to it. 1242*14414594SDavid du Colombier+ */ 1243*14414594SDavid du Colombier+ if (getpages && !(bp->b_flags & B_VMIO)) { 1244*14414594SDavid du Colombier+ #ifdef DIAGNOSTIC 1245*14414594SDavid du Colombier+ printf("u9fs_bioread: non vmio buf found, discarding\n"); 1246*14414594SDavid du Colombier+ #endif 1247*14414594SDavid du Colombier+ bp->b_flags |= B_NOCACHE; 1248*14414594SDavid du Colombier+ if (bp->b_dirtyend > 0) { 1249*14414594SDavid du Colombier+ if ((bp->b_flags & B_DELWRI) == 0) 1250*14414594SDavid du Colombier+ panic("u9fsbioread"); 1251*14414594SDavid du Colombier+ if (VOP_BWRITE(bp) == EINTR) 1252*14414594SDavid du Colombier+ return (EINTR); 1253*14414594SDavid du Colombier+ } else 1254*14414594SDavid du Colombier+ brelse(bp); 1255*14414594SDavid du Colombier+ goto again; 1256*14414594SDavid du Colombier+ } 1257*14414594SDavid du Colombier+ if ((bp->b_flags & B_CACHE) == 0) { 1258*14414594SDavid du Colombier+ bp->b_flags |= B_READ; 1259*14414594SDavid du Colombier+ bp->b_flags &= ~(B_DONE | B_ERROR | B_INVAL); 1260*14414594SDavid du Colombier+ not_readin = 0; 1261*14414594SDavid du Colombier+ vfs_busy_pages(bp, 0); 1262*14414594SDavid du Colombier+ error = u9fs_doio(bp, cred, p); 1263*14414594SDavid du Colombier+ if (error) { 1264*14414594SDavid du Colombier+ brelse(bp); 1265*14414594SDavid du Colombier+ return (error); 1266*14414594SDavid du Colombier+ } 1267*14414594SDavid du Colombier+ np->n_qid.vers = np->n_dir.dir_qid.vers; 1268*14414594SDavid du Colombier+ } 1269*14414594SDavid du Colombier+ if (bufsize > on) { 1270*14414594SDavid du Colombier+ n = min((unsigned)(bufsize - on), uio->uio_resid); 1271*14414594SDavid du Colombier+ } else { 1272*14414594SDavid du Colombier+ n = 0; 1273*14414594SDavid du Colombier+ } 1274*14414594SDavid du Colombier+ diff = np->n_size - uio->uio_offset; 1275*14414594SDavid du Colombier+ if (diff < n) 1276*14414594SDavid du Colombier+ n = diff; 1277*14414594SDavid du Colombier+ if (not_readin && n > 0) { 1278*14414594SDavid du Colombier+ if (on < bp->b_validoff || (on + n) > bp->b_validend) { 1279*14414594SDavid du Colombier+ bp->b_flags |= B_NOCACHE; 1280*14414594SDavid du Colombier+ if (bp->b_dirtyend > 0) { 1281*14414594SDavid du Colombier+ if ((bp->b_flags & B_DELWRI) == 0) 1282*14414594SDavid du Colombier+ panic("u9fsbioread"); 1283*14414594SDavid du Colombier+ if (VOP_BWRITE(bp) == EINTR) 1284*14414594SDavid du Colombier+ return (EINTR); 1285*14414594SDavid du Colombier+ } else 1286*14414594SDavid du Colombier+ brelse(bp); 1287*14414594SDavid du Colombier+ goto again; 1288*14414594SDavid du Colombier+ } 1289*14414594SDavid du Colombier+ } 1290*14414594SDavid du Colombier+ vp->v_lastr = lbn; 1291*14414594SDavid du Colombier+ diff = (on >= bp->b_validend) ? 0 : (bp->b_validend - on); 1292*14414594SDavid du Colombier+ if (diff < n) 1293*14414594SDavid du Colombier+ n = diff; 1294*14414594SDavid du Colombier+ break; 1295*14414594SDavid du Colombier+ case VDIR: 1296*14414594SDavid du Colombier+ biosize = nmp->nm_readdirsize; 1297*14414594SDavid du Colombier+ lbn = (uoff_t)uio->uio_offset / biosize; 1298*14414594SDavid du Colombier+ on = uio->uio_offset % biosize; 1299*14414594SDavid du Colombier+ bp = u9fs_getcacheblk(vp, lbn, biosize, p); 1300*14414594SDavid du Colombier+ if (!bp) 1301*14414594SDavid du Colombier+ return (EINTR); 1302*14414594SDavid du Colombier+ if ((bp->b_flags & B_CACHE) == 0) { 1303*14414594SDavid du Colombier+ bp->b_flags |= B_READ; 1304*14414594SDavid du Colombier+ vfs_busy_pages(bp, 0); 1305*14414594SDavid du Colombier+ error = u9fs_doio(bp, cred, p); 1306*14414594SDavid du Colombier+ if (error) { 1307*14414594SDavid du Colombier+ brelse(bp); 1308*14414594SDavid du Colombier+ } 1309*14414594SDavid du Colombier+ if (error) 1310*14414594SDavid du Colombier+ return (error); 1311*14414594SDavid du Colombier+ np->n_qid.vers = np->n_dir.dir_qid.vers; 1312*14414594SDavid du Colombier+ } 1313*14414594SDavid du Colombier+ 1314*14414594SDavid du Colombier+ /* 1315*14414594SDavid du Colombier+ * Make sure we use a signed variant of min() since 1316*14414594SDavid du Colombier+ * the second term may be negative. 1317*14414594SDavid du Colombier+ */ 1318*14414594SDavid du Colombier+ n = lmin(uio->uio_resid, biosize - bp->b_resid - on); 1319*14414594SDavid du Colombier+ break; 1320*14414594SDavid du Colombier+ default: 1321*14414594SDavid du Colombier+ printf(" u9fs_bioread: type %x unexpected\n",vp->v_type); 1322*14414594SDavid du Colombier+ break; 1323*14414594SDavid du Colombier+ }; 1324*14414594SDavid du Colombier+ 1325*14414594SDavid du Colombier+ if (n > 0) { 1326*14414594SDavid du Colombier+ error = uiomove(bp->b_data + on, (int)n, uio); 1327*14414594SDavid du Colombier+ } 1328*14414594SDavid du Colombier+ brelse(bp); 1329*14414594SDavid du Colombier+ } while (error == 0 && uio->uio_resid > 0 && n > 0); 1330*14414594SDavid du Colombier+ return (error); 1331*14414594SDavid du Colombier+ } 1332*14414594SDavid du Colombier+ 1333*14414594SDavid du Colombier+ /* 1334*14414594SDavid du Colombier+ * Vnode op for write using bio 1335*14414594SDavid du Colombier+ */ 1336*14414594SDavid du Colombier+ int 1337*14414594SDavid du Colombier+ u9fs_biowrite(vp, uio, ioflag, cred) 1338*14414594SDavid du Colombier+ register struct vnode *vp; 1339*14414594SDavid du Colombier+ register struct uio *uio; 1340*14414594SDavid du Colombier+ register int ioflag; 1341*14414594SDavid du Colombier+ register struct ucred *cred; 1342*14414594SDavid du Colombier+ { 1343*14414594SDavid du Colombier+ register int biosize; 1344*14414594SDavid du Colombier+ struct proc *p = uio->uio_procp; 1345*14414594SDavid du Colombier+ struct u9fsnode *np = VTOU9FS(vp); 1346*14414594SDavid du Colombier+ struct buf *bp; 1347*14414594SDavid du Colombier+ struct vattr vattr; 1348*14414594SDavid du Colombier+ struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount); 1349*14414594SDavid du Colombier+ daddr_t lbn; 1350*14414594SDavid du Colombier+ int bufsize; 1351*14414594SDavid du Colombier+ int n, on, error = 0; 1352*14414594SDavid du Colombier+ 1353*14414594SDavid du Colombier+ if (ioflag & (IO_APPEND | IO_SYNC)) { 1354*14414594SDavid du Colombier+ if (ioflag & IO_APPEND) { 1355*14414594SDavid du Colombier+ error = VOP_GETATTR(vp, &vattr, cred, p); 1356*14414594SDavid du Colombier+ if (error) 1357*14414594SDavid du Colombier+ return (error); 1358*14414594SDavid du Colombier+ uio->uio_offset = np->n_size; 1359*14414594SDavid du Colombier+ } 1360*14414594SDavid du Colombier+ } 1361*14414594SDavid du Colombier+ if (uio->uio_offset < 0) 1362*14414594SDavid du Colombier+ return (EINVAL); 1363*14414594SDavid du Colombier+ if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize) 1364*14414594SDavid du Colombier+ return (EFBIG); 1365*14414594SDavid du Colombier+ if (uio->uio_resid == 0) 1366*14414594SDavid du Colombier+ return (0); 1367*14414594SDavid du Colombier+ 1368*14414594SDavid du Colombier+ /* 1369*14414594SDavid du Colombier+ * I use nm_rsize, not nm_wsize so that all buffer cache blocks 1370*14414594SDavid du Colombier+ * will be the same size within a filesystem. nfs_writerpc will 1371*14414594SDavid du Colombier+ * still use nm_wsize when sizing the rpc's. 1372*14414594SDavid du Colombier+ */ 1373*14414594SDavid du Colombier+ biosize = vp->v_mount->mnt_stat.f_iosize; 1374*14414594SDavid du Colombier+ do { 1375*14414594SDavid du Colombier+ lbn = uio->uio_offset / biosize; 1376*14414594SDavid du Colombier+ on = uio->uio_offset & (biosize-1); 1377*14414594SDavid du Colombier+ n = min((unsigned)(biosize - on), uio->uio_resid); 1378*14414594SDavid du Colombier+ if (uio->uio_offset + n > np->n_size) { 1379*14414594SDavid du Colombier+ np->n_size = uio->uio_offset + n; 1380*14414594SDavid du Colombier+ vnode_pager_setsize(vp, np->n_size); 1381*14414594SDavid du Colombier+ } 1382*14414594SDavid du Colombier+ bufsize = biosize; 1383*14414594SDavid du Colombier+ if ((off_t)(lbn + 1) * biosize > np->n_size) { 1384*14414594SDavid du Colombier+ bufsize = np->n_size - (off_t)lbn * biosize; 1385*14414594SDavid du Colombier+ bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 1386*14414594SDavid du Colombier+ } 1387*14414594SDavid du Colombier+ bp = u9fs_getcacheblk(vp, lbn, bufsize, p); 1388*14414594SDavid du Colombier+ if (!bp) 1389*14414594SDavid du Colombier+ return (EINTR); 1390*14414594SDavid du Colombier+ if (bp->b_wcred == NOCRED) { 1391*14414594SDavid du Colombier+ crhold(cred); 1392*14414594SDavid du Colombier+ bp->b_wcred = cred; 1393*14414594SDavid du Colombier+ } 1394*14414594SDavid du Colombier+ 1395*14414594SDavid du Colombier+ error = uiomove((char *)bp->b_data + on, n, uio); 1396*14414594SDavid du Colombier+ if (error) { 1397*14414594SDavid du Colombier+ bp->b_flags |= B_ERROR; 1398*14414594SDavid du Colombier+ brelse(bp); 1399*14414594SDavid du Colombier+ return (error); 1400*14414594SDavid du Colombier+ } 1401*14414594SDavid du Colombier+ 1402*14414594SDavid du Colombier+ /* 1403*14414594SDavid du Colombier+ * This will keep the buffer and mmaped regions more coherent. 1404*14414594SDavid du Colombier+ */ 1405*14414594SDavid du Colombier+ u9fs_prot_buf(bp, on, n); 1406*14414594SDavid du Colombier+ bp->b_dirtyoff = on; 1407*14414594SDavid du Colombier+ bp->b_dirtyend = on + n; 1408*14414594SDavid du Colombier+ 1409*14414594SDavid du Colombier+ if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff || 1410*14414594SDavid du Colombier+ bp->b_validoff > bp->b_dirtyend) { 1411*14414594SDavid du Colombier+ /* XXX: destroys our read cache if not overlapping */ 1412*14414594SDavid du Colombier+ /* two choice: none implemented 1413*14414594SDavid du Colombier+ 1> keep the bigger(smaller) piece 1414*14414594SDavid du Colombier+ 2> read the missing segment 1415*14414594SDavid du Colombier+ */ 1416*14414594SDavid du Colombier+ bp->b_validoff = bp->b_dirtyoff; 1417*14414594SDavid du Colombier+ bp->b_validend = bp->b_dirtyend; 1418*14414594SDavid du Colombier+ } else { 1419*14414594SDavid du Colombier+ bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff); 1420*14414594SDavid du Colombier+ bp->b_validend = max(bp->b_validend, bp->b_dirtyend); 1421*14414594SDavid du Colombier+ } 1422*14414594SDavid du Colombier+ 1423*14414594SDavid du Colombier+ error = bwrite(bp); 1424*14414594SDavid du Colombier+ if( error ) { 1425*14414594SDavid du Colombier+ bp->b_flags |= B_ERROR; 1426*14414594SDavid du Colombier+ /* brelse(bp); */ 1427*14414594SDavid du Colombier+ return error; 1428*14414594SDavid du Colombier+ } 1429*14414594SDavid du Colombier+ } while (uio->uio_resid > 0 && n > 0); 1430*14414594SDavid du Colombier+ return 0; 1431*14414594SDavid du Colombier+ } 1432*14414594SDavid du Colombier+ 1433*14414594SDavid du Colombier+ /* 1434*14414594SDavid du Colombier+ * Do an I/O operation to/from a cache block. This may be called 1435*14414594SDavid du Colombier+ * synchronously or from an u9fsiod. 1436*14414594SDavid du Colombier+ */ 1437*14414594SDavid du Colombier+ int 1438*14414594SDavid du Colombier+ u9fs_doio(bp, cr, p) 1439*14414594SDavid du Colombier+ register struct buf *bp; 1440*14414594SDavid du Colombier+ struct ucred *cr; 1441*14414594SDavid du Colombier+ struct proc *p; 1442*14414594SDavid du Colombier+ { 1443*14414594SDavid du Colombier+ register struct uio *uiop; 1444*14414594SDavid du Colombier+ register struct vnode *vp; 1445*14414594SDavid du Colombier+ struct u9fsnode *np; 1446*14414594SDavid du Colombier+ struct u9fsmount *nmp; 1447*14414594SDavid du Colombier+ int error = 0, diff, len; 1448*14414594SDavid du Colombier+ struct uio uio; 1449*14414594SDavid du Colombier+ struct iovec io; 1450*14414594SDavid du Colombier+ 1451*14414594SDavid du Colombier+ vp = bp->b_vp; 1452*14414594SDavid du Colombier+ np = VTOU9FS(vp); 1453*14414594SDavid du Colombier+ nmp = VFSTOU9FS(vp->v_mount); 1454*14414594SDavid du Colombier+ uiop = &uio; 1455*14414594SDavid du Colombier+ uiop->uio_iov = &io; 1456*14414594SDavid du Colombier+ uiop->uio_iovcnt = 1; 1457*14414594SDavid du Colombier+ uiop->uio_segflg = UIO_SYSSPACE; 1458*14414594SDavid du Colombier+ uiop->uio_procp = p; 1459*14414594SDavid du Colombier+ 1460*14414594SDavid du Colombier+ if (bp->b_flags & B_READ ) { 1461*14414594SDavid du Colombier+ io.iov_len = uiop->uio_resid = bp->b_bcount; 1462*14414594SDavid du Colombier+ io.iov_base = bp->b_data; 1463*14414594SDavid du Colombier+ uiop->uio_rw = UIO_READ; 1464*14414594SDavid du Colombier+ switch (vp->v_type) { 1465*14414594SDavid du Colombier+ case VREG: 1466*14414594SDavid du Colombier+ uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE; 1467*14414594SDavid du Colombier+ error = u9fs_readrpc(vp, uiop, cr); 1468*14414594SDavid du Colombier+ if (!error) { 1469*14414594SDavid du Colombier+ bp->b_validoff = 0; 1470*14414594SDavid du Colombier+ if (uiop->uio_resid) { 1471*14414594SDavid du Colombier+ /* 1472*14414594SDavid du Colombier+ * If len > 0, there is a hole in the file and 1473*14414594SDavid du Colombier+ * no writes after the hole have been pushed to 1474*14414594SDavid du Colombier+ * the server yet. 1475*14414594SDavid du Colombier+ * Just zero fill the rest of the valid area. 1476*14414594SDavid du Colombier+ */ 1477*14414594SDavid du Colombier+ diff = bp->b_bcount - uiop->uio_resid; 1478*14414594SDavid du Colombier+ len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE 1479*14414594SDavid du Colombier+ + diff); 1480*14414594SDavid du Colombier+ if (len > 0) { 1481*14414594SDavid du Colombier+ len = min(len, uiop->uio_resid); 1482*14414594SDavid du Colombier+ bzero((char *)bp->b_data + diff, len); 1483*14414594SDavid du Colombier+ bp->b_validend = diff + len; 1484*14414594SDavid du Colombier+ } else 1485*14414594SDavid du Colombier+ bp->b_validend = diff; 1486*14414594SDavid du Colombier+ } else 1487*14414594SDavid du Colombier+ bp->b_validend = bp->b_bcount; 1488*14414594SDavid du Colombier+ } 1489*14414594SDavid du Colombier+ break; 1490*14414594SDavid du Colombier+ case VDIR: 1491*14414594SDavid du Colombier+ uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * nmp->nm_readdirsize; 1492*14414594SDavid du Colombier+ error = u9fs_readdirrpc(vp, uiop, cr); 1493*14414594SDavid du Colombier+ if (error == 0 && uiop->uio_resid == bp->b_bcount) 1494*14414594SDavid du Colombier+ bp->b_flags |= B_INVAL; 1495*14414594SDavid du Colombier+ break; 1496*14414594SDavid du Colombier+ default: 1497*14414594SDavid du Colombier+ printf("u9fs_doio: type %x unexpected\n",vp->v_type); 1498*14414594SDavid du Colombier+ break; 1499*14414594SDavid du Colombier+ }; 1500*14414594SDavid du Colombier+ if (error) { 1501*14414594SDavid du Colombier+ bp->b_flags |= B_ERROR; 1502*14414594SDavid du Colombier+ bp->b_error = error; 1503*14414594SDavid du Colombier+ } 1504*14414594SDavid du Colombier+ } else { 1505*14414594SDavid du Colombier+ if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size) 1506*14414594SDavid du Colombier+ bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE; 1507*14414594SDavid du Colombier+ 1508*14414594SDavid du Colombier+ if (bp->b_dirtyend > bp->b_dirtyoff) { 1509*14414594SDavid du Colombier+ io.iov_len = uiop->uio_resid = bp->b_dirtyend 1510*14414594SDavid du Colombier+ - bp->b_dirtyoff; 1511*14414594SDavid du Colombier+ uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE 1512*14414594SDavid du Colombier+ + bp->b_dirtyoff; 1513*14414594SDavid du Colombier+ io.iov_base = (char *)bp->b_data + bp->b_dirtyoff; 1514*14414594SDavid du Colombier+ uiop->uio_rw = UIO_WRITE; 1515*14414594SDavid du Colombier+ bp->b_flags |= B_WRITEINPROG; 1516*14414594SDavid du Colombier+ error = u9fs_writerpc(vp, uiop, cr); 1517*14414594SDavid du Colombier+ bp->b_flags &= ~B_WRITEINPROG; 1518*14414594SDavid du Colombier+ 1519*14414594SDavid du Colombier+ if (error) { 1520*14414594SDavid du Colombier+ bp->b_flags |= B_ERROR; 1521*14414594SDavid du Colombier+ bp->b_error = np->n_error = error; 1522*14414594SDavid du Colombier+ np->n_flag |= NWRITEERR; 1523*14414594SDavid du Colombier+ } 1524*14414594SDavid du Colombier+ bp->b_dirtyoff = bp->b_dirtyend = 0; 1525*14414594SDavid du Colombier+ } else { 1526*14414594SDavid du Colombier+ bp->b_resid = 0; 1527*14414594SDavid du Colombier+ biodone(bp); 1528*14414594SDavid du Colombier+ return (0); 1529*14414594SDavid du Colombier+ } 1530*14414594SDavid du Colombier+ } 1531*14414594SDavid du Colombier+ bp->b_resid = uiop->uio_resid; 1532*14414594SDavid du Colombier+ biodone(bp); 1533*14414594SDavid du Colombier+ return error; 1534*14414594SDavid du Colombier+ } 1535*14414594SDavid du Colombier+ 1536*14414594SDavid du Colombier+ /* 1537*14414594SDavid du Colombier+ * Get an u9fs cache block. 1538*14414594SDavid du Colombier+ * Allocate a new one if the block isn't currently in the cache 1539*14414594SDavid du Colombier+ * and return the block marked busy. If the calling process is 1540*14414594SDavid du Colombier+ * interrupted by a signal for an interruptible mount point, return 1541*14414594SDavid du Colombier+ * NULL. 1542*14414594SDavid du Colombier+ */ 1543*14414594SDavid du Colombier+ static struct buf * 1544*14414594SDavid du Colombier+ u9fs_getcacheblk(vp, bn, size, p) 1545*14414594SDavid du Colombier+ struct vnode *vp; 1546*14414594SDavid du Colombier+ daddr_t bn; 1547*14414594SDavid du Colombier+ int size; 1548*14414594SDavid du Colombier+ struct proc *p; 1549*14414594SDavid du Colombier+ { 1550*14414594SDavid du Colombier+ register struct buf *bp; 1551*14414594SDavid du Colombier+ struct mount *mp; 1552*14414594SDavid du Colombier+ struct u9fsmount *nmp; 1553*14414594SDavid du Colombier+ 1554*14414594SDavid du Colombier+ mp = vp->v_mount; 1555*14414594SDavid du Colombier+ nmp = VFSTOU9FS(mp); 1556*14414594SDavid du Colombier+ 1557*14414594SDavid du Colombier+ if (nmp->nm_flag & U9FSMNT_INT) { 1558*14414594SDavid du Colombier+ bp = getblk(vp, bn, size, PCATCH, 0); 1559*14414594SDavid du Colombier+ while (bp == (struct buf *)0) { 1560*14414594SDavid du Colombier+ if (u9fs_sigintr(nmp, p)) 1561*14414594SDavid du Colombier+ return ((struct buf *)0); 1562*14414594SDavid du Colombier+ bp = getblk(vp, bn, size, 0, 2 * hz); 1563*14414594SDavid du Colombier+ } 1564*14414594SDavid du Colombier+ } else 1565*14414594SDavid du Colombier+ bp = getblk(vp, bn, size, 0, 0); 1566*14414594SDavid du Colombier+ 1567*14414594SDavid du Colombier+ if (vp->v_type == VREG) { 1568*14414594SDavid du Colombier+ int biosize; 1569*14414594SDavid du Colombier+ biosize = mp->mnt_stat.f_iosize; 1570*14414594SDavid du Colombier+ bp->b_blkno = bn * (biosize / DEV_BSIZE); 1571*14414594SDavid du Colombier+ } 1572*14414594SDavid du Colombier+ 1573*14414594SDavid du Colombier+ return (bp); 1574*14414594SDavid du Colombier+ } 1575*14414594SDavid du Colombier+ 1576*14414594SDavid du Colombier+ static void 1577*14414594SDavid du Colombier+ u9fs_prot_buf(bp, off, n) 1578*14414594SDavid du Colombier+ struct buf *bp; 1579*14414594SDavid du Colombier+ int off; 1580*14414594SDavid du Colombier+ int n; 1581*14414594SDavid du Colombier+ { 1582*14414594SDavid du Colombier+ int pindex, boff, end; 1583*14414594SDavid du Colombier+ 1584*14414594SDavid du Colombier+ if ((bp->b_flags & B_VMIO) == 0) 1585*14414594SDavid du Colombier+ return; 1586*14414594SDavid du Colombier+ 1587*14414594SDavid du Colombier+ end = round_page(off + n); 1588*14414594SDavid du Colombier+ for (boff = trunc_page(off); boff < end; boff += PAGE_SIZE) { 1589*14414594SDavid du Colombier+ pindex = boff >> PAGE_SHIFT; 1590*14414594SDavid du Colombier+ vm_page_protect(bp->b_pages[pindex], VM_PROT_NONE); 1591*14414594SDavid du Colombier+ } 1592*14414594SDavid du Colombier+ } 1593*14414594SDavid du Colombier+ 1594*14414594SDavid du Colombier+ /* 1595*14414594SDavid du Colombier+ * Flush and invalidate all dirty buffers. If another process is already 1596*14414594SDavid du Colombier+ * doing the flush, just wait for completion. 1597*14414594SDavid du Colombier+ */ 1598*14414594SDavid du Colombier+ int 1599*14414594SDavid du Colombier+ u9fs_vinvalbuf(vp, flags, cred, p, intrflg) 1600*14414594SDavid du Colombier+ struct vnode *vp; 1601*14414594SDavid du Colombier+ int flags; 1602*14414594SDavid du Colombier+ struct ucred *cred; 1603*14414594SDavid du Colombier+ struct proc *p; 1604*14414594SDavid du Colombier+ int intrflg; 1605*14414594SDavid du Colombier+ { 1606*14414594SDavid du Colombier+ register struct u9fsnode *np = VTOU9FS(vp); 1607*14414594SDavid du Colombier+ struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount); 1608*14414594SDavid du Colombier+ int error = 0, slpflag, slptimeo; 1609*14414594SDavid du Colombier+ 1610*14414594SDavid du Colombier+ if (vp->v_flag & VXLOCK) { 1611*14414594SDavid du Colombier+ return (0); 1612*14414594SDavid du Colombier+ } 1613*14414594SDavid du Colombier+ 1614*14414594SDavid du Colombier+ if ((nmp->nm_flag & U9FSMNT_INT) == 0) 1615*14414594SDavid du Colombier+ intrflg = 0; 1616*14414594SDavid du Colombier+ if (intrflg) { 1617*14414594SDavid du Colombier+ slpflag = PCATCH; 1618*14414594SDavid du Colombier+ slptimeo = 2 * hz; 1619*14414594SDavid du Colombier+ } else { 1620*14414594SDavid du Colombier+ slpflag = 0; 1621*14414594SDavid du Colombier+ slptimeo = 0; 1622*14414594SDavid du Colombier+ } 1623*14414594SDavid du Colombier+ /* 1624*14414594SDavid du Colombier+ * First wait for any other process doing a flush to complete. 1625*14414594SDavid du Colombier+ */ 1626*14414594SDavid du Colombier+ while (np->n_flag & NFLUSHINPROG) { 1627*14414594SDavid du Colombier+ np->n_flag |= NFLUSHWANT; 1628*14414594SDavid du Colombier+ error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "u9fsvinval", 1629*14414594SDavid du Colombier+ slptimeo); 1630*14414594SDavid du Colombier+ if (error && intrflg && u9fs_sigintr(nmp, p)) 1631*14414594SDavid du Colombier+ return (EINTR); 1632*14414594SDavid du Colombier+ } 1633*14414594SDavid du Colombier+ 1634*14414594SDavid du Colombier+ /* 1635*14414594SDavid du Colombier+ * Now, flush as required. 1636*14414594SDavid du Colombier+ */ 1637*14414594SDavid du Colombier+ np->n_flag |= NFLUSHINPROG; 1638*14414594SDavid du Colombier+ error = vinvalbuf(vp, flags, cred, p, slpflag, 0); 1639*14414594SDavid du Colombier+ while (error) { 1640*14414594SDavid du Colombier+ if (intrflg && u9fs_sigintr(nmp, p)) { 1641*14414594SDavid du Colombier+ np->n_flag &= ~NFLUSHINPROG; 1642*14414594SDavid du Colombier+ if (np->n_flag & NFLUSHWANT) { 1643*14414594SDavid du Colombier+ np->n_flag &= ~NFLUSHWANT; 1644*14414594SDavid du Colombier+ wakeup((caddr_t)&np->n_flag); 1645*14414594SDavid du Colombier+ } 1646*14414594SDavid du Colombier+ return (EINTR); 1647*14414594SDavid du Colombier+ } 1648*14414594SDavid du Colombier+ error = vinvalbuf(vp, flags, cred, p, 0, slptimeo); 1649*14414594SDavid du Colombier+ } 1650*14414594SDavid du Colombier+ np->n_flag &= ~(NMODIFIED | NFLUSHINPROG); 1651*14414594SDavid du Colombier+ if (np->n_flag & NFLUSHWANT) { 1652*14414594SDavid du Colombier+ np->n_flag &= ~NFLUSHWANT; 1653*14414594SDavid du Colombier+ wakeup((caddr_t)&np->n_flag); 1654*14414594SDavid du Colombier+ } 1655*14414594SDavid du Colombier+ return (0); 1656*14414594SDavid du Colombier+ } 1657*14414594SDavid du Colombier+ 1658*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_node.c ./9fs/9fs_node.c 1659*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_node.c Wed Dec 31 19:00:00 1969 1660*14414594SDavid du Colombier--- ./9fs/9fs_node.c Thu Nov 25 15:36:49 1999 1661*14414594SDavid du Colombier*************** 1662*14414594SDavid du Colombier*** 0 **** 1663*14414594SDavid du Colombier--- 1,132 ---- 1664*14414594SDavid du Colombier+ #include <sys/param.h> 1665*14414594SDavid du Colombier+ #include <sys/sockio.h> 1666*14414594SDavid du Colombier+ #include <sys/proc.h> 1667*14414594SDavid du Colombier+ #include <sys/vnode.h> 1668*14414594SDavid du Colombier+ #include <sys/kernel.h> 1669*14414594SDavid du Colombier+ #include <sys/sysctl.h> 1670*14414594SDavid du Colombier+ #include <sys/malloc.h> 1671*14414594SDavid du Colombier+ #include <sys/mount.h> 1672*14414594SDavid du Colombier+ #include <sys/mbuf.h> 1673*14414594SDavid du Colombier+ #include <sys/socket.h> 1674*14414594SDavid du Colombier+ #include <sys/socketvar.h> 1675*14414594SDavid du Colombier+ #include <sys/systm.h> 1676*14414594SDavid du Colombier+ #include <sys/protosw.h> 1677*14414594SDavid du Colombier+ #include <sys/syslog.h> 1678*14414594SDavid du Colombier+ 1679*14414594SDavid du Colombier+ #include <netinet/in.h> 1680*14414594SDavid du Colombier+ #include <netinet/tcp.h> 1681*14414594SDavid du Colombier+ 1682*14414594SDavid du Colombier+ #include <vm/vm.h> 1683*14414594SDavid du Colombier+ #include <vm/vm_extern.h> 1684*14414594SDavid du Colombier+ #include <vm/vm_zone.h> 1685*14414594SDavid du Colombier+ 1686*14414594SDavid du Colombier+ #include <net/if.h> 1687*14414594SDavid du Colombier+ #include <net/route.h> 1688*14414594SDavid du Colombier+ #include <netinet/in.h> 1689*14414594SDavid du Colombier+ 1690*14414594SDavid du Colombier+ #include <9fs/bitstring.h> 1691*14414594SDavid du Colombier+ #include <9fs/9p.h> 1692*14414594SDavid du Colombier+ #include <9fs/9auth.h> 1693*14414594SDavid du Colombier+ #include <9fs/9fs.h> 1694*14414594SDavid du Colombier+ 1695*14414594SDavid du Colombier+ vm_zone_t u9fsnode_zone; 1696*14414594SDavid du Colombier+ static LIST_HEAD(u9fsnodehashhead, u9fsnode) *u9fsnodehashtbl; 1697*14414594SDavid du Colombier+ static u_long u9fsnodehash; 1698*14414594SDavid du Colombier+ MALLOC_DEFINE(M_U9FSHASH, "U9FS hash", "U9FS hash tables"); 1699*14414594SDavid du Colombier+ 1700*14414594SDavid du Colombier+ /* 1701*14414594SDavid du Colombier+ * Initialize hash links for u9fsnodes 1702*14414594SDavid du Colombier+ * and build u9fsnode free list. 1703*14414594SDavid du Colombier+ */ 1704*14414594SDavid du Colombier+ void 1705*14414594SDavid du Colombier+ u9fs_nhinit() 1706*14414594SDavid du Colombier+ { 1707*14414594SDavid du Colombier+ u9fsnode_zone = zinit("U9FSNODE", sizeof(struct u9fsnode), 0, 0, 1); 1708*14414594SDavid du Colombier+ u9fsnodehashtbl = phashinit(desiredvnodes, M_U9FSHASH, &u9fsnodehash); 1709*14414594SDavid du Colombier+ } 1710*14414594SDavid du Colombier+ 1711*14414594SDavid du Colombier+ /* 1712*14414594SDavid du Colombier+ * Look up a vnode/u9fsnode by file handle. 1713*14414594SDavid du Colombier+ * Callers must check for mount points!! 1714*14414594SDavid du Colombier+ * In all cases, a pointer to a 1715*14414594SDavid du Colombier+ * u9fsnode structure is returned. 1716*14414594SDavid du Colombier+ */ 1717*14414594SDavid du Colombier+ static int u9fs_node_hash_lock; 1718*14414594SDavid du Colombier+ 1719*14414594SDavid du Colombier+ int 1720*14414594SDavid du Colombier+ u9fs_nget(mntp, fh, npp, p) 1721*14414594SDavid du Colombier+ struct mount *mntp; 1722*14414594SDavid du Colombier+ register u9fsfh_t fh; 1723*14414594SDavid du Colombier+ struct u9fsnode **npp; 1724*14414594SDavid du Colombier+ struct proc * p; 1725*14414594SDavid du Colombier+ { 1726*14414594SDavid du Colombier+ struct u9fsnode *np; 1727*14414594SDavid du Colombier+ struct u9fsnodehashhead *nhpp; 1728*14414594SDavid du Colombier+ register struct vnode *vp; 1729*14414594SDavid du Colombier+ struct vnode *nvp; 1730*14414594SDavid du Colombier+ int error; 1731*14414594SDavid du Colombier+ 1732*14414594SDavid du Colombier+ nhpp = U9FSNOHASH(fh); 1733*14414594SDavid du Colombier+ loop: 1734*14414594SDavid du Colombier+ for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 1735*14414594SDavid du Colombier+ if (mntp != U9FSTOV(np)->v_mount || fh != np->n_qid.path ) 1736*14414594SDavid du Colombier+ continue; 1737*14414594SDavid du Colombier+ vp = U9FSTOV(np); 1738*14414594SDavid du Colombier+ if (vget(vp, LK_EXCLUSIVE, p)) 1739*14414594SDavid du Colombier+ goto loop; 1740*14414594SDavid du Colombier+ *npp = np; 1741*14414594SDavid du Colombier+ return(0); 1742*14414594SDavid du Colombier+ } 1743*14414594SDavid du Colombier+ /* 1744*14414594SDavid du Colombier+ * Obtain a lock to prevent a race condition if the getnewvnode() 1745*14414594SDavid du Colombier+ * or MALLOC() below happens to block. 1746*14414594SDavid du Colombier+ */ 1747*14414594SDavid du Colombier+ if (u9fs_node_hash_lock) { 1748*14414594SDavid du Colombier+ while (u9fs_node_hash_lock) { 1749*14414594SDavid du Colombier+ u9fs_node_hash_lock = -1; 1750*14414594SDavid du Colombier+ tsleep(&u9fs_node_hash_lock, PVM, "u9fsngt", 0); 1751*14414594SDavid du Colombier+ } 1752*14414594SDavid du Colombier+ goto loop; 1753*14414594SDavid du Colombier+ } 1754*14414594SDavid du Colombier+ u9fs_node_hash_lock = 1; 1755*14414594SDavid du Colombier+ 1756*14414594SDavid du Colombier+ /* 1757*14414594SDavid du Colombier+ * allocate before getnewvnode since doing so afterward 1758*14414594SDavid du Colombier+ * might cause a bogus v_data pointer to get dereferenced 1759*14414594SDavid du Colombier+ * elsewhere if zalloc should block. 1760*14414594SDavid du Colombier+ */ 1761*14414594SDavid du Colombier+ np = zalloc(u9fsnode_zone); 1762*14414594SDavid du Colombier+ 1763*14414594SDavid du Colombier+ error = getnewvnode(VT_U9FS, mntp, u9fs_vnodeop_p, &nvp); 1764*14414594SDavid du Colombier+ if (error) { 1765*14414594SDavid du Colombier+ if (u9fs_node_hash_lock < 0) 1766*14414594SDavid du Colombier+ wakeup(&u9fs_node_hash_lock); 1767*14414594SDavid du Colombier+ u9fs_node_hash_lock = 0; 1768*14414594SDavid du Colombier+ *npp = 0; 1769*14414594SDavid du Colombier+ zfree(u9fsnode_zone, np); 1770*14414594SDavid du Colombier+ return (error); 1771*14414594SDavid du Colombier+ } 1772*14414594SDavid du Colombier+ vp = nvp; 1773*14414594SDavid du Colombier+ bzero((caddr_t)np, sizeof *np); 1774*14414594SDavid du Colombier+ vp->v_data = np; 1775*14414594SDavid du Colombier+ np->n_vnode = vp; 1776*14414594SDavid du Colombier+ /* 1777*14414594SDavid du Colombier+ * Insert the u9fsnode in the hash queue for its new file handle 1778*14414594SDavid du Colombier+ */ 1779*14414594SDavid du Colombier+ LIST_INSERT_HEAD(nhpp, np, n_hash); 1780*14414594SDavid du Colombier+ np->n_qid.path = fh; 1781*14414594SDavid du Colombier+ np->n_qid.vers = 0; /* not in cache yet */ 1782*14414594SDavid du Colombier+ np->n_fid = 0; /* should be set by the caller */ 1783*14414594SDavid du Colombier+ *npp = np; 1784*14414594SDavid du Colombier+ 1785*14414594SDavid du Colombier+ if (u9fs_node_hash_lock < 0) 1786*14414594SDavid du Colombier+ wakeup(&u9fs_node_hash_lock); 1787*14414594SDavid du Colombier+ u9fs_node_hash_lock = 0; 1788*14414594SDavid du Colombier+ 1789*14414594SDavid du Colombier+ /* 1790*14414594SDavid du Colombier+ * Lock the new u9fsnode. 1791*14414594SDavid du Colombier+ */ 1792*14414594SDavid du Colombier+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1793*14414594SDavid du Colombier+ 1794*14414594SDavid du Colombier+ return (0); 1795*14414594SDavid du Colombier+ } 1796*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_socket.c ./9fs/9fs_socket.c 1797*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_socket.c Wed Dec 31 19:00:00 1969 1798*14414594SDavid du Colombier--- ./9fs/9fs_socket.c Thu Nov 25 15:48:46 1999 1799*14414594SDavid du Colombier*************** 1800*14414594SDavid du Colombier*** 0 **** 1801*14414594SDavid du Colombier--- 1,503 ---- 1802*14414594SDavid du Colombier+ #include <sys/param.h> 1803*14414594SDavid du Colombier+ #include <sys/sockio.h> 1804*14414594SDavid du Colombier+ #include <sys/proc.h> 1805*14414594SDavid du Colombier+ #include <sys/vnode.h> 1806*14414594SDavid du Colombier+ #include <sys/kernel.h> 1807*14414594SDavid du Colombier+ #include <sys/sysctl.h> 1808*14414594SDavid du Colombier+ #include <sys/malloc.h> 1809*14414594SDavid du Colombier+ #include <sys/mount.h> 1810*14414594SDavid du Colombier+ #include <sys/mbuf.h> 1811*14414594SDavid du Colombier+ #include <sys/socket.h> 1812*14414594SDavid du Colombier+ #include <sys/socketvar.h> 1813*14414594SDavid du Colombier+ #include <sys/systm.h> 1814*14414594SDavid du Colombier+ #include <sys/protosw.h> 1815*14414594SDavid du Colombier+ #include <sys/syslog.h> 1816*14414594SDavid du Colombier+ 1817*14414594SDavid du Colombier+ #include <netinet/in.h> 1818*14414594SDavid du Colombier+ #include <netinet/tcp.h> 1819*14414594SDavid du Colombier+ 1820*14414594SDavid du Colombier+ #include <vm/vm.h> 1821*14414594SDavid du Colombier+ #include <vm/vm_extern.h> 1822*14414594SDavid du Colombier+ #include <vm/vm_zone.h> 1823*14414594SDavid du Colombier+ 1824*14414594SDavid du Colombier+ #include <net/if.h> 1825*14414594SDavid du Colombier+ #include <net/route.h> 1826*14414594SDavid du Colombier+ #include <netinet/in.h> 1827*14414594SDavid du Colombier+ 1828*14414594SDavid du Colombier+ #include <9fs/bitstring.h> 1829*14414594SDavid du Colombier+ #include <9fs/9p.h> 1830*14414594SDavid du Colombier+ #include <9fs/9auth.h> 1831*14414594SDavid du Colombier+ #include <9fs/9fs.h> 1832*14414594SDavid du Colombier+ 1833*14414594SDavid du Colombier+ static int u9fs_reply __P((struct u9fsreq * req)); 1834*14414594SDavid du Colombier+ static int u9fs_send __P((struct socket * so, struct mbuf * mreq, struct u9fsreq * req)); 1835*14414594SDavid du Colombier+ static int u9fs_receive __P((struct socket * so, struct mbuf **mrep, struct u9fsreq * req)); 1836*14414594SDavid du Colombier+ 1837*14414594SDavid du Colombier+ static int u9fs_sndlock __P((int *flagp, int *statep, struct u9fsreq *rep)); 1838*14414594SDavid du Colombier+ static void u9fs_sndunlock __P((int *flagp, int *statep)); 1839*14414594SDavid du Colombier+ static int u9fs_rcvlock __P((struct u9fsreq *req)); 1840*14414594SDavid du Colombier+ static void u9fs_rcvunlock __P((int *flagp, int *statep)); 1841*14414594SDavid du Colombier+ 1842*14414594SDavid du Colombier+ int 1843*14414594SDavid du Colombier+ u9fs_connect(struct socket ** sop, struct sockaddr * saddr, int sotype, int soproto, struct proc * p) 1844*14414594SDavid du Colombier+ { 1845*14414594SDavid du Colombier+ register struct socket * so; 1846*14414594SDavid du Colombier+ int error, s; 1847*14414594SDavid du Colombier+ 1848*14414594SDavid du Colombier+ *sop = 0; 1849*14414594SDavid du Colombier+ error = socreate(saddr->sa_family, sop, sotype, soproto, p); 1850*14414594SDavid du Colombier+ if( error ) 1851*14414594SDavid du Colombier+ return error; 1852*14414594SDavid du Colombier+ so = *sop; 1853*14414594SDavid du Colombier+ error = soconnect(so, saddr, p); 1854*14414594SDavid du Colombier+ if( error ) 1855*14414594SDavid du Colombier+ return error; 1856*14414594SDavid du Colombier+ 1857*14414594SDavid du Colombier+ /* 1858*14414594SDavid du Colombier+ * Wait for the connection to complete. Cribbed from the 1859*14414594SDavid du Colombier+ * connect system call but with the wait timing out so 1860*14414594SDavid du Colombier+ * that interruptible mounts don't hang here for a long time. 1861*14414594SDavid du Colombier+ */ 1862*14414594SDavid du Colombier+ s = splnet(); 1863*14414594SDavid du Colombier+ while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 1864*14414594SDavid du Colombier+ (void) tsleep((caddr_t)&so->so_timeo, PSOCK, 1865*14414594SDavid du Colombier+ "u9fscon", 2 * hz); 1866*14414594SDavid du Colombier+ 1867*14414594SDavid du Colombier+ if (so->so_error) { 1868*14414594SDavid du Colombier+ error = so->so_error; 1869*14414594SDavid du Colombier+ so->so_error = 0; 1870*14414594SDavid du Colombier+ splx(s); 1871*14414594SDavid du Colombier+ return error; 1872*14414594SDavid du Colombier+ } 1873*14414594SDavid du Colombier+ splx(s); 1874*14414594SDavid du Colombier+ 1875*14414594SDavid du Colombier+ return (0); 1876*14414594SDavid du Colombier+ } 1877*14414594SDavid du Colombier+ 1878*14414594SDavid du Colombier+ int u9fs_connect_9auth(struct u9fsmount * nmp, struct u9fs_args * argp, struct socket ** sop) 1879*14414594SDavid du Colombier+ { 1880*14414594SDavid du Colombier+ int error; 1881*14414594SDavid du Colombier+ struct proc * p = & proc0; 1882*14414594SDavid du Colombier+ struct sockaddr *nam; 1883*14414594SDavid du Colombier+ 1884*14414594SDavid du Colombier+ error = getsockaddr(&nam, (caddr_t)argp->authaddr, argp->authaddrlen); 1885*14414594SDavid du Colombier+ if( error ) 1886*14414594SDavid du Colombier+ return error; 1887*14414594SDavid du Colombier+ error = u9fs_connect(sop, nam, argp->authsotype, 1888*14414594SDavid du Colombier+ argp->authsoproto, p); 1889*14414594SDavid du Colombier+ if( error == 0 ) 1890*14414594SDavid du Colombier+ return 0; 1891*14414594SDavid du Colombier+ 1892*14414594SDavid du Colombier+ u9fs_disconnect(*sop); 1893*14414594SDavid du Colombier+ *sop = 0; 1894*14414594SDavid du Colombier+ return error; 1895*14414594SDavid du Colombier+ } 1896*14414594SDavid du Colombier+ 1897*14414594SDavid du Colombier+ /* 1898*14414594SDavid du Colombier+ * Initialize sockets and congestion for a new U9FS connection. 1899*14414594SDavid du Colombier+ * We do not free the sockaddr if error. 1900*14414594SDavid du Colombier+ */ 1901*14414594SDavid du Colombier+ int 1902*14414594SDavid du Colombier+ u9fs_connect_9fs(nmp) 1903*14414594SDavid du Colombier+ register struct u9fsmount *nmp; 1904*14414594SDavid du Colombier+ { 1905*14414594SDavid du Colombier+ register struct socket *so; 1906*14414594SDavid du Colombier+ int error, rcvreserve, sndreserve; 1907*14414594SDavid du Colombier+ struct proc *p = &proc0; /* only used for socreate and sobind */ 1908*14414594SDavid du Colombier+ 1909*14414594SDavid du Colombier+ error = u9fs_connect(&nmp->nm_so, nmp->nm_nam, nmp->nm_sotype, 1910*14414594SDavid du Colombier+ nmp->nm_soproto, p); 1911*14414594SDavid du Colombier+ if (error) 1912*14414594SDavid du Colombier+ goto bad; 1913*14414594SDavid du Colombier+ so = nmp->nm_so; 1914*14414594SDavid du Colombier+ nmp->nm_soflags = so->so_proto->pr_flags; 1915*14414594SDavid du Colombier+ 1916*14414594SDavid du Colombier+ if (nmp->nm_flag & (U9FSMNT_SOFT | U9FSMNT_INT)) { 1917*14414594SDavid du Colombier+ so->so_rcv.sb_timeo = (5 * hz); 1918*14414594SDavid du Colombier+ so->so_snd.sb_timeo = (5 * hz); 1919*14414594SDavid du Colombier+ } else { 1920*14414594SDavid du Colombier+ so->so_rcv.sb_timeo = 0; 1921*14414594SDavid du Colombier+ so->so_snd.sb_timeo = 0; 1922*14414594SDavid du Colombier+ } 1923*14414594SDavid du Colombier+ 1924*14414594SDavid du Colombier+ /* XXX: i dont understand this, only one outstanding request? */ 1925*14414594SDavid du Colombier+ if (nmp->nm_sotype == SOCK_SEQPACKET) { 1926*14414594SDavid du Colombier+ sndreserve = (nmp->nm_wsize) * 2; 1927*14414594SDavid du Colombier+ rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize)) * 2; 1928*14414594SDavid du Colombier+ } else { 1929*14414594SDavid du Colombier+ if (nmp->nm_sotype != SOCK_STREAM) 1930*14414594SDavid du Colombier+ panic("u9fscon sotype"); 1931*14414594SDavid du Colombier+ if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 1932*14414594SDavid du Colombier+ struct sockopt sopt; 1933*14414594SDavid du Colombier+ int val; 1934*14414594SDavid du Colombier+ 1935*14414594SDavid du Colombier+ bzero(&sopt, sizeof sopt); 1936*14414594SDavid du Colombier+ sopt.sopt_level = SOL_SOCKET; 1937*14414594SDavid du Colombier+ sopt.sopt_name = SO_KEEPALIVE; 1938*14414594SDavid du Colombier+ sopt.sopt_val = &val; 1939*14414594SDavid du Colombier+ sopt.sopt_valsize = sizeof val; 1940*14414594SDavid du Colombier+ val = 1; 1941*14414594SDavid du Colombier+ sosetopt(so, &sopt); 1942*14414594SDavid du Colombier+ } 1943*14414594SDavid du Colombier+ if (so->so_proto->pr_protocol == IPPROTO_TCP) { 1944*14414594SDavid du Colombier+ struct sockopt sopt; 1945*14414594SDavid du Colombier+ int val; 1946*14414594SDavid du Colombier+ 1947*14414594SDavid du Colombier+ bzero(&sopt, sizeof sopt); 1948*14414594SDavid du Colombier+ sopt.sopt_level = IPPROTO_TCP; 1949*14414594SDavid du Colombier+ sopt.sopt_name = TCP_NODELAY; 1950*14414594SDavid du Colombier+ sopt.sopt_val = &val; 1951*14414594SDavid du Colombier+ sopt.sopt_valsize = sizeof val; 1952*14414594SDavid du Colombier+ val = 1; 1953*14414594SDavid du Colombier+ sosetopt(so, &sopt); 1954*14414594SDavid du Colombier+ } 1955*14414594SDavid du Colombier+ sndreserve = (nmp->nm_wsize) * 2; 1956*14414594SDavid du Colombier+ rcvreserve = (nmp->nm_rsize) * 2; 1957*14414594SDavid du Colombier+ } 1958*14414594SDavid du Colombier+ error = soreserve(so, sndreserve, rcvreserve); 1959*14414594SDavid du Colombier+ if (error) 1960*14414594SDavid du Colombier+ goto bad; 1961*14414594SDavid du Colombier+ so->so_rcv.sb_flags |= SB_NOINTR; 1962*14414594SDavid du Colombier+ so->so_snd.sb_flags |= SB_NOINTR; 1963*14414594SDavid du Colombier+ 1964*14414594SDavid du Colombier+ /* Initialize other non-zero congestion variables */ 1965*14414594SDavid du Colombier+ nmp->nm_sent = 0; 1966*14414594SDavid du Colombier+ return (0); 1967*14414594SDavid du Colombier+ 1968*14414594SDavid du Colombier+ bad: 1969*14414594SDavid du Colombier+ u9fs_disconnect(nmp->nm_so); 1970*14414594SDavid du Colombier+ nmp->nm_so = 0; 1971*14414594SDavid du Colombier+ return (error); 1972*14414594SDavid du Colombier+ } 1973*14414594SDavid du Colombier+ 1974*14414594SDavid du Colombier+ /* 1975*14414594SDavid du Colombier+ * U9FS disconnect. Clean up and unlink. 1976*14414594SDavid du Colombier+ */ 1977*14414594SDavid du Colombier+ void 1978*14414594SDavid du Colombier+ u9fs_disconnect(struct socket * so) 1979*14414594SDavid du Colombier+ { 1980*14414594SDavid du Colombier+ soshutdown(so, 2); 1981*14414594SDavid du Colombier+ soclose(so); 1982*14414594SDavid du Colombier+ } 1983*14414594SDavid du Colombier+ 1984*14414594SDavid du Colombier+ /* 1985*14414594SDavid du Colombier+ * Lock a socket against others. 1986*14414594SDavid du Colombier+ * Necessary for STREAM sockets to ensure you get an entire rpc request/reply 1987*14414594SDavid du Colombier+ * and also to avoid race conditions between the processes with u9fs requests 1988*14414594SDavid du Colombier+ * in progress when a reconnect is necessary. 1989*14414594SDavid du Colombier+ */ 1990*14414594SDavid du Colombier+ static int 1991*14414594SDavid du Colombier+ u9fs_sndlock(flagp, statep, rep) 1992*14414594SDavid du Colombier+ register int *flagp; 1993*14414594SDavid du Colombier+ register int *statep; 1994*14414594SDavid du Colombier+ struct u9fsreq *rep; 1995*14414594SDavid du Colombier+ { 1996*14414594SDavid du Colombier+ struct proc *p; 1997*14414594SDavid du Colombier+ int slpflag = 0, slptimeo = 0; 1998*14414594SDavid du Colombier+ 1999*14414594SDavid du Colombier+ if (rep) { 2000*14414594SDavid du Colombier+ p = rep->r_procp; 2001*14414594SDavid du Colombier+ if (rep->r_nmp->nm_flag & U9FSMNT_INT) 2002*14414594SDavid du Colombier+ slpflag = PCATCH; 2003*14414594SDavid du Colombier+ } else 2004*14414594SDavid du Colombier+ p = (struct proc *)0; 2005*14414594SDavid du Colombier+ while (*statep & U9FSSTA_SNDLOCK) { 2006*14414594SDavid du Colombier+ if (u9fs_sigintr(rep->r_nmp, p)) 2007*14414594SDavid du Colombier+ return (EINTR); 2008*14414594SDavid du Colombier+ *statep |= U9FSSTA_WANTSND; 2009*14414594SDavid du Colombier+ (void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), 2010*14414594SDavid du Colombier+ "u9fsndlck", slptimeo); 2011*14414594SDavid du Colombier+ if (slpflag == PCATCH) { 2012*14414594SDavid du Colombier+ slpflag = 0; 2013*14414594SDavid du Colombier+ slptimeo = 2 * hz; 2014*14414594SDavid du Colombier+ } 2015*14414594SDavid du Colombier+ } 2016*14414594SDavid du Colombier+ *statep |= U9FSSTA_SNDLOCK; 2017*14414594SDavid du Colombier+ return (0); 2018*14414594SDavid du Colombier+ } 2019*14414594SDavid du Colombier+ 2020*14414594SDavid du Colombier+ 2021*14414594SDavid du Colombier+ /* 2022*14414594SDavid du Colombier+ * Unlock the stream socket for others. 2023*14414594SDavid du Colombier+ */ 2024*14414594SDavid du Colombier+ static void 2025*14414594SDavid du Colombier+ u9fs_sndunlock(flagp, statep) 2026*14414594SDavid du Colombier+ register int *flagp; 2027*14414594SDavid du Colombier+ register int *statep; 2028*14414594SDavid du Colombier+ { 2029*14414594SDavid du Colombier+ 2030*14414594SDavid du Colombier+ if ((*statep & U9FSSTA_SNDLOCK) == 0) 2031*14414594SDavid du Colombier+ panic("u9fs sndunlock"); 2032*14414594SDavid du Colombier+ *statep &= ~U9FSSTA_SNDLOCK; 2033*14414594SDavid du Colombier+ if (*statep & U9FSSTA_WANTSND) { 2034*14414594SDavid du Colombier+ *statep &= ~U9FSSTA_WANTSND; 2035*14414594SDavid du Colombier+ wakeup((caddr_t)flagp); 2036*14414594SDavid du Colombier+ } 2037*14414594SDavid du Colombier+ } 2038*14414594SDavid du Colombier+ 2039*14414594SDavid du Colombier+ /* 2040*14414594SDavid du Colombier+ * Test for a termination condition pending on the process. 2041*14414594SDavid du Colombier+ * This is used for U9FSMNT_INT mounts. 2042*14414594SDavid du Colombier+ */ 2043*14414594SDavid du Colombier+ int 2044*14414594SDavid du Colombier+ u9fs_sigintr(nmp, p) 2045*14414594SDavid du Colombier+ struct u9fsmount *nmp; 2046*14414594SDavid du Colombier+ struct proc * p; 2047*14414594SDavid du Colombier+ { 2048*14414594SDavid du Colombier+ if (!(nmp->nm_flag & U9FSMNT_INT)) 2049*14414594SDavid du Colombier+ return (0); 2050*14414594SDavid du Colombier+ if (p && p->p_siglist && 2051*14414594SDavid du Colombier+ (((p->p_siglist & ~p->p_sigmask) & ~p->p_sigignore) & 2052*14414594SDavid du Colombier+ U9FSINT_SIGMASK)) 2053*14414594SDavid du Colombier+ return (EINTR); 2054*14414594SDavid du Colombier+ return (0); 2055*14414594SDavid du Colombier+ } 2056*14414594SDavid du Colombier+ 2057*14414594SDavid du Colombier+ /* 2058*14414594SDavid du Colombier+ * This is the u9fs send routine. For connection based socket types, it 2059*14414594SDavid du Colombier+ * must be called with an u9fs_sndlock() on the socket. 2060*14414594SDavid du Colombier+ * "rep == NULL" indicates that it has been called from a server. 2061*14414594SDavid du Colombier+ * For the client side: 2062*14414594SDavid du Colombier+ * - return EINTR if the RPC is terminated, 0 otherwise 2063*14414594SDavid du Colombier+ * - set R_MUSTRESEND if the send fails for any reason 2064*14414594SDavid du Colombier+ * - do any cleanup required by recoverable socket errors (?) 2065*14414594SDavid du Colombier+ * For the server side: 2066*14414594SDavid du Colombier+ * - return EINTR or ERESTART if interrupted by a signal 2067*14414594SDavid du Colombier+ * - return EPIPE if a connection is lost for connection based sockets (TCP...) 2068*14414594SDavid du Colombier+ * - do any cleanup required by recoverable socket errors (?) 2069*14414594SDavid du Colombier+ */ 2070*14414594SDavid du Colombier+ static int 2071*14414594SDavid du Colombier+ u9fs_send(so, top, req) 2072*14414594SDavid du Colombier+ register struct socket *so; 2073*14414594SDavid du Colombier+ register struct mbuf *top; 2074*14414594SDavid du Colombier+ struct u9fsreq *req; 2075*14414594SDavid du Colombier+ { 2076*14414594SDavid du Colombier+ int error, soflags, flags; 2077*14414594SDavid du Colombier+ 2078*14414594SDavid du Colombier+ soflags = so->so_proto->pr_flags; 2079*14414594SDavid du Colombier+ if (so->so_type == SOCK_SEQPACKET) 2080*14414594SDavid du Colombier+ flags = MSG_EOR; 2081*14414594SDavid du Colombier+ else 2082*14414594SDavid du Colombier+ flags = 0; 2083*14414594SDavid du Colombier+ 2084*14414594SDavid du Colombier+ error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 0, top, 0, 2085*14414594SDavid du Colombier+ flags, req->r_procp); 2086*14414594SDavid du Colombier+ if (error) 2087*14414594SDavid du Colombier+ log(LOG_INFO, "u9fs send error %d for server %s\n",error, 2088*14414594SDavid du Colombier+ req->r_nmp->nm_mountp->mnt_stat.f_mntfromname); 2089*14414594SDavid du Colombier+ 2090*14414594SDavid du Colombier+ return (error); 2091*14414594SDavid du Colombier+ } 2092*14414594SDavid du Colombier+ 2093*14414594SDavid du Colombier+ static int 2094*14414594SDavid du Colombier+ u9fs_receive(so, mrep, req) 2095*14414594SDavid du Colombier+ register struct socket * so; 2096*14414594SDavid du Colombier+ struct mbuf **mrep; 2097*14414594SDavid du Colombier+ struct u9fsreq * req; 2098*14414594SDavid du Colombier+ { 2099*14414594SDavid du Colombier+ struct uio auio; 2100*14414594SDavid du Colombier+ u_int32_t len; 2101*14414594SDavid du Colombier+ int error = 0, sotype, rcvflg; 2102*14414594SDavid du Colombier+ 2103*14414594SDavid du Colombier+ /* 2104*14414594SDavid du Colombier+ * Set up arguments for soreceive() 2105*14414594SDavid du Colombier+ */ 2106*14414594SDavid du Colombier+ *mrep = (struct mbuf *)0; 2107*14414594SDavid du Colombier+ sotype = req->r_nmp->nm_sotype; 2108*14414594SDavid du Colombier+ 2109*14414594SDavid du Colombier+ /* 2110*14414594SDavid du Colombier+ * For reliable protocols, lock against other senders/receivers 2111*14414594SDavid du Colombier+ * in case a reconnect is necessary. 2112*14414594SDavid du Colombier+ * For SOCK_STREAM, first get the Record Mark to find out how much 2113*14414594SDavid du Colombier+ * more there is to get. 2114*14414594SDavid du Colombier+ * We must lock the socket against other receivers 2115*14414594SDavid du Colombier+ * until we have an entire rpc request/reply. 2116*14414594SDavid du Colombier+ */ 2117*14414594SDavid du Colombier+ if (sotype == SOCK_SEQPACKET ) { 2118*14414594SDavid du Colombier+ if( (so->so_state & SS_ISCONNECTED) == 0 ) 2119*14414594SDavid du Colombier+ return (EACCES); 2120*14414594SDavid du Colombier+ auio.uio_resid = len = 1000000; 2121*14414594SDavid du Colombier+ auio.uio_procp = req->r_procp; 2122*14414594SDavid du Colombier+ do { 2123*14414594SDavid du Colombier+ rcvflg = 0; 2124*14414594SDavid du Colombier+ error = so->so_proto->pr_usrreqs->pru_soreceive 2125*14414594SDavid du Colombier+ (so, 0, &auio, mrep, 2126*14414594SDavid du Colombier+ (struct mbuf **)0, &rcvflg); 2127*14414594SDavid du Colombier+ } while (error == EWOULDBLOCK); 2128*14414594SDavid du Colombier+ len -= auio.uio_resid; 2129*14414594SDavid du Colombier+ } 2130*14414594SDavid du Colombier+ if (error) { 2131*14414594SDavid du Colombier+ m_freem(*mrep); 2132*14414594SDavid du Colombier+ *mrep = (struct mbuf *)0; 2133*14414594SDavid du Colombier+ } 2134*14414594SDavid du Colombier+ return (error); 2135*14414594SDavid du Colombier+ } 2136*14414594SDavid du Colombier+ 2137*14414594SDavid du Colombier+ static int 2138*14414594SDavid du Colombier+ u9fs_rcvlock(req) 2139*14414594SDavid du Colombier+ register struct u9fsreq *req; 2140*14414594SDavid du Colombier+ { 2141*14414594SDavid du Colombier+ register int *flagp = &req->r_nmp->nm_flag; 2142*14414594SDavid du Colombier+ register int *statep = &req->r_nmp->nm_state; 2143*14414594SDavid du Colombier+ int slpflag, slptimeo = 0; 2144*14414594SDavid du Colombier+ 2145*14414594SDavid du Colombier+ if (*flagp & U9FSMNT_INT) 2146*14414594SDavid du Colombier+ slpflag = PCATCH; 2147*14414594SDavid du Colombier+ else 2148*14414594SDavid du Colombier+ slpflag = 0; 2149*14414594SDavid du Colombier+ while (*statep & U9FSSTA_RCVLOCK) { 2150*14414594SDavid du Colombier+ if (u9fs_sigintr(req->r_nmp, req->r_procp)) 2151*14414594SDavid du Colombier+ return (EINTR); 2152*14414594SDavid du Colombier+ *statep |= U9FSSTA_WANTRCV; 2153*14414594SDavid du Colombier+ (void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), "u9fsrcvlk", 2154*14414594SDavid du Colombier+ slptimeo); 2155*14414594SDavid du Colombier+ /* 2156*14414594SDavid du Colombier+ * If our reply was recieved while we were sleeping, 2157*14414594SDavid du Colombier+ * then just return without taking the lock to avoid a 2158*14414594SDavid du Colombier+ * situation where a single iod could 'capture' the 2159*14414594SDavid du Colombier+ * recieve lock. 2160*14414594SDavid du Colombier+ */ 2161*14414594SDavid du Colombier+ if (req->r_mrep != NULL) 2162*14414594SDavid du Colombier+ return (EALREADY); 2163*14414594SDavid du Colombier+ if (slpflag == PCATCH) { 2164*14414594SDavid du Colombier+ slpflag = 0; 2165*14414594SDavid du Colombier+ slptimeo = 2 * hz; 2166*14414594SDavid du Colombier+ } 2167*14414594SDavid du Colombier+ } 2168*14414594SDavid du Colombier+ *statep |= U9FSSTA_RCVLOCK; 2169*14414594SDavid du Colombier+ return (0); 2170*14414594SDavid du Colombier+ } 2171*14414594SDavid du Colombier+ 2172*14414594SDavid du Colombier+ /* 2173*14414594SDavid du Colombier+ * Unlock the stream socket for others. 2174*14414594SDavid du Colombier+ */ 2175*14414594SDavid du Colombier+ static void 2176*14414594SDavid du Colombier+ u9fs_rcvunlock(flagp, statep) 2177*14414594SDavid du Colombier+ register int *flagp; 2178*14414594SDavid du Colombier+ register int *statep; 2179*14414594SDavid du Colombier+ { 2180*14414594SDavid du Colombier+ 2181*14414594SDavid du Colombier+ if ((*statep & U9FSSTA_RCVLOCK) == 0) 2182*14414594SDavid du Colombier+ panic("u9fs rcvunlock"); 2183*14414594SDavid du Colombier+ *statep &= ~U9FSSTA_RCVLOCK; 2184*14414594SDavid du Colombier+ if (*statep & U9FSSTA_WANTRCV) { 2185*14414594SDavid du Colombier+ *statep &= ~U9FSSTA_WANTRCV; 2186*14414594SDavid du Colombier+ wakeup((caddr_t)flagp); 2187*14414594SDavid du Colombier+ } 2188*14414594SDavid du Colombier+ } 2189*14414594SDavid du Colombier+ 2190*14414594SDavid du Colombier+ /* 2191*14414594SDavid du Colombier+ * Implement receipt of reply on a socket. 2192*14414594SDavid du Colombier+ * We must search through the list of received datagrams matching them 2193*14414594SDavid du Colombier+ * with outstanding requests using the xid, until ours is found. 2194*14414594SDavid du Colombier+ */ 2195*14414594SDavid du Colombier+ /* ARGSUSED */ 2196*14414594SDavid du Colombier+ static 2197*14414594SDavid du Colombier+ int u9fs_reply(struct u9fsreq * req) 2198*14414594SDavid du Colombier+ { 2199*14414594SDavid du Colombier+ int error; 2200*14414594SDavid du Colombier+ struct mbuf * mrep; 2201*14414594SDavid du Colombier+ register struct u9fsmount *nmp = req->r_nmp; 2202*14414594SDavid du Colombier+ u_short tag; 2203*14414594SDavid du Colombier+ struct u9fsreq * qp; 2204*14414594SDavid du Colombier+ 2205*14414594SDavid du Colombier+ /* 2206*14414594SDavid du Colombier+ * Loop around until we get our own reply 2207*14414594SDavid du Colombier+ */ 2208*14414594SDavid du Colombier+ for (;;) { 2209*14414594SDavid du Colombier+ /* 2210*14414594SDavid du Colombier+ * Lock against other receivers so that I don't get stuck in 2211*14414594SDavid du Colombier+ * sbwait() after someone else has received my reply for me. 2212*14414594SDavid du Colombier+ * Also necessary for connection based protocols to avoid 2213*14414594SDavid du Colombier+ * race conditions during a reconnect. 2214*14414594SDavid du Colombier+ * If u9fs_rcvlock() returns EALREADY, that means that 2215*14414594SDavid du Colombier+ * the reply has already been recieved by another 2216*14414594SDavid du Colombier+ * process and we can return immediately. In this 2217*14414594SDavid du Colombier+ * case, the lock is not taken to avoid races with 2218*14414594SDavid du Colombier+ * other processes. 2219*14414594SDavid du Colombier+ */ 2220*14414594SDavid du Colombier+ error = u9fs_rcvlock(req); 2221*14414594SDavid du Colombier+ if (error == EALREADY) 2222*14414594SDavid du Colombier+ return (0); 2223*14414594SDavid du Colombier+ if (error) 2224*14414594SDavid du Colombier+ return (error); 2225*14414594SDavid du Colombier+ /* 2226*14414594SDavid du Colombier+ * Get the next Rpc reply off the socket 2227*14414594SDavid du Colombier+ */ 2228*14414594SDavid du Colombier+ error = u9fs_receive(nmp->nm_so, &mrep, req); 2229*14414594SDavid du Colombier+ u9fs_rcvunlock(&nmp->nm_flag, &nmp->nm_state); 2230*14414594SDavid du Colombier+ if (error) 2231*14414594SDavid du Colombier+ return (error); 2232*14414594SDavid du Colombier+ 2233*14414594SDavid du Colombier+ /* extract the tag */ 2234*14414594SDavid du Colombier+ tag = u9p_m_tag(&mrep); 2235*14414594SDavid du Colombier+ 2236*14414594SDavid du Colombier+ /* 2237*14414594SDavid du Colombier+ * Loop through the request list to match up the reply 2238*14414594SDavid du Colombier+ * Iff no match, just drop the datagram 2239*14414594SDavid du Colombier+ */ 2240*14414594SDavid du Colombier+ for (qp = nmp->nm_reqq.tqh_first; qp != 0; qp = qp->r_chain.tqe_next) { 2241*14414594SDavid du Colombier+ if ( qp->r_mrep == 0 && qp->r_tag == tag ) 2242*14414594SDavid du Colombier+ break; 2243*14414594SDavid du Colombier+ } 2244*14414594SDavid du Colombier+ if( qp == 0 ) { 2245*14414594SDavid du Colombier+ m_freem(mrep); 2246*14414594SDavid du Colombier+ continue; 2247*14414594SDavid du Colombier+ } 2248*14414594SDavid du Colombier+ 2249*14414594SDavid du Colombier+ if( u9p_m_m2s(&mrep, qp->r_rep) ) { /* freed by m2s */ 2250*14414594SDavid du Colombier+ continue; 2251*14414594SDavid du Colombier+ } 2252*14414594SDavid du Colombier+ 2253*14414594SDavid du Colombier+ qp->r_mrep = mrep; /* should not be freed until the reply is read */ 2254*14414594SDavid du Colombier+ 2255*14414594SDavid du Colombier+ if( qp == req ) 2256*14414594SDavid du Colombier+ return 0; 2257*14414594SDavid du Colombier+ } 2258*14414594SDavid du Colombier+ } 2259*14414594SDavid du Colombier+ 2260*14414594SDavid du Colombier+ int u9fs_request(struct u9fsreq * req, struct u9fsreq * rep, int relm) 2261*14414594SDavid du Colombier+ { 2262*14414594SDavid du Colombier+ struct mbuf * mreq; 2263*14414594SDavid du Colombier+ int error,s; 2264*14414594SDavid du Colombier+ struct u9fsmount * nmp; 2265*14414594SDavid du Colombier+ 2266*14414594SDavid du Colombier+ req->r_rep = rep; 2267*14414594SDavid du Colombier+ req->r_mrep = 0; 2268*14414594SDavid du Colombier+ nmp = req->r_nmp; 2269*14414594SDavid du Colombier+ req->r_tag = u9fs_id_new(nmp->nm_tags); 2270*14414594SDavid du Colombier+ 2271*14414594SDavid du Colombier+ mreq = u9p_m_s2m(req); 2272*14414594SDavid du Colombier+ 2273*14414594SDavid du Colombier+ /* 2274*14414594SDavid du Colombier+ * Chain request into list of outstanding requests. Be sure 2275*14414594SDavid du Colombier+ * to put it LAST so timer finds oldest requests first. 2276*14414594SDavid du Colombier+ */ 2277*14414594SDavid du Colombier+ s = splsoftclock(); 2278*14414594SDavid du Colombier+ TAILQ_INSERT_TAIL(&nmp->nm_reqq, req, r_chain); 2279*14414594SDavid du Colombier+ splx(s); 2280*14414594SDavid du Colombier+ 2281*14414594SDavid du Colombier+ error = u9fs_send(nmp->nm_so, mreq, req); 2282*14414594SDavid du Colombier+ 2283*14414594SDavid du Colombier+ if( !error ) 2284*14414594SDavid du Colombier+ error = u9fs_reply(req); 2285*14414594SDavid du Colombier+ 2286*14414594SDavid du Colombier+ /* 2287*14414594SDavid du Colombier+ * RPC done, unlink the request. 2288*14414594SDavid du Colombier+ */ 2289*14414594SDavid du Colombier+ s = splsoftclock(); 2290*14414594SDavid du Colombier+ TAILQ_REMOVE(&nmp->nm_reqq, req, r_chain); 2291*14414594SDavid du Colombier+ splx(s); 2292*14414594SDavid du Colombier+ 2293*14414594SDavid du Colombier+ u9fs_id_free(nmp->nm_tags, req->r_tag); 2294*14414594SDavid du Colombier+ 2295*14414594SDavid du Colombier+ if( !error && relm ) { 2296*14414594SDavid du Colombier+ m_freem(req->r_mrep); 2297*14414594SDavid du Colombier+ req->r_mrep = 0; 2298*14414594SDavid du Colombier+ } 2299*14414594SDavid du Colombier+ if( rep->r_type == Rerror ) 2300*14414594SDavid du Colombier+ error = EACCES; 2301*14414594SDavid du Colombier+ 2302*14414594SDavid du Colombier+ return error; 2303*14414594SDavid du Colombier+ } 2304*14414594SDavid du Colombier+ 2305*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_subr.c ./9fs/9fs_subr.c 2306*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_subr.c Wed Dec 31 19:00:00 1969 2307*14414594SDavid du Colombier--- ./9fs/9fs_subr.c Fri Nov 26 12:28:17 1999 2308*14414594SDavid du Colombier*************** 2309*14414594SDavid du Colombier*** 0 **** 2310*14414594SDavid du Colombier--- 1,240 ---- 2311*14414594SDavid du Colombier+ #include <sys/param.h> 2312*14414594SDavid du Colombier+ #include <sys/sockio.h> 2313*14414594SDavid du Colombier+ #include <sys/proc.h> 2314*14414594SDavid du Colombier+ #include <sys/vnode.h> 2315*14414594SDavid du Colombier+ #include <sys/kernel.h> 2316*14414594SDavid du Colombier+ #include <sys/sysctl.h> 2317*14414594SDavid du Colombier+ #include <sys/malloc.h> 2318*14414594SDavid du Colombier+ #include <sys/mount.h> 2319*14414594SDavid du Colombier+ #include <sys/mbuf.h> 2320*14414594SDavid du Colombier+ #include <sys/socket.h> 2321*14414594SDavid du Colombier+ #include <sys/socketvar.h> 2322*14414594SDavid du Colombier+ #include <sys/systm.h> 2323*14414594SDavid du Colombier+ #include <sys/protosw.h> 2324*14414594SDavid du Colombier+ #include <sys/syslog.h> 2325*14414594SDavid du Colombier+ 2326*14414594SDavid du Colombier+ #include <netinet/in.h> 2327*14414594SDavid du Colombier+ #include <netinet/tcp.h> 2328*14414594SDavid du Colombier+ 2329*14414594SDavid du Colombier+ #include <vm/vm.h> 2330*14414594SDavid du Colombier+ #include <vm/vm_extern.h> 2331*14414594SDavid du Colombier+ #include <vm/vm_zone.h> 2332*14414594SDavid du Colombier+ 2333*14414594SDavid du Colombier+ #include <net/if.h> 2334*14414594SDavid du Colombier+ #include <net/route.h> 2335*14414594SDavid du Colombier+ #include <netinet/in.h> 2336*14414594SDavid du Colombier+ 2337*14414594SDavid du Colombier+ #include <9fs/bitstring.h> 2338*14414594SDavid du Colombier+ #include <9fs/9p.h> 2339*14414594SDavid du Colombier+ #include <9fs/9auth.h> 2340*14414594SDavid du Colombier+ #include <9fs/9fs.h> 2341*14414594SDavid du Colombier+ 2342*14414594SDavid du Colombier+ vm_zone_t u9fsuser_zone; 2343*14414594SDavid du Colombier+ LIST_HEAD(u9fsuserhashhead, u9fsuser) * u9fsuidhashtbl, * u9fsunamehashtbl; 2344*14414594SDavid du Colombier+ u_long u9fsuidhash; 2345*14414594SDavid du Colombier+ u_long u9fsunamehash; 2346*14414594SDavid du Colombier+ MALLOC_DEFINE(M_U9FSBITS, "U9FS bits", "U9FS tag/fid maps"); 2347*14414594SDavid du Colombier+ 2348*14414594SDavid du Colombier+ static int u9fs_hashname __P((char * name)); 2349*14414594SDavid du Colombier+ 2350*14414594SDavid du Colombier+ void u9fs_uhinit() 2351*14414594SDavid du Colombier+ { 2352*14414594SDavid du Colombier+ u9fsuser_zone = zinit("U9FSUSER", sizeof(struct u9fsuser), 0, 0, 1); 2353*14414594SDavid du Colombier+ u9fsuidhashtbl = phashinit(U9FS_USER_HASHSIZE, M_U9FSHASH, &u9fsuidhash); 2354*14414594SDavid du Colombier+ u9fsunamehashtbl = phashinit(U9FS_USER_HASHSIZE, M_U9FSHASH, &u9fsunamehash); 2355*14414594SDavid du Colombier+ } 2356*14414594SDavid du Colombier+ 2357*14414594SDavid du Colombier+ void 2358*14414594SDavid du Colombier+ u9fs_id_init(bits) 2359*14414594SDavid du Colombier+ bitstr_t ** bits; 2360*14414594SDavid du Colombier+ { 2361*14414594SDavid du Colombier+ bit_alloc(*bits, 0x10000, M_U9FSBITS, M_WAITOK); 2362*14414594SDavid du Colombier+ bit_nset(*bits, 1, 0xffff); /* we dont use zero */ 2363*14414594SDavid du Colombier+ } 2364*14414594SDavid du Colombier+ 2365*14414594SDavid du Colombier+ u_short 2366*14414594SDavid du Colombier+ u9fs_id_new(bits) 2367*14414594SDavid du Colombier+ bitstr_t * bits; 2368*14414594SDavid du Colombier+ { 2369*14414594SDavid du Colombier+ int v; 2370*14414594SDavid du Colombier+ 2371*14414594SDavid du Colombier+ bit_ffs(bits, 0x10000, &v); 2372*14414594SDavid du Colombier+ if( v < 0 ) 2373*14414594SDavid du Colombier+ panic("no more u9fs bits!"); 2374*14414594SDavid du Colombier+ 2375*14414594SDavid du Colombier+ bit_clear(bits, v); 2376*14414594SDavid du Colombier+ return ((u_short)v); 2377*14414594SDavid du Colombier+ } 2378*14414594SDavid du Colombier+ 2379*14414594SDavid du Colombier+ void 2380*14414594SDavid du Colombier+ u9fs_id_free(bits, v) 2381*14414594SDavid du Colombier+ bitstr_t * bits; 2382*14414594SDavid du Colombier+ u_short v; 2383*14414594SDavid du Colombier+ { 2384*14414594SDavid du Colombier+ bit_set(bits, v); 2385*14414594SDavid du Colombier+ } 2386*14414594SDavid du Colombier+ 2387*14414594SDavid du Colombier+ 2388*14414594SDavid du Colombier+ static int u9fs_hashname(char * cp) 2389*14414594SDavid du Colombier+ { 2390*14414594SDavid du Colombier+ int h = 0; 2391*14414594SDavid du Colombier+ 2392*14414594SDavid du Colombier+ cp[U9FS_NAMELEN-1] = 0; 2393*14414594SDavid du Colombier+ do 2394*14414594SDavid du Colombier+ h += *cp; 2395*14414594SDavid du Colombier+ while ( *cp++ ); 2396*14414594SDavid du Colombier+ 2397*14414594SDavid du Colombier+ return h; 2398*14414594SDavid du Colombier+ } 2399*14414594SDavid du Colombier+ 2400*14414594SDavid du Colombier+ void u9fs_hashuser(uid_t uid, char * name) 2401*14414594SDavid du Colombier+ { 2402*14414594SDavid du Colombier+ int h; 2403*14414594SDavid du Colombier+ struct u9fsuser * u9p, *u9p2; 2404*14414594SDavid du Colombier+ struct u9fsuserhashhead * u9hp; 2405*14414594SDavid du Colombier+ 2406*14414594SDavid du Colombier+ if( u9fs_name2uid(name) != 65534 ) /* already hashed by previous mount */ 2407*14414594SDavid du Colombier+ return; 2408*14414594SDavid du Colombier+ 2409*14414594SDavid du Colombier+ u9p = zalloc(u9fsuser_zone); 2410*14414594SDavid du Colombier+ bzero(u9p, sizeof(*u9p)); 2411*14414594SDavid du Colombier+ u9p->u_uid = uid; 2412*14414594SDavid du Colombier+ strncpy(u9p->u_name, name, U9FS_NAMELEN); 2413*14414594SDavid du Colombier+ u9hp = & u9fsuidhashtbl[uid % u9fsuidhash]; 2414*14414594SDavid du Colombier+ LIST_INSERT_HEAD(u9hp, u9p, u_hash); 2415*14414594SDavid du Colombier+ 2416*14414594SDavid du Colombier+ u9p2 = zalloc(u9fsuser_zone); 2417*14414594SDavid du Colombier+ bcopy(u9p, u9p2, sizeof(*u9p)); 2418*14414594SDavid du Colombier+ h = u9fs_hashname(name); 2419*14414594SDavid du Colombier+ u9hp = & u9fsunamehashtbl[h%u9fsunamehash]; 2420*14414594SDavid du Colombier+ LIST_INSERT_HEAD(u9hp, u9p2, u_hash); 2421*14414594SDavid du Colombier+ } 2422*14414594SDavid du Colombier+ 2423*14414594SDavid du Colombier+ /* name must be at least U9FS_NAMELEN long! */ 2424*14414594SDavid du Colombier+ struct u9fsuser * u9fs_finduser(uid_t uid) 2425*14414594SDavid du Colombier+ { 2426*14414594SDavid du Colombier+ struct u9fsuser * u9p; 2427*14414594SDavid du Colombier+ struct u9fsuserhashhead * u9hp; 2428*14414594SDavid du Colombier+ 2429*14414594SDavid du Colombier+ u9hp = & u9fsuidhashtbl[uid % u9fsuidhash]; 2430*14414594SDavid du Colombier+ LIST_FOREACH(u9p, u9hp, u_hash) 2431*14414594SDavid du Colombier+ if( u9p->u_uid == uid ) 2432*14414594SDavid du Colombier+ break; 2433*14414594SDavid du Colombier+ 2434*14414594SDavid du Colombier+ return u9p; 2435*14414594SDavid du Colombier+ } 2436*14414594SDavid du Colombier+ 2437*14414594SDavid du Colombier+ uid_t u9fs_name2uid(char *name) 2438*14414594SDavid du Colombier+ { 2439*14414594SDavid du Colombier+ struct u9fsuser * u9p; 2440*14414594SDavid du Colombier+ struct u9fsuserhashhead * u9hp; 2441*14414594SDavid du Colombier+ int h; 2442*14414594SDavid du Colombier+ 2443*14414594SDavid du Colombier+ h = u9fs_hashname(name); 2444*14414594SDavid du Colombier+ u9hp = & u9fsunamehashtbl[h%u9fsunamehash]; 2445*14414594SDavid du Colombier+ LIST_FOREACH(u9p, u9hp, u_hash) 2446*14414594SDavid du Colombier+ if( strcmp(u9p->u_name, name) == 0 ) 2447*14414594SDavid du Colombier+ break; 2448*14414594SDavid du Colombier+ 2449*14414594SDavid du Colombier+ if( u9p ) 2450*14414594SDavid du Colombier+ return u9p->u_uid; 2451*14414594SDavid du Colombier+ else 2452*14414594SDavid du Colombier+ return 65534; /* nobody */ 2453*14414594SDavid du Colombier+ } 2454*14414594SDavid du Colombier+ 2455*14414594SDavid du Colombier+ /* 2456*14414594SDavid du Colombier+ * copies a uio scatter/gather list to an mbuf chain. 2457*14414594SDavid du Colombier+ */ 2458*14414594SDavid du Colombier+ int 2459*14414594SDavid du Colombier+ u9fs_uiotombuf(uiop, mq, siz) 2460*14414594SDavid du Colombier+ register struct uio *uiop; 2461*14414594SDavid du Colombier+ struct mbuf **mq; 2462*14414594SDavid du Colombier+ int siz; 2463*14414594SDavid du Colombier+ { 2464*14414594SDavid du Colombier+ register struct mbuf *m; 2465*14414594SDavid du Colombier+ struct mbuf * top, **mp; 2466*14414594SDavid du Colombier+ int mlen, len, error = 0; 2467*14414594SDavid du Colombier+ 2468*14414594SDavid du Colombier+ mp = & top; 2469*14414594SDavid du Colombier+ while(siz) { 2470*14414594SDavid du Colombier+ MGET(m, M_WAIT, MT_DATA); 2471*14414594SDavid du Colombier+ mlen = MLEN; 2472*14414594SDavid du Colombier+ if (siz >= MINCLSIZE) { 2473*14414594SDavid du Colombier+ MCLGET(m, M_WAIT); 2474*14414594SDavid du Colombier+ if ((m->m_flags & M_EXT)) 2475*14414594SDavid du Colombier+ mlen = MCLBYTES; 2476*14414594SDavid du Colombier+ } 2477*14414594SDavid du Colombier+ len = min(mlen, siz); 2478*14414594SDavid du Colombier+ error = uiomove(mtod(m, caddr_t), (int)len, uiop); 2479*14414594SDavid du Colombier+ siz -= len; 2480*14414594SDavid du Colombier+ m->m_len = len; 2481*14414594SDavid du Colombier+ *mp = m; 2482*14414594SDavid du Colombier+ if (error) 2483*14414594SDavid du Colombier+ goto release; 2484*14414594SDavid du Colombier+ mp = &m->m_next; 2485*14414594SDavid du Colombier+ } 2486*14414594SDavid du Colombier+ *mq = top; 2487*14414594SDavid du Colombier+ return 0; 2488*14414594SDavid du Colombier+ 2489*14414594SDavid du Colombier+ release: 2490*14414594SDavid du Colombier+ if( top ) 2491*14414594SDavid du Colombier+ m_freem(top); 2492*14414594SDavid du Colombier+ 2493*14414594SDavid du Colombier+ return error; 2494*14414594SDavid du Colombier+ } 2495*14414594SDavid du Colombier+ 2496*14414594SDavid du Colombier+ /* 2497*14414594SDavid du Colombier+ * copies mbuf chain to the uio scatter/gather list 2498*14414594SDavid du Colombier+ */ 2499*14414594SDavid du Colombier+ int 2500*14414594SDavid du Colombier+ u9fs_mbuftouio(m, uiop, siz) 2501*14414594SDavid du Colombier+ struct mbuf *m; 2502*14414594SDavid du Colombier+ register struct uio *uiop; 2503*14414594SDavid du Colombier+ int siz; 2504*14414594SDavid du Colombier+ { 2505*14414594SDavid du Colombier+ register char *mbufcp, *uiocp; 2506*14414594SDavid du Colombier+ register int xfer, left, len; 2507*14414594SDavid du Colombier+ long uiosiz; 2508*14414594SDavid du Colombier+ 2509*14414594SDavid du Colombier+ mbufcp = mtod(m, char *); 2510*14414594SDavid du Colombier+ len = m->m_len; 2511*14414594SDavid du Colombier+ while (siz > 0) { 2512*14414594SDavid du Colombier+ if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 2513*14414594SDavid du Colombier+ return (EFBIG); 2514*14414594SDavid du Colombier+ left = uiop->uio_iov->iov_len; 2515*14414594SDavid du Colombier+ uiocp = uiop->uio_iov->iov_base; 2516*14414594SDavid du Colombier+ if (left > siz) 2517*14414594SDavid du Colombier+ left = siz; 2518*14414594SDavid du Colombier+ uiosiz = left; 2519*14414594SDavid du Colombier+ while (left > 0) { 2520*14414594SDavid du Colombier+ while (len == 0) { 2521*14414594SDavid du Colombier+ m = m->m_next; 2522*14414594SDavid du Colombier+ if (m == NULL) 2523*14414594SDavid du Colombier+ return (EBADRPC); 2524*14414594SDavid du Colombier+ mbufcp = mtod(m, caddr_t); 2525*14414594SDavid du Colombier+ len = m->m_len; 2526*14414594SDavid du Colombier+ } 2527*14414594SDavid du Colombier+ xfer = (left > len) ? len : left; 2528*14414594SDavid du Colombier+ if (uiop->uio_segflg == UIO_SYSSPACE) 2529*14414594SDavid du Colombier+ bcopy(mbufcp, uiocp, xfer); 2530*14414594SDavid du Colombier+ else 2531*14414594SDavid du Colombier+ copyout(mbufcp, uiocp, xfer); 2532*14414594SDavid du Colombier+ left -= xfer; 2533*14414594SDavid du Colombier+ len -= xfer; 2534*14414594SDavid du Colombier+ mbufcp += xfer; 2535*14414594SDavid du Colombier+ uiocp += xfer; 2536*14414594SDavid du Colombier+ uiop->uio_offset += xfer; 2537*14414594SDavid du Colombier+ uiop->uio_resid -= xfer; 2538*14414594SDavid du Colombier+ } 2539*14414594SDavid du Colombier+ if (uiop->uio_iov->iov_len <= siz) { 2540*14414594SDavid du Colombier+ uiop->uio_iovcnt--; 2541*14414594SDavid du Colombier+ uiop->uio_iov++; 2542*14414594SDavid du Colombier+ } else { 2543*14414594SDavid du Colombier+ uiop->uio_iov->iov_base += uiosiz; 2544*14414594SDavid du Colombier+ uiop->uio_iov->iov_len -= uiosiz; 2545*14414594SDavid du Colombier+ } 2546*14414594SDavid du Colombier+ siz -= uiosiz; 2547*14414594SDavid du Colombier+ } 2548*14414594SDavid du Colombier+ return (0); 2549*14414594SDavid du Colombier+ } 2550*14414594SDavid du Colombier+ 2551*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_vfsops.c ./9fs/9fs_vfsops.c 2552*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_vfsops.c Wed Dec 31 19:00:00 1969 2553*14414594SDavid du Colombier--- ./9fs/9fs_vfsops.c Mon May 22 16:33:47 2000 2554*14414594SDavid du Colombier*************** 2555*14414594SDavid du Colombier*** 0 **** 2556*14414594SDavid du Colombier--- 1,639 ---- 2557*14414594SDavid du Colombier+ /* 2558*14414594SDavid du Colombier+ * Copyright (c) 1989, 1993, 1995 2559*14414594SDavid du Colombier+ * The Regents of the University of California. All rights reserved. 2560*14414594SDavid du Colombier+ * 2561*14414594SDavid du Colombier+ * This code is derived from software contributed to Berkeley by 2562*14414594SDavid du Colombier+ * Rick Macklem at The University of Guelph. 2563*14414594SDavid du Colombier+ * 2564*14414594SDavid du Colombier+ * Redistribution and use in source and binary forms, with or without 2565*14414594SDavid du Colombier+ * modification, are permitted provided that the following conditions 2566*14414594SDavid du Colombier+ * are met: 2567*14414594SDavid du Colombier+ * 1. Redistributions of source code must retain the above copyright 2568*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer. 2569*14414594SDavid du Colombier+ * 2. Redistributions in binary form must reproduce the above copyright 2570*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer in the 2571*14414594SDavid du Colombier+ * documentation and/or other materials provided with the distribution. 2572*14414594SDavid du Colombier+ * 3. All advertising materials mentioning features or use of this software 2573*14414594SDavid du Colombier+ * must display the following acknowledgement: 2574*14414594SDavid du Colombier+ * This product includes software developed by the University of 2575*14414594SDavid du Colombier+ * California, Berkeley and its contributors. 2576*14414594SDavid du Colombier+ * 4. Neither the name of the University nor the names of its contributors 2577*14414594SDavid du Colombier+ * may be used to endorse or promote products derived from this software 2578*14414594SDavid du Colombier+ * without specific prior written permission. 2579*14414594SDavid du Colombier+ * 2580*14414594SDavid du Colombier+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2581*14414594SDavid du Colombier+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2582*14414594SDavid du Colombier+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2583*14414594SDavid du Colombier+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2584*14414594SDavid du Colombier+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2585*14414594SDavid du Colombier+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2586*14414594SDavid du Colombier+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2587*14414594SDavid du Colombier+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2588*14414594SDavid du Colombier+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2589*14414594SDavid du Colombier+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2590*14414594SDavid du Colombier+ * SUCH DAMAGE. 2591*14414594SDavid du Colombier+ * 2592*14414594SDavid du Colombier+ * @(#)u9fs_vfsops.c 8.12 (Berkeley) 5/20/95 2593*14414594SDavid du Colombier+ * $Id: u9fs_vfsops.c,v 1.79 1998/12/04 22:54:54 archie Exp $ 2594*14414594SDavid du Colombier+ */ 2595*14414594SDavid du Colombier+ 2596*14414594SDavid du Colombier+ #include <sys/param.h> 2597*14414594SDavid du Colombier+ #include <sys/sockio.h> 2598*14414594SDavid du Colombier+ #include <sys/proc.h> 2599*14414594SDavid du Colombier+ #include <sys/vnode.h> 2600*14414594SDavid du Colombier+ #include <sys/kernel.h> 2601*14414594SDavid du Colombier+ #include <sys/sysctl.h> 2602*14414594SDavid du Colombier+ #include <sys/malloc.h> 2603*14414594SDavid du Colombier+ #include <sys/mount.h> 2604*14414594SDavid du Colombier+ #include <sys/mbuf.h> 2605*14414594SDavid du Colombier+ #include <sys/socket.h> 2606*14414594SDavid du Colombier+ #include <sys/socketvar.h> 2607*14414594SDavid du Colombier+ #include <sys/systm.h> 2608*14414594SDavid du Colombier+ #include <sys/protosw.h> 2609*14414594SDavid du Colombier+ #include <sys/syslog.h> 2610*14414594SDavid du Colombier+ 2611*14414594SDavid du Colombier+ #include <netinet/in.h> 2612*14414594SDavid du Colombier+ #include <netinet/tcp.h> 2613*14414594SDavid du Colombier+ 2614*14414594SDavid du Colombier+ #include <vm/vm.h> 2615*14414594SDavid du Colombier+ #include <vm/vm_extern.h> 2616*14414594SDavid du Colombier+ #include <vm/vm_zone.h> 2617*14414594SDavid du Colombier+ 2618*14414594SDavid du Colombier+ #include <net/if.h> 2619*14414594SDavid du Colombier+ #include <net/route.h> 2620*14414594SDavid du Colombier+ #include <netinet/in.h> 2621*14414594SDavid du Colombier+ 2622*14414594SDavid du Colombier+ #include <9fs/bitstring.h> 2623*14414594SDavid du Colombier+ #include <9fs/9p.h> 2624*14414594SDavid du Colombier+ #include <9fs/9auth.h> 2625*14414594SDavid du Colombier+ #include <9fs/9fs.h> 2626*14414594SDavid du Colombier+ 2627*14414594SDavid du Colombier+ vm_zone_t u9fsmount_zone; 2628*14414594SDavid du Colombier+ 2629*14414594SDavid du Colombier+ static int u9fs_mount __P(( struct mount *mp, char *path, caddr_t data, 2630*14414594SDavid du Colombier+ struct nameidata *ndp, struct proc *p)); 2631*14414594SDavid du Colombier+ static int u9fs_start __P(( struct mount *mp, int flags, 2632*14414594SDavid du Colombier+ struct proc *p)); 2633*14414594SDavid du Colombier+ static int u9fs_unmount __P(( struct mount *mp, int mntflags, 2634*14414594SDavid du Colombier+ struct proc *p)); 2635*14414594SDavid du Colombier+ static int u9fs_root __P(( struct mount *mp, struct vnode **vpp)); 2636*14414594SDavid du Colombier+ static int u9fs_quotactl __P(( struct mount *mp, int cmds, uid_t uid, 2637*14414594SDavid du Colombier+ caddr_t arg, struct proc *p)); 2638*14414594SDavid du Colombier+ static int u9fs_statfs __P(( struct mount *mp, struct statfs *sbp, 2639*14414594SDavid du Colombier+ struct proc *p)); 2640*14414594SDavid du Colombier+ static int u9fs_sync __P(( struct mount *mp, int waitfor, 2641*14414594SDavid du Colombier+ struct ucred *cred, struct proc *p)); 2642*14414594SDavid du Colombier+ static int u9fs_vptofh __P(( struct vnode *vp, struct fid *fhp)); 2643*14414594SDavid du Colombier+ static int u9fs_fhtovp __P((struct mount *mp, struct fid *fhp, 2644*14414594SDavid du Colombier+ struct sockaddr *nam, struct vnode **vpp, 2645*14414594SDavid du Colombier+ int *exflagsp, struct ucred **credanonp)); 2646*14414594SDavid du Colombier+ static int u9fs_vget __P((struct mount *, ino_t, struct vnode **)); 2647*14414594SDavid du Colombier+ static int u9fs_init __P((struct vfsconf *vfsp)); 2648*14414594SDavid du Colombier+ int u9fs_uninit __P((struct vfsconf *vfsp)); 2649*14414594SDavid du Colombier+ 2650*14414594SDavid du Colombier+ /* */ 2651*14414594SDavid du Colombier+ static int mountu9fs __P((struct u9fs_args *,struct mount *, 2652*14414594SDavid du Colombier+ struct sockaddr *,char *,char *,struct vnode **, struct proc *p)); 2653*14414594SDavid du Colombier+ static int u9fs_iosize __P((struct u9fsmount *nmp)); 2654*14414594SDavid du Colombier+ static void u9fs_decode_args __P((struct u9fsmount *nmp, struct u9fs_args *argp, struct proc *p)); 2655*14414594SDavid du Colombier+ 2656*14414594SDavid du Colombier+ /* 2657*14414594SDavid du Colombier+ * u9fs vfs operations. 2658*14414594SDavid du Colombier+ */ 2659*14414594SDavid du Colombier+ static struct vfsops u9fs_vfsops = { 2660*14414594SDavid du Colombier+ u9fs_mount, 2661*14414594SDavid du Colombier+ u9fs_start, 2662*14414594SDavid du Colombier+ u9fs_unmount, 2663*14414594SDavid du Colombier+ u9fs_root, 2664*14414594SDavid du Colombier+ u9fs_quotactl, 2665*14414594SDavid du Colombier+ u9fs_statfs, 2666*14414594SDavid du Colombier+ u9fs_sync, 2667*14414594SDavid du Colombier+ u9fs_vget, 2668*14414594SDavid du Colombier+ u9fs_fhtovp, 2669*14414594SDavid du Colombier+ u9fs_vptofh, 2670*14414594SDavid du Colombier+ u9fs_init, 2671*14414594SDavid du Colombier+ u9fs_uninit, 2672*14414594SDavid du Colombier+ 0 2673*14414594SDavid du Colombier+ }; 2674*14414594SDavid du Colombier+ VFS_SET(u9fs_vfsops, u9fs, VFCF_NETWORK); 2675*14414594SDavid du Colombier+ 2676*14414594SDavid du Colombier+ /* 2677*14414594SDavid du Colombier+ * u9fs statfs call 2678*14414594SDavid du Colombier+ */ 2679*14414594SDavid du Colombier+ static int 2680*14414594SDavid du Colombier+ u9fs_statfs(mp, sbp, p) 2681*14414594SDavid du Colombier+ struct mount *mp; 2682*14414594SDavid du Colombier+ register struct statfs *sbp; 2683*14414594SDavid du Colombier+ struct proc *p; 2684*14414594SDavid du Colombier+ { 2685*14414594SDavid du Colombier+ /* we have a worm with infinite storage, 2686*14414594SDavid du Colombier+ stat not supported by 9fs */ 2687*14414594SDavid du Colombier+ return 0; 2688*14414594SDavid du Colombier+ } 2689*14414594SDavid du Colombier+ 2690*14414594SDavid du Colombier+ /* 2691*14414594SDavid du Colombier+ * Common code for mount and mountroot 2692*14414594SDavid du Colombier+ */ 2693*14414594SDavid du Colombier+ static int 2694*14414594SDavid du Colombier+ mountu9fs(argp, mp, nam, pth, hst, vpp, p) 2695*14414594SDavid du Colombier+ register struct u9fs_args *argp; 2696*14414594SDavid du Colombier+ register struct mount *mp; 2697*14414594SDavid du Colombier+ struct sockaddr *nam; 2698*14414594SDavid du Colombier+ char *pth, *hst; 2699*14414594SDavid du Colombier+ struct vnode **vpp; 2700*14414594SDavid du Colombier+ struct proc *p; 2701*14414594SDavid du Colombier+ { 2702*14414594SDavid du Colombier+ register struct u9fsmount *nmp; 2703*14414594SDavid du Colombier+ struct u9fsnode *np; 2704*14414594SDavid du Colombier+ int error; 2705*14414594SDavid du Colombier+ struct vattr attrs; 2706*14414594SDavid du Colombier+ struct u9fsreq req, rep; 2707*14414594SDavid du Colombier+ char * mntpoint; 2708*14414594SDavid du Colombier+ struct u9fsuser * u9p; 2709*14414594SDavid du Colombier+ struct socket * so; 2710*14414594SDavid du Colombier+ 2711*14414594SDavid du Colombier+ if (mp->mnt_flag & MNT_UPDATE) { 2712*14414594SDavid du Colombier+ #if 0 2713*14414594SDavid du Colombier+ nmp = VFSTONFS(mp); 2714*14414594SDavid du Colombier+ < /* update paths, file handles, etc, here XXX */ 2715*14414594SDavid du Colombier+ FREE(nam, M_SONAME); 2716*14414594SDavid du Colombier+ #endif 2717*14414594SDavid du Colombier+ return (0); 2718*14414594SDavid du Colombier+ } else { 2719*14414594SDavid du Colombier+ nmp = zalloc(u9fsmount_zone); 2720*14414594SDavid du Colombier+ bzero((caddr_t)nmp, sizeof (struct u9fsmount)); 2721*14414594SDavid du Colombier+ #if 0 2722*14414594SDavid du Colombier+ TAILQ_INIT(&nmp->nm_uidlruhead); 2723*14414594SDavid du Colombier+ TAILQ_INIT(&nmp->nm_bufq); 2724*14414594SDavid du Colombier+ #endif 2725*14414594SDavid du Colombier+ mp->mnt_data = (qaddr_t)nmp; 2726*14414594SDavid du Colombier+ } 2727*14414594SDavid du Colombier+ vfs_getnewfsid(mp); 2728*14414594SDavid du Colombier+ nmp->nm_mountp = mp; 2729*14414594SDavid du Colombier+ 2730*14414594SDavid du Colombier+ nmp->nm_maxfilesize = (u_int64_t)0xffffffffffffffffLL; 2731*14414594SDavid du Colombier+ 2732*14414594SDavid du Colombier+ nmp->nm_wsize = U9FS_MAXFDATA; 2733*14414594SDavid du Colombier+ nmp->nm_rsize = U9FS_MAXFDATA; 2734*14414594SDavid du Colombier+ nmp->nm_readdirsize = U9FS_MAXDDATA; 2735*14414594SDavid du Colombier+ bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); 2736*14414594SDavid du Colombier+ bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); 2737*14414594SDavid du Colombier+ nmp->nm_nam = nam; 2738*14414594SDavid du Colombier+ 2739*14414594SDavid du Colombier+ mntpoint = index(hst, '/'); 2740*14414594SDavid du Colombier+ if( mntpoint ) 2741*14414594SDavid du Colombier+ mntpoint++; 2742*14414594SDavid du Colombier+ 2743*14414594SDavid du Colombier+ /* Set up the sockets and per-host congestion */ 2744*14414594SDavid du Colombier+ nmp->nm_sotype = argp->sotype; 2745*14414594SDavid du Colombier+ nmp->nm_soproto = argp->proto; 2746*14414594SDavid du Colombier+ 2747*14414594SDavid du Colombier+ u9fs_decode_args(nmp, argp, p); 2748*14414594SDavid du Colombier+ 2749*14414594SDavid du Colombier+ lockinit(& nmp->nm_lock, PVFS, "u9fsmount", 0, 0); 2750*14414594SDavid du Colombier+ u9fs_id_init(&nmp->nm_tags); 2751*14414594SDavid du Colombier+ u9fs_id_init(&nmp->nm_fids); 2752*14414594SDavid du Colombier+ TAILQ_INIT(&nmp->nm_reqq); 2753*14414594SDavid du Colombier+ 2754*14414594SDavid du Colombier+ if ((error = u9fs_connect_9fs(nmp))) 2755*14414594SDavid du Colombier+ goto bad; 2756*14414594SDavid du Colombier+ 2757*14414594SDavid du Colombier+ /* "Tnop 1", "Tsession 1 0", "Tattach 1 1 none main 0 0", */ 2758*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 2759*14414594SDavid du Colombier+ req.r_nmp = nmp; 2760*14414594SDavid du Colombier+ req.r_procp = p; 2761*14414594SDavid du Colombier+ 2762*14414594SDavid du Colombier+ req.r_type = Tnop; 2763*14414594SDavid du Colombier+ error = u9fs_request(& req, & rep, 1); 2764*14414594SDavid du Colombier+ if( error ) 2765*14414594SDavid du Colombier+ return error; 2766*14414594SDavid du Colombier+ 2767*14414594SDavid du Colombier+ req.r_type = Tsession; 2768*14414594SDavid du Colombier+ /* bzero(req.r_chal, sizeof(req.r_chal)); */ 2769*14414594SDavid du Colombier+ u9auth_genchal(req.r_chal); 2770*14414594SDavid du Colombier+ error = u9fs_request(& req, & rep, 1); 2771*14414594SDavid du Colombier+ if( error ) 2772*14414594SDavid du Colombier+ return error; 2773*14414594SDavid du Colombier+ 2774*14414594SDavid du Colombier+ if( argp->authaddr ) { 2775*14414594SDavid du Colombier+ /* get tickets from the auth server */ 2776*14414594SDavid du Colombier+ error = u9fs_connect_9auth(nmp, argp, & so); 2777*14414594SDavid du Colombier+ if( error ) 2778*14414594SDavid du Colombier+ goto bad; 2779*14414594SDavid du Colombier+ u9p = u9fs_finduser(u9fs_name2uid(argp->user)); 2780*14414594SDavid du Colombier+ error = u9auth_gettickets(so, & rep, argp->user, u9p->u_ckey, 2781*14414594SDavid du Colombier+ req.r_ticket, req.r_auth, p); 2782*14414594SDavid du Colombier+ u9fs_disconnect(so); 2783*14414594SDavid du Colombier+ if( error ) 2784*14414594SDavid du Colombier+ goto bad; 2785*14414594SDavid du Colombier+ } 2786*14414594SDavid du Colombier+ 2787*14414594SDavid du Colombier+ req.r_type = Tattach; 2788*14414594SDavid du Colombier+ req.r_fid = u9fs_id_new(nmp->nm_fids); 2789*14414594SDavid du Colombier+ strcpy(req.r_uname, argp->user); 2790*14414594SDavid du Colombier+ strcpy(req.r_aname, mntpoint); 2791*14414594SDavid du Colombier+ error = u9fs_request(& req, & rep, 1); 2792*14414594SDavid du Colombier+ if( error ) 2793*14414594SDavid du Colombier+ return error; 2794*14414594SDavid du Colombier+ nmp->nm_fh = rep.r_qid.path; 2795*14414594SDavid du Colombier+ nmp->nm_fid = req.r_fid; 2796*14414594SDavid du Colombier+ /* XXX: we should have checked our challenge to the server! */ 2797*14414594SDavid du Colombier+ 2798*14414594SDavid du Colombier+ /* 2799*14414594SDavid du Colombier+ * This is silly, but it has to be set so that vinifod() works. 2800*14414594SDavid du Colombier+ * We do not want to do an u9fs_statfs() here since we can get 2801*14414594SDavid du Colombier+ * stuck on a dead server and we are holding a lock on the mount 2802*14414594SDavid du Colombier+ * point. 2803*14414594SDavid du Colombier+ */ 2804*14414594SDavid du Colombier+ mp->mnt_stat.f_iosize = u9fs_iosize(nmp); 2805*14414594SDavid du Colombier+ 2806*14414594SDavid du Colombier+ /* 2807*14414594SDavid du Colombier+ * A reference count is needed on the u9fsnode representing the 2808*14414594SDavid du Colombier+ * remote root. If this object is not persistent, then backward 2809*14414594SDavid du Colombier+ * traversals of the mount point (i.e. "..") will not work if 2810*14414594SDavid du Colombier+ * the u9fsnode gets flushed out of the cache. Ufs does not have 2811*14414594SDavid du Colombier+ * this problem, because one can identify root inodes by their 2812*14414594SDavid du Colombier+ * number == ROOTINO (2). 2813*14414594SDavid du Colombier+ */ 2814*14414594SDavid du Colombier+ error = u9fs_nget(mp, nmp->nm_fh, &np, p); 2815*14414594SDavid du Colombier+ np->n_fid = nmp->nm_fid; 2816*14414594SDavid du Colombier+ 2817*14414594SDavid du Colombier+ nmp->nm_authuid = p->p_ucred->cr_uid; 2818*14414594SDavid du Colombier+ 2819*14414594SDavid du Colombier+ if (error) 2820*14414594SDavid du Colombier+ goto bad; 2821*14414594SDavid du Colombier+ *vpp = U9FSTOV(np); 2822*14414594SDavid du Colombier+ 2823*14414594SDavid du Colombier+ /* 2824*14414594SDavid du Colombier+ * Get file attributes for the mountpoint. This has the side 2825*14414594SDavid du Colombier+ * effect of filling in (*vpp)->v_type with the correct value. 2826*14414594SDavid du Colombier+ */ 2827*14414594SDavid du Colombier+ VOP_GETATTR(*vpp, &attrs, p->p_ucred, p); 2828*14414594SDavid du Colombier+ 2829*14414594SDavid du Colombier+ /* 2830*14414594SDavid du Colombier+ * Lose the lock but keep the ref. 2831*14414594SDavid du Colombier+ */ 2832*14414594SDavid du Colombier+ VOP_UNLOCK(*vpp, 0, p); 2833*14414594SDavid du Colombier+ 2834*14414594SDavid du Colombier+ return (0); 2835*14414594SDavid du Colombier+ bad: 2836*14414594SDavid du Colombier+ u9fs_disconnect(nmp->nm_so); 2837*14414594SDavid du Colombier+ zfree(u9fsmount_zone, nmp); 2838*14414594SDavid du Colombier+ FREE(nam, M_SONAME); 2839*14414594SDavid du Colombier+ return (error); 2840*14414594SDavid du Colombier+ } 2841*14414594SDavid du Colombier+ 2842*14414594SDavid du Colombier+ /* 2843*14414594SDavid du Colombier+ * VFS Operations. 2844*14414594SDavid du Colombier+ * 2845*14414594SDavid du Colombier+ * mount system call 2846*14414594SDavid du Colombier+ * It seems a bit dumb to copyinstr() the host and path here and then 2847*14414594SDavid du Colombier+ * bcopy() them in mountu9fs(), but I wanted to detect errors before 2848*14414594SDavid du Colombier+ * doing the sockargs() call because sockargs() allocates an mbuf and 2849*14414594SDavid du Colombier+ * an error after that means that I have to release the mbuf. 2850*14414594SDavid du Colombier+ */ 2851*14414594SDavid du Colombier+ /* ARGSUSED */ 2852*14414594SDavid du Colombier+ static int 2853*14414594SDavid du Colombier+ u9fs_mount(mp, path, data, ndp, p) 2854*14414594SDavid du Colombier+ struct mount *mp; 2855*14414594SDavid du Colombier+ char *path; 2856*14414594SDavid du Colombier+ caddr_t data; 2857*14414594SDavid du Colombier+ struct nameidata *ndp; 2858*14414594SDavid du Colombier+ struct proc *p; 2859*14414594SDavid du Colombier+ { 2860*14414594SDavid du Colombier+ int error; 2861*14414594SDavid du Colombier+ struct u9fs_args args; 2862*14414594SDavid du Colombier+ struct sockaddr *nam; 2863*14414594SDavid du Colombier+ struct vnode *vp; 2864*14414594SDavid du Colombier+ char pth[MNAMELEN], hst[MNAMELEN]; 2865*14414594SDavid du Colombier+ size_t len; 2866*14414594SDavid du Colombier+ 2867*14414594SDavid du Colombier+ if( path == NULL ) 2868*14414594SDavid du Colombier+ return (EOPNOTSUPP); 2869*14414594SDavid du Colombier+ 2870*14414594SDavid du Colombier+ error = copyin(data, (caddr_t)&args, sizeof (struct u9fs_args)); 2871*14414594SDavid du Colombier+ if (error) 2872*14414594SDavid du Colombier+ return (error); 2873*14414594SDavid du Colombier+ 2874*14414594SDavid du Colombier+ if (args.version != U9FS_ARGSVERSION) 2875*14414594SDavid du Colombier+ return (EPROGMISMATCH); 2876*14414594SDavid du Colombier+ 2877*14414594SDavid du Colombier+ if (mp->mnt_flag & MNT_UPDATE) { 2878*14414594SDavid du Colombier+ #if 0 2879*14414594SDavid du Colombier+ register struct u9fsmount *nmp = VFSTONFS(mp); 2880*14414594SDavid du Colombier+ 2881*14414594SDavid du Colombier+ if (nmp == NULL) 2882*14414594SDavid du Colombier+ return (EIO); 2883*14414594SDavid du Colombier+ /* 2884*14414594SDavid du Colombier+ * When doing an update, we can't change from or to 2885*14414594SDavid du Colombier+ * v3 and/or nqu9fs, or change cookie translation 2886*14414594SDavid du Colombier+ */ 2887*14414594SDavid du Colombier+ args.flags = (args.flags & 2888*14414594SDavid du Colombier+ ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) | 2889*14414594SDavid du Colombier+ (nmp->nm_flag & 2890*14414594SDavid du Colombier+ (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)); 2891*14414594SDavid du Colombier+ u9fs_decode_args(nmp, &args, p); 2892*14414594SDavid du Colombier+ #endif 2893*14414594SDavid du Colombier+ return (0); 2894*14414594SDavid du Colombier+ } 2895*14414594SDavid du Colombier+ 2896*14414594SDavid du Colombier+ error = copyinstr(path, pth, MNAMELEN-1, &len); 2897*14414594SDavid du Colombier+ if (error) 2898*14414594SDavid du Colombier+ return (error); 2899*14414594SDavid du Colombier+ bzero(&pth[len], MNAMELEN - len); 2900*14414594SDavid du Colombier+ error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); 2901*14414594SDavid du Colombier+ if (error) 2902*14414594SDavid du Colombier+ return (error); 2903*14414594SDavid du Colombier+ bzero(&hst[len], MNAMELEN - len); 2904*14414594SDavid du Colombier+ /* sockargs() call must be after above copyin() calls */ 2905*14414594SDavid du Colombier+ error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen); 2906*14414594SDavid du Colombier+ if (error) 2907*14414594SDavid du Colombier+ return (error); 2908*14414594SDavid du Colombier+ error = mountu9fs(&args, mp, nam, pth, hst, &vp, p); 2909*14414594SDavid du Colombier+ return (error); 2910*14414594SDavid du Colombier+ } 2911*14414594SDavid du Colombier+ 2912*14414594SDavid du Colombier+ /* 2913*14414594SDavid du Colombier+ * unmount system call 2914*14414594SDavid du Colombier+ */ 2915*14414594SDavid du Colombier+ static int 2916*14414594SDavid du Colombier+ u9fs_unmount(mp, mntflags, p) 2917*14414594SDavid du Colombier+ struct mount *mp; 2918*14414594SDavid du Colombier+ int mntflags; 2919*14414594SDavid du Colombier+ struct proc *p; 2920*14414594SDavid du Colombier+ { 2921*14414594SDavid du Colombier+ register struct u9fsmount *nmp; 2922*14414594SDavid du Colombier+ struct u9fsnode *np; 2923*14414594SDavid du Colombier+ struct vnode *vp; 2924*14414594SDavid du Colombier+ int error, flags = 0; 2925*14414594SDavid du Colombier+ 2926*14414594SDavid du Colombier+ if (mntflags & MNT_FORCE) 2927*14414594SDavid du Colombier+ flags |= FORCECLOSE; 2928*14414594SDavid du Colombier+ nmp = VFSTOU9FS(mp); 2929*14414594SDavid du Colombier+ 2930*14414594SDavid du Colombier+ if( p->p_ucred->cr_uid != nmp->nm_authuid ) 2931*14414594SDavid du Colombier+ return (EPERM); 2932*14414594SDavid du Colombier+ 2933*14414594SDavid du Colombier+ /* 2934*14414594SDavid du Colombier+ * Goes something like this.. 2935*14414594SDavid du Colombier+ * - Check for activity on the root vnode (other than ourselves). 2936*14414594SDavid du Colombier+ * - Call vflush() to clear out vnodes for this file system, 2937*14414594SDavid du Colombier+ * except for the root vnode. 2938*14414594SDavid du Colombier+ * - Decrement reference on the vnode representing remote root. 2939*14414594SDavid du Colombier+ * - Close the socket 2940*14414594SDavid du Colombier+ * - Free up the data structures 2941*14414594SDavid du Colombier+ */ 2942*14414594SDavid du Colombier+ /* 2943*14414594SDavid du Colombier+ * We need to decrement the ref. count on the u9fsnode representing 2944*14414594SDavid du Colombier+ * the remote root. See comment in mountu9fs(). The VFS unmount() 2945*14414594SDavid du Colombier+ * has done vput on this vnode, otherwise we would get deadlock! 2946*14414594SDavid du Colombier+ */ 2947*14414594SDavid du Colombier+ error = u9fs_nget(mp, nmp->nm_fh, &np, p); 2948*14414594SDavid du Colombier+ if (error) 2949*14414594SDavid du Colombier+ return(error); 2950*14414594SDavid du Colombier+ vp = U9FSTOV(np); 2951*14414594SDavid du Colombier+ if (vp->v_usecount > 2) { 2952*14414594SDavid du Colombier+ vput(vp); 2953*14414594SDavid du Colombier+ return (EBUSY); 2954*14414594SDavid du Colombier+ } 2955*14414594SDavid du Colombier+ 2956*14414594SDavid du Colombier+ error = vflush(mp, vp, flags); 2957*14414594SDavid du Colombier+ if (error) { 2958*14414594SDavid du Colombier+ vput(vp); 2959*14414594SDavid du Colombier+ return (error); 2960*14414594SDavid du Colombier+ } 2961*14414594SDavid du Colombier+ 2962*14414594SDavid du Colombier+ /* 2963*14414594SDavid du Colombier+ * We are now committed to the unmount. 2964*14414594SDavid du Colombier+ */ 2965*14414594SDavid du Colombier+ /* 2966*14414594SDavid du Colombier+ * There are two reference counts and one lock to get rid of here. 2967*14414594SDavid du Colombier+ */ 2968*14414594SDavid du Colombier+ vput(vp); 2969*14414594SDavid du Colombier+ vrele(vp); 2970*14414594SDavid du Colombier+ vgone(vp); 2971*14414594SDavid du Colombier+ u9fs_disconnect(nmp->nm_so); 2972*14414594SDavid du Colombier+ FREE(nmp->nm_nam, M_SONAME); 2973*14414594SDavid du Colombier+ 2974*14414594SDavid du Colombier+ zfree(u9fsmount_zone, nmp); 2975*14414594SDavid du Colombier+ return (0); 2976*14414594SDavid du Colombier+ } 2977*14414594SDavid du Colombier+ 2978*14414594SDavid du Colombier+ /* 2979*14414594SDavid du Colombier+ * Return root of a filesystem 2980*14414594SDavid du Colombier+ */ 2981*14414594SDavid du Colombier+ static int 2982*14414594SDavid du Colombier+ u9fs_root(mp, vpp) 2983*14414594SDavid du Colombier+ struct mount *mp; 2984*14414594SDavid du Colombier+ struct vnode **vpp; 2985*14414594SDavid du Colombier+ { 2986*14414594SDavid du Colombier+ register struct vnode *vp; 2987*14414594SDavid du Colombier+ struct u9fsmount *nmp; 2988*14414594SDavid du Colombier+ struct u9fsnode *np; 2989*14414594SDavid du Colombier+ int error; 2990*14414594SDavid du Colombier+ 2991*14414594SDavid du Colombier+ nmp = VFSTOU9FS(mp); 2992*14414594SDavid du Colombier+ error = u9fs_nget(mp, nmp->nm_fh, &np, curproc); /* XXX */ 2993*14414594SDavid du Colombier+ if (error) 2994*14414594SDavid du Colombier+ return (error); 2995*14414594SDavid du Colombier+ vp = U9FSTOV(np); 2996*14414594SDavid du Colombier+ if (vp->v_type == VNON) 2997*14414594SDavid du Colombier+ vp->v_type = VDIR; 2998*14414594SDavid du Colombier+ vp->v_flag = VROOT; 2999*14414594SDavid du Colombier+ *vpp = vp; 3000*14414594SDavid du Colombier+ return (0); 3001*14414594SDavid du Colombier+ } 3002*14414594SDavid du Colombier+ 3003*14414594SDavid du Colombier+ extern int syncprt; 3004*14414594SDavid du Colombier+ 3005*14414594SDavid du Colombier+ /* 3006*14414594SDavid du Colombier+ * Flush out the buffer cache 3007*14414594SDavid du Colombier+ */ 3008*14414594SDavid du Colombier+ /* ARGSUSED */ 3009*14414594SDavid du Colombier+ static int 3010*14414594SDavid du Colombier+ u9fs_sync(mp, waitfor, cred, p) 3011*14414594SDavid du Colombier+ struct mount *mp; 3012*14414594SDavid du Colombier+ int waitfor; 3013*14414594SDavid du Colombier+ struct ucred *cred; 3014*14414594SDavid du Colombier+ struct proc *p; 3015*14414594SDavid du Colombier+ { 3016*14414594SDavid du Colombier+ /* no cache yet */ 3017*14414594SDavid du Colombier+ return 0; 3018*14414594SDavid du Colombier+ } 3019*14414594SDavid du Colombier+ 3020*14414594SDavid du Colombier+ /* 3021*14414594SDavid du Colombier+ * U9FS flat namespace lookup. 3022*14414594SDavid du Colombier+ * Currently unsupported. 3023*14414594SDavid du Colombier+ */ 3024*14414594SDavid du Colombier+ /* ARGSUSED */ 3025*14414594SDavid du Colombier+ static int 3026*14414594SDavid du Colombier+ u9fs_vget(mp, ino, vpp) 3027*14414594SDavid du Colombier+ struct mount *mp; 3028*14414594SDavid du Colombier+ ino_t ino; 3029*14414594SDavid du Colombier+ struct vnode **vpp; 3030*14414594SDavid du Colombier+ { 3031*14414594SDavid du Colombier+ 3032*14414594SDavid du Colombier+ return (EOPNOTSUPP); 3033*14414594SDavid du Colombier+ } 3034*14414594SDavid du Colombier+ 3035*14414594SDavid du Colombier+ /* 3036*14414594SDavid du Colombier+ * At this point, this should never happen 3037*14414594SDavid du Colombier+ */ 3038*14414594SDavid du Colombier+ /* ARGSUSED */ 3039*14414594SDavid du Colombier+ static int 3040*14414594SDavid du Colombier+ u9fs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 3041*14414594SDavid du Colombier+ register struct mount *mp; 3042*14414594SDavid du Colombier+ struct fid *fhp; 3043*14414594SDavid du Colombier+ struct sockaddr *nam; 3044*14414594SDavid du Colombier+ struct vnode **vpp; 3045*14414594SDavid du Colombier+ int *exflagsp; 3046*14414594SDavid du Colombier+ struct ucred **credanonp; 3047*14414594SDavid du Colombier+ { 3048*14414594SDavid du Colombier+ 3049*14414594SDavid du Colombier+ return (EINVAL); 3050*14414594SDavid du Colombier+ } 3051*14414594SDavid du Colombier+ 3052*14414594SDavid du Colombier+ /* 3053*14414594SDavid du Colombier+ * Vnode pointer to File handle, should never happen either 3054*14414594SDavid du Colombier+ */ 3055*14414594SDavid du Colombier+ /* ARGSUSED */ 3056*14414594SDavid du Colombier+ static int 3057*14414594SDavid du Colombier+ u9fs_vptofh(vp, fhp) 3058*14414594SDavid du Colombier+ struct vnode *vp; 3059*14414594SDavid du Colombier+ struct fid *fhp; 3060*14414594SDavid du Colombier+ { 3061*14414594SDavid du Colombier+ 3062*14414594SDavid du Colombier+ return (EINVAL); 3063*14414594SDavid du Colombier+ } 3064*14414594SDavid du Colombier+ 3065*14414594SDavid du Colombier+ /* 3066*14414594SDavid du Colombier+ * Vfs start routine, a no-op. 3067*14414594SDavid du Colombier+ */ 3068*14414594SDavid du Colombier+ /* ARGSUSED */ 3069*14414594SDavid du Colombier+ static int 3070*14414594SDavid du Colombier+ u9fs_start(mp, flags, p) 3071*14414594SDavid du Colombier+ struct mount *mp; 3072*14414594SDavid du Colombier+ int flags; 3073*14414594SDavid du Colombier+ struct proc *p; 3074*14414594SDavid du Colombier+ { 3075*14414594SDavid du Colombier+ 3076*14414594SDavid du Colombier+ return (0); 3077*14414594SDavid du Colombier+ } 3078*14414594SDavid du Colombier+ 3079*14414594SDavid du Colombier+ /* 3080*14414594SDavid du Colombier+ * Do operations associated with quotas, not supported 3081*14414594SDavid du Colombier+ */ 3082*14414594SDavid du Colombier+ /* ARGSUSED */ 3083*14414594SDavid du Colombier+ static int 3084*14414594SDavid du Colombier+ u9fs_quotactl(mp, cmd, uid, arg, p) 3085*14414594SDavid du Colombier+ struct mount *mp; 3086*14414594SDavid du Colombier+ int cmd; 3087*14414594SDavid du Colombier+ uid_t uid; 3088*14414594SDavid du Colombier+ caddr_t arg; 3089*14414594SDavid du Colombier+ struct proc *p; 3090*14414594SDavid du Colombier+ { 3091*14414594SDavid du Colombier+ 3092*14414594SDavid du Colombier+ return (EOPNOTSUPP); 3093*14414594SDavid du Colombier+ } 3094*14414594SDavid du Colombier+ 3095*14414594SDavid du Colombier+ /* 3096*14414594SDavid du Colombier+ * Called once to initialize data structures... 3097*14414594SDavid du Colombier+ */ 3098*14414594SDavid du Colombier+ int 3099*14414594SDavid du Colombier+ u9fs_init(vfsp) 3100*14414594SDavid du Colombier+ struct vfsconf *vfsp; 3101*14414594SDavid du Colombier+ { 3102*14414594SDavid du Colombier+ u9fsmount_zone = zinit("U9FSMOUNT", sizeof(struct u9fsmount), 0, 0, 1); 3103*14414594SDavid du Colombier+ u9fs_nhinit(); /* Init the u9fsnode table */ 3104*14414594SDavid du Colombier+ u9fs_uhinit(); 3105*14414594SDavid du Colombier+ return 0; 3106*14414594SDavid du Colombier+ } 3107*14414594SDavid du Colombier+ 3108*14414594SDavid du Colombier+ int 3109*14414594SDavid du Colombier+ u9fs_uninit(vfsp) 3110*14414594SDavid du Colombier+ struct vfsconf *vfsp; 3111*14414594SDavid du Colombier+ { 3112*14414594SDavid du Colombier+ return 0; 3113*14414594SDavid du Colombier+ } 3114*14414594SDavid du Colombier+ 3115*14414594SDavid du Colombier+ static int 3116*14414594SDavid du Colombier+ u9fs_iosize(nmp) 3117*14414594SDavid du Colombier+ struct u9fsmount* nmp; 3118*14414594SDavid du Colombier+ { 3119*14414594SDavid du Colombier+ int iosize; 3120*14414594SDavid du Colombier+ 3121*14414594SDavid du Colombier+ /* 3122*14414594SDavid du Colombier+ * Calculate the size used for io buffers. Use the larger 3123*14414594SDavid du Colombier+ * of the two sizes to minimise u9fs requests but make sure 3124*14414594SDavid du Colombier+ * that it is at least one VM page to avoid wasting buffer 3125*14414594SDavid du Colombier+ * space. 3126*14414594SDavid du Colombier+ */ 3127*14414594SDavid du Colombier+ iosize = max(nmp->nm_rsize, nmp->nm_wsize); 3128*14414594SDavid du Colombier+ if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; 3129*14414594SDavid du Colombier+ return iosize; 3130*14414594SDavid du Colombier+ } 3131*14414594SDavid du Colombier+ 3132*14414594SDavid du Colombier+ static void 3133*14414594SDavid du Colombier+ u9fs_decode_args(nmp, argp, p) 3134*14414594SDavid du Colombier+ struct u9fsmount *nmp; 3135*14414594SDavid du Colombier+ struct u9fs_args *argp; 3136*14414594SDavid du Colombier+ struct proc * p; 3137*14414594SDavid du Colombier+ { 3138*14414594SDavid du Colombier+ int s, i; 3139*14414594SDavid du Colombier+ int maxio; 3140*14414594SDavid du Colombier+ struct p9user * p9p, p9u; 3141*14414594SDavid du Colombier+ struct u9fsuser * u9p; 3142*14414594SDavid du Colombier+ 3143*14414594SDavid du Colombier+ s = splnet(); 3144*14414594SDavid du Colombier+ /* Update flags atomically. Don't change the lock bits. */ 3145*14414594SDavid du Colombier+ nmp->nm_flag = argp->flags | nmp->nm_flag; 3146*14414594SDavid du Colombier+ splx(s); 3147*14414594SDavid du Colombier+ 3148*14414594SDavid du Colombier+ maxio = U9FS_MAXFDATA; 3149*14414594SDavid du Colombier+ 3150*14414594SDavid du Colombier+ if (argp->wsize > 0) { 3151*14414594SDavid du Colombier+ nmp->nm_wsize = argp->wsize; 3152*14414594SDavid du Colombier+ /* Round down to multiple of blocksize */ 3153*14414594SDavid du Colombier+ nmp->nm_wsize &= ~(U9FS_FABLKSIZE - 1); 3154*14414594SDavid du Colombier+ if (nmp->nm_wsize <= 0) 3155*14414594SDavid du Colombier+ nmp->nm_wsize = U9FS_FABLKSIZE; 3156*14414594SDavid du Colombier+ } 3157*14414594SDavid du Colombier+ if (nmp->nm_wsize > maxio) 3158*14414594SDavid du Colombier+ nmp->nm_wsize = maxio; 3159*14414594SDavid du Colombier+ if (nmp->nm_wsize > MAXBSIZE) 3160*14414594SDavid du Colombier+ nmp->nm_wsize = MAXBSIZE; 3161*14414594SDavid du Colombier+ 3162*14414594SDavid du Colombier+ if (argp->rsize > 0) { 3163*14414594SDavid du Colombier+ nmp->nm_rsize = argp->rsize; 3164*14414594SDavid du Colombier+ /* Round down to multiple of blocksize */ 3165*14414594SDavid du Colombier+ nmp->nm_rsize &= ~(U9FS_FABLKSIZE - 1); 3166*14414594SDavid du Colombier+ if (nmp->nm_rsize <= 0) 3167*14414594SDavid du Colombier+ nmp->nm_rsize = U9FS_FABLKSIZE; 3168*14414594SDavid du Colombier+ } 3169*14414594SDavid du Colombier+ if (nmp->nm_rsize > maxio) 3170*14414594SDavid du Colombier+ nmp->nm_rsize = maxio; 3171*14414594SDavid du Colombier+ if (nmp->nm_rsize > MAXBSIZE) 3172*14414594SDavid du Colombier+ nmp->nm_rsize = MAXBSIZE; 3173*14414594SDavid du Colombier+ 3174*14414594SDavid du Colombier+ if (argp->readdirsize > 0) { 3175*14414594SDavid du Colombier+ nmp->nm_readdirsize = argp->readdirsize; 3176*14414594SDavid du Colombier+ } 3177*14414594SDavid du Colombier+ if (nmp->nm_readdirsize > maxio) 3178*14414594SDavid du Colombier+ nmp->nm_readdirsize = maxio; 3179*14414594SDavid du Colombier+ if (nmp->nm_readdirsize > nmp->nm_rsize) 3180*14414594SDavid du Colombier+ nmp->nm_readdirsize = nmp->nm_rsize; 3181*14414594SDavid du Colombier+ 3182*14414594SDavid du Colombier+ if( argp->nusers ) { 3183*14414594SDavid du Colombier+ p9p = argp->users; 3184*14414594SDavid du Colombier+ for(i = 0; i < argp->nusers; i++) { 3185*14414594SDavid du Colombier+ copyin(p9p, &p9u, sizeof(p9u)); 3186*14414594SDavid du Colombier+ u9fs_hashuser(p9u.p9_uid, p9u.p9_name); 3187*14414594SDavid du Colombier+ p9p ++; 3188*14414594SDavid du Colombier+ } 3189*14414594SDavid du Colombier+ printf("%d p9users loaded\n", argp->nusers); 3190*14414594SDavid du Colombier+ } 3191*14414594SDavid du Colombier+ 3192*14414594SDavid du Colombier+ if( (u9p = u9fs_finduser(u9fs_name2uid(argp->user))) ) { 3193*14414594SDavid du Colombier+ bcopy(argp->key, u9p->u_ckey, U9AUTH_DESKEYLEN); 3194*14414594SDavid du Colombier+ } 3195*14414594SDavid du Colombier+ } 3196*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9fs_vnops.c ./9fs/9fs_vnops.c 3197*14414594SDavid du Colombier*** /usr/src/sys/9fs/9fs_vnops.c Wed Dec 31 19:00:00 1969 3198*14414594SDavid du Colombier--- ./9fs/9fs_vnops.c Mon May 22 11:40:00 2000 3199*14414594SDavid du Colombier*************** 3200*14414594SDavid du Colombier*** 0 **** 3201*14414594SDavid du Colombier--- 1,1794 ---- 3202*14414594SDavid du Colombier+ /* 3203*14414594SDavid du Colombier+ * Copyright (c) 1989, 1993 3204*14414594SDavid du Colombier+ * The Regents of the University of California. All rights reserved. 3205*14414594SDavid du Colombier+ * 3206*14414594SDavid du Colombier+ * This code is derived from software contributed to Berkeley by 3207*14414594SDavid du Colombier+ * Rick Macklem at The University of Guelph. 3208*14414594SDavid du Colombier+ * 3209*14414594SDavid du Colombier+ * Redistribution and use in source and binary forms, with or without 3210*14414594SDavid du Colombier+ * modification, are permitted provided that the following conditions 3211*14414594SDavid du Colombier+ * are met: 3212*14414594SDavid du Colombier+ * 1. Redistributions of source code must retain the above copyright 3213*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer. 3214*14414594SDavid du Colombier+ * 2. Redistributions in binary form must reproduce the above copyright 3215*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer in the 3216*14414594SDavid du Colombier+ * documentation and/or other materials provided with the distribution. 3217*14414594SDavid du Colombier+ * 3. All advertising materials mentioning features or use of this software 3218*14414594SDavid du Colombier+ * must display the following acknowledgement: 3219*14414594SDavid du Colombier+ * This product includes software developed by the University of 3220*14414594SDavid du Colombier+ * California, Berkeley and its contributors. 3221*14414594SDavid du Colombier+ * 4. Neither the name of the University nor the names of its contributors 3222*14414594SDavid du Colombier+ * may be used to endorse or promote products derived from this software 3223*14414594SDavid du Colombier+ * without specific prior written permission. 3224*14414594SDavid du Colombier+ * 3225*14414594SDavid du Colombier+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 3226*14414594SDavid du Colombier+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3227*14414594SDavid du Colombier+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3228*14414594SDavid du Colombier+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3229*14414594SDavid du Colombier+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3230*14414594SDavid du Colombier+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3231*14414594SDavid du Colombier+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3232*14414594SDavid du Colombier+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3233*14414594SDavid du Colombier+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3234*14414594SDavid du Colombier+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3235*14414594SDavid du Colombier+ * SUCH DAMAGE. 3236*14414594SDavid du Colombier+ * 3237*14414594SDavid du Colombier+ * @(#)u9fs_vnops.c 8.16 (Berkeley) 5/27/95 3238*14414594SDavid du Colombier+ * $Id: u9fs_vnops.c,v 1.116.2.3 1999/02/13 08:03:47 dillon Exp $ 3239*14414594SDavid du Colombier+ */ 3240*14414594SDavid du Colombier+ 3241*14414594SDavid du Colombier+ 3242*14414594SDavid du Colombier+ /* 3243*14414594SDavid du Colombier+ * vnode op calls for 9FS 3244*14414594SDavid du Colombier+ */ 3245*14414594SDavid du Colombier+ 3246*14414594SDavid du Colombier+ #include "opt_inet.h" 3247*14414594SDavid du Colombier+ 3248*14414594SDavid du Colombier+ #include <sys/param.h> 3249*14414594SDavid du Colombier+ #include <sys/kernel.h> 3250*14414594SDavid du Colombier+ #include <sys/systm.h> 3251*14414594SDavid du Colombier+ #include <sys/resourcevar.h> 3252*14414594SDavid du Colombier+ #include <sys/proc.h> 3253*14414594SDavid du Colombier+ #include <sys/mount.h> 3254*14414594SDavid du Colombier+ #include <sys/buf.h> 3255*14414594SDavid du Colombier+ #include <sys/malloc.h> 3256*14414594SDavid du Colombier+ #include <sys/mbuf.h> 3257*14414594SDavid du Colombier+ #include <sys/namei.h> 3258*14414594SDavid du Colombier+ #include <sys/socket.h> 3259*14414594SDavid du Colombier+ #include <sys/vnode.h> 3260*14414594SDavid du Colombier+ #include <sys/dirent.h> 3261*14414594SDavid du Colombier+ #include <sys/fcntl.h> 3262*14414594SDavid du Colombier+ #include <sys/lockf.h> 3263*14414594SDavid du Colombier+ #include <sys/stat.h> 3264*14414594SDavid du Colombier+ #include <sys/sysctl.h> 3265*14414594SDavid du Colombier+ 3266*14414594SDavid du Colombier+ #include <vm/vm.h> 3267*14414594SDavid du Colombier+ #include <vm/vm_extern.h> 3268*14414594SDavid du Colombier+ #include <vm/vm_zone.h> 3269*14414594SDavid du Colombier+ #include <vm/vm_prot.h> 3270*14414594SDavid du Colombier+ #include <vm/vm_page.h> 3271*14414594SDavid du Colombier+ #include <vm/vm_object.h> 3272*14414594SDavid du Colombier+ #include <vm/vm_pager.h> 3273*14414594SDavid du Colombier+ #include <vm/vnode_pager.h> 3274*14414594SDavid du Colombier+ 3275*14414594SDavid du Colombier+ #include <net/if.h> 3276*14414594SDavid du Colombier+ #include <netinet/in.h> 3277*14414594SDavid du Colombier+ #include <netinet/in_var.h> 3278*14414594SDavid du Colombier+ 3279*14414594SDavid du Colombier+ #include <9fs/bitstring.h> 3280*14414594SDavid du Colombier+ #include <9fs/9p.h> 3281*14414594SDavid du Colombier+ #include <9fs/9auth.h> 3282*14414594SDavid du Colombier+ #include <9fs/9fs.h> 3283*14414594SDavid du Colombier+ 3284*14414594SDavid du Colombier+ #define u9fs_poll vop_nopoll 3285*14414594SDavid du Colombier+ static int u9fs_lookup __P((struct vop_lookup_args *)); 3286*14414594SDavid du Colombier+ static int u9fs_create __P((struct vop_create_args *)); 3287*14414594SDavid du Colombier+ static int u9fs_mknod __P((struct vop_mknod_args *)); 3288*14414594SDavid du Colombier+ static int u9fs_open __P((struct vop_open_args *)); 3289*14414594SDavid du Colombier+ static int u9fs_close __P((struct vop_close_args *)); 3290*14414594SDavid du Colombier+ static int u9fs_access __P((struct vop_access_args *)); 3291*14414594SDavid du Colombier+ static int u9fs_getattr __P((struct vop_getattr_args *)); 3292*14414594SDavid du Colombier+ static int u9fs_setattr __P((struct vop_setattr_args *)); 3293*14414594SDavid du Colombier+ static int u9fs_read __P((struct vop_read_args *)); 3294*14414594SDavid du Colombier+ static int u9fs_mmap __P((struct vop_mmap_args *)); 3295*14414594SDavid du Colombier+ static int u9fs_fsync __P((struct vop_fsync_args *)); 3296*14414594SDavid du Colombier+ static int u9fs_remove __P((struct vop_remove_args *)); 3297*14414594SDavid du Colombier+ static int u9fs_link __P((struct vop_link_args *)); 3298*14414594SDavid du Colombier+ static int u9fs_rename __P((struct vop_rename_args *)); 3299*14414594SDavid du Colombier+ static int u9fs_mkdir __P((struct vop_mkdir_args *)); 3300*14414594SDavid du Colombier+ static int u9fs_rmdir __P((struct vop_rmdir_args *)); 3301*14414594SDavid du Colombier+ static int u9fs_symlink __P((struct vop_symlink_args *)); 3302*14414594SDavid du Colombier+ static int u9fs_readdir __P((struct vop_readdir_args *)); 3303*14414594SDavid du Colombier+ static int u9fs_bmap __P((struct vop_bmap_args *)); 3304*14414594SDavid du Colombier+ static int u9fs_strategy __P((struct vop_strategy_args *)); 3305*14414594SDavid du Colombier+ static int u9fs_readlink __P((struct vop_readlink_args *)); 3306*14414594SDavid du Colombier+ static int u9fs_print __P((struct vop_print_args *)); 3307*14414594SDavid du Colombier+ static int u9fs_advlock __P((struct vop_advlock_args *)); 3308*14414594SDavid du Colombier+ static int u9fs_bwrite __P((struct vop_bwrite_args *)); 3309*14414594SDavid du Colombier+ static int u9fs_abortop __P((struct vop_abortop_args *)); 3310*14414594SDavid du Colombier+ static int u9fs_getpages __P((struct vop_getpages_args *)); 3311*14414594SDavid du Colombier+ static int u9fs_putpages __P((struct vop_putpages_args *)); 3312*14414594SDavid du Colombier+ static int u9fs_inactive __P((struct vop_inactive_args *)); 3313*14414594SDavid du Colombier+ static int u9fs_reclaim __P((struct vop_reclaim_args *)); 3314*14414594SDavid du Colombier+ static int u9fs_write __P((struct vop_write_args *)); 3315*14414594SDavid du Colombier+ 3316*14414594SDavid du Colombier+ /* 3317*14414594SDavid du Colombier+ * Global vfs data structures for u9fs 3318*14414594SDavid du Colombier+ */ 3319*14414594SDavid du Colombier+ vop_t **u9fs_vnodeop_p; 3320*14414594SDavid du Colombier+ static struct vnodeopv_entry_desc u9fs_vnodeop_entries[] = { 3321*14414594SDavid du Colombier+ { &vop_default_desc, (vop_t *) vop_defaultop }, 3322*14414594SDavid du Colombier+ { &vop_abortop_desc, (vop_t *) u9fs_abortop }, 3323*14414594SDavid du Colombier+ { &vop_access_desc, (vop_t *) u9fs_access }, 3324*14414594SDavid du Colombier+ { &vop_advlock_desc, (vop_t *) u9fs_advlock }, 3325*14414594SDavid du Colombier+ { &vop_bmap_desc, (vop_t *) u9fs_bmap }, 3326*14414594SDavid du Colombier+ { &vop_bwrite_desc, (vop_t *) u9fs_bwrite }, 3327*14414594SDavid du Colombier+ { &vop_close_desc, (vop_t *) u9fs_close }, 3328*14414594SDavid du Colombier+ { &vop_create_desc, (vop_t *) u9fs_create }, 3329*14414594SDavid du Colombier+ { &vop_fsync_desc, (vop_t *) u9fs_fsync }, 3330*14414594SDavid du Colombier+ { &vop_getattr_desc, (vop_t *) u9fs_getattr }, 3331*14414594SDavid du Colombier+ { &vop_getpages_desc, (vop_t *) u9fs_getpages }, 3332*14414594SDavid du Colombier+ { &vop_putpages_desc, (vop_t *) u9fs_putpages }, 3333*14414594SDavid du Colombier+ { &vop_inactive_desc, (vop_t *) u9fs_inactive }, 3334*14414594SDavid du Colombier+ { &vop_lease_desc, (vop_t *) vop_null }, 3335*14414594SDavid du Colombier+ { &vop_link_desc, (vop_t *) u9fs_link }, 3336*14414594SDavid du Colombier+ { &vop_lock_desc, (vop_t *) vop_sharedlock }, 3337*14414594SDavid du Colombier+ { &vop_lookup_desc, (vop_t *) u9fs_lookup }, 3338*14414594SDavid du Colombier+ { &vop_mkdir_desc, (vop_t *) u9fs_mkdir }, 3339*14414594SDavid du Colombier+ { &vop_mknod_desc, (vop_t *) u9fs_mknod }, 3340*14414594SDavid du Colombier+ { &vop_mmap_desc, (vop_t *) u9fs_mmap }, 3341*14414594SDavid du Colombier+ { &vop_open_desc, (vop_t *) u9fs_open }, 3342*14414594SDavid du Colombier+ { &vop_poll_desc, (vop_t *) vop_nopoll }, 3343*14414594SDavid du Colombier+ { &vop_print_desc, (vop_t *) u9fs_print }, 3344*14414594SDavid du Colombier+ { &vop_read_desc, (vop_t *) u9fs_read }, 3345*14414594SDavid du Colombier+ { &vop_readdir_desc, (vop_t *) u9fs_readdir }, 3346*14414594SDavid du Colombier+ { &vop_readlink_desc, (vop_t *) u9fs_readlink }, 3347*14414594SDavid du Colombier+ { &vop_reclaim_desc, (vop_t *) u9fs_reclaim }, 3348*14414594SDavid du Colombier+ { &vop_remove_desc, (vop_t *) u9fs_remove }, 3349*14414594SDavid du Colombier+ { &vop_rename_desc, (vop_t *) u9fs_rename }, 3350*14414594SDavid du Colombier+ { &vop_rmdir_desc, (vop_t *) u9fs_rmdir }, 3351*14414594SDavid du Colombier+ { &vop_setattr_desc, (vop_t *) u9fs_setattr }, 3352*14414594SDavid du Colombier+ { &vop_strategy_desc, (vop_t *) u9fs_strategy }, 3353*14414594SDavid du Colombier+ { &vop_symlink_desc, (vop_t *) u9fs_symlink }, 3354*14414594SDavid du Colombier+ { &vop_write_desc, (vop_t *) u9fs_write }, 3355*14414594SDavid du Colombier+ { NULL, NULL } 3356*14414594SDavid du Colombier+ }; 3357*14414594SDavid du Colombier+ static struct vnodeopv_desc u9fs_vnodeop_opv_desc = 3358*14414594SDavid du Colombier+ { &u9fs_vnodeop_p, u9fs_vnodeop_entries }; 3359*14414594SDavid du Colombier+ VNODEOP_SET(u9fs_vnodeop_opv_desc); 3360*14414594SDavid du Colombier+ 3361*14414594SDavid du Colombier+ extern vm_zone_t u9fsnode_zone; 3362*14414594SDavid du Colombier+ 3363*14414594SDavid du Colombier+ static int u9fs_trunc(struct vnode * vp, struct ucred * cred, struct proc * p); 3364*14414594SDavid du Colombier+ static void u9fs_free_fid __P((u_short fid, struct u9fsmount * nmp, struct proc * p)); 3365*14414594SDavid du Colombier+ static void u9fs_updtcache __P((struct u9fsnode *, struct u9fsreq *)); 3366*14414594SDavid du Colombier+ 3367*14414594SDavid du Colombier+ #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 3368*14414594SDavid du Colombier+ 3369*14414594SDavid du Colombier+ /* open returns a qid for cache consistent check */ 3370*14414594SDavid du Colombier+ static void 3371*14414594SDavid du Colombier+ u9fs_updtcache(struct u9fsnode * np, struct u9fsreq * rep) 3372*14414594SDavid du Colombier+ { 3373*14414594SDavid du Colombier+ if( rep->r_type != Rerror ) 3374*14414594SDavid du Colombier+ np->n_dir.dir_qid = rep->r_qid; 3375*14414594SDavid du Colombier+ } 3376*14414594SDavid du Colombier+ 3377*14414594SDavid du Colombier+ static int 3378*14414594SDavid du Colombier+ u9fs_trunc(vp, cred, p) 3379*14414594SDavid du Colombier+ register struct vnode * vp; 3380*14414594SDavid du Colombier+ struct ucred * cred; 3381*14414594SDavid du Colombier+ struct proc * p; 3382*14414594SDavid du Colombier+ { 3383*14414594SDavid du Colombier+ struct u9fsnode *np = VTOU9FS(vp); 3384*14414594SDavid du Colombier+ struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount); 3385*14414594SDavid du Colombier+ int error; 3386*14414594SDavid du Colombier+ u_short newfid; 3387*14414594SDavid du Colombier+ struct u9fsreq req, rep; 3388*14414594SDavid du Colombier+ u_char mode; 3389*14414594SDavid du Colombier+ 3390*14414594SDavid du Colombier+ /* 3391*14414594SDavid du Colombier+ * Disallow write attempts on filesystems mounted read-only; 3392*14414594SDavid du Colombier+ * unless the file is a socket, fifo, or a block or character 3393*14414594SDavid du Colombier+ * device resident on the filesystem. 3394*14414594SDavid du Colombier+ */ 3395*14414594SDavid du Colombier+ if ( (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3396*14414594SDavid du Colombier+ switch (vp->v_type) { 3397*14414594SDavid du Colombier+ case VREG: 3398*14414594SDavid du Colombier+ case VDIR: 3399*14414594SDavid du Colombier+ case VLNK: 3400*14414594SDavid du Colombier+ return (EROFS); 3401*14414594SDavid du Colombier+ default: 3402*14414594SDavid du Colombier+ break; 3403*14414594SDavid du Colombier+ } 3404*14414594SDavid du Colombier+ } 3405*14414594SDavid du Colombier+ mode = U9P_MODE_WR | U9P_MODE_TRUNC; 3406*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 3407*14414594SDavid du Colombier+ req.r_nmp = nmp; 3408*14414594SDavid du Colombier+ req.r_procp = p; 3409*14414594SDavid du Colombier+ newfid = u9fs_id_new(nmp->nm_fids); 3410*14414594SDavid du Colombier+ req.r_type = Tclone; 3411*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 3412*14414594SDavid du Colombier+ req.r_newfid = newfid; 3413*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3414*14414594SDavid du Colombier+ if( error ) 3415*14414594SDavid du Colombier+ return error; 3416*14414594SDavid du Colombier+ req.r_type = Topen; 3417*14414594SDavid du Colombier+ req.r_fid = newfid; 3418*14414594SDavid du Colombier+ req.r_mode = mode; 3419*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3420*14414594SDavid du Colombier+ if( !error ) 3421*14414594SDavid du Colombier+ u9fs_vinvalbuf(vp, 0, cred, p, 0); 3422*14414594SDavid du Colombier+ if( error || np->n_wrfid ) { 3423*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 3424*14414594SDavid du Colombier+ return error; 3425*14414594SDavid du Colombier+ } 3426*14414594SDavid du Colombier+ 3427*14414594SDavid du Colombier+ if( !U9P_PERM_EXCL(np->n_dir.dir_mode)) 3428*14414594SDavid du Colombier+ np->n_wrfid = newfid; 3429*14414594SDavid du Colombier+ else 3430*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 3431*14414594SDavid du Colombier+ 3432*14414594SDavid du Colombier+ return (0); 3433*14414594SDavid du Colombier+ } 3434*14414594SDavid du Colombier+ 3435*14414594SDavid du Colombier+ /* 3436*14414594SDavid du Colombier+ * u9fs access vnode op. 3437*14414594SDavid du Colombier+ */ 3438*14414594SDavid du Colombier+ static int 3439*14414594SDavid du Colombier+ u9fs_access(ap) 3440*14414594SDavid du Colombier+ struct vop_access_args /* { 3441*14414594SDavid du Colombier+ struct vnode *a_vp; 3442*14414594SDavid du Colombier+ int a_mode; 3443*14414594SDavid du Colombier+ struct ucred *a_cred; 3444*14414594SDavid du Colombier+ struct proc *a_p; 3445*14414594SDavid du Colombier+ } */ *ap; 3446*14414594SDavid du Colombier+ { 3447*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 3448*14414594SDavid du Colombier+ struct u9fsnode *np = VTOU9FS(vp); 3449*14414594SDavid du Colombier+ struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount); 3450*14414594SDavid du Colombier+ struct proc * p = ap->a_p; 3451*14414594SDavid du Colombier+ int error, a_mode = ap->a_mode; 3452*14414594SDavid du Colombier+ u_short * fidp = 0, *fidp2 = 0, newfid; 3453*14414594SDavid du Colombier+ struct u9fsreq req, rep; 3454*14414594SDavid du Colombier+ u_char mode; 3455*14414594SDavid du Colombier+ struct ucred * cred = ap->a_cred; 3456*14414594SDavid du Colombier+ 3457*14414594SDavid du Colombier+ /* XXX: for the moment, only the authenticator has access */ 3458*14414594SDavid du Colombier+ if( cred->cr_uid != nmp->nm_authuid ) 3459*14414594SDavid du Colombier+ return (EPERM); 3460*14414594SDavid du Colombier+ 3461*14414594SDavid du Colombier+ /* 3462*14414594SDavid du Colombier+ * Disallow write attempts on filesystems mounted read-only; 3463*14414594SDavid du Colombier+ * unless the file is a socket, fifo, or a block or character 3464*14414594SDavid du Colombier+ * device resident on the filesystem. 3465*14414594SDavid du Colombier+ */ 3466*14414594SDavid du Colombier+ if ((a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3467*14414594SDavid du Colombier+ switch (vp->v_type) { 3468*14414594SDavid du Colombier+ case VREG: 3469*14414594SDavid du Colombier+ case VDIR: 3470*14414594SDavid du Colombier+ case VLNK: 3471*14414594SDavid du Colombier+ return (EROFS); 3472*14414594SDavid du Colombier+ default: 3473*14414594SDavid du Colombier+ break; 3474*14414594SDavid du Colombier+ } 3475*14414594SDavid du Colombier+ } 3476*14414594SDavid du Colombier+ 3477*14414594SDavid du Colombier+ /* we cant open an exclusive open file here */ 3478*14414594SDavid du Colombier+ if( U9P_PERM_EXCL(np->n_dir.dir_mode) ) 3479*14414594SDavid du Colombier+ return 0; 3480*14414594SDavid du Colombier+ 3481*14414594SDavid du Colombier+ /* check permission by actually opening it */ 3482*14414594SDavid du Colombier+ /* translate mode */ 3483*14414594SDavid du Colombier+ mode = 0; 3484*14414594SDavid du Colombier+ if( a_mode & VREAD ) { 3485*14414594SDavid du Colombier+ fidp = &np->n_rdfid; 3486*14414594SDavid du Colombier+ mode = U9P_MODE_RD; 3487*14414594SDavid du Colombier+ } 3488*14414594SDavid du Colombier+ if( a_mode & VWRITE ) { 3489*14414594SDavid du Colombier+ fidp = &np->n_wrfid; 3490*14414594SDavid du Colombier+ mode = U9P_MODE_WR; 3491*14414594SDavid du Colombier+ } 3492*14414594SDavid du Colombier+ if( (a_mode & (VREAD|VWRITE)) == (VREAD|VWRITE) ) { 3493*14414594SDavid du Colombier+ fidp2 = &np->n_rdfid; 3494*14414594SDavid du Colombier+ mode = U9P_MODE_RDWR; 3495*14414594SDavid du Colombier+ } 3496*14414594SDavid du Colombier+ 3497*14414594SDavid du Colombier+ if( a_mode & VEXEC ) { 3498*14414594SDavid du Colombier+ fidp = &np->n_rdfid; 3499*14414594SDavid du Colombier+ if( vp->v_type == VREG ) 3500*14414594SDavid du Colombier+ mode = U9P_MODE_EX; 3501*14414594SDavid du Colombier+ } 3502*14414594SDavid du Colombier+ 3503*14414594SDavid du Colombier+ if( fidp2 == 0 ) 3504*14414594SDavid du Colombier+ fidp2 = fidp; 3505*14414594SDavid du Colombier+ 3506*14414594SDavid du Colombier+ /* open fid mode */ 3507*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 3508*14414594SDavid du Colombier+ req.r_nmp = nmp; 3509*14414594SDavid du Colombier+ req.r_procp = p; 3510*14414594SDavid du Colombier+ newfid = u9fs_id_new(nmp->nm_fids); 3511*14414594SDavid du Colombier+ req.r_type = Tclone; 3512*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 3513*14414594SDavid du Colombier+ req.r_newfid = newfid; 3514*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3515*14414594SDavid du Colombier+ if( error ) 3516*14414594SDavid du Colombier+ return error; 3517*14414594SDavid du Colombier+ req.r_type = Topen; 3518*14414594SDavid du Colombier+ req.r_fid = newfid; 3519*14414594SDavid du Colombier+ req.r_mode = mode; 3520*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3521*14414594SDavid du Colombier+ u9fs_updtcache(np, &rep); 3522*14414594SDavid du Colombier+ if( error || (*fidp && *fidp2 ) ) { 3523*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 3524*14414594SDavid du Colombier+ return error; 3525*14414594SDavid du Colombier+ } 3526*14414594SDavid du Colombier+ 3527*14414594SDavid du Colombier+ *fidp = *fidp2 = newfid; 3528*14414594SDavid du Colombier+ 3529*14414594SDavid du Colombier+ return (0); 3530*14414594SDavid du Colombier+ } 3531*14414594SDavid du Colombier+ 3532*14414594SDavid du Colombier+ /* 3533*14414594SDavid du Colombier+ * u9fs open vnode op 3534*14414594SDavid du Colombier+ * Check to see if the type is ok 3535*14414594SDavid du Colombier+ * and that deletion is not in progress. 3536*14414594SDavid du Colombier+ * For paged in text files, you will need to flush the page cache 3537*14414594SDavid du Colombier+ * if consistency is lost. 3538*14414594SDavid du Colombier+ */ 3539*14414594SDavid du Colombier+ /* ARGSUSED */ 3540*14414594SDavid du Colombier+ static int 3541*14414594SDavid du Colombier+ u9fs_open(ap) 3542*14414594SDavid du Colombier+ struct vop_open_args /* { 3543*14414594SDavid du Colombier+ struct vnode *a_vp; 3544*14414594SDavid du Colombier+ int a_mode; 3545*14414594SDavid du Colombier+ struct ucred *a_cred; 3546*14414594SDavid du Colombier+ struct proc *a_p; 3547*14414594SDavid du Colombier+ } */ *ap; 3548*14414594SDavid du Colombier+ { 3549*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 3550*14414594SDavid du Colombier+ struct u9fsnode *np = VTOU9FS(vp); 3551*14414594SDavid du Colombier+ int error=0, a_mode = ap->a_mode; 3552*14414594SDavid du Colombier+ u_short * fidp = 0, *fidp2 = 0, newfid; 3553*14414594SDavid du Colombier+ struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount); 3554*14414594SDavid du Colombier+ struct proc * p = ap->a_p; 3555*14414594SDavid du Colombier+ struct u9fsreq req, rep; 3556*14414594SDavid du Colombier+ u_char mode; 3557*14414594SDavid du Colombier+ struct ucred * cred = ap->a_cred; 3558*14414594SDavid du Colombier+ 3559*14414594SDavid du Colombier+ /* assume access permissions have been checked via VOP_ACCESS */ 3560*14414594SDavid du Colombier+ /* the file is actually opened except the rdwr case */ 3561*14414594SDavid du Colombier+ 3562*14414594SDavid du Colombier+ if( a_mode & (O_EXCL|O_SHLOCK|O_EXLOCK) ) { 3563*14414594SDavid du Colombier+ #if 0 /* XXX: what can we do here? */ 3564*14414594SDavid du Colombier+ return (EOPNOTSUPP); 3565*14414594SDavid du Colombier+ #endif 3566*14414594SDavid du Colombier+ } 3567*14414594SDavid du Colombier+ 3568*14414594SDavid du Colombier+ /* translate mode */ 3569*14414594SDavid du Colombier+ mode = 0; 3570*14414594SDavid du Colombier+ if( a_mode & FREAD ) { 3571*14414594SDavid du Colombier+ fidp = &np->n_rdfid; 3572*14414594SDavid du Colombier+ mode = U9P_MODE_RD; 3573*14414594SDavid du Colombier+ } 3574*14414594SDavid du Colombier+ if( a_mode & FWRITE ) { 3575*14414594SDavid du Colombier+ fidp = &np->n_wrfid; 3576*14414594SDavid du Colombier+ mode = U9P_MODE_WR; 3577*14414594SDavid du Colombier+ } 3578*14414594SDavid du Colombier+ if( (a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE) ) { 3579*14414594SDavid du Colombier+ fidp2 = & np->n_rdfid; 3580*14414594SDavid du Colombier+ mode = U9P_MODE_RDWR; 3581*14414594SDavid du Colombier+ } 3582*14414594SDavid du Colombier+ if( fidp2 == 0) 3583*14414594SDavid du Colombier+ fidp2 = fidp; 3584*14414594SDavid du Colombier+ 3585*14414594SDavid du Colombier+ if( U9P_PERM_EXCL(np->n_dir.dir_mode) ) { 3586*14414594SDavid du Colombier+ if( *fidp || *fidp2 ) 3587*14414594SDavid du Colombier+ return ENOLCK; 3588*14414594SDavid du Colombier+ 3589*14414594SDavid du Colombier+ /* open fid mode */ 3590*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 3591*14414594SDavid du Colombier+ req.r_nmp = nmp; 3592*14414594SDavid du Colombier+ req.r_procp = p; 3593*14414594SDavid du Colombier+ newfid = u9fs_id_new(nmp->nm_fids); 3594*14414594SDavid du Colombier+ req.r_type = Tclone; 3595*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 3596*14414594SDavid du Colombier+ req.r_newfid = newfid; 3597*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3598*14414594SDavid du Colombier+ if( error ) 3599*14414594SDavid du Colombier+ return error; 3600*14414594SDavid du Colombier+ req.r_type = Topen; 3601*14414594SDavid du Colombier+ req.r_fid = newfid; 3602*14414594SDavid du Colombier+ req.r_mode = mode; 3603*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3604*14414594SDavid du Colombier+ if( error ) { 3605*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 3606*14414594SDavid du Colombier+ return error; 3607*14414594SDavid du Colombier+ } 3608*14414594SDavid du Colombier+ u9fs_updtcache(np, &rep); 3609*14414594SDavid du Colombier+ 3610*14414594SDavid du Colombier+ *fidp = *fidp2 = newfid; 3611*14414594SDavid du Colombier+ } 3612*14414594SDavid du Colombier+ 3613*14414594SDavid du Colombier+ if( *fidp == 0 ) 3614*14414594SDavid du Colombier+ panic("open"); 3615*14414594SDavid du Colombier+ 3616*14414594SDavid du Colombier+ if( *fidp2 == 0 ) { 3617*14414594SDavid du Colombier+ /* open fid mode */ 3618*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 3619*14414594SDavid du Colombier+ req.r_nmp = nmp; 3620*14414594SDavid du Colombier+ req.r_procp = p; 3621*14414594SDavid du Colombier+ newfid = u9fs_id_new(nmp->nm_fids); 3622*14414594SDavid du Colombier+ req.r_type = Tclone; 3623*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 3624*14414594SDavid du Colombier+ req.r_newfid = newfid; 3625*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3626*14414594SDavid du Colombier+ if( error ) 3627*14414594SDavid du Colombier+ return error; 3628*14414594SDavid du Colombier+ req.r_type = Topen; 3629*14414594SDavid du Colombier+ req.r_fid = newfid; 3630*14414594SDavid du Colombier+ req.r_mode = mode; 3631*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 3632*14414594SDavid du Colombier+ if( error ) { 3633*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 3634*14414594SDavid du Colombier+ return error; 3635*14414594SDavid du Colombier+ } 3636*14414594SDavid du Colombier+ u9fs_updtcache(np, &rep); 3637*14414594SDavid du Colombier+ *fidp2 = newfid; 3638*14414594SDavid du Colombier+ } 3639*14414594SDavid du Colombier+ 3640*14414594SDavid du Colombier+ if( np->n_qid.vers != np->n_dir.dir_qid.vers ) /* content changed */ 3641*14414594SDavid du Colombier+ u9fs_vinvalbuf(vp, 0, cred, p, 0); 3642*14414594SDavid du Colombier+ 3643*14414594SDavid du Colombier+ return 0; 3644*14414594SDavid du Colombier+ } 3645*14414594SDavid du Colombier+ 3646*14414594SDavid du Colombier+ /* 3647*14414594SDavid du Colombier+ * u9fs close vnode op 3648*14414594SDavid du Colombier+ * What an U9FS client should do upon close after writing is a debatable issue. 3649*14414594SDavid du Colombier+ * Most U9FS clients push delayed writes to the server upon close, basically for 3650*14414594SDavid du Colombier+ * two reasons: 3651*14414594SDavid du Colombier+ * 1 - So that any write errors may be reported back to the client process 3652*14414594SDavid du Colombier+ * doing the close system call. By far the two most likely errors are 3653*14414594SDavid du Colombier+ * U9FSERR_NOSPC and U9FSERR_DQUOT to indicate space allocation failure. 3654*14414594SDavid du Colombier+ * 2 - To put a worst case upper bound on cache inconsistency between 3655*14414594SDavid du Colombier+ * multiple clients for the file. 3656*14414594SDavid du Colombier+ * There is also a consistency problem for Version 2 of the protocol w.r.t. 3657*14414594SDavid du Colombier+ * not being able to tell if other clients are writing a file concurrently, 3658*14414594SDavid du Colombier+ * since there is no way of knowing if the changed modify time in the reply 3659*14414594SDavid du Colombier+ * is only due to the write for this client. 3660*14414594SDavid du Colombier+ * (U9FS Version 3 provides weak cache consistency data in the reply that 3661*14414594SDavid du Colombier+ * should be sufficient to detect and handle this case.) 3662*14414594SDavid du Colombier+ * 3663*14414594SDavid du Colombier+ * The current code does the following: 3664*14414594SDavid du Colombier+ * for U9FS Version 2 - play it safe and flush/invalidate all dirty buffers 3665*14414594SDavid du Colombier+ * for U9FS Version 3 - flush dirty buffers to the server but don't invalidate 3666*14414594SDavid du Colombier+ * or commit them (this satisfies 1 and 2 except for the 3667*14414594SDavid du Colombier+ * case where the server crashes after this close but 3668*14414594SDavid du Colombier+ * before the commit RPC, which is felt to be "good 3669*14414594SDavid du Colombier+ * enough". Changing the last argument to u9fs_flush() to 3670*14414594SDavid du Colombier+ * a 1 would force a commit operation, if it is felt a 3671*14414594SDavid du Colombier+ * commit is necessary now. 3672*14414594SDavid du Colombier+ * for NQU9FS - do nothing now, since 2 is dealt with via leases and 3673*14414594SDavid du Colombier+ * 1 should be dealt with via an fsync() system call for 3674*14414594SDavid du Colombier+ * cases where write errors are important. 3675*14414594SDavid du Colombier+ */ 3676*14414594SDavid du Colombier+ /* ARGSUSED */ 3677*14414594SDavid du Colombier+ static int 3678*14414594SDavid du Colombier+ u9fs_close(ap) 3679*14414594SDavid du Colombier+ struct vop_close_args /* { 3680*14414594SDavid du Colombier+ struct vnodeop_desc *a_desc; 3681*14414594SDavid du Colombier+ struct vnode *a_vp; 3682*14414594SDavid du Colombier+ int a_fflag; 3683*14414594SDavid du Colombier+ struct ucred *a_cred; 3684*14414594SDavid du Colombier+ struct proc *a_p; 3685*14414594SDavid du Colombier+ } */ *ap; 3686*14414594SDavid du Colombier+ { 3687*14414594SDavid du Colombier+ int fflag = ap->a_fflag; 3688*14414594SDavid du Colombier+ struct vnode * vp = ap->a_vp; 3689*14414594SDavid du Colombier+ struct u9fsnode * np = VTOU9FS(vp); 3690*14414594SDavid du Colombier+ struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount); 3691*14414594SDavid du Colombier+ struct proc * p = ap->a_p; 3692*14414594SDavid du Colombier+ 3693*14414594SDavid du Colombier+ if( U9P_PERM_EXCL(np->n_dir.dir_mode) ) { 3694*14414594SDavid du Colombier+ if( (fflag & FREAD) ) { 3695*14414594SDavid du Colombier+ u9fs_free_fid(np->n_rdfid, nmp, p); 3696*14414594SDavid du Colombier+ np->n_rdfid = 0; 3697*14414594SDavid du Colombier+ } 3698*14414594SDavid du Colombier+ 3699*14414594SDavid du Colombier+ if( (fflag & FWRITE) == FWRITE ) { 3700*14414594SDavid du Colombier+ u9fs_free_fid(np->n_wrfid, nmp, p); 3701*14414594SDavid du Colombier+ np->n_wrfid = 0; 3702*14414594SDavid du Colombier+ } 3703*14414594SDavid du Colombier+ 3704*14414594SDavid du Colombier+ if( (fflag & (FREAD|FWRITE)) == (FREAD|FWRITE) ) 3705*14414594SDavid du Colombier+ np->n_wrfid = 0; 3706*14414594SDavid du Colombier+ } 3707*14414594SDavid du Colombier+ 3708*14414594SDavid du Colombier+ return 0; 3709*14414594SDavid du Colombier+ } 3710*14414594SDavid du Colombier+ 3711*14414594SDavid du Colombier+ /* 3712*14414594SDavid du Colombier+ * u9fs getattr call from vfs. 3713*14414594SDavid du Colombier+ */ 3714*14414594SDavid du Colombier+ static int 3715*14414594SDavid du Colombier+ u9fs_getattr(ap) 3716*14414594SDavid du Colombier+ struct vop_getattr_args /* { 3717*14414594SDavid du Colombier+ struct vnode *a_vp; 3718*14414594SDavid du Colombier+ struct vattr *a_vap; 3719*14414594SDavid du Colombier+ struct ucred *a_cred; 3720*14414594SDavid du Colombier+ struct proc *a_p; 3721*14414594SDavid du Colombier+ } */ *ap; 3722*14414594SDavid du Colombier+ { 3723*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 3724*14414594SDavid du Colombier+ register struct u9fsnode *np = VTOU9FS(vp); 3725*14414594SDavid du Colombier+ int error = 0; 3726*14414594SDavid du Colombier+ struct u9fsreq req, rep; 3727*14414594SDavid du Colombier+ struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount); 3728*14414594SDavid du Colombier+ struct u9fsdir * dir; 3729*14414594SDavid du Colombier+ struct vattr * vap = ap->a_vap; 3730*14414594SDavid du Colombier+ 3731*14414594SDavid du Colombier+ /* 3732*14414594SDavid du Colombier+ * Update local times for special files. 3733*14414594SDavid du Colombier+ */ 3734*14414594SDavid du Colombier+ if (np->n_flag & (NACC | NUPD)) 3735*14414594SDavid du Colombier+ np->n_flag |= NCHG; 3736*14414594SDavid du Colombier+ #if 0 3737*14414594SDavid du Colombier+ /* 3738*14414594SDavid du Colombier+ * First look in the cache. 3739*14414594SDavid du Colombier+ */ 3740*14414594SDavid du Colombier+ if (u9fs_getattrcache(vp, ap->a_vap) == 0) 3741*14414594SDavid du Colombier+ return (0); 3742*14414594SDavid du Colombier+ #endif 3743*14414594SDavid du Colombier+ if( np->n_fid == 0 ) 3744*14414594SDavid du Colombier+ panic("u9fs_getattr"); 3745*14414594SDavid du Colombier+ 3746*14414594SDavid du Colombier+ /* stat fid */ 3747*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 3748*14414594SDavid du Colombier+ req.r_nmp = nmp; 3749*14414594SDavid du Colombier+ req.r_procp = ap->a_p; 3750*14414594SDavid du Colombier+ req.r_type = Tstat; 3751*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 3752*14414594SDavid du Colombier+ error = u9fs_request(& req, & rep, 1); 3753*14414594SDavid du Colombier+ if( error ) 3754*14414594SDavid du Colombier+ return error; 3755*14414594SDavid du Colombier+ 3756*14414594SDavid du Colombier+ /* fill in vattr */ 3757*14414594SDavid du Colombier+ dir = & np->n_dir; 3758*14414594SDavid du Colombier+ u9p_m2d(rep.r_stat, dir); 3759*14414594SDavid du Colombier+ 3760*14414594SDavid du Colombier+ bzero(vap, sizeof(*vap)); 3761*14414594SDavid du Colombier+ /* the plan9 file system has no other types. */ 3762*14414594SDavid du Colombier+ /* XXX: we have not delt with devices yet */ 3763*14414594SDavid du Colombier+ if( U9P_PERM_CHDIR(dir->dir_mode) ) 3764*14414594SDavid du Colombier+ vap->va_type = VDIR; 3765*14414594SDavid du Colombier+ else 3766*14414594SDavid du Colombier+ vap->va_type = VREG; 3767*14414594SDavid du Colombier+ 3768*14414594SDavid du Colombier+ vap->va_mode = U9P_PERM_ALL(dir->dir_mode); 3769*14414594SDavid du Colombier+ vap->va_nlink = 1; 3770*14414594SDavid du Colombier+ vap->va_uid = u9fs_name2uid(dir->dir_uid); 3771*14414594SDavid du Colombier+ vap->va_gid = u9fs_name2uid(dir->dir_gid); 3772*14414594SDavid du Colombier+ vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 3773*14414594SDavid du Colombier+ vap->va_fileid = dir->dir_qid.path; 3774*14414594SDavid du Colombier+ vap->va_size = np->n_size = dir->dir_length; 3775*14414594SDavid du Colombier+ vap->va_blocksize = PAGE_SIZE; 3776*14414594SDavid du Colombier+ vap->va_atime.tv_sec = dir->dir_atime; 3777*14414594SDavid du Colombier+ vap->va_atime.tv_nsec = 0; 3778*14414594SDavid du Colombier+ vap->va_mtime.tv_sec = dir->dir_mtime; 3779*14414594SDavid du Colombier+ vap->va_mtime.tv_nsec = 0; 3780*14414594SDavid du Colombier+ vap->va_ctime.tv_sec = dir->dir_mtime; 3781*14414594SDavid du Colombier+ vap->va_ctime.tv_nsec = dir->dir_mtime; 3782*14414594SDavid du Colombier+ vap->va_gen = VNOVAL; 3783*14414594SDavid du Colombier+ vap->va_flags = 0; 3784*14414594SDavid du Colombier+ vap->va_bytes = vap->va_size; 3785*14414594SDavid du Colombier+ vap->va_filerev = dir->dir_qid.vers; 3786*14414594SDavid du Colombier+ 3787*14414594SDavid du Colombier+ vp->v_type = vap->va_type; 3788*14414594SDavid du Colombier+ vp->v_tag = VT_U9FS; 3789*14414594SDavid du Colombier+ 3790*14414594SDavid du Colombier+ return (error); 3791*14414594SDavid du Colombier+ } 3792*14414594SDavid du Colombier+ 3793*14414594SDavid du Colombier+ /* 3794*14414594SDavid du Colombier+ * u9fs setattr call. 3795*14414594SDavid du Colombier+ */ 3796*14414594SDavid du Colombier+ static int 3797*14414594SDavid du Colombier+ u9fs_setattr(ap) 3798*14414594SDavid du Colombier+ struct vop_setattr_args /* { 3799*14414594SDavid du Colombier+ struct vnodeop_desc *a_desc; 3800*14414594SDavid du Colombier+ struct vnode *a_vp; 3801*14414594SDavid du Colombier+ struct vattr *a_vap; 3802*14414594SDavid du Colombier+ struct ucred *a_cred; 3803*14414594SDavid du Colombier+ struct proc *a_p; 3804*14414594SDavid du Colombier+ } */ *ap; 3805*14414594SDavid du Colombier+ { 3806*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 3807*14414594SDavid du Colombier+ register struct u9fsnode *np = VTOU9FS(vp); 3808*14414594SDavid du Colombier+ register struct vattr *vap = ap->a_vap; 3809*14414594SDavid du Colombier+ int error = 0; 3810*14414594SDavid du Colombier+ struct u9fsmount * nmp = VFSTOU9FS(vp->v_mount); 3811*14414594SDavid du Colombier+ struct u9fsdir dir; 3812*14414594SDavid du Colombier+ struct u9fsuser * u9p; 3813*14414594SDavid du Colombier+ struct vattr attr; 3814*14414594SDavid du Colombier+ struct u9fsreq req, rep; 3815*14414594SDavid du Colombier+ 3816*14414594SDavid du Colombier+ if( vp->v_mount->mnt_flag & MNT_RDONLY ) 3817*14414594SDavid du Colombier+ return (EROFS); 3818*14414594SDavid du Colombier+ 3819*14414594SDavid du Colombier+ if( vap->va_nlink != VNOVAL || vap->va_uid != VNOVAL || 3820*14414594SDavid du Colombier+ vap->va_fsid != VNOVAL || vap->va_fileid != VNOVAL || 3821*14414594SDavid du Colombier+ #if 0 3822*14414594SDavid du Colombier+ vap->va_size != VNOVAL || vap->va_blocksize != VNOVAL || 3823*14414594SDavid du Colombier+ #endif 3824*14414594SDavid du Colombier+ vap->va_atime.tv_sec != VNOVAL || vap->va_ctime.tv_sec != VNOVAL || 3825*14414594SDavid du Colombier+ vap->va_gen != VNOVAL || 3826*14414594SDavid du Colombier+ vap->va_flags != VNOVAL || vap->va_bytes != VNOVAL ) { 3827*14414594SDavid du Colombier+ #if 0 3828*14414594SDavid du Colombier+ printf("%d %d %d %d %d %d %d %d %d %d %d\n", vap->va_nlink, vap->va_uid, vap->va_fsid, 3829*14414594SDavid du Colombier+ vap->va_fileid, vap->va_size, vap->va_blocksize, 3830*14414594SDavid du Colombier+ vap->va_atime.tv_sec, vap->va_ctime.tv_sec, vap->va_gen, 3831*14414594SDavid du Colombier+ vap->va_flags, vap->va_bytes); 3832*14414594SDavid du Colombier+ printf("unsupported setattr\n"); 3833*14414594SDavid du Colombier+ /* touch tries to change ctime first. 3834*14414594SDavid du Colombier+ * if fails, it touches the first byte 3835*14414594SDavid du Colombier+ */ 3836*14414594SDavid du Colombier+ #endif 3837*14414594SDavid du Colombier+ return (EOPNOTSUPP); 3838*14414594SDavid du Colombier+ } 3839*14414594SDavid du Colombier+ 3840*14414594SDavid du Colombier+ if( vap->va_size == 0 ) 3841*14414594SDavid du Colombier+ u9fs_trunc(vp, ap->a_cred, ap->a_p); 3842*14414594SDavid du Colombier+ 3843*14414594SDavid du Colombier+ bcopy(&np->n_dir, &dir, sizeof(dir)); 3844*14414594SDavid du Colombier+ if( vap->va_mode != (mode_t)VNOVAL ) { 3845*14414594SDavid du Colombier+ dir.dir_mode = U9P_PERM_NONPERM(dir.dir_mode)|U9P_PERM_ALL(vap->va_mode); 3846*14414594SDavid du Colombier+ } 3847*14414594SDavid du Colombier+ if( vap->va_gid != VNOVAL ) { 3848*14414594SDavid du Colombier+ if( (u9p = u9fs_finduser(vap->va_gid)) == 0 ) 3849*14414594SDavid du Colombier+ return (EINVAL); 3850*14414594SDavid du Colombier+ strncpy(u9p->u_name, dir.dir_gid, U9FS_NAMELEN); 3851*14414594SDavid du Colombier+ } 3852*14414594SDavid du Colombier+ if( vap->va_mtime.tv_sec != VNOVAL ) { 3853*14414594SDavid du Colombier+ dir.dir_mtime = vap->va_mtime.tv_sec; 3854*14414594SDavid du Colombier+ } 3855*14414594SDavid du Colombier+ 3856*14414594SDavid du Colombier+ /* stat fid */ 3857*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 3858*14414594SDavid du Colombier+ req.r_nmp = nmp; 3859*14414594SDavid du Colombier+ req.r_procp = ap->a_p; 3860*14414594SDavid du Colombier+ req.r_type = Twstat; 3861*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 3862*14414594SDavid du Colombier+ u9p_d2m(&dir, req.r_stat); 3863*14414594SDavid du Colombier+ error = u9fs_request(& req, & rep, 1); 3864*14414594SDavid du Colombier+ if( error ) 3865*14414594SDavid du Colombier+ return error; 3866*14414594SDavid du Colombier+ VOP_GETATTR(vp, &attr, ap->a_cred, ap->a_p); 3867*14414594SDavid du Colombier+ 3868*14414594SDavid du Colombier+ return 0; 3869*14414594SDavid du Colombier+ } 3870*14414594SDavid du Colombier+ 3871*14414594SDavid du Colombier+ /* 3872*14414594SDavid du Colombier+ * u9fs lookup call, one step at a time... 3873*14414594SDavid du Colombier+ * First look in cache 3874*14414594SDavid du Colombier+ * If not found, unlock the directory u9fsnode and do the rpc 3875*14414594SDavid du Colombier+ */ 3876*14414594SDavid du Colombier+ static int 3877*14414594SDavid du Colombier+ u9fs_lookup(ap) 3878*14414594SDavid du Colombier+ struct vop_lookup_args /* { 3879*14414594SDavid du Colombier+ struct vnodeop_desc *a_desc; 3880*14414594SDavid du Colombier+ struct vnode *a_dvp; 3881*14414594SDavid du Colombier+ struct vnode **a_vpp; 3882*14414594SDavid du Colombier+ struct componentname *a_cnp; 3883*14414594SDavid du Colombier+ } */ *ap; 3884*14414594SDavid du Colombier+ { 3885*14414594SDavid du Colombier+ struct componentname *cnp = ap->a_cnp; 3886*14414594SDavid du Colombier+ struct vnode *dvp = ap->a_dvp; 3887*14414594SDavid du Colombier+ struct vnode **vpp = ap->a_vpp; 3888*14414594SDavid du Colombier+ int flags = cnp->cn_flags; 3889*14414594SDavid du Colombier+ struct vnode *newvp; 3890*14414594SDavid du Colombier+ struct u9fsmount *nmp; 3891*14414594SDavid du Colombier+ long len; 3892*14414594SDavid du Colombier+ u9fsfh_t fh; 3893*14414594SDavid du Colombier+ struct u9fsnode *np; 3894*14414594SDavid du Colombier+ int lockparent, wantparent, error = 0; 3895*14414594SDavid du Colombier+ struct proc *p = cnp->cn_proc; 3896*14414594SDavid du Colombier+ struct u9fsreq req, rep; 3897*14414594SDavid du Colombier+ u_short newfid; 3898*14414594SDavid du Colombier+ struct vattr attrs; 3899*14414594SDavid du Colombier+ 3900*14414594SDavid du Colombier+ *vpp = NULLVP; 3901*14414594SDavid du Colombier+ if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 3902*14414594SDavid du Colombier+ (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 3903*14414594SDavid du Colombier+ return (EROFS); 3904*14414594SDavid du Colombier+ if (dvp->v_type != VDIR) 3905*14414594SDavid du Colombier+ return (ENOTDIR); 3906*14414594SDavid du Colombier+ lockparent = flags & LOCKPARENT; 3907*14414594SDavid du Colombier+ wantparent = flags & (LOCKPARENT|WANTPARENT); 3908*14414594SDavid du Colombier+ nmp = VFSTOU9FS(dvp->v_mount); 3909*14414594SDavid du Colombier+ np = VTOU9FS(dvp); 3910*14414594SDavid du Colombier+ #if 0 3911*14414594SDavid du Colombier+ if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 3912*14414594SDavid du Colombier+ struct vattr vattr; 3913*14414594SDavid du Colombier+ int vpid; 3914*14414594SDavid du Colombier+ 3915*14414594SDavid du Colombier+ if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) { 3916*14414594SDavid du Colombier+ *vpp = NULLVP; 3917*14414594SDavid du Colombier+ return (error); 3918*14414594SDavid du Colombier+ } 3919*14414594SDavid du Colombier+ 3920*14414594SDavid du Colombier+ newvp = *vpp; 3921*14414594SDavid du Colombier+ vpid = newvp->v_id; 3922*14414594SDavid du Colombier+ /* 3923*14414594SDavid du Colombier+ * See the comment starting `Step through' in ufs/ufs_lookup.c 3924*14414594SDavid du Colombier+ * for an explanation of the locking protocol 3925*14414594SDavid du Colombier+ */ 3926*14414594SDavid du Colombier+ if (dvp == newvp) { 3927*14414594SDavid du Colombier+ VREF(newvp); 3928*14414594SDavid du Colombier+ error = 0; 3929*14414594SDavid du Colombier+ } else if (flags & ISDOTDOT) { 3930*14414594SDavid du Colombier+ VOP_UNLOCK(dvp, 0, p); 3931*14414594SDavid du Colombier+ error = vget(newvp, LK_EXCLUSIVE, p); 3932*14414594SDavid du Colombier+ if (!error && lockparent && (flags & ISLASTCN)) 3933*14414594SDavid du Colombier+ error = vn_lock(dvp, LK_EXCLUSIVE, p); 3934*14414594SDavid du Colombier+ } else { 3935*14414594SDavid du Colombier+ error = vget(newvp, LK_EXCLUSIVE, p); 3936*14414594SDavid du Colombier+ if (!lockparent || error || !(flags & ISLASTCN)) 3937*14414594SDavid du Colombier+ VOP_UNLOCK(dvp, 0, p); 3938*14414594SDavid du Colombier+ } 3939*14414594SDavid du Colombier+ if (!error) { 3940*14414594SDavid du Colombier+ if (vpid == newvp->v_id) { 3941*14414594SDavid du Colombier+ if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p) 3942*14414594SDavid du Colombier+ && vattr.va_ctime.tv_sec == VTOU9FS(newvp)->n_ctime) { 3943*14414594SDavid du Colombier+ u9fsstats.lookupcache_hits++; 3944*14414594SDavid du Colombier+ if (cnp->cn_nameiop != LOOKUP && 3945*14414594SDavid du Colombier+ (flags & ISLASTCN)) 3946*14414594SDavid du Colombier+ cnp->cn_flags |= SAVENAME; 3947*14414594SDavid du Colombier+ return (0); 3948*14414594SDavid du Colombier+ } 3949*14414594SDavid du Colombier+ cache_purge(newvp); 3950*14414594SDavid du Colombier+ } 3951*14414594SDavid du Colombier+ vput(newvp); 3952*14414594SDavid du Colombier+ if (lockparent && dvp != newvp && (flags & ISLASTCN)) 3953*14414594SDavid du Colombier+ VOP_UNLOCK(dvp, 0, p); 3954*14414594SDavid du Colombier+ } 3955*14414594SDavid du Colombier+ error = vn_lock(dvp, LK_EXCLUSIVE, p); 3956*14414594SDavid du Colombier+ *vpp = NULLVP; 3957*14414594SDavid du Colombier+ if (error) 3958*14414594SDavid du Colombier+ return (error); 3959*14414594SDavid du Colombier+ } 3960*14414594SDavid du Colombier+ #endif 3961*14414594SDavid du Colombier+ error = 0; 3962*14414594SDavid du Colombier+ newvp = NULLVP; 3963*14414594SDavid du Colombier+ len = cnp->cn_namelen; 3964*14414594SDavid du Colombier+ 3965*14414594SDavid du Colombier+ /* Tclwalk tag fid newfid name */ 3966*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 3967*14414594SDavid du Colombier+ req.r_procp = p; 3968*14414594SDavid du Colombier+ req.r_nmp = nmp; 3969*14414594SDavid du Colombier+ req.r_type = Tclwalk; 3970*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 3971*14414594SDavid du Colombier+ newfid = req.r_newfid = u9fs_id_new(nmp->nm_fids); 3972*14414594SDavid du Colombier+ bcopy(cnp->cn_nameptr, req.r_name, len); 3973*14414594SDavid du Colombier+ if( (error = u9fs_request(&req, &rep, 1)) ) { 3974*14414594SDavid du Colombier+ u9fs_id_free(nmp->nm_fids, newfid); 3975*14414594SDavid du Colombier+ return error; 3976*14414594SDavid du Colombier+ } 3977*14414594SDavid du Colombier+ 3978*14414594SDavid du Colombier+ fh = rep.r_qid.path; 3979*14414594SDavid du Colombier+ if( fh == 0 ) { 3980*14414594SDavid du Colombier+ u9fs_id_free(nmp->nm_fids, newfid); 3981*14414594SDavid du Colombier+ error = ENOENT; 3982*14414594SDavid du Colombier+ goto lastcheck; 3983*14414594SDavid du Colombier+ } 3984*14414594SDavid du Colombier+ 3985*14414594SDavid du Colombier+ /* 3986*14414594SDavid du Colombier+ * Handle RENAME case... 3987*14414594SDavid du Colombier+ */ 3988*14414594SDavid du Colombier+ if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 3989*14414594SDavid du Colombier+ #if 0 3990*14414594SDavid du Colombier+ /* XXX: I dont understand this. rename foo foo? */ 3991*14414594SDavid du Colombier+ if (U9FS_CMPFH(np, fhp, fhsize)) { 3992*14414594SDavid du Colombier+ m_freem(mrep); 3993*14414594SDavid du Colombier+ return (EISDIR); 3994*14414594SDavid du Colombier+ } 3995*14414594SDavid du Colombier+ #endif 3996*14414594SDavid du Colombier+ error = u9fs_nget(dvp->v_mount, fh, &np, p); 3997*14414594SDavid du Colombier+ if (error) 3998*14414594SDavid du Colombier+ goto fail; 3999*14414594SDavid du Colombier+ 4000*14414594SDavid du Colombier+ if ( np->n_fid ) 4001*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 4002*14414594SDavid du Colombier+ else 4003*14414594SDavid du Colombier+ np->n_fid = newfid; 4004*14414594SDavid du Colombier+ 4005*14414594SDavid du Colombier+ newvp = U9FSTOV(np); 4006*14414594SDavid du Colombier+ *vpp = newvp; 4007*14414594SDavid du Colombier+ cnp->cn_flags |= SAVENAME; 4008*14414594SDavid du Colombier+ if (!lockparent) 4009*14414594SDavid du Colombier+ VOP_UNLOCK(dvp, 0, p); 4010*14414594SDavid du Colombier+ return (0); 4011*14414594SDavid du Colombier+ } 4012*14414594SDavid du Colombier+ 4013*14414594SDavid du Colombier+ if (flags & ISDOTDOT) { 4014*14414594SDavid du Colombier+ VOP_UNLOCK(dvp, 0, p); 4015*14414594SDavid du Colombier+ error = u9fs_nget(dvp->v_mount, fh, &np, p); 4016*14414594SDavid du Colombier+ if (error) { 4017*14414594SDavid du Colombier+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 4018*14414594SDavid du Colombier+ goto fail; 4019*14414594SDavid du Colombier+ } 4020*14414594SDavid du Colombier+ if( np->n_fid ) 4021*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 4022*14414594SDavid du Colombier+ else 4023*14414594SDavid du Colombier+ np->n_fid = req.r_newfid; 4024*14414594SDavid du Colombier+ 4025*14414594SDavid du Colombier+ newvp = U9FSTOV(np); 4026*14414594SDavid du Colombier+ if (lockparent && (flags & ISLASTCN) && 4027*14414594SDavid du Colombier+ (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { 4028*14414594SDavid du Colombier+ vput(newvp); 4029*14414594SDavid du Colombier+ return (error); 4030*14414594SDavid du Colombier+ } 4031*14414594SDavid du Colombier+ } else if (np->n_qid.path == fh) { 4032*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 4033*14414594SDavid du Colombier+ VREF(dvp); 4034*14414594SDavid du Colombier+ newvp = dvp; 4035*14414594SDavid du Colombier+ } else { 4036*14414594SDavid du Colombier+ error = u9fs_nget(dvp->v_mount, fh, &np, p); 4037*14414594SDavid du Colombier+ if (error) 4038*14414594SDavid du Colombier+ goto fail; 4039*14414594SDavid du Colombier+ 4040*14414594SDavid du Colombier+ if( np->n_fid ) 4041*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 4042*14414594SDavid du Colombier+ else 4043*14414594SDavid du Colombier+ np->n_fid = req.r_newfid; 4044*14414594SDavid du Colombier+ 4045*14414594SDavid du Colombier+ if (!lockparent || !(flags & ISLASTCN)) 4046*14414594SDavid du Colombier+ VOP_UNLOCK(dvp, 0, p); 4047*14414594SDavid du Colombier+ newvp = U9FSTOV(np); 4048*14414594SDavid du Colombier+ 4049*14414594SDavid du Colombier+ VOP_GETATTR(newvp, & attrs, p->p_ucred, p); 4050*14414594SDavid du Colombier+ } 4051*14414594SDavid du Colombier+ 4052*14414594SDavid du Colombier+ if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 4053*14414594SDavid du Colombier+ cnp->cn_flags |= SAVENAME; 4054*14414594SDavid du Colombier+ #if 0 4055*14414594SDavid du Colombier+ if ((cnp->cn_flags & MAKEENTRY) && 4056*14414594SDavid du Colombier+ (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 4057*14414594SDavid du Colombier+ np->n_ctime = np->n_vattr.va_ctime.tv_sec; 4058*14414594SDavid du Colombier+ cache_enter(dvp, newvp, cnp); 4059*14414594SDavid du Colombier+ } 4060*14414594SDavid du Colombier+ #endif 4061*14414594SDavid du Colombier+ *vpp = newvp; 4062*14414594SDavid du Colombier+ lastcheck: 4063*14414594SDavid du Colombier+ if (error) { 4064*14414594SDavid du Colombier+ if (newvp != NULLVP) { 4065*14414594SDavid du Colombier+ vrele(newvp); 4066*14414594SDavid du Colombier+ *vpp = NULLVP; 4067*14414594SDavid du Colombier+ } 4068*14414594SDavid du Colombier+ if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 4069*14414594SDavid du Colombier+ (flags & ISLASTCN) && error == ENOENT) { 4070*14414594SDavid du Colombier+ if (!lockparent) 4071*14414594SDavid du Colombier+ VOP_UNLOCK(dvp, 0, p); 4072*14414594SDavid du Colombier+ if (dvp->v_mount->mnt_flag & MNT_RDONLY) 4073*14414594SDavid du Colombier+ error = EROFS; 4074*14414594SDavid du Colombier+ else 4075*14414594SDavid du Colombier+ error = EJUSTRETURN; 4076*14414594SDavid du Colombier+ } 4077*14414594SDavid du Colombier+ if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 4078*14414594SDavid du Colombier+ cnp->cn_flags |= SAVENAME; 4079*14414594SDavid du Colombier+ } 4080*14414594SDavid du Colombier+ return (error); 4081*14414594SDavid du Colombier+ 4082*14414594SDavid du Colombier+ fail: 4083*14414594SDavid du Colombier+ u9fs_free_fid(newfid, nmp, p); 4084*14414594SDavid du Colombier+ return (error); 4085*14414594SDavid du Colombier+ } 4086*14414594SDavid du Colombier+ 4087*14414594SDavid du Colombier+ /* 4088*14414594SDavid du Colombier+ * u9fs read call. 4089*14414594SDavid du Colombier+ * Just call u9fs_bioread() to do the work. 4090*14414594SDavid du Colombier+ */ 4091*14414594SDavid du Colombier+ static int 4092*14414594SDavid du Colombier+ u9fs_read(ap) 4093*14414594SDavid du Colombier+ struct vop_read_args /* { 4094*14414594SDavid du Colombier+ struct vnode *a_vp; 4095*14414594SDavid du Colombier+ struct uio *a_uio; 4096*14414594SDavid du Colombier+ int a_ioflag; 4097*14414594SDavid du Colombier+ struct ucred *a_cred; 4098*14414594SDavid du Colombier+ } */ *ap; 4099*14414594SDavid du Colombier+ { 4100*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 4101*14414594SDavid du Colombier+ 4102*14414594SDavid du Colombier+ if (vp->v_type != VREG) 4103*14414594SDavid du Colombier+ return (EPERM); 4104*14414594SDavid du Colombier+ return (u9fs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0)); 4105*14414594SDavid du Colombier+ } 4106*14414594SDavid du Colombier+ 4107*14414594SDavid du Colombier+ /* 4108*14414594SDavid du Colombier+ * u9fs readlink call 4109*14414594SDavid du Colombier+ */ 4110*14414594SDavid du Colombier+ static int 4111*14414594SDavid du Colombier+ u9fs_readlink(ap) 4112*14414594SDavid du Colombier+ struct vop_readlink_args /* { 4113*14414594SDavid du Colombier+ struct vnode *a_vp; 4114*14414594SDavid du Colombier+ struct uio *a_uio; 4115*14414594SDavid du Colombier+ struct ucred *a_cred; 4116*14414594SDavid du Colombier+ } */ *ap; 4117*14414594SDavid du Colombier+ { 4118*14414594SDavid du Colombier+ return (EOPNOTSUPP); 4119*14414594SDavid du Colombier+ } 4120*14414594SDavid du Colombier+ 4121*14414594SDavid du Colombier+ /* 4122*14414594SDavid du Colombier+ * u9fs mknod vop 4123*14414594SDavid du Colombier+ * just call u9fs_mknodrpc() to do the work. 4124*14414594SDavid du Colombier+ */ 4125*14414594SDavid du Colombier+ /* ARGSUSED */ 4126*14414594SDavid du Colombier+ static int 4127*14414594SDavid du Colombier+ u9fs_mknod(ap) 4128*14414594SDavid du Colombier+ struct vop_mknod_args /* { 4129*14414594SDavid du Colombier+ struct vnode *a_dvp; 4130*14414594SDavid du Colombier+ struct vnode **a_vpp; 4131*14414594SDavid du Colombier+ struct componentname *a_cnp; 4132*14414594SDavid du Colombier+ struct vattr *a_vap; 4133*14414594SDavid du Colombier+ } */ *ap; 4134*14414594SDavid du Colombier+ { 4135*14414594SDavid du Colombier+ return (EOPNOTSUPP); 4136*14414594SDavid du Colombier+ } 4137*14414594SDavid du Colombier+ 4138*14414594SDavid du Colombier+ /* 4139*14414594SDavid du Colombier+ * u9fs file create call 4140*14414594SDavid du Colombier+ */ 4141*14414594SDavid du Colombier+ static int 4142*14414594SDavid du Colombier+ u9fs_create(ap) 4143*14414594SDavid du Colombier+ struct vop_create_args /* { 4144*14414594SDavid du Colombier+ struct vnode *a_dvp; 4145*14414594SDavid du Colombier+ struct vnode **a_vpp; 4146*14414594SDavid du Colombier+ struct componentname *a_cnp; 4147*14414594SDavid du Colombier+ struct vattr *a_vap; 4148*14414594SDavid du Colombier+ } */ *ap; 4149*14414594SDavid du Colombier+ { 4150*14414594SDavid du Colombier+ register struct vnode *dvp = ap->a_dvp; 4151*14414594SDavid du Colombier+ register struct vattr *vap = ap->a_vap; 4152*14414594SDavid du Colombier+ register struct componentname *cnp = ap->a_cnp; 4153*14414594SDavid du Colombier+ struct u9fsnode *np = (struct u9fsnode *)0; 4154*14414594SDavid du Colombier+ struct vnode *newvp = (struct vnode *)0; 4155*14414594SDavid du Colombier+ int error = 0, len; 4156*14414594SDavid du Colombier+ struct vattr vattr; 4157*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4158*14414594SDavid du Colombier+ struct u9fsmount *nmp; 4159*14414594SDavid du Colombier+ u9fsfh_t fh; 4160*14414594SDavid du Colombier+ struct proc * p; 4161*14414594SDavid du Colombier+ int pfid; 4162*14414594SDavid du Colombier+ 4163*14414594SDavid du Colombier+ #if 0 4164*14414594SDavid du Colombier+ /* 4165*14414594SDavid du Colombier+ * Oops, not for me.. 4166*14414594SDavid du Colombier+ */ 4167*14414594SDavid du Colombier+ if (vap->va_type == VSOCK) 4168*14414594SDavid du Colombier+ return (u9fs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 4169*14414594SDavid du Colombier+ #endif 4170*14414594SDavid du Colombier+ 4171*14414594SDavid du Colombier+ if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 4172*14414594SDavid du Colombier+ VOP_ABORTOP(dvp, cnp); 4173*14414594SDavid du Colombier+ return (error); 4174*14414594SDavid du Colombier+ } 4175*14414594SDavid du Colombier+ 4176*14414594SDavid du Colombier+ nmp = VFSTOU9FS(dvp->v_mount); 4177*14414594SDavid du Colombier+ np = VTOU9FS(dvp); 4178*14414594SDavid du Colombier+ p = cnp->cn_proc; 4179*14414594SDavid du Colombier+ 4180*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4181*14414594SDavid du Colombier+ req.r_nmp = nmp; 4182*14414594SDavid du Colombier+ req.r_procp = p; 4183*14414594SDavid du Colombier+ 4184*14414594SDavid du Colombier+ req.r_type = Tclone; 4185*14414594SDavid du Colombier+ pfid = req.r_fid = np->n_fid; 4186*14414594SDavid du Colombier+ req.r_newfid = u9fs_id_new(nmp->nm_fids); 4187*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 4188*14414594SDavid du Colombier+ if( error ) 4189*14414594SDavid du Colombier+ return error; 4190*14414594SDavid du Colombier+ 4191*14414594SDavid du Colombier+ req.r_type = Tcreate; 4192*14414594SDavid du Colombier+ req.r_fid = req.r_newfid; 4193*14414594SDavid du Colombier+ len = cnp->cn_namelen; 4194*14414594SDavid du Colombier+ if( len > U9FS_NAMELEN ) 4195*14414594SDavid du Colombier+ len = U9FS_NAMELEN; 4196*14414594SDavid du Colombier+ strncpy(req.r_name, cnp->cn_nameptr, len); 4197*14414594SDavid du Colombier+ req.r_name[U9FS_NAMELEN] = 0; 4198*14414594SDavid du Colombier+ req.r_perm = U9P_PERM_ALL(vap->va_mode); 4199*14414594SDavid du Colombier+ if( vap->va_type == VDIR ) { 4200*14414594SDavid du Colombier+ req.r_perm |= 0x80000000; 4201*14414594SDavid du Colombier+ req.r_mode = U9P_MODE_RD; 4202*14414594SDavid du Colombier+ } else 4203*14414594SDavid du Colombier+ req.r_mode = U9P_MODE_WR | U9P_MODE_TRUNC; 4204*14414594SDavid du Colombier+ if(vap->va_vaflags & VA_EXCLUSIVE) 4205*14414594SDavid du Colombier+ req.r_mode = U9P_MODE_EX; 4206*14414594SDavid du Colombier+ 4207*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 4208*14414594SDavid du Colombier+ if( error ) 4209*14414594SDavid du Colombier+ return error; 4210*14414594SDavid du Colombier+ 4211*14414594SDavid du Colombier+ fh = rep.r_qid.path; 4212*14414594SDavid du Colombier+ u9fs_nget(dvp->v_mount, fh, &np, p); 4213*14414594SDavid du Colombier+ newvp = U9FSTOV(np); 4214*14414594SDavid du Colombier+ if( vap->va_type == VDIR ) 4215*14414594SDavid du Colombier+ np->n_rdfid = req.r_fid; 4216*14414594SDavid du Colombier+ else 4217*14414594SDavid du Colombier+ np->n_wrfid = req.r_fid; 4218*14414594SDavid du Colombier+ 4219*14414594SDavid du Colombier+ req.r_type = Tclwalk; 4220*14414594SDavid du Colombier+ req.r_fid = pfid; 4221*14414594SDavid du Colombier+ req.r_newfid = u9fs_id_new(nmp->nm_fids); 4222*14414594SDavid du Colombier+ /* r_name is already filled */ 4223*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 4224*14414594SDavid du Colombier+ if( error ) 4225*14414594SDavid du Colombier+ return error; 4226*14414594SDavid du Colombier+ np->n_fid = req.r_newfid; 4227*14414594SDavid du Colombier+ VOP_GETATTR(newvp, & vattr, p->p_ucred, p); 4228*14414594SDavid du Colombier+ 4229*14414594SDavid du Colombier+ *ap->a_vpp = newvp; 4230*14414594SDavid du Colombier+ zfree(namei_zone, cnp->cn_pnbuf); 4231*14414594SDavid du Colombier+ 4232*14414594SDavid du Colombier+ return 0; 4233*14414594SDavid du Colombier+ } 4234*14414594SDavid du Colombier+ 4235*14414594SDavid du Colombier+ /* 4236*14414594SDavid du Colombier+ * u9fs file remove call 4237*14414594SDavid du Colombier+ * To try and make u9fs semantics closer to ufs semantics, a file that has 4238*14414594SDavid du Colombier+ * other processes using the vnode is renamed instead of removed and then 4239*14414594SDavid du Colombier+ * removed later on the last close. 4240*14414594SDavid du Colombier+ * - If v_usecount > 1 4241*14414594SDavid du Colombier+ * If a rename is not already in the works 4242*14414594SDavid du Colombier+ * call u9fs_sillyrename() to set it up 4243*14414594SDavid du Colombier+ * else 4244*14414594SDavid du Colombier+ * do the remove rpc 4245*14414594SDavid du Colombier+ */ 4246*14414594SDavid du Colombier+ static int 4247*14414594SDavid du Colombier+ u9fs_remove(ap) 4248*14414594SDavid du Colombier+ struct vop_remove_args /* { 4249*14414594SDavid du Colombier+ struct vnodeop_desc *a_desc; 4250*14414594SDavid du Colombier+ struct vnode * a_dvp; 4251*14414594SDavid du Colombier+ struct vnode * a_vp; 4252*14414594SDavid du Colombier+ struct componentname * a_cnp; 4253*14414594SDavid du Colombier+ } */ *ap; 4254*14414594SDavid du Colombier+ { 4255*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 4256*14414594SDavid du Colombier+ register struct componentname *cnp = ap->a_cnp; 4257*14414594SDavid du Colombier+ struct u9fsnode *np; 4258*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4259*14414594SDavid du Colombier+ struct u9fsmount *nmp; 4260*14414594SDavid du Colombier+ struct proc * p; 4261*14414594SDavid du Colombier+ int error; 4262*14414594SDavid du Colombier+ 4263*14414594SDavid du Colombier+ nmp = VFSTOU9FS(vp->v_mount); 4264*14414594SDavid du Colombier+ np = VTOU9FS(vp); 4265*14414594SDavid du Colombier+ p = cnp->cn_proc; 4266*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4267*14414594SDavid du Colombier+ req.r_nmp = nmp; 4268*14414594SDavid du Colombier+ req.r_procp = p; 4269*14414594SDavid du Colombier+ req.r_type = Tremove; 4270*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 4271*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 4272*14414594SDavid du Colombier+ if( error ) 4273*14414594SDavid du Colombier+ return error; 4274*14414594SDavid du Colombier+ zfree(namei_zone, cnp->cn_pnbuf); 4275*14414594SDavid du Colombier+ return 0; 4276*14414594SDavid du Colombier+ } 4277*14414594SDavid du Colombier+ 4278*14414594SDavid du Colombier+ /* 4279*14414594SDavid du Colombier+ * u9fs file rename call 4280*14414594SDavid du Colombier+ */ 4281*14414594SDavid du Colombier+ static int 4282*14414594SDavid du Colombier+ u9fs_rename(ap) 4283*14414594SDavid du Colombier+ struct vop_rename_args /* { 4284*14414594SDavid du Colombier+ struct vnode *a_fdvp; 4285*14414594SDavid du Colombier+ struct vnode *a_fvp; 4286*14414594SDavid du Colombier+ struct componentname *a_fcnp; 4287*14414594SDavid du Colombier+ struct vnode *a_tdvp; 4288*14414594SDavid du Colombier+ struct vnode *a_tvp; 4289*14414594SDavid du Colombier+ struct componentname *a_tcnp; 4290*14414594SDavid du Colombier+ } */ *ap; 4291*14414594SDavid du Colombier+ { 4292*14414594SDavid du Colombier+ register struct vnode *fvp = ap->a_fvp; 4293*14414594SDavid du Colombier+ register struct vnode *tvp = ap->a_tvp; 4294*14414594SDavid du Colombier+ register struct vnode *fdvp = ap->a_fdvp; 4295*14414594SDavid du Colombier+ register struct vnode *tdvp = ap->a_tdvp; 4296*14414594SDavid du Colombier+ register struct componentname *tcnp = ap->a_tcnp; 4297*14414594SDavid du Colombier+ register struct componentname *fcnp = ap->a_fcnp; 4298*14414594SDavid du Colombier+ int error, len; 4299*14414594SDavid du Colombier+ struct u9fsmount * nmp; 4300*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4301*14414594SDavid du Colombier+ struct u9fsdir dir; 4302*14414594SDavid du Colombier+ struct u9fsnode * np; 4303*14414594SDavid du Colombier+ 4304*14414594SDavid du Colombier+ /* we cant do cross-directory renaming or move to an existing file */ 4305*14414594SDavid du Colombier+ if( fdvp != tdvp || tvp != 0 || fvp->v_mount->mnt_flag & MNT_RDONLY ){ 4306*14414594SDavid du Colombier+ printf("rename to existing file not supported\n"); 4307*14414594SDavid du Colombier+ error = EOPNOTSUPP; 4308*14414594SDavid du Colombier+ goto out; 4309*14414594SDavid du Colombier+ } 4310*14414594SDavid du Colombier+ 4311*14414594SDavid du Colombier+ nmp = VFSTOU9FS(fvp->v_mount); 4312*14414594SDavid du Colombier+ np = VTOU9FS(fvp); 4313*14414594SDavid du Colombier+ 4314*14414594SDavid du Colombier+ bcopy(&np->n_dir, &dir, sizeof(dir)); 4315*14414594SDavid du Colombier+ len = tcnp->cn_namelen; 4316*14414594SDavid du Colombier+ if( len > U9FS_NAMELEN ) 4317*14414594SDavid du Colombier+ len = U9FS_NAMELEN; 4318*14414594SDavid du Colombier+ strncpy(dir.dir_name, tcnp->cn_nameptr, len); 4319*14414594SDavid du Colombier+ dir.dir_name[U9FS_NAMELEN-1] = 0; 4320*14414594SDavid du Colombier+ 4321*14414594SDavid du Colombier+ /* stat fid */ 4322*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4323*14414594SDavid du Colombier+ req.r_nmp = nmp; 4324*14414594SDavid du Colombier+ req.r_procp = fcnp->cn_proc; 4325*14414594SDavid du Colombier+ req.r_type = Twstat; 4326*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 4327*14414594SDavid du Colombier+ u9p_d2m(&dir, req.r_stat); 4328*14414594SDavid du Colombier+ error = u9fs_request(& req, & rep, 1); 4329*14414594SDavid du Colombier+ 4330*14414594SDavid du Colombier+ out: 4331*14414594SDavid du Colombier+ if (tdvp == tvp) 4332*14414594SDavid du Colombier+ vrele(tdvp); 4333*14414594SDavid du Colombier+ else 4334*14414594SDavid du Colombier+ vput(tdvp); 4335*14414594SDavid du Colombier+ if (tvp) 4336*14414594SDavid du Colombier+ vput(tvp); 4337*14414594SDavid du Colombier+ vrele(fdvp); 4338*14414594SDavid du Colombier+ vrele(fvp); 4339*14414594SDavid du Colombier+ 4340*14414594SDavid du Colombier+ return error; 4341*14414594SDavid du Colombier+ } 4342*14414594SDavid du Colombier+ 4343*14414594SDavid du Colombier+ /* 4344*14414594SDavid du Colombier+ * u9fs hard link create call 4345*14414594SDavid du Colombier+ */ 4346*14414594SDavid du Colombier+ static int 4347*14414594SDavid du Colombier+ u9fs_link(ap) 4348*14414594SDavid du Colombier+ struct vop_link_args /* { 4349*14414594SDavid du Colombier+ struct vnode *a_tdvp; 4350*14414594SDavid du Colombier+ struct vnode *a_vp; 4351*14414594SDavid du Colombier+ struct componentname *a_cnp; 4352*14414594SDavid du Colombier+ } */ *ap; 4353*14414594SDavid du Colombier+ { 4354*14414594SDavid du Colombier+ return (EOPNOTSUPP); 4355*14414594SDavid du Colombier+ } 4356*14414594SDavid du Colombier+ 4357*14414594SDavid du Colombier+ /* 4358*14414594SDavid du Colombier+ * u9fs symbolic link create call 4359*14414594SDavid du Colombier+ */ 4360*14414594SDavid du Colombier+ static int 4361*14414594SDavid du Colombier+ u9fs_symlink(ap) 4362*14414594SDavid du Colombier+ struct vop_symlink_args /* { 4363*14414594SDavid du Colombier+ struct vnode *a_dvp; 4364*14414594SDavid du Colombier+ struct vnode **a_vpp; 4365*14414594SDavid du Colombier+ struct componentname *a_cnp; 4366*14414594SDavid du Colombier+ struct vattr *a_vap; 4367*14414594SDavid du Colombier+ char *a_target; 4368*14414594SDavid du Colombier+ } */ *ap; 4369*14414594SDavid du Colombier+ { 4370*14414594SDavid du Colombier+ return (EOPNOTSUPP); 4371*14414594SDavid du Colombier+ } 4372*14414594SDavid du Colombier+ 4373*14414594SDavid du Colombier+ /* 4374*14414594SDavid du Colombier+ * u9fs make dir call 4375*14414594SDavid du Colombier+ */ 4376*14414594SDavid du Colombier+ static int 4377*14414594SDavid du Colombier+ u9fs_mkdir(ap) 4378*14414594SDavid du Colombier+ struct vop_mkdir_args /* { 4379*14414594SDavid du Colombier+ struct vnode *a_dvp; 4380*14414594SDavid du Colombier+ struct vnode **a_vpp; 4381*14414594SDavid du Colombier+ struct componentname *a_cnp; 4382*14414594SDavid du Colombier+ struct vattr *a_vap; 4383*14414594SDavid du Colombier+ } */ *ap; 4384*14414594SDavid du Colombier+ { 4385*14414594SDavid du Colombier+ struct vop_create_args cap; 4386*14414594SDavid du Colombier+ 4387*14414594SDavid du Colombier+ cap.a_dvp = ap->a_dvp; 4388*14414594SDavid du Colombier+ cap.a_vpp = ap->a_vpp; 4389*14414594SDavid du Colombier+ cap.a_cnp = ap->a_cnp; 4390*14414594SDavid du Colombier+ cap.a_vap = ap->a_vap; 4391*14414594SDavid du Colombier+ return u9fs_create(&cap); 4392*14414594SDavid du Colombier+ } 4393*14414594SDavid du Colombier+ 4394*14414594SDavid du Colombier+ /* 4395*14414594SDavid du Colombier+ * u9fs remove directory call 4396*14414594SDavid du Colombier+ */ 4397*14414594SDavid du Colombier+ static int 4398*14414594SDavid du Colombier+ u9fs_rmdir(ap) 4399*14414594SDavid du Colombier+ struct vop_rmdir_args /* { 4400*14414594SDavid du Colombier+ struct vnode *a_dvp; 4401*14414594SDavid du Colombier+ struct vnode *a_vp; 4402*14414594SDavid du Colombier+ struct componentname *a_cnp; 4403*14414594SDavid du Colombier+ } */ *ap; 4404*14414594SDavid du Colombier+ { 4405*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 4406*14414594SDavid du Colombier+ register struct componentname *cnp = ap->a_cnp; 4407*14414594SDavid du Colombier+ struct u9fsnode *np; 4408*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4409*14414594SDavid du Colombier+ struct u9fsmount *nmp; 4410*14414594SDavid du Colombier+ struct proc * p; 4411*14414594SDavid du Colombier+ int error; 4412*14414594SDavid du Colombier+ 4413*14414594SDavid du Colombier+ nmp = VFSTOU9FS(vp->v_mount); 4414*14414594SDavid du Colombier+ np = VTOU9FS(vp); 4415*14414594SDavid du Colombier+ p = cnp->cn_proc; 4416*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4417*14414594SDavid du Colombier+ req.r_nmp = nmp; 4418*14414594SDavid du Colombier+ req.r_procp = p; 4419*14414594SDavid du Colombier+ req.r_type = Tremove; 4420*14414594SDavid du Colombier+ req.r_fid = np->n_fid; 4421*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 4422*14414594SDavid du Colombier+ if( error ) 4423*14414594SDavid du Colombier+ return error; 4424*14414594SDavid du Colombier+ u9fs_id_free(nmp->nm_fids, np->n_fid); 4425*14414594SDavid du Colombier+ np->n_fid = 0; 4426*14414594SDavid du Colombier+ zfree(namei_zone, cnp->cn_pnbuf); 4427*14414594SDavid du Colombier+ return 0; 4428*14414594SDavid du Colombier+ } 4429*14414594SDavid du Colombier+ 4430*14414594SDavid du Colombier+ /* 4431*14414594SDavid du Colombier+ * u9fs readdir call 4432*14414594SDavid du Colombier+ */ 4433*14414594SDavid du Colombier+ static int 4434*14414594SDavid du Colombier+ u9fs_readdir(ap) 4435*14414594SDavid du Colombier+ struct vop_readdir_args /* { 4436*14414594SDavid du Colombier+ struct vnode *a_vp; 4437*14414594SDavid du Colombier+ struct uio *a_uio; 4438*14414594SDavid du Colombier+ struct ucred *a_cred; 4439*14414594SDavid du Colombier+ } */ *ap; 4440*14414594SDavid du Colombier+ { 4441*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 4442*14414594SDavid du Colombier+ register struct uio *uio = ap->a_uio; 4443*14414594SDavid du Colombier+ int error; 4444*14414594SDavid du Colombier+ 4445*14414594SDavid du Colombier+ if (vp->v_type != VDIR) 4446*14414594SDavid du Colombier+ return (EPERM); 4447*14414594SDavid du Colombier+ 4448*14414594SDavid du Colombier+ /* 4449*14414594SDavid du Colombier+ * Call u9fs_bioread() to do the real work. 4450*14414594SDavid du Colombier+ */ 4451*14414594SDavid du Colombier+ error = u9fs_bioread(vp, uio, 0, ap->a_cred, 0); 4452*14414594SDavid du Colombier+ 4453*14414594SDavid du Colombier+ return (error); 4454*14414594SDavid du Colombier+ } 4455*14414594SDavid du Colombier+ 4456*14414594SDavid du Colombier+ /* 4457*14414594SDavid du Colombier+ * Kludge City.. 4458*14414594SDavid du Colombier+ * - make u9fs_bmap() essentially a no-op that does no translation 4459*14414594SDavid du Colombier+ * - do u9fs_strategy() by doing I/O with u9fs_readrpc/u9fs_writerpc 4460*14414594SDavid du Colombier+ * (Maybe I could use the process's page mapping, but I was concerned that 4461*14414594SDavid du Colombier+ * Kernel Write might not be enabled and also figured copyout() would do 4462*14414594SDavid du Colombier+ * a lot more work than bcopy() and also it currently happens in the 4463*14414594SDavid du Colombier+ * context of the swapper process (2). 4464*14414594SDavid du Colombier+ */ 4465*14414594SDavid du Colombier+ static int 4466*14414594SDavid du Colombier+ u9fs_bmap(ap) 4467*14414594SDavid du Colombier+ struct vop_bmap_args /* { 4468*14414594SDavid du Colombier+ struct vnode *a_vp; 4469*14414594SDavid du Colombier+ daddr_t a_bn; 4470*14414594SDavid du Colombier+ struct vnode **a_vpp; 4471*14414594SDavid du Colombier+ daddr_t *a_bnp; 4472*14414594SDavid du Colombier+ int *a_runp; 4473*14414594SDavid du Colombier+ int *a_runb; 4474*14414594SDavid du Colombier+ } */ *ap; 4475*14414594SDavid du Colombier+ { 4476*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 4477*14414594SDavid du Colombier+ 4478*14414594SDavid du Colombier+ if (ap->a_vpp != NULL) 4479*14414594SDavid du Colombier+ *ap->a_vpp = vp; 4480*14414594SDavid du Colombier+ if (ap->a_bnp != NULL) 4481*14414594SDavid du Colombier+ *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 4482*14414594SDavid du Colombier+ if (ap->a_runp != NULL) 4483*14414594SDavid du Colombier+ *ap->a_runp = 0; 4484*14414594SDavid du Colombier+ if (ap->a_runb != NULL) 4485*14414594SDavid du Colombier+ *ap->a_runb = 0; 4486*14414594SDavid du Colombier+ return (0); 4487*14414594SDavid du Colombier+ 4488*14414594SDavid du Colombier+ return 0; 4489*14414594SDavid du Colombier+ } 4490*14414594SDavid du Colombier+ 4491*14414594SDavid du Colombier+ /* 4492*14414594SDavid du Colombier+ * Strategy routine. 4493*14414594SDavid du Colombier+ * For async requests when u9fsiod(s) are running, queue the request by 4494*14414594SDavid du Colombier+ * calling u9fs_asyncio(), otherwise just all u9fs_doio() to do the 4495*14414594SDavid du Colombier+ * request. 4496*14414594SDavid du Colombier+ */ 4497*14414594SDavid du Colombier+ static int 4498*14414594SDavid du Colombier+ u9fs_strategy(ap) 4499*14414594SDavid du Colombier+ struct vop_strategy_args *ap; 4500*14414594SDavid du Colombier+ { 4501*14414594SDavid du Colombier+ register struct buf *bp = ap->a_bp; 4502*14414594SDavid du Colombier+ struct ucred *cr; 4503*14414594SDavid du Colombier+ struct proc *p; 4504*14414594SDavid du Colombier+ int error = 0; 4505*14414594SDavid du Colombier+ 4506*14414594SDavid du Colombier+ if (bp->b_flags & B_PHYS) 4507*14414594SDavid du Colombier+ panic("nfs physio"); 4508*14414594SDavid du Colombier+ if (bp->b_flags & B_ASYNC) 4509*14414594SDavid du Colombier+ panic("u9fs async"); 4510*14414594SDavid du Colombier+ 4511*14414594SDavid du Colombier+ p = curproc; /* XXX */ 4512*14414594SDavid du Colombier+ if (bp->b_flags & B_READ) 4513*14414594SDavid du Colombier+ cr = bp->b_rcred; 4514*14414594SDavid du Colombier+ else 4515*14414594SDavid du Colombier+ cr = bp->b_wcred; 4516*14414594SDavid du Colombier+ error = u9fs_doio(bp, cr, p); 4517*14414594SDavid du Colombier+ return (error); 4518*14414594SDavid du Colombier+ } 4519*14414594SDavid du Colombier+ 4520*14414594SDavid du Colombier+ /* 4521*14414594SDavid du Colombier+ * Mmap a file 4522*14414594SDavid du Colombier+ * 4523*14414594SDavid du Colombier+ * NB Currently unsupported. 4524*14414594SDavid du Colombier+ */ 4525*14414594SDavid du Colombier+ /* ARGSUSED */ 4526*14414594SDavid du Colombier+ static int 4527*14414594SDavid du Colombier+ u9fs_mmap(ap) 4528*14414594SDavid du Colombier+ struct vop_mmap_args /* { 4529*14414594SDavid du Colombier+ struct vnode *a_vp; 4530*14414594SDavid du Colombier+ int a_fflags; 4531*14414594SDavid du Colombier+ struct ucred *a_cred; 4532*14414594SDavid du Colombier+ struct proc *a_p; 4533*14414594SDavid du Colombier+ } */ *ap; 4534*14414594SDavid du Colombier+ { 4535*14414594SDavid du Colombier+ return (EINVAL); 4536*14414594SDavid du Colombier+ } 4537*14414594SDavid du Colombier+ 4538*14414594SDavid du Colombier+ /* 4539*14414594SDavid du Colombier+ * fsync vnode op. Just call u9fs_flush() with commit == 1. 4540*14414594SDavid du Colombier+ */ 4541*14414594SDavid du Colombier+ /* ARGSUSED */ 4542*14414594SDavid du Colombier+ static int 4543*14414594SDavid du Colombier+ u9fs_fsync(ap) 4544*14414594SDavid du Colombier+ struct vop_fsync_args /* { 4545*14414594SDavid du Colombier+ struct vnodeop_desc *a_desc; 4546*14414594SDavid du Colombier+ struct vnode * a_vp; 4547*14414594SDavid du Colombier+ struct ucred * a_cred; 4548*14414594SDavid du Colombier+ int a_waitfor; 4549*14414594SDavid du Colombier+ struct proc * a_p; 4550*14414594SDavid du Colombier+ } */ *ap; 4551*14414594SDavid du Colombier+ { 4552*14414594SDavid du Colombier+ /* we have a blocking writeback cache */ 4553*14414594SDavid du Colombier+ return 0; 4554*14414594SDavid du Colombier+ } 4555*14414594SDavid du Colombier+ 4556*14414594SDavid du Colombier+ /* 4557*14414594SDavid du Colombier+ * U9FS advisory byte-level locks. 4558*14414594SDavid du Colombier+ * Currently unsupported. 4559*14414594SDavid du Colombier+ */ 4560*14414594SDavid du Colombier+ static int 4561*14414594SDavid du Colombier+ u9fs_advlock(ap) 4562*14414594SDavid du Colombier+ struct vop_advlock_args /* { 4563*14414594SDavid du Colombier+ struct vnode *a_vp; 4564*14414594SDavid du Colombier+ caddr_t a_id; 4565*14414594SDavid du Colombier+ int a_op; 4566*14414594SDavid du Colombier+ struct flock *a_fl; 4567*14414594SDavid du Colombier+ int a_flags; 4568*14414594SDavid du Colombier+ } */ *ap; 4569*14414594SDavid du Colombier+ { 4570*14414594SDavid du Colombier+ register struct u9fsnode *np = VTOU9FS(ap->a_vp); 4571*14414594SDavid du Colombier+ 4572*14414594SDavid du Colombier+ /* 4573*14414594SDavid du Colombier+ * The following kludge is to allow diskless support to work 4574*14414594SDavid du Colombier+ * until a real NFS lockd is implemented. Basically, just pretend 4575*14414594SDavid du Colombier+ * that this is a local lock. 4576*14414594SDavid du Colombier+ */ 4577*14414594SDavid du Colombier+ return (lf_advlock(ap, &(np->n_lockf), np->n_size)); 4578*14414594SDavid du Colombier+ } 4579*14414594SDavid du Colombier+ 4580*14414594SDavid du Colombier+ /* 4581*14414594SDavid du Colombier+ * Print out the contents of an u9fsnode. 4582*14414594SDavid du Colombier+ */ 4583*14414594SDavid du Colombier+ static int 4584*14414594SDavid du Colombier+ u9fs_print(ap) 4585*14414594SDavid du Colombier+ struct vop_print_args /* { 4586*14414594SDavid du Colombier+ struct vnode *a_vp; 4587*14414594SDavid du Colombier+ } */ *ap; 4588*14414594SDavid du Colombier+ { 4589*14414594SDavid du Colombier+ panic("u9fs_print"); 4590*14414594SDavid du Colombier+ return 0; 4591*14414594SDavid du Colombier+ } 4592*14414594SDavid du Colombier+ 4593*14414594SDavid du Colombier+ /* 4594*14414594SDavid du Colombier+ * Just call u9fs_writebp() with the force argument set to 1. 4595*14414594SDavid du Colombier+ */ 4596*14414594SDavid du Colombier+ static int 4597*14414594SDavid du Colombier+ u9fs_bwrite(ap) 4598*14414594SDavid du Colombier+ struct vop_bwrite_args /* { 4599*14414594SDavid du Colombier+ struct vnode *a_bp; 4600*14414594SDavid du Colombier+ } */ *ap; 4601*14414594SDavid du Colombier+ { 4602*14414594SDavid du Colombier+ panic("u9fs_bwrite"); 4603*14414594SDavid du Colombier+ return 0; 4604*14414594SDavid du Colombier+ } 4605*14414594SDavid du Colombier+ 4606*14414594SDavid du Colombier+ /* 4607*14414594SDavid du Colombier+ * Vnode op for VM getpages. 4608*14414594SDavid du Colombier+ */ 4609*14414594SDavid du Colombier+ static int 4610*14414594SDavid du Colombier+ u9fs_getpages(ap) 4611*14414594SDavid du Colombier+ struct vop_getpages_args /* { 4612*14414594SDavid du Colombier+ struct vnode *a_vp; 4613*14414594SDavid du Colombier+ vm_page_t *a_m; 4614*14414594SDavid du Colombier+ int a_count; 4615*14414594SDavid du Colombier+ int a_reqpage; 4616*14414594SDavid du Colombier+ vm_ooffset_t a_offset; 4617*14414594SDavid du Colombier+ } */ *ap; 4618*14414594SDavid du Colombier+ { 4619*14414594SDavid du Colombier+ int i, error, nextoff, size, toff, npages, count; 4620*14414594SDavid du Colombier+ struct uio uio; 4621*14414594SDavid du Colombier+ struct iovec iov; 4622*14414594SDavid du Colombier+ vm_offset_t kva; 4623*14414594SDavid du Colombier+ struct buf *bp; 4624*14414594SDavid du Colombier+ struct vnode *vp; 4625*14414594SDavid du Colombier+ struct proc *p; 4626*14414594SDavid du Colombier+ struct ucred *cred; 4627*14414594SDavid du Colombier+ struct u9fsmount *nmp; 4628*14414594SDavid du Colombier+ vm_page_t *pages; 4629*14414594SDavid du Colombier+ 4630*14414594SDavid du Colombier+ vp = ap->a_vp; 4631*14414594SDavid du Colombier+ p = curproc; /* XXX */ 4632*14414594SDavid du Colombier+ cred = curproc->p_ucred; /* XXX */ 4633*14414594SDavid du Colombier+ nmp = VFSTOU9FS(vp->v_mount); 4634*14414594SDavid du Colombier+ pages = ap->a_m; 4635*14414594SDavid du Colombier+ count = ap->a_count; 4636*14414594SDavid du Colombier+ 4637*14414594SDavid du Colombier+ if (vp->v_object == NULL) { 4638*14414594SDavid du Colombier+ printf("u9fs_getpages: called with non-merged cache vnode??\n"); 4639*14414594SDavid du Colombier+ return VM_PAGER_ERROR; 4640*14414594SDavid du Colombier+ } 4641*14414594SDavid du Colombier+ 4642*14414594SDavid du Colombier+ /* 4643*14414594SDavid du Colombier+ * We use only the kva address for the buffer, but this is extremely 4644*14414594SDavid du Colombier+ * convienient and fast. 4645*14414594SDavid du Colombier+ */ 4646*14414594SDavid du Colombier+ bp = getpbuf(); 4647*14414594SDavid du Colombier+ 4648*14414594SDavid du Colombier+ npages = btoc(count); 4649*14414594SDavid du Colombier+ kva = (vm_offset_t) bp->b_data; 4650*14414594SDavid du Colombier+ pmap_qenter(kva, pages, npages); 4651*14414594SDavid du Colombier+ 4652*14414594SDavid du Colombier+ iov.iov_base = (caddr_t) kva; 4653*14414594SDavid du Colombier+ iov.iov_len = count; 4654*14414594SDavid du Colombier+ uio.uio_iov = &iov; 4655*14414594SDavid du Colombier+ uio.uio_iovcnt = 1; 4656*14414594SDavid du Colombier+ uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); 4657*14414594SDavid du Colombier+ uio.uio_resid = count; 4658*14414594SDavid du Colombier+ uio.uio_segflg = UIO_SYSSPACE; 4659*14414594SDavid du Colombier+ uio.uio_rw = UIO_READ; 4660*14414594SDavid du Colombier+ uio.uio_procp = p; 4661*14414594SDavid du Colombier+ 4662*14414594SDavid du Colombier+ error = u9fs_readrpc(vp, &uio, cred); 4663*14414594SDavid du Colombier+ pmap_qremove(kva, npages); 4664*14414594SDavid du Colombier+ 4665*14414594SDavid du Colombier+ relpbuf(bp); 4666*14414594SDavid du Colombier+ 4667*14414594SDavid du Colombier+ if (error && (uio.uio_resid == count)) 4668*14414594SDavid du Colombier+ return VM_PAGER_ERROR; 4669*14414594SDavid du Colombier+ 4670*14414594SDavid du Colombier+ size = count - uio.uio_resid; 4671*14414594SDavid du Colombier+ 4672*14414594SDavid du Colombier+ for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { 4673*14414594SDavid du Colombier+ vm_page_t m; 4674*14414594SDavid du Colombier+ nextoff = toff + PAGE_SIZE; 4675*14414594SDavid du Colombier+ m = pages[i]; 4676*14414594SDavid du Colombier+ 4677*14414594SDavid du Colombier+ m->flags &= ~PG_ZERO; 4678*14414594SDavid du Colombier+ 4679*14414594SDavid du Colombier+ if (nextoff <= size) { 4680*14414594SDavid du Colombier+ m->valid = VM_PAGE_BITS_ALL; 4681*14414594SDavid du Colombier+ m->dirty = 0; 4682*14414594SDavid du Colombier+ } else { 4683*14414594SDavid du Colombier+ int nvalid = ((size + DEV_BSIZE - 1) - toff) & ~(DEV_BSIZE - 1); 4684*14414594SDavid du Colombier+ vm_page_set_validclean(m, 0, nvalid); 4685*14414594SDavid du Colombier+ } 4686*14414594SDavid du Colombier+ 4687*14414594SDavid du Colombier+ if (i != ap->a_reqpage) { 4688*14414594SDavid du Colombier+ /* 4689*14414594SDavid du Colombier+ * Whether or not to leave the page activated is up in 4690*14414594SDavid du Colombier+ * the air, but we should put the page on a page queue 4691*14414594SDavid du Colombier+ * somewhere (it already is in the object). Result: 4692*14414594SDavid du Colombier+ * It appears that emperical results show that 4693*14414594SDavid du Colombier+ * deactivating pages is best. 4694*14414594SDavid du Colombier+ */ 4695*14414594SDavid du Colombier+ 4696*14414594SDavid du Colombier+ /* 4697*14414594SDavid du Colombier+ * Just in case someone was asking for this page we 4698*14414594SDavid du Colombier+ * now tell them that it is ok to use. 4699*14414594SDavid du Colombier+ */ 4700*14414594SDavid du Colombier+ if (!error) { 4701*14414594SDavid du Colombier+ if (m->flags & PG_WANTED) 4702*14414594SDavid du Colombier+ vm_page_activate(m); 4703*14414594SDavid du Colombier+ else 4704*14414594SDavid du Colombier+ vm_page_deactivate(m); 4705*14414594SDavid du Colombier+ vm_page_wakeup(m); 4706*14414594SDavid du Colombier+ } else { 4707*14414594SDavid du Colombier+ vnode_pager_freepage(m); 4708*14414594SDavid du Colombier+ } 4709*14414594SDavid du Colombier+ } 4710*14414594SDavid du Colombier+ } 4711*14414594SDavid du Colombier+ return 0; 4712*14414594SDavid du Colombier+ } 4713*14414594SDavid du Colombier+ 4714*14414594SDavid du Colombier+ /* 4715*14414594SDavid du Colombier+ * Vnode op for VM putpages. 4716*14414594SDavid du Colombier+ */ 4717*14414594SDavid du Colombier+ static int 4718*14414594SDavid du Colombier+ u9fs_putpages(ap) 4719*14414594SDavid du Colombier+ struct vop_putpages_args /* { 4720*14414594SDavid du Colombier+ struct vnode *a_vp; 4721*14414594SDavid du Colombier+ vm_page_t *a_m; 4722*14414594SDavid du Colombier+ int a_count; 4723*14414594SDavid du Colombier+ int a_sync; 4724*14414594SDavid du Colombier+ int *a_rtvals; 4725*14414594SDavid du Colombier+ vm_ooffset_t a_offset; 4726*14414594SDavid du Colombier+ } */ *ap; 4727*14414594SDavid du Colombier+ { 4728*14414594SDavid du Colombier+ panic("u9fs_putpages"); 4729*14414594SDavid du Colombier+ return 0; 4730*14414594SDavid du Colombier+ } 4731*14414594SDavid du Colombier+ 4732*14414594SDavid du Colombier+ static int 4733*14414594SDavid du Colombier+ u9fs_inactive(ap) 4734*14414594SDavid du Colombier+ struct vop_inactive_args /* { 4735*14414594SDavid du Colombier+ struct vnode *a_vp; 4736*14414594SDavid du Colombier+ struct proc *a_p; 4737*14414594SDavid du Colombier+ } */ *ap; 4738*14414594SDavid du Colombier+ { 4739*14414594SDavid du Colombier+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p); 4740*14414594SDavid du Colombier+ return 0; 4741*14414594SDavid du Colombier+ } 4742*14414594SDavid du Colombier+ 4743*14414594SDavid du Colombier+ /* 4744*14414594SDavid du Colombier+ * Reclaim an u9fsnode so that it can be used for other purposes. 4745*14414594SDavid du Colombier+ */ 4746*14414594SDavid du Colombier+ static int 4747*14414594SDavid du Colombier+ u9fs_reclaim(ap) 4748*14414594SDavid du Colombier+ struct vop_reclaim_args /* { 4749*14414594SDavid du Colombier+ struct vnode *a_vp; 4750*14414594SDavid du Colombier+ } */ *ap; 4751*14414594SDavid du Colombier+ { 4752*14414594SDavid du Colombier+ register struct vnode *vp = ap->a_vp; 4753*14414594SDavid du Colombier+ register struct u9fsnode *np = VTOU9FS(vp); 4754*14414594SDavid du Colombier+ register struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount); 4755*14414594SDavid du Colombier+ struct proc * p = curproc; 4756*14414594SDavid du Colombier+ 4757*14414594SDavid du Colombier+ /* some vnodes do not have fids due to previous access failure */ 4758*14414594SDavid du Colombier+ if( np->n_fid ) { 4759*14414594SDavid du Colombier+ /* clunk fids */ 4760*14414594SDavid du Colombier+ u9fs_free_fid(np->n_fid, nmp, p); 4761*14414594SDavid du Colombier+ if( np->n_rdfid ) 4762*14414594SDavid du Colombier+ u9fs_free_fid(np->n_rdfid, nmp, p); 4763*14414594SDavid du Colombier+ if( np->n_wrfid ) 4764*14414594SDavid du Colombier+ u9fs_free_fid(np->n_wrfid, nmp, p); 4765*14414594SDavid du Colombier+ } 4766*14414594SDavid du Colombier+ 4767*14414594SDavid du Colombier+ LIST_REMOVE(np, n_hash); 4768*14414594SDavid du Colombier+ cache_purge(vp); 4769*14414594SDavid du Colombier+ zfree(u9fsnode_zone, vp->v_data); 4770*14414594SDavid du Colombier+ vp->v_data = (void *)0; 4771*14414594SDavid du Colombier+ 4772*14414594SDavid du Colombier+ return (0); 4773*14414594SDavid du Colombier+ } 4774*14414594SDavid du Colombier+ 4775*14414594SDavid du Colombier+ /* 4776*14414594SDavid du Colombier+ * Vnode op for write using bio 4777*14414594SDavid du Colombier+ */ 4778*14414594SDavid du Colombier+ static int 4779*14414594SDavid du Colombier+ u9fs_write(ap) 4780*14414594SDavid du Colombier+ struct vop_write_args /* { 4781*14414594SDavid du Colombier+ struct vnode *a_vp; 4782*14414594SDavid du Colombier+ struct uio *a_uio; 4783*14414594SDavid du Colombier+ int a_ioflag; 4784*14414594SDavid du Colombier+ struct ucred *a_cred; 4785*14414594SDavid du Colombier+ } */ *ap; 4786*14414594SDavid du Colombier+ { 4787*14414594SDavid du Colombier+ if (ap->a_vp->v_type != VREG) 4788*14414594SDavid du Colombier+ return (EIO); 4789*14414594SDavid du Colombier+ 4790*14414594SDavid du Colombier+ return u9fs_biowrite(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred); 4791*14414594SDavid du Colombier+ } 4792*14414594SDavid du Colombier+ 4793*14414594SDavid du Colombier+ /* 4794*14414594SDavid du Colombier+ * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 4795*14414594SDavid du Colombier+ * done. Currently nothing to do. 4796*14414594SDavid du Colombier+ */ 4797*14414594SDavid du Colombier+ /* ARGSUSED */ 4798*14414594SDavid du Colombier+ static int 4799*14414594SDavid du Colombier+ u9fs_abortop(ap) 4800*14414594SDavid du Colombier+ struct vop_abortop_args /* { 4801*14414594SDavid du Colombier+ struct vnode *a_dvp; 4802*14414594SDavid du Colombier+ struct componentname *a_cnp; 4803*14414594SDavid du Colombier+ } */ *ap; 4804*14414594SDavid du Colombier+ { 4805*14414594SDavid du Colombier+ return (0); 4806*14414594SDavid du Colombier+ } 4807*14414594SDavid du Colombier+ 4808*14414594SDavid du Colombier+ /* 4809*14414594SDavid du Colombier+ * u9fs write call 4810*14414594SDavid du Colombier+ */ 4811*14414594SDavid du Colombier+ int 4812*14414594SDavid du Colombier+ u9fs_writerpc(vp, uiop, cred) 4813*14414594SDavid du Colombier+ register struct vnode *vp; 4814*14414594SDavid du Colombier+ register struct uio *uiop; 4815*14414594SDavid du Colombier+ struct ucred *cred; 4816*14414594SDavid du Colombier+ { 4817*14414594SDavid du Colombier+ struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount); 4818*14414594SDavid du Colombier+ int error = 0, len, tsiz, rlen; 4819*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4820*14414594SDavid du Colombier+ struct u9fsnode * np = VTOU9FS(vp); 4821*14414594SDavid du Colombier+ struct proc * p = uiop->uio_procp; 4822*14414594SDavid du Colombier+ struct mbuf * top; 4823*14414594SDavid du Colombier+ 4824*14414594SDavid du Colombier+ tsiz = uiop->uio_resid; 4825*14414594SDavid du Colombier+ if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) 4826*14414594SDavid du Colombier+ return (EFBIG); 4827*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4828*14414594SDavid du Colombier+ req.r_nmp = nmp; 4829*14414594SDavid du Colombier+ req.r_procp = p; 4830*14414594SDavid du Colombier+ req.r_type = Twrite; 4831*14414594SDavid du Colombier+ req.r_fid = np->n_wrfid; 4832*14414594SDavid du Colombier+ while (tsiz > 0) { 4833*14414594SDavid du Colombier+ len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 4834*14414594SDavid du Colombier+ req.r_offset = uiop->uio_offset; 4835*14414594SDavid du Colombier+ req.r_count = len; 4836*14414594SDavid du Colombier+ error = u9fs_uiotombuf(uiop, &top, len); 4837*14414594SDavid du Colombier+ if( error ) 4838*14414594SDavid du Colombier+ break; 4839*14414594SDavid du Colombier+ req.r_data = (char *)top; 4840*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 1); 4841*14414594SDavid du Colombier+ if( error ) 4842*14414594SDavid du Colombier+ break; 4843*14414594SDavid du Colombier+ rlen = rep.r_count; 4844*14414594SDavid du Colombier+ if( rlen < len ) { 4845*14414594SDavid du Colombier+ error = EIO; 4846*14414594SDavid du Colombier+ break; 4847*14414594SDavid du Colombier+ } 4848*14414594SDavid du Colombier+ tsiz -= len; 4849*14414594SDavid du Colombier+ 4850*14414594SDavid du Colombier+ /* each write message increments version number by one. 4851*14414594SDavid du Colombier+ to avoid flushing our write cache, update the version */ 4852*14414594SDavid du Colombier+ if( np->n_qid.vers ) 4853*14414594SDavid du Colombier+ np->n_qid.vers++; 4854*14414594SDavid du Colombier+ else 4855*14414594SDavid du Colombier+ np->n_qid.vers = np->n_dir.dir_qid.vers + 1; 4856*14414594SDavid du Colombier+ } 4857*14414594SDavid du Colombier+ if (error) 4858*14414594SDavid du Colombier+ uiop->uio_resid = tsiz; 4859*14414594SDavid du Colombier+ return (error); 4860*14414594SDavid du Colombier+ } 4861*14414594SDavid du Colombier+ 4862*14414594SDavid du Colombier+ /* 4863*14414594SDavid du Colombier+ * Readdir rpc call. 4864*14414594SDavid du Colombier+ * Called from below the buffer cache by u9fs_doio(). 4865*14414594SDavid du Colombier+ */ 4866*14414594SDavid du Colombier+ int 4867*14414594SDavid du Colombier+ u9fs_readdirrpc(vp, uiop, cred) 4868*14414594SDavid du Colombier+ struct vnode *vp; 4869*14414594SDavid du Colombier+ register struct uio *uiop; 4870*14414594SDavid du Colombier+ struct ucred *cred; 4871*14414594SDavid du Colombier+ 4872*14414594SDavid du Colombier+ { 4873*14414594SDavid du Colombier+ register int len, left; 4874*14414594SDavid du Colombier+ register struct dirent *dp; 4875*14414594SDavid du Colombier+ struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount); 4876*14414594SDavid du Colombier+ struct u9fsnode *np = VTOU9FS(vp); 4877*14414594SDavid du Colombier+ int error = 0, tlen, more_dirs = 1, bigenough; 4878*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4879*14414594SDavid du Colombier+ int count; 4880*14414594SDavid du Colombier+ struct u9fsdir u9dir; 4881*14414594SDavid du Colombier+ 4882*14414594SDavid du Colombier+ bigenough = uiop->uio_resid >= sizeof(struct dirent); 4883*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4884*14414594SDavid du Colombier+ req.r_nmp = nmp; 4885*14414594SDavid du Colombier+ req.r_type = Tread; 4886*14414594SDavid du Colombier+ req.r_fid = np->n_rdfid; 4887*14414594SDavid du Colombier+ req.r_count = nmp->nm_readdirsize; 4888*14414594SDavid du Colombier+ while ( more_dirs && bigenough ) { 4889*14414594SDavid du Colombier+ req.r_offset = uiop->uio_offset; 4890*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 0); 4891*14414594SDavid du Colombier+ if( error ) 4892*14414594SDavid du Colombier+ return error; 4893*14414594SDavid du Colombier+ 4894*14414594SDavid du Colombier+ count = rep.r_count; 4895*14414594SDavid du Colombier+ more_dirs = (count == req.r_count); 4896*14414594SDavid du Colombier+ len = 0; 4897*14414594SDavid du Colombier+ dp = (struct dirent *)uiop->uio_iov->iov_base; 4898*14414594SDavid du Colombier+ left = uiop->uio_resid; 4899*14414594SDavid du Colombier+ while( len < count ) { 4900*14414594SDavid du Colombier+ /* XXX: too conservative, but OK */ 4901*14414594SDavid du Colombier+ if( left < sizeof(*dp) ) { 4902*14414594SDavid du Colombier+ bigenough = 0; 4903*14414594SDavid du Colombier+ break; 4904*14414594SDavid du Colombier+ } 4905*14414594SDavid du Colombier+ if( u9p_m_m2d(&req.r_mrep, & u9dir) ) { 4906*14414594SDavid du Colombier+ printf("u9p_m_m2d failed!\n"); 4907*14414594SDavid du Colombier+ return (EIO); 4908*14414594SDavid du Colombier+ } 4909*14414594SDavid du Colombier+ 4910*14414594SDavid du Colombier+ dp->d_fileno = u9dir.dir_qid.path; 4911*14414594SDavid du Colombier+ if( U9P_PERM_CHDIR(u9dir.dir_mode) ) 4912*14414594SDavid du Colombier+ dp->d_type = DT_DIR; 4913*14414594SDavid du Colombier+ else 4914*14414594SDavid du Colombier+ dp->d_type = DT_REG; 4915*14414594SDavid du Colombier+ u9dir.dir_name[U9FS_NAMELEN-1] = 0; /* just to be sure */ 4916*14414594SDavid du Colombier+ dp->d_namlen = strlen(u9dir.dir_name); 4917*14414594SDavid du Colombier+ memcpy(dp->d_name, u9dir.dir_name, dp->d_namlen+1); 4918*14414594SDavid du Colombier+ tlen = DIRHDSIZ + dp->d_namlen + 4; 4919*14414594SDavid du Colombier+ tlen = tlen - (tlen & 0x3); 4920*14414594SDavid du Colombier+ dp->d_reclen = tlen; 4921*14414594SDavid du Colombier+ dp = (struct dirent *)(((char *)dp) + tlen); 4922*14414594SDavid du Colombier+ left -= tlen; 4923*14414594SDavid du Colombier+ len += sizeof(u9dir); 4924*14414594SDavid du Colombier+ } 4925*14414594SDavid du Colombier+ tlen = uiop->uio_resid - left; 4926*14414594SDavid du Colombier+ uiop->uio_resid = left; 4927*14414594SDavid du Colombier+ uiop->uio_iov->iov_base += tlen; 4928*14414594SDavid du Colombier+ uiop->uio_iov->iov_len -= tlen; 4929*14414594SDavid du Colombier+ uiop->uio_offset += len; 4930*14414594SDavid du Colombier+ m_freem(req.r_mrep); 4931*14414594SDavid du Colombier+ } 4932*14414594SDavid du Colombier+ return 0; 4933*14414594SDavid du Colombier+ } 4934*14414594SDavid du Colombier+ 4935*14414594SDavid du Colombier+ /* 4936*14414594SDavid du Colombier+ * u9fs read rpc call 4937*14414594SDavid du Colombier+ * Ditto above 4938*14414594SDavid du Colombier+ */ 4939*14414594SDavid du Colombier+ int 4940*14414594SDavid du Colombier+ u9fs_readrpc(vp, uiop, cred) 4941*14414594SDavid du Colombier+ register struct vnode *vp; 4942*14414594SDavid du Colombier+ struct uio *uiop; 4943*14414594SDavid du Colombier+ struct ucred *cred; 4944*14414594SDavid du Colombier+ { 4945*14414594SDavid du Colombier+ struct u9fsmount *nmp; 4946*14414594SDavid du Colombier+ struct u9fsnode *np = VTOU9FS(vp); 4947*14414594SDavid du Colombier+ int error = 0, len, retlen, tsiz; 4948*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4949*14414594SDavid du Colombier+ 4950*14414594SDavid du Colombier+ nmp = VFSTOU9FS(vp->v_mount); 4951*14414594SDavid du Colombier+ tsiz = uiop->uio_resid; 4952*14414594SDavid du Colombier+ if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) 4953*14414594SDavid du Colombier+ return (EFBIG); 4954*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4955*14414594SDavid du Colombier+ req.r_nmp = nmp; 4956*14414594SDavid du Colombier+ req.r_type = Tread; 4957*14414594SDavid du Colombier+ req.r_fid = np->n_rdfid; 4958*14414594SDavid du Colombier+ while (tsiz > 0) { 4959*14414594SDavid du Colombier+ len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 4960*14414594SDavid du Colombier+ req.r_count = len; 4961*14414594SDavid du Colombier+ req.r_offset = uiop->uio_offset; 4962*14414594SDavid du Colombier+ error = u9fs_request(&req, &rep, 0); 4963*14414594SDavid du Colombier+ if( error ) 4964*14414594SDavid du Colombier+ return error; 4965*14414594SDavid du Colombier+ retlen = rep.r_count; 4966*14414594SDavid du Colombier+ if( retlen && (error = u9fs_mbuftouio(req.r_mrep, uiop, retlen)) ) { 4967*14414594SDavid du Colombier+ m_freem(req.r_mrep); 4968*14414594SDavid du Colombier+ return error; 4969*14414594SDavid du Colombier+ } 4970*14414594SDavid du Colombier+ 4971*14414594SDavid du Colombier+ m_freem(req.r_mrep); 4972*14414594SDavid du Colombier+ req.r_mrep = 0; 4973*14414594SDavid du Colombier+ tsiz -= retlen; 4974*14414594SDavid du Colombier+ if (retlen < len) 4975*14414594SDavid du Colombier+ tsiz = 0; 4976*14414594SDavid du Colombier+ } 4977*14414594SDavid du Colombier+ return (0); 4978*14414594SDavid du Colombier+ } 4979*14414594SDavid du Colombier+ 4980*14414594SDavid du Colombier+ static void u9fs_free_fid(fid, nmp, p) 4981*14414594SDavid du Colombier+ u_short fid; 4982*14414594SDavid du Colombier+ struct u9fsmount * nmp; 4983*14414594SDavid du Colombier+ struct proc * p; 4984*14414594SDavid du Colombier+ { 4985*14414594SDavid du Colombier+ struct u9fsreq req, rep; 4986*14414594SDavid du Colombier+ 4987*14414594SDavid du Colombier+ /* clunk fid */ 4988*14414594SDavid du Colombier+ bzero(&req, sizeof(req)); 4989*14414594SDavid du Colombier+ req.r_nmp = nmp; 4990*14414594SDavid du Colombier+ req.r_procp = p; 4991*14414594SDavid du Colombier+ req.r_type = Tclunk; 4992*14414594SDavid du Colombier+ req.r_fid = fid; 4993*14414594SDavid du Colombier+ u9fs_request(&req, &rep, 1); 4994*14414594SDavid du Colombier+ u9fs_id_free(nmp->nm_fids, fid); 4995*14414594SDavid du Colombier+ } 4996*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9p.c ./9fs/9p.c 4997*14414594SDavid du Colombier*** /usr/src/sys/9fs/9p.c Wed Dec 31 19:00:00 1969 4998*14414594SDavid du Colombier--- ./9fs/9p.c Thu Nov 25 15:04:16 1999 4999*14414594SDavid du Colombier*************** 5000*14414594SDavid du Colombier*** 0 **** 5001*14414594SDavid du Colombier--- 1,974 ---- 5002*14414594SDavid du Colombier+ #include <sys/param.h> 5003*14414594SDavid du Colombier+ #include <sys/systm.h> 5004*14414594SDavid du Colombier+ #include <sys/socket.h> 5005*14414594SDavid du Colombier+ #include <sys/socketvar.h> 5006*14414594SDavid du Colombier+ #include <netinet/in.h> 5007*14414594SDavid du Colombier+ #include <sys/mbuf.h> 5008*14414594SDavid du Colombier+ #include <sys/malloc.h> 5009*14414594SDavid du Colombier+ #include <sys/vnode.h> 5010*14414594SDavid du Colombier+ #include <sys/mount.h> 5011*14414594SDavid du Colombier+ 5012*14414594SDavid du Colombier+ #include <9fs/bitstring.h> 5013*14414594SDavid du Colombier+ #include <9fs/9p.h> 5014*14414594SDavid du Colombier+ #include <9fs/9auth.h> 5015*14414594SDavid du Colombier+ #include <9fs/9fs.h> 5016*14414594SDavid du Colombier+ 5017*14414594SDavid du Colombier+ int u9p_usetcp = 0; 5018*14414594SDavid du Colombier+ struct u9fs_reqq u9fs_reqq; 5019*14414594SDavid du Colombier+ 5020*14414594SDavid du Colombier+ #define N2HCHAR(x) x = *p++ 5021*14414594SDavid du Colombier+ #define N2HSHORT(x) x = (p[0] | (p[1]<<8)); p += 2 5022*14414594SDavid du Colombier+ #define N2HLONG(x) x = (p[0] | (p[1]<<8) |\ 5023*14414594SDavid du Colombier+ (p[2]<<16) | (p[3]<<24)); p += 4 5024*14414594SDavid du Colombier+ #define N2HQUAD(x) x = (u_int64_t)(p[0] | (p[1]<<8) |\ 5025*14414594SDavid du Colombier+ (p[2]<<16) | (p[3]<<24)) |\ 5026*14414594SDavid du Colombier+ ((u_int64_t)(p[4] | (p[5]<<8) |\ 5027*14414594SDavid du Colombier+ (p[6]<<16) | (p[7]<<24)) << 32); p += 8 5028*14414594SDavid du Colombier+ #define N2HSTRING(x,n) bcopy(p, x, n); p += n 5029*14414594SDavid du Colombier+ 5030*14414594SDavid du Colombier+ #define H2NCHAR(x) *p++ = x 5031*14414594SDavid du Colombier+ #define H2NSHORT(x) p[0]=x; p[1]=x>>8; p += 2 5032*14414594SDavid du Colombier+ #define H2NLONG(x) p[0]=x; p[1]=x>>8; p[2]=x>>16; p[3]=x>>24; p += 4 5033*14414594SDavid du Colombier+ #define H2NQUAD(x) p[0]=x; p[1]=x>>8;\ 5034*14414594SDavid du Colombier+ p[2]=x>>16; p[3]=x>>24;\ 5035*14414594SDavid du Colombier+ p[4]=x>>32; p[5]=x>>40;\ 5036*14414594SDavid du Colombier+ p[6]=x>>48; p[7]=x>>56;\ 5037*14414594SDavid du Colombier+ p += 8 5038*14414594SDavid du Colombier+ #define H2NSTRING(x,n) bcopy(x, p, n); p += n 5039*14414594SDavid du Colombier+ 5040*14414594SDavid du Colombier+ static void u9p_print __P((u_char * m, int len, struct u9fsreq * f)); 5041*14414594SDavid du Colombier+ 5042*14414594SDavid du Colombier+ static char * u9p_types[] = { 5043*14414594SDavid du Colombier+ "Tnop", 5044*14414594SDavid du Colombier+ "Rnop", 5045*14414594SDavid du Colombier+ "Tosession", 5046*14414594SDavid du Colombier+ "Rosession", 5047*14414594SDavid du Colombier+ "Terror", 5048*14414594SDavid du Colombier+ "Rerror", 5049*14414594SDavid du Colombier+ "Tflush", 5050*14414594SDavid du Colombier+ "Rflush", 5051*14414594SDavid du Colombier+ "Toattach", 5052*14414594SDavid du Colombier+ "Roattach", 5053*14414594SDavid du Colombier+ "Tclone", 5054*14414594SDavid du Colombier+ "Rclone", 5055*14414594SDavid du Colombier+ "Twalk", 5056*14414594SDavid du Colombier+ "Rwalk", 5057*14414594SDavid du Colombier+ "Topen", 5058*14414594SDavid du Colombier+ "Ropen", 5059*14414594SDavid du Colombier+ "Tcreate", 5060*14414594SDavid du Colombier+ "Rcreate", 5061*14414594SDavid du Colombier+ "Tread", 5062*14414594SDavid du Colombier+ "Rread", 5063*14414594SDavid du Colombier+ "Twrite", 5064*14414594SDavid du Colombier+ "Rwrite", 5065*14414594SDavid du Colombier+ "Tclunk", 5066*14414594SDavid du Colombier+ "Rclunk", 5067*14414594SDavid du Colombier+ "Tremove", 5068*14414594SDavid du Colombier+ "Rremove", 5069*14414594SDavid du Colombier+ "Tstat", 5070*14414594SDavid du Colombier+ "Rstat", 5071*14414594SDavid du Colombier+ "Twstat", 5072*14414594SDavid du Colombier+ "Rwstat", 5073*14414594SDavid du Colombier+ "Tclwalk", 5074*14414594SDavid du Colombier+ "Rclwalk", 5075*14414594SDavid du Colombier+ "Tauth", 5076*14414594SDavid du Colombier+ "Rauth", 5077*14414594SDavid du Colombier+ "Tsession", 5078*14414594SDavid du Colombier+ "Rsession", 5079*14414594SDavid du Colombier+ "Tattach", 5080*14414594SDavid du Colombier+ "Rattach", 5081*14414594SDavid du Colombier+ "Ttunnel", 5082*14414594SDavid du Colombier+ "Rtunnel", 5083*14414594SDavid du Colombier+ "Tmax" 5084*14414594SDavid du Colombier+ }; 5085*14414594SDavid du Colombier+ 5086*14414594SDavid du Colombier+ int u9p_m2s(char *ap, int n, struct u9fsreq *f) 5087*14414594SDavid du Colombier+ { 5088*14414594SDavid du Colombier+ u_char *p; 5089*14414594SDavid du Colombier+ 5090*14414594SDavid du Colombier+ p = (u_char*)ap; 5091*14414594SDavid du Colombier+ N2HCHAR(f->r_type); 5092*14414594SDavid du Colombier+ N2HSHORT(f->r_tag); 5093*14414594SDavid du Colombier+ switch(f->r_type) 5094*14414594SDavid du Colombier+ { 5095*14414594SDavid du Colombier+ default: 5096*14414594SDavid du Colombier+ return 0; 5097*14414594SDavid du Colombier+ 5098*14414594SDavid du Colombier+ case Tnop: 5099*14414594SDavid du Colombier+ case Tosession: 5100*14414594SDavid du Colombier+ break; 5101*14414594SDavid du Colombier+ 5102*14414594SDavid du Colombier+ case Tsession: 5103*14414594SDavid du Colombier+ N2HSTRING(f->r_chal, sizeof(f->r_chal)); 5104*14414594SDavid du Colombier+ break; 5105*14414594SDavid du Colombier+ 5106*14414594SDavid du Colombier+ case Tflush: 5107*14414594SDavid du Colombier+ N2HSHORT(f->r_oldtag); 5108*14414594SDavid du Colombier+ break; 5109*14414594SDavid du Colombier+ 5110*14414594SDavid du Colombier+ case Tattach: 5111*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5112*14414594SDavid du Colombier+ N2HSTRING(f->r_uname, sizeof(f->r_uname)); 5113*14414594SDavid du Colombier+ N2HSTRING(f->r_aname, sizeof(f->r_aname)); 5114*14414594SDavid du Colombier+ N2HSTRING(f->r_ticket, sizeof(f->r_ticket)); 5115*14414594SDavid du Colombier+ N2HSTRING(f->r_auth, sizeof(f->r_auth)); 5116*14414594SDavid du Colombier+ break; 5117*14414594SDavid du Colombier+ 5118*14414594SDavid du Colombier+ case Toattach: 5119*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5120*14414594SDavid du Colombier+ N2HSTRING(f->r_uname, sizeof(f->r_uname)); 5121*14414594SDavid du Colombier+ N2HSTRING(f->r_aname, sizeof(f->r_aname)); 5122*14414594SDavid du Colombier+ N2HSTRING(f->r_ticket, U9FS_NAMELEN); 5123*14414594SDavid du Colombier+ break; 5124*14414594SDavid du Colombier+ 5125*14414594SDavid du Colombier+ case Tauth: 5126*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5127*14414594SDavid du Colombier+ N2HSTRING(f->r_uname, sizeof(f->r_uname)); 5128*14414594SDavid du Colombier+ N2HSTRING(f->r_ticket, 8+U9FS_NAMELEN); 5129*14414594SDavid du Colombier+ break; 5130*14414594SDavid du Colombier+ 5131*14414594SDavid du Colombier+ case Tclone: 5132*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5133*14414594SDavid du Colombier+ N2HSHORT(f->r_newfid); 5134*14414594SDavid du Colombier+ break; 5135*14414594SDavid du Colombier+ 5136*14414594SDavid du Colombier+ case Twalk: 5137*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5138*14414594SDavid du Colombier+ N2HSTRING(f->r_name, sizeof(f->r_name)); 5139*14414594SDavid du Colombier+ break; 5140*14414594SDavid du Colombier+ 5141*14414594SDavid du Colombier+ case Topen: 5142*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5143*14414594SDavid du Colombier+ N2HCHAR(f->r_mode); 5144*14414594SDavid du Colombier+ break; 5145*14414594SDavid du Colombier+ 5146*14414594SDavid du Colombier+ case Tcreate: 5147*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5148*14414594SDavid du Colombier+ N2HSTRING(f->r_name, sizeof(f->r_name)); 5149*14414594SDavid du Colombier+ N2HLONG(f->r_perm); 5150*14414594SDavid du Colombier+ N2HCHAR(f->r_mode); 5151*14414594SDavid du Colombier+ break; 5152*14414594SDavid du Colombier+ 5153*14414594SDavid du Colombier+ case Tread: 5154*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5155*14414594SDavid du Colombier+ N2HQUAD(f->r_offset); 5156*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5157*14414594SDavid du Colombier+ break; 5158*14414594SDavid du Colombier+ 5159*14414594SDavid du Colombier+ case Twrite: 5160*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5161*14414594SDavid du Colombier+ N2HQUAD(f->r_offset); 5162*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5163*14414594SDavid du Colombier+ p++; /* pad(1) */ 5164*14414594SDavid du Colombier+ f->r_data = (char*)p; p += f->r_count; 5165*14414594SDavid du Colombier+ break; 5166*14414594SDavid du Colombier+ 5167*14414594SDavid du Colombier+ case Ttunnel: 5168*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5169*14414594SDavid du Colombier+ break; 5170*14414594SDavid du Colombier+ 5171*14414594SDavid du Colombier+ case Tclunk: 5172*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5173*14414594SDavid du Colombier+ break; 5174*14414594SDavid du Colombier+ 5175*14414594SDavid du Colombier+ case Tremove: 5176*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5177*14414594SDavid du Colombier+ break; 5178*14414594SDavid du Colombier+ 5179*14414594SDavid du Colombier+ case Tstat: 5180*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5181*14414594SDavid du Colombier+ break; 5182*14414594SDavid du Colombier+ 5183*14414594SDavid du Colombier+ case Twstat: 5184*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5185*14414594SDavid du Colombier+ N2HSTRING(f->r_stat, sizeof(f->r_stat)); 5186*14414594SDavid du Colombier+ break; 5187*14414594SDavid du Colombier+ 5188*14414594SDavid du Colombier+ case Tclwalk: 5189*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5190*14414594SDavid du Colombier+ N2HSHORT(f->r_newfid); 5191*14414594SDavid du Colombier+ N2HSTRING(f->r_name, sizeof(f->r_name)); 5192*14414594SDavid du Colombier+ break; 5193*14414594SDavid du Colombier+ /* 5194*14414594SDavid du Colombier+ */ 5195*14414594SDavid du Colombier+ case Rnop: 5196*14414594SDavid du Colombier+ case Rosession: 5197*14414594SDavid du Colombier+ break; 5198*14414594SDavid du Colombier+ 5199*14414594SDavid du Colombier+ case Rsession: 5200*14414594SDavid du Colombier+ N2HSTRING(f->r_chal, sizeof(f->r_chal)); 5201*14414594SDavid du Colombier+ N2HSTRING(f->r_authid, sizeof(f->r_authid)); 5202*14414594SDavid du Colombier+ N2HSTRING(f->r_authdom, sizeof(f->r_authdom)); 5203*14414594SDavid du Colombier+ break; 5204*14414594SDavid du Colombier+ 5205*14414594SDavid du Colombier+ case Rerror: 5206*14414594SDavid du Colombier+ N2HSTRING(f->r_ename, sizeof(f->r_ename)); 5207*14414594SDavid du Colombier+ break; 5208*14414594SDavid du Colombier+ 5209*14414594SDavid du Colombier+ case Rflush: 5210*14414594SDavid du Colombier+ break; 5211*14414594SDavid du Colombier+ 5212*14414594SDavid du Colombier+ case Rattach: 5213*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5214*14414594SDavid du Colombier+ N2HLONG(f->r_qid.path); 5215*14414594SDavid du Colombier+ N2HLONG(f->r_qid.vers); 5216*14414594SDavid du Colombier+ N2HSTRING(f->r_rauth, sizeof(f->r_rauth)); 5217*14414594SDavid du Colombier+ break; 5218*14414594SDavid du Colombier+ 5219*14414594SDavid du Colombier+ case Roattach: 5220*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5221*14414594SDavid du Colombier+ N2HLONG(f->r_qid.path); 5222*14414594SDavid du Colombier+ N2HLONG(f->r_qid.vers); 5223*14414594SDavid du Colombier+ break; 5224*14414594SDavid du Colombier+ 5225*14414594SDavid du Colombier+ case Rauth: 5226*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5227*14414594SDavid du Colombier+ N2HSTRING(f->r_ticket, 8+8+7+7); 5228*14414594SDavid du Colombier+ break; 5229*14414594SDavid du Colombier+ 5230*14414594SDavid du Colombier+ case Rclone: 5231*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5232*14414594SDavid du Colombier+ break; 5233*14414594SDavid du Colombier+ 5234*14414594SDavid du Colombier+ case Rwalk: 5235*14414594SDavid du Colombier+ case Rclwalk: 5236*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5237*14414594SDavid du Colombier+ N2HLONG(f->r_qid.path); 5238*14414594SDavid du Colombier+ N2HLONG(f->r_qid.vers); 5239*14414594SDavid du Colombier+ break; 5240*14414594SDavid du Colombier+ 5241*14414594SDavid du Colombier+ case Ropen: 5242*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5243*14414594SDavid du Colombier+ N2HLONG(f->r_qid.path); 5244*14414594SDavid du Colombier+ N2HLONG(f->r_qid.vers); 5245*14414594SDavid du Colombier+ break; 5246*14414594SDavid du Colombier+ 5247*14414594SDavid du Colombier+ case Rcreate: 5248*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5249*14414594SDavid du Colombier+ N2HLONG(f->r_qid.path); 5250*14414594SDavid du Colombier+ N2HLONG(f->r_qid.vers); 5251*14414594SDavid du Colombier+ break; 5252*14414594SDavid du Colombier+ 5253*14414594SDavid du Colombier+ case Rread: 5254*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5255*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5256*14414594SDavid du Colombier+ p++; /* pad(1) */ 5257*14414594SDavid du Colombier+ f->r_data = (char*)p; p += f->r_count; 5258*14414594SDavid du Colombier+ break; 5259*14414594SDavid du Colombier+ 5260*14414594SDavid du Colombier+ case Rwrite: 5261*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5262*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5263*14414594SDavid du Colombier+ break; 5264*14414594SDavid du Colombier+ 5265*14414594SDavid du Colombier+ case Rtunnel: 5266*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5267*14414594SDavid du Colombier+ break; 5268*14414594SDavid du Colombier+ 5269*14414594SDavid du Colombier+ case Rclunk: 5270*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5271*14414594SDavid du Colombier+ break; 5272*14414594SDavid du Colombier+ 5273*14414594SDavid du Colombier+ case Rremove: 5274*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5275*14414594SDavid du Colombier+ break; 5276*14414594SDavid du Colombier+ 5277*14414594SDavid du Colombier+ case Rstat: 5278*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5279*14414594SDavid du Colombier+ N2HSTRING(f->r_stat, sizeof(f->r_stat)); 5280*14414594SDavid du Colombier+ break; 5281*14414594SDavid du Colombier+ 5282*14414594SDavid du Colombier+ case Rwstat: 5283*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5284*14414594SDavid du Colombier+ break; 5285*14414594SDavid du Colombier+ } 5286*14414594SDavid du Colombier+ if((u_char*)ap+n == p) 5287*14414594SDavid du Colombier+ return n; 5288*14414594SDavid du Colombier+ return 0; 5289*14414594SDavid du Colombier+ } 5290*14414594SDavid du Colombier+ 5291*14414594SDavid du Colombier+ void u9p_print(u_char * m, int len, struct u9fsreq * f) 5292*14414594SDavid du Colombier+ { 5293*14414594SDavid du Colombier+ struct u9fsreq u9fsreq; 5294*14414594SDavid du Colombier+ 5295*14414594SDavid du Colombier+ if( f == 0 ) 5296*14414594SDavid du Colombier+ f = & u9fsreq; 5297*14414594SDavid du Colombier+ 5298*14414594SDavid du Colombier+ if( len < 3 ) { 5299*14414594SDavid du Colombier+ printf("truncated-9p %d", len); 5300*14414594SDavid du Colombier+ return; 5301*14414594SDavid du Colombier+ } 5302*14414594SDavid du Colombier+ 5303*14414594SDavid du Colombier+ if( u9p_m2s((char *)m, len, f) == 0 ) 5304*14414594SDavid du Colombier+ return; 5305*14414594SDavid du Colombier+ 5306*14414594SDavid du Colombier+ printf("%s tag %d ", u9p_types[f->r_type-Tnop], f->r_tag); 5307*14414594SDavid du Colombier+ 5308*14414594SDavid du Colombier+ switch( f->r_type ) { 5309*14414594SDavid du Colombier+ default: 5310*14414594SDavid du Colombier+ return; 5311*14414594SDavid du Colombier+ 5312*14414594SDavid du Colombier+ case Tnop: 5313*14414594SDavid du Colombier+ case Tosession: 5314*14414594SDavid du Colombier+ case Toattach: 5315*14414594SDavid du Colombier+ case Tauth: 5316*14414594SDavid du Colombier+ break; 5317*14414594SDavid du Colombier+ 5318*14414594SDavid du Colombier+ case Tsession: 5319*14414594SDavid du Colombier+ case Rsession: 5320*14414594SDavid du Colombier+ printf("chal 0x%x 0x%x", *(u_int *)&f->r_chal[0], *(u_int *)&f->r_chal[4]); 5321*14414594SDavid du Colombier+ break; 5322*14414594SDavid du Colombier+ 5323*14414594SDavid du Colombier+ case Tflush: 5324*14414594SDavid du Colombier+ printf("oldtag %d", f->r_oldtag); 5325*14414594SDavid du Colombier+ break; 5326*14414594SDavid du Colombier+ 5327*14414594SDavid du Colombier+ case Tclone: 5328*14414594SDavid du Colombier+ printf("fid %d newfid %d", f->r_fid, f->r_newfid); 5329*14414594SDavid du Colombier+ break; 5330*14414594SDavid du Colombier+ 5331*14414594SDavid du Colombier+ case Twalk: 5332*14414594SDavid du Colombier+ printf("fid %d name %s", f->r_fid, f->r_name); 5333*14414594SDavid du Colombier+ break; 5334*14414594SDavid du Colombier+ 5335*14414594SDavid du Colombier+ case Topen: 5336*14414594SDavid du Colombier+ printf("fid %d %c", f->r_fid, f->r_mode); 5337*14414594SDavid du Colombier+ break; 5338*14414594SDavid du Colombier+ 5339*14414594SDavid du Colombier+ case Tcreate: 5340*14414594SDavid du Colombier+ printf("fid %d name %s perm 0x%x mode %c", f->r_fid, 5341*14414594SDavid du Colombier+ f->r_name, f->r_perm, f->r_mode); 5342*14414594SDavid du Colombier+ break; 5343*14414594SDavid du Colombier+ 5344*14414594SDavid du Colombier+ case Tread: 5345*14414594SDavid du Colombier+ case Twrite: 5346*14414594SDavid du Colombier+ printf("fid %d offset 0x%llx count %d", f->r_fid, 5347*14414594SDavid du Colombier+ f->r_offset, f->r_count); 5348*14414594SDavid du Colombier+ break; 5349*14414594SDavid du Colombier+ 5350*14414594SDavid du Colombier+ case Tattach: 5351*14414594SDavid du Colombier+ case Ttunnel: 5352*14414594SDavid du Colombier+ case Tclunk: 5353*14414594SDavid du Colombier+ case Tremove: 5354*14414594SDavid du Colombier+ case Tstat: 5355*14414594SDavid du Colombier+ case Twstat: 5356*14414594SDavid du Colombier+ case Rclone: 5357*14414594SDavid du Colombier+ case Rtunnel: 5358*14414594SDavid du Colombier+ case Rclunk: 5359*14414594SDavid du Colombier+ case Rremove: 5360*14414594SDavid du Colombier+ case Rstat: 5361*14414594SDavid du Colombier+ case Rwstat: 5362*14414594SDavid du Colombier+ printf("fid %d", f->r_fid); 5363*14414594SDavid du Colombier+ break; 5364*14414594SDavid du Colombier+ 5365*14414594SDavid du Colombier+ case Tclwalk: 5366*14414594SDavid du Colombier+ printf("fid %d ", f->r_fid); 5367*14414594SDavid du Colombier+ printf("newfid %d ", f->r_newfid); 5368*14414594SDavid du Colombier+ printf("name %s", f->r_name); 5369*14414594SDavid du Colombier+ break; 5370*14414594SDavid du Colombier+ /* 5371*14414594SDavid du Colombier+ */ 5372*14414594SDavid du Colombier+ case Rnop: 5373*14414594SDavid du Colombier+ case Rosession: 5374*14414594SDavid du Colombier+ case Rflush: 5375*14414594SDavid du Colombier+ case Roattach: 5376*14414594SDavid du Colombier+ case Rauth: 5377*14414594SDavid du Colombier+ break; 5378*14414594SDavid du Colombier+ 5379*14414594SDavid du Colombier+ case Rerror: 5380*14414594SDavid du Colombier+ printf("ename %s", f->r_ename); 5381*14414594SDavid du Colombier+ break; 5382*14414594SDavid du Colombier+ 5383*14414594SDavid du Colombier+ case Rattach: 5384*14414594SDavid du Colombier+ case Rwalk: 5385*14414594SDavid du Colombier+ case Rclwalk: 5386*14414594SDavid du Colombier+ case Ropen: 5387*14414594SDavid du Colombier+ case Rcreate: 5388*14414594SDavid du Colombier+ printf("fid %d ", f->r_fid); 5389*14414594SDavid du Colombier+ printf("qid 0x%x 0x%x", f->r_qid.path, f->r_qid.vers); 5390*14414594SDavid du Colombier+ break; 5391*14414594SDavid du Colombier+ 5392*14414594SDavid du Colombier+ case Rread: 5393*14414594SDavid du Colombier+ printf("fid %d count %d ", f->r_fid, f->r_count); 5394*14414594SDavid du Colombier+ break; 5395*14414594SDavid du Colombier+ 5396*14414594SDavid du Colombier+ case Rwrite: 5397*14414594SDavid du Colombier+ printf("fid %d count %d", f->r_fid, f->r_count); 5398*14414594SDavid du Colombier+ break; 5399*14414594SDavid du Colombier+ } 5400*14414594SDavid du Colombier+ } 5401*14414594SDavid du Colombier+ 5402*14414594SDavid du Colombier+ int 5403*14414594SDavid du Colombier+ u9p_s2m(struct u9fsreq *f, char *ap, int copydata) 5404*14414594SDavid du Colombier+ { 5405*14414594SDavid du Colombier+ u_char *p; 5406*14414594SDavid du Colombier+ 5407*14414594SDavid du Colombier+ p = (u_char*)ap; 5408*14414594SDavid du Colombier+ H2NCHAR(f->r_type); 5409*14414594SDavid du Colombier+ H2NSHORT(f->r_tag); 5410*14414594SDavid du Colombier+ switch(f->r_type) 5411*14414594SDavid du Colombier+ { 5412*14414594SDavid du Colombier+ default: 5413*14414594SDavid du Colombier+ return 0; 5414*14414594SDavid du Colombier+ 5415*14414594SDavid du Colombier+ case Tosession: 5416*14414594SDavid du Colombier+ case Tnop: 5417*14414594SDavid du Colombier+ break; 5418*14414594SDavid du Colombier+ 5419*14414594SDavid du Colombier+ case Tsession: 5420*14414594SDavid du Colombier+ H2NSTRING(f->r_chal, sizeof(f->r_chal)); 5421*14414594SDavid du Colombier+ break; 5422*14414594SDavid du Colombier+ 5423*14414594SDavid du Colombier+ case Tflush: 5424*14414594SDavid du Colombier+ H2NSHORT(f->r_oldtag); 5425*14414594SDavid du Colombier+ break; 5426*14414594SDavid du Colombier+ 5427*14414594SDavid du Colombier+ case Tattach: 5428*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5429*14414594SDavid du Colombier+ H2NSTRING(f->r_uname, sizeof(f->r_uname)); 5430*14414594SDavid du Colombier+ H2NSTRING(f->r_aname, sizeof(f->r_aname)); 5431*14414594SDavid du Colombier+ H2NSTRING(f->r_ticket, sizeof(f->r_ticket)); 5432*14414594SDavid du Colombier+ H2NSTRING(f->r_auth, sizeof(f->r_auth)); 5433*14414594SDavid du Colombier+ break; 5434*14414594SDavid du Colombier+ 5435*14414594SDavid du Colombier+ case Toattach: 5436*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5437*14414594SDavid du Colombier+ H2NSTRING(f->r_uname, sizeof(f->r_uname)); 5438*14414594SDavid du Colombier+ H2NSTRING(f->r_aname, sizeof(f->r_aname)); 5439*14414594SDavid du Colombier+ H2NSTRING(f->r_ticket, U9FS_NAMELEN); 5440*14414594SDavid du Colombier+ break; 5441*14414594SDavid du Colombier+ 5442*14414594SDavid du Colombier+ case Tauth: 5443*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5444*14414594SDavid du Colombier+ H2NSTRING(f->r_uname, sizeof(f->r_uname)); 5445*14414594SDavid du Colombier+ H2NSTRING(f->r_ticket, 8+U9FS_NAMELEN); 5446*14414594SDavid du Colombier+ break; 5447*14414594SDavid du Colombier+ 5448*14414594SDavid du Colombier+ case Tclone: 5449*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5450*14414594SDavid du Colombier+ H2NSHORT(f->r_newfid); 5451*14414594SDavid du Colombier+ break; 5452*14414594SDavid du Colombier+ 5453*14414594SDavid du Colombier+ case Twalk: 5454*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5455*14414594SDavid du Colombier+ H2NSTRING(f->r_name, sizeof(f->r_name)); 5456*14414594SDavid du Colombier+ break; 5457*14414594SDavid du Colombier+ 5458*14414594SDavid du Colombier+ case Topen: 5459*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5460*14414594SDavid du Colombier+ H2NCHAR(f->r_mode); 5461*14414594SDavid du Colombier+ break; 5462*14414594SDavid du Colombier+ 5463*14414594SDavid du Colombier+ case Tcreate: 5464*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5465*14414594SDavid du Colombier+ H2NSTRING(f->r_name, sizeof(f->r_name)); 5466*14414594SDavid du Colombier+ H2NLONG(f->r_perm); 5467*14414594SDavid du Colombier+ H2NCHAR(f->r_mode); 5468*14414594SDavid du Colombier+ break; 5469*14414594SDavid du Colombier+ 5470*14414594SDavid du Colombier+ case Tread: 5471*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5472*14414594SDavid du Colombier+ H2NQUAD(f->r_offset); 5473*14414594SDavid du Colombier+ H2NSHORT(f->r_count); 5474*14414594SDavid du Colombier+ break; 5475*14414594SDavid du Colombier+ 5476*14414594SDavid du Colombier+ case Twrite: 5477*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5478*14414594SDavid du Colombier+ H2NQUAD(f->r_offset); 5479*14414594SDavid du Colombier+ H2NSHORT(f->r_count); 5480*14414594SDavid du Colombier+ p++; /* pad(1) */ 5481*14414594SDavid du Colombier+ if( copydata ) { 5482*14414594SDavid du Colombier+ H2NSTRING(f->r_data, f->r_count); 5483*14414594SDavid du Colombier+ } 5484*14414594SDavid du Colombier+ break; 5485*14414594SDavid du Colombier+ 5486*14414594SDavid du Colombier+ case Ttunnel: 5487*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5488*14414594SDavid du Colombier+ break; 5489*14414594SDavid du Colombier+ 5490*14414594SDavid du Colombier+ case Tclunk: 5491*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5492*14414594SDavid du Colombier+ break; 5493*14414594SDavid du Colombier+ 5494*14414594SDavid du Colombier+ case Tremove: 5495*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5496*14414594SDavid du Colombier+ break; 5497*14414594SDavid du Colombier+ 5498*14414594SDavid du Colombier+ case Tstat: 5499*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5500*14414594SDavid du Colombier+ break; 5501*14414594SDavid du Colombier+ 5502*14414594SDavid du Colombier+ case Twstat: 5503*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5504*14414594SDavid du Colombier+ H2NSTRING(f->r_stat, sizeof(f->r_stat)); 5505*14414594SDavid du Colombier+ break; 5506*14414594SDavid du Colombier+ 5507*14414594SDavid du Colombier+ case Tclwalk: 5508*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5509*14414594SDavid du Colombier+ H2NSHORT(f->r_newfid); 5510*14414594SDavid du Colombier+ H2NSTRING(f->r_name, sizeof(f->r_name)); 5511*14414594SDavid du Colombier+ break; 5512*14414594SDavid du Colombier+ /* 5513*14414594SDavid du Colombier+ */ 5514*14414594SDavid du Colombier+ case Rosession: 5515*14414594SDavid du Colombier+ case Rnop: 5516*14414594SDavid du Colombier+ break; 5517*14414594SDavid du Colombier+ 5518*14414594SDavid du Colombier+ case Rsession: 5519*14414594SDavid du Colombier+ H2NSTRING(f->r_chal, sizeof(f->r_chal)); 5520*14414594SDavid du Colombier+ H2NSTRING(f->r_authid, sizeof(f->r_authid)); 5521*14414594SDavid du Colombier+ H2NSTRING(f->r_authdom, sizeof(f->r_authdom)); 5522*14414594SDavid du Colombier+ break; 5523*14414594SDavid du Colombier+ 5524*14414594SDavid du Colombier+ case Rerror: 5525*14414594SDavid du Colombier+ H2NSTRING(f->r_ename, sizeof(f->r_ename)); 5526*14414594SDavid du Colombier+ break; 5527*14414594SDavid du Colombier+ 5528*14414594SDavid du Colombier+ case Rflush: 5529*14414594SDavid du Colombier+ break; 5530*14414594SDavid du Colombier+ 5531*14414594SDavid du Colombier+ case Rattach: 5532*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5533*14414594SDavid du Colombier+ H2NLONG(f->r_qid.path); 5534*14414594SDavid du Colombier+ H2NLONG(f->r_qid.vers); 5535*14414594SDavid du Colombier+ H2NSTRING(f->r_rauth, sizeof(f->r_rauth)); 5536*14414594SDavid du Colombier+ break; 5537*14414594SDavid du Colombier+ 5538*14414594SDavid du Colombier+ case Roattach: 5539*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5540*14414594SDavid du Colombier+ H2NLONG(f->r_qid.path); 5541*14414594SDavid du Colombier+ H2NLONG(f->r_qid.vers); 5542*14414594SDavid du Colombier+ break; 5543*14414594SDavid du Colombier+ 5544*14414594SDavid du Colombier+ case Rauth: 5545*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5546*14414594SDavid du Colombier+ H2NSTRING(f->r_ticket, 8+8+7+7); 5547*14414594SDavid du Colombier+ break; 5548*14414594SDavid du Colombier+ 5549*14414594SDavid du Colombier+ case Rclone: 5550*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5551*14414594SDavid du Colombier+ break; 5552*14414594SDavid du Colombier+ 5553*14414594SDavid du Colombier+ case Rwalk: 5554*14414594SDavid du Colombier+ case Rclwalk: 5555*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5556*14414594SDavid du Colombier+ H2NLONG(f->r_qid.path); 5557*14414594SDavid du Colombier+ H2NLONG(f->r_qid.vers); 5558*14414594SDavid du Colombier+ break; 5559*14414594SDavid du Colombier+ 5560*14414594SDavid du Colombier+ case Ropen: 5561*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5562*14414594SDavid du Colombier+ H2NLONG(f->r_qid.path); 5563*14414594SDavid du Colombier+ H2NLONG(f->r_qid.vers); 5564*14414594SDavid du Colombier+ break; 5565*14414594SDavid du Colombier+ 5566*14414594SDavid du Colombier+ case Rcreate: 5567*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5568*14414594SDavid du Colombier+ H2NLONG(f->r_qid.path); 5569*14414594SDavid du Colombier+ H2NLONG(f->r_qid.vers); 5570*14414594SDavid du Colombier+ break; 5571*14414594SDavid du Colombier+ 5572*14414594SDavid du Colombier+ case Rread: 5573*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5574*14414594SDavid du Colombier+ H2NSHORT(f->r_count); 5575*14414594SDavid du Colombier+ p++; /* pad(1) */ 5576*14414594SDavid du Colombier+ if( copydata ) { 5577*14414594SDavid du Colombier+ H2NSTRING(f->r_data, f->r_count); 5578*14414594SDavid du Colombier+ } 5579*14414594SDavid du Colombier+ break; 5580*14414594SDavid du Colombier+ 5581*14414594SDavid du Colombier+ case Rwrite: 5582*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5583*14414594SDavid du Colombier+ H2NSHORT(f->r_count); 5584*14414594SDavid du Colombier+ break; 5585*14414594SDavid du Colombier+ 5586*14414594SDavid du Colombier+ case Rtunnel: 5587*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5588*14414594SDavid du Colombier+ break; 5589*14414594SDavid du Colombier+ 5590*14414594SDavid du Colombier+ case Rclunk: 5591*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5592*14414594SDavid du Colombier+ break; 5593*14414594SDavid du Colombier+ 5594*14414594SDavid du Colombier+ case Rremove: 5595*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5596*14414594SDavid du Colombier+ break; 5597*14414594SDavid du Colombier+ 5598*14414594SDavid du Colombier+ case Rstat: 5599*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5600*14414594SDavid du Colombier+ if( copydata ) 5601*14414594SDavid du Colombier+ H2NSTRING(f->r_stat, sizeof(f->r_stat)); 5602*14414594SDavid du Colombier+ break; 5603*14414594SDavid du Colombier+ 5604*14414594SDavid du Colombier+ case Rwstat: 5605*14414594SDavid du Colombier+ H2NSHORT(f->r_fid); 5606*14414594SDavid du Colombier+ break; 5607*14414594SDavid du Colombier+ } 5608*14414594SDavid du Colombier+ return p - (u_char*)ap; 5609*14414594SDavid du Colombier+ } 5610*14414594SDavid du Colombier+ 5611*14414594SDavid du Colombier+ int 5612*14414594SDavid du Colombier+ u9p_m2d(char *ap, struct u9fsdir *f) 5613*14414594SDavid du Colombier+ { 5614*14414594SDavid du Colombier+ u_char *p; 5615*14414594SDavid du Colombier+ 5616*14414594SDavid du Colombier+ p = (u_char*)ap; 5617*14414594SDavid du Colombier+ N2HSTRING(f->dir_name, sizeof(f->dir_name)); 5618*14414594SDavid du Colombier+ N2HSTRING(f->dir_uid, sizeof(f->dir_uid)); 5619*14414594SDavid du Colombier+ N2HSTRING(f->dir_gid, sizeof(f->dir_gid)); 5620*14414594SDavid du Colombier+ N2HLONG(f->dir_qid.path); 5621*14414594SDavid du Colombier+ N2HLONG(f->dir_qid.vers); 5622*14414594SDavid du Colombier+ N2HLONG(f->dir_mode); 5623*14414594SDavid du Colombier+ N2HLONG(f->dir_atime); 5624*14414594SDavid du Colombier+ N2HLONG(f->dir_mtime); 5625*14414594SDavid du Colombier+ N2HQUAD(f->dir_length); 5626*14414594SDavid du Colombier+ N2HSHORT(f->dir_type); 5627*14414594SDavid du Colombier+ N2HSHORT(f->dir_dev); 5628*14414594SDavid du Colombier+ return p - (u_char*)ap; 5629*14414594SDavid du Colombier+ } 5630*14414594SDavid du Colombier+ 5631*14414594SDavid du Colombier+ int 5632*14414594SDavid du Colombier+ u9p_d2m(struct u9fsdir *f, char *ap) 5633*14414594SDavid du Colombier+ { 5634*14414594SDavid du Colombier+ u_char *p; 5635*14414594SDavid du Colombier+ 5636*14414594SDavid du Colombier+ p = (u_char*)ap; 5637*14414594SDavid du Colombier+ H2NSTRING(f->dir_name, sizeof(f->dir_name)); 5638*14414594SDavid du Colombier+ H2NSTRING(f->dir_uid, sizeof(f->dir_uid)); 5639*14414594SDavid du Colombier+ H2NSTRING(f->dir_gid, sizeof(f->dir_gid)); 5640*14414594SDavid du Colombier+ H2NLONG(f->dir_qid.path); 5641*14414594SDavid du Colombier+ H2NLONG(f->dir_qid.vers); 5642*14414594SDavid du Colombier+ H2NLONG(f->dir_mode); 5643*14414594SDavid du Colombier+ H2NLONG(f->dir_atime); 5644*14414594SDavid du Colombier+ H2NLONG(f->dir_mtime); 5645*14414594SDavid du Colombier+ H2NQUAD(f->dir_length); 5646*14414594SDavid du Colombier+ H2NSHORT(f->dir_type); 5647*14414594SDavid du Colombier+ H2NSHORT(f->dir_dev); 5648*14414594SDavid du Colombier+ return p - (u_char*)ap; 5649*14414594SDavid du Colombier+ } 5650*14414594SDavid du Colombier+ 5651*14414594SDavid du Colombier+ /* parse 9P types */ 5652*14414594SDavid du Colombier+ int u9p_type(char * t) 5653*14414594SDavid du Colombier+ { 5654*14414594SDavid du Colombier+ int i; 5655*14414594SDavid du Colombier+ 5656*14414594SDavid du Colombier+ for(i = 0; i < sizeof(u9p_types)/sizeof(u9p_types[0]); i++) { 5657*14414594SDavid du Colombier+ if( strcmp(u9p_types[i], t) == 0 ) 5658*14414594SDavid du Colombier+ return (i+Tnop); 5659*14414594SDavid du Colombier+ } 5660*14414594SDavid du Colombier+ return 0; 5661*14414594SDavid du Colombier+ } 5662*14414594SDavid du Colombier+ 5663*14414594SDavid du Colombier+ /* m is freed if shorter than s */ 5664*14414594SDavid du Colombier+ #if 1 5665*14414594SDavid du Colombier+ #define U9P_PULLUP(m,s) if( (*(m))->m_len < (s) && ((*(m)) = m_pullup((*(m)),(s))) == 0 ) return 1; p = mtod((*(m)), u_char *) 5666*14414594SDavid du Colombier+ #else 5667*14414594SDavid du Colombier+ #define U9P_PULLUP(m,s) if( (*(m))->m_len < (s) && ((*(m)) = m_pullup((*(m)),(s))) == 0 ) panic("PULLUP"); p = mtod((*(m)), u_char *) 5668*14414594SDavid du Colombier+ #endif 5669*14414594SDavid du Colombier+ 5670*14414594SDavid du Colombier+ #define U9P_ADJ(m,s) (*(m))->m_len -= (s); (*(m))->m_data += (s) 5671*14414594SDavid du Colombier+ 5672*14414594SDavid du Colombier+ u_short u9p_m_tag(struct mbuf ** m) 5673*14414594SDavid du Colombier+ { 5674*14414594SDavid du Colombier+ char * p; 5675*14414594SDavid du Colombier+ u_short t; 5676*14414594SDavid du Colombier+ 5677*14414594SDavid du Colombier+ U9P_PULLUP(m,3); 5678*14414594SDavid du Colombier+ p = mtod(*m, char *); 5679*14414594SDavid du Colombier+ p++; 5680*14414594SDavid du Colombier+ N2HSHORT(t); 5681*14414594SDavid du Colombier+ 5682*14414594SDavid du Colombier+ return t; 5683*14414594SDavid du Colombier+ } 5684*14414594SDavid du Colombier+ 5685*14414594SDavid du Colombier+ int 5686*14414594SDavid du Colombier+ u9p_m_m2s(struct mbuf **m, struct u9fsreq *f) 5687*14414594SDavid du Colombier+ { 5688*14414594SDavid du Colombier+ u_char *p; 5689*14414594SDavid du Colombier+ 5690*14414594SDavid du Colombier+ U9P_PULLUP(m,3); 5691*14414594SDavid du Colombier+ N2HCHAR(f->r_type); 5692*14414594SDavid du Colombier+ N2HSHORT(f->r_tag); 5693*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_type)+sizeof(f->r_tag)); 5694*14414594SDavid du Colombier+ 5695*14414594SDavid du Colombier+ switch(f->r_type) { 5696*14414594SDavid du Colombier+ default: 5697*14414594SDavid du Colombier+ goto drop; 5698*14414594SDavid du Colombier+ 5699*14414594SDavid du Colombier+ case Tnop: 5700*14414594SDavid du Colombier+ break; 5701*14414594SDavid du Colombier+ 5702*14414594SDavid du Colombier+ case Tsession: 5703*14414594SDavid du Colombier+ U9P_PULLUP(m,sizeof(f->r_chal)); 5704*14414594SDavid du Colombier+ N2HSTRING(f->r_chal, sizeof(f->r_chal)); 5705*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_chal)); 5706*14414594SDavid du Colombier+ break; 5707*14414594SDavid du Colombier+ 5708*14414594SDavid du Colombier+ case Tflush: 5709*14414594SDavid du Colombier+ U9P_PULLUP(m,sizeof(f->r_oldtag)); 5710*14414594SDavid du Colombier+ N2HSHORT(f->r_oldtag); 5711*14414594SDavid du Colombier+ U9P_ADJ(m, f->r_oldtag); 5712*14414594SDavid du Colombier+ break; 5713*14414594SDavid du Colombier+ 5714*14414594SDavid du Colombier+ case Tattach: 5715*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_uname)+sizeof(f->r_aname)); 5716*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5717*14414594SDavid du Colombier+ N2HSTRING(f->r_uname, sizeof(f->r_uname)); 5718*14414594SDavid du Colombier+ N2HSTRING(f->r_aname, sizeof(f->r_aname)); 5719*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_uname)+sizeof(f->r_aname)); 5720*14414594SDavid du Colombier+ 5721*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_ticket)+sizeof(f->r_auth)); 5722*14414594SDavid du Colombier+ N2HSTRING(f->r_ticket, sizeof(f->r_ticket)); 5723*14414594SDavid du Colombier+ N2HSTRING(f->r_auth, sizeof(f->r_auth)); 5724*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_ticket)+sizeof(f->r_auth)); 5725*14414594SDavid du Colombier+ break; 5726*14414594SDavid du Colombier+ 5727*14414594SDavid du Colombier+ case Tclone: 5728*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_newfid)); 5729*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5730*14414594SDavid du Colombier+ N2HSHORT(f->r_newfid); 5731*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_newfid)); 5732*14414594SDavid du Colombier+ break; 5733*14414594SDavid du Colombier+ 5734*14414594SDavid du Colombier+ case Twalk: 5735*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_name)); 5736*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5737*14414594SDavid du Colombier+ N2HSTRING(f->r_name, sizeof(f->r_name)); 5738*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_name)); 5739*14414594SDavid du Colombier+ break; 5740*14414594SDavid du Colombier+ 5741*14414594SDavid du Colombier+ case Topen: 5742*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_mode)); 5743*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5744*14414594SDavid du Colombier+ N2HCHAR(f->r_mode); 5745*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_mode)); 5746*14414594SDavid du Colombier+ break; 5747*14414594SDavid du Colombier+ 5748*14414594SDavid du Colombier+ case Tcreate: 5749*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_name) 5750*14414594SDavid du Colombier+ +sizeof(f->r_perm)+sizeof(f->r_mode)); 5751*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5752*14414594SDavid du Colombier+ N2HSTRING(f->r_name, sizeof(f->r_name)); 5753*14414594SDavid du Colombier+ N2HLONG(f->r_perm); 5754*14414594SDavid du Colombier+ N2HCHAR(f->r_mode); 5755*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_name) 5756*14414594SDavid du Colombier+ +sizeof(f->r_perm)+sizeof(f->r_mode)); 5757*14414594SDavid du Colombier+ break; 5758*14414594SDavid du Colombier+ 5759*14414594SDavid du Colombier+ case Tread: 5760*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count)); 5761*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5762*14414594SDavid du Colombier+ N2HQUAD(f->r_offset); 5763*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5764*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count)); 5765*14414594SDavid du Colombier+ break; 5766*14414594SDavid du Colombier+ 5767*14414594SDavid du Colombier+ case Twrite: 5768*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count)); 5769*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5770*14414594SDavid du Colombier+ N2HQUAD(f->r_offset); 5771*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5772*14414594SDavid du Colombier+ p++; /* pad(1) */ 5773*14414594SDavid du Colombier+ f->r_data = (char*)p; p += f->r_count; 5774*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_offset)+sizeof(f->r_count)+1); 5775*14414594SDavid du Colombier+ break; 5776*14414594SDavid du Colombier+ 5777*14414594SDavid du Colombier+ case Tclunk: 5778*14414594SDavid du Colombier+ case Tremove: 5779*14414594SDavid du Colombier+ case Tstat: 5780*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)); 5781*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5782*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)); 5783*14414594SDavid du Colombier+ break; 5784*14414594SDavid du Colombier+ 5785*14414594SDavid du Colombier+ case Twstat: 5786*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)); 5787*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5788*14414594SDavid du Colombier+ m_copydata(*m, sizeof(f->r_fid), sizeof(f->r_stat), f->r_stat); 5789*14414594SDavid du Colombier+ m_adj(*m, sizeof(f->r_fid)+sizeof(f->r_stat)); 5790*14414594SDavid du Colombier+ break; 5791*14414594SDavid du Colombier+ 5792*14414594SDavid du Colombier+ case Tclwalk: 5793*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_newfid)+sizeof(f->r_name)); 5794*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5795*14414594SDavid du Colombier+ N2HSHORT(f->r_newfid); 5796*14414594SDavid du Colombier+ N2HSTRING(f->r_name, sizeof(f->r_name)); 5797*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_newfid)+sizeof(f->r_name)); 5798*14414594SDavid du Colombier+ break; 5799*14414594SDavid du Colombier+ /* 5800*14414594SDavid du Colombier+ */ 5801*14414594SDavid du Colombier+ case Rnop: 5802*14414594SDavid du Colombier+ break; 5803*14414594SDavid du Colombier+ 5804*14414594SDavid du Colombier+ case Rsession: 5805*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_authid)+sizeof(f->r_authdom)); 5806*14414594SDavid du Colombier+ N2HSTRING(f->r_chal, sizeof(f->r_chal)); 5807*14414594SDavid du Colombier+ N2HSTRING(f->r_authid, sizeof(f->r_authid)); 5808*14414594SDavid du Colombier+ N2HSTRING(f->r_authdom, sizeof(f->r_authdom)); 5809*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_authid)+sizeof(f->r_authdom)); 5810*14414594SDavid du Colombier+ break; 5811*14414594SDavid du Colombier+ 5812*14414594SDavid du Colombier+ case Rerror: 5813*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_ename)); 5814*14414594SDavid du Colombier+ N2HSTRING(f->r_ename, sizeof(f->r_ename)); 5815*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_ename)); 5816*14414594SDavid du Colombier+ break; 5817*14414594SDavid du Colombier+ 5818*14414594SDavid du Colombier+ case Rflush: 5819*14414594SDavid du Colombier+ break; 5820*14414594SDavid du Colombier+ 5821*14414594SDavid du Colombier+ case Rattach: 5822*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_qid.path) 5823*14414594SDavid du Colombier+ +sizeof(f->r_qid.vers)+sizeof(f->r_rauth)); 5824*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5825*14414594SDavid du Colombier+ N2HLONG(f->r_qid.path); 5826*14414594SDavid du Colombier+ N2HLONG(f->r_qid.vers); 5827*14414594SDavid du Colombier+ N2HSTRING(f->r_rauth, sizeof(f->r_rauth)); 5828*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_qid.path) 5829*14414594SDavid du Colombier+ +sizeof(f->r_qid.vers)+sizeof(f->r_rauth)); 5830*14414594SDavid du Colombier+ break; 5831*14414594SDavid du Colombier+ 5832*14414594SDavid du Colombier+ case Rclone: 5833*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)); 5834*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5835*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)); 5836*14414594SDavid du Colombier+ break; 5837*14414594SDavid du Colombier+ 5838*14414594SDavid du Colombier+ case Rwalk: 5839*14414594SDavid du Colombier+ case Rclwalk: 5840*14414594SDavid du Colombier+ case Ropen: 5841*14414594SDavid du Colombier+ case Rcreate: 5842*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_qid.path) 5843*14414594SDavid du Colombier+ +sizeof(f->r_qid.vers)); 5844*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5845*14414594SDavid du Colombier+ N2HLONG(f->r_qid.path); 5846*14414594SDavid du Colombier+ N2HLONG(f->r_qid.vers); 5847*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_qid.path) 5848*14414594SDavid du Colombier+ +sizeof(f->r_qid.vers)); 5849*14414594SDavid du Colombier+ break; 5850*14414594SDavid du Colombier+ 5851*14414594SDavid du Colombier+ case Rread: 5852*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_count)); 5853*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5854*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5855*14414594SDavid du Colombier+ p++; /* pad(1) */ 5856*14414594SDavid du Colombier+ f->r_data = (char*)p; p += f->r_count; 5857*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_count)+1); 5858*14414594SDavid du Colombier+ break; 5859*14414594SDavid du Colombier+ 5860*14414594SDavid du Colombier+ case Rwrite: 5861*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)+sizeof(f->r_count)); 5862*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5863*14414594SDavid du Colombier+ N2HSHORT(f->r_count); 5864*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)+sizeof(f->r_count)); 5865*14414594SDavid du Colombier+ break; 5866*14414594SDavid du Colombier+ 5867*14414594SDavid du Colombier+ case Rclunk: 5868*14414594SDavid du Colombier+ case Rremove: 5869*14414594SDavid du Colombier+ case Rwstat: 5870*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)); 5871*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5872*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->r_fid)); 5873*14414594SDavid du Colombier+ break; 5874*14414594SDavid du Colombier+ 5875*14414594SDavid du Colombier+ case Rstat: 5876*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->r_fid)); 5877*14414594SDavid du Colombier+ N2HSHORT(f->r_fid); 5878*14414594SDavid du Colombier+ m_copydata(*m, sizeof(f->r_fid), sizeof(f->r_stat), f->r_stat); 5879*14414594SDavid du Colombier+ m_adj(*m, sizeof(f->r_fid)+sizeof(f->r_stat)); 5880*14414594SDavid du Colombier+ break; 5881*14414594SDavid du Colombier+ 5882*14414594SDavid du Colombier+ } 5883*14414594SDavid du Colombier+ return 0; 5884*14414594SDavid du Colombier+ 5885*14414594SDavid du Colombier+ drop: 5886*14414594SDavid du Colombier+ m_freem(*m); 5887*14414594SDavid du Colombier+ return 1; 5888*14414594SDavid du Colombier+ } 5889*14414594SDavid du Colombier+ 5890*14414594SDavid du Colombier+ struct mbuf * 5891*14414594SDavid du Colombier+ u9p_m_s2m (struct u9fsreq *f) 5892*14414594SDavid du Colombier+ { 5893*14414594SDavid du Colombier+ register struct mbuf * m; 5894*14414594SDavid du Colombier+ struct mbuf * m0; 5895*14414594SDavid du Colombier+ char * ap; 5896*14414594SDavid du Colombier+ int sz; 5897*14414594SDavid du Colombier+ 5898*14414594SDavid du Colombier+ /* we want one contiguous piece */ 5899*14414594SDavid du Colombier+ if( f->r_type == Tattach || f->r_type == Rstat || f->r_type == Twstat ) 5900*14414594SDavid du Colombier+ sz = 146; /* sizeof a Tattach */ 5901*14414594SDavid du Colombier+ else 5902*14414594SDavid du Colombier+ sz = 87; /* sizeof a Tsession */ 5903*14414594SDavid du Colombier+ 5904*14414594SDavid du Colombier+ MGETHDR(m, M_WAIT, MT_DATA); 5905*14414594SDavid du Colombier+ if( sz > MHLEN ) 5906*14414594SDavid du Colombier+ MCLGET(m, M_WAIT); 5907*14414594SDavid du Colombier+ m->m_len = 0; 5908*14414594SDavid du Colombier+ 5909*14414594SDavid du Colombier+ if ( M_TRAILINGSPACE(m) < sz ) 5910*14414594SDavid du Colombier+ panic("u9p_m_s2m"); 5911*14414594SDavid du Colombier+ 5912*14414594SDavid du Colombier+ ap = mtod(m, char *); 5913*14414594SDavid du Colombier+ m->m_len = u9p_s2m(f, ap, 0); 5914*14414594SDavid du Colombier+ m->m_pkthdr.len = m->m_len; 5915*14414594SDavid du Colombier+ 5916*14414594SDavid du Colombier+ /* append data mbufs */ 5917*14414594SDavid du Colombier+ switch ( f->r_type ) { 5918*14414594SDavid du Colombier+ default: 5919*14414594SDavid du Colombier+ break; 5920*14414594SDavid du Colombier+ case Twrite: 5921*14414594SDavid du Colombier+ case Rread: 5922*14414594SDavid du Colombier+ m0 = (struct mbuf *)f->r_data; 5923*14414594SDavid du Colombier+ m->m_next = m0; 5924*14414594SDavid du Colombier+ m->m_pkthdr.len += f->r_count; 5925*14414594SDavid du Colombier+ break; 5926*14414594SDavid du Colombier+ } 5927*14414594SDavid du Colombier+ 5928*14414594SDavid du Colombier+ return m; 5929*14414594SDavid du Colombier+ } 5930*14414594SDavid du Colombier+ 5931*14414594SDavid du Colombier+ int 5932*14414594SDavid du Colombier+ u9p_m_m2d (struct mbuf **m, struct u9fsdir *f) 5933*14414594SDavid du Colombier+ { 5934*14414594SDavid du Colombier+ u_char *p; 5935*14414594SDavid du Colombier+ 5936*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->dir_name)+sizeof(f->dir_uid)+sizeof(f->dir_gid)); 5937*14414594SDavid du Colombier+ N2HSTRING(f->dir_name, sizeof(f->dir_name)); 5938*14414594SDavid du Colombier+ N2HSTRING(f->dir_uid, sizeof(f->dir_uid)); 5939*14414594SDavid du Colombier+ N2HSTRING(f->dir_gid, sizeof(f->dir_gid)); 5940*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->dir_name)+sizeof(f->dir_uid)+sizeof(f->dir_gid)); 5941*14414594SDavid du Colombier+ 5942*14414594SDavid du Colombier+ U9P_PULLUP(m, sizeof(f->dir_qid)+sizeof(f->dir_mode) 5943*14414594SDavid du Colombier+ +sizeof(f->dir_atime)+sizeof(f->dir_mtime) 5944*14414594SDavid du Colombier+ +sizeof(f->dir_length)+sizeof(f->dir_type)+sizeof(f->dir_dev)); 5945*14414594SDavid du Colombier+ N2HLONG(f->dir_qid.path); 5946*14414594SDavid du Colombier+ N2HLONG(f->dir_qid.vers); 5947*14414594SDavid du Colombier+ N2HLONG(f->dir_mode); 5948*14414594SDavid du Colombier+ N2HLONG(f->dir_atime); 5949*14414594SDavid du Colombier+ N2HLONG(f->dir_mtime); 5950*14414594SDavid du Colombier+ N2HQUAD(f->dir_length); 5951*14414594SDavid du Colombier+ N2HSHORT(f->dir_type); 5952*14414594SDavid du Colombier+ N2HSHORT(f->dir_dev); 5953*14414594SDavid du Colombier+ U9P_ADJ(m, sizeof(f->dir_qid)+sizeof(f->dir_mode) 5954*14414594SDavid du Colombier+ +sizeof(f->dir_atime)+sizeof(f->dir_mtime) 5955*14414594SDavid du Colombier+ +sizeof(f->dir_length)+sizeof(f->dir_type)+sizeof(f->dir_dev)); 5956*14414594SDavid du Colombier+ 5957*14414594SDavid du Colombier+ return 0; 5958*14414594SDavid du Colombier+ } 5959*14414594SDavid du Colombier+ 5960*14414594SDavid du Colombier+ struct mbuf * u9p_m_d2m (struct u9fsdir *f) 5961*14414594SDavid du Colombier+ { 5962*14414594SDavid du Colombier+ char * ap; 5963*14414594SDavid du Colombier+ struct mbuf * m; 5964*14414594SDavid du Colombier+ MGET(m, M_WAIT, MT_DATA); 5965*14414594SDavid du Colombier+ MCLGET(m, M_WAIT); 5966*14414594SDavid du Colombier+ m->m_len = 0; 5967*14414594SDavid du Colombier+ 5968*14414594SDavid du Colombier+ if ( M_TRAILINGSPACE(m) < sizeof(struct u9fsdir) ) 5969*14414594SDavid du Colombier+ panic("u9p_m_d2m"); 5970*14414594SDavid du Colombier+ 5971*14414594SDavid du Colombier+ ap = mtod(m, char *); 5972*14414594SDavid du Colombier+ m->m_len = u9p_d2m(f, ap); 5973*14414594SDavid du Colombier+ 5974*14414594SDavid du Colombier+ return m; 5975*14414594SDavid du Colombier+ } 5976*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/9p.h ./9fs/9p.h 5977*14414594SDavid du Colombier*** /usr/src/sys/9fs/9p.h Wed Dec 31 19:00:00 1969 5978*14414594SDavid du Colombier--- ./9fs/9p.h Thu Nov 25 15:45:46 1999 5979*14414594SDavid du Colombier*************** 5980*14414594SDavid du Colombier*** 0 **** 5981*14414594SDavid du Colombier--- 1,183 ---- 5982*14414594SDavid du Colombier+ #ifndef _9FS_9P_H_ 5983*14414594SDavid du Colombier+ #define _9FS_9P_H_ 5984*14414594SDavid du Colombier+ 5985*14414594SDavid du Colombier+ 5986*14414594SDavid du Colombier+ #define U9FS_AUTHLEN 13 5987*14414594SDavid du Colombier+ #define U9FS_NAMELEN 28 5988*14414594SDavid du Colombier+ #define U9FS_TICKETLEN 72 5989*14414594SDavid du Colombier+ #define U9FS_ERRLEN 64 5990*14414594SDavid du Colombier+ #define U9FS_DOMLEN 48 5991*14414594SDavid du Colombier+ #define U9FS_CHALLEN 8 5992*14414594SDavid du Colombier+ #define U9FS_DIRLEN 116 5993*14414594SDavid du Colombier+ #define U9FS_MAXFDATA 8192 5994*14414594SDavid du Colombier+ #define U9FS_MAXDDATA (((int)U9FS_MAXFDATA/U9FS_DIRLEN)*U9FS_DIRLEN) 5995*14414594SDavid du Colombier+ 5996*14414594SDavid du Colombier+ #define U9P_MODE_RD 0x0 5997*14414594SDavid du Colombier+ #define U9P_MODE_WR 0x1 5998*14414594SDavid du Colombier+ #define U9P_MODE_RDWR 0x2 5999*14414594SDavid du Colombier+ #define U9P_MODE_EX 0x3 6000*14414594SDavid du Colombier+ #define U9P_MODE_TRUNC 0x10 6001*14414594SDavid du Colombier+ #define U9P_MODE_CLOSE 0x40 6002*14414594SDavid du Colombier+ 6003*14414594SDavid du Colombier+ #define U9P_PERM_CHDIR(m) (0x80000000&(m)) 6004*14414594SDavid du Colombier+ #define U9P_PERM_OWNER(m) ((m)&0x7) 6005*14414594SDavid du Colombier+ #define U9P_PERM_GROUP(m) (((m)>>3)&0x7) 6006*14414594SDavid du Colombier+ #define U9P_PERM_OTHER(m) (((m)>>6)&0x7) 6007*14414594SDavid du Colombier+ #define U9P_PERM_ALL(m) ((m)&0777) 6008*14414594SDavid du Colombier+ #define U9P_PERM_EXCL(m) ((m)&0x20000000) 6009*14414594SDavid du Colombier+ #define U9P_PERM_APPEND(m) ((m)&0x40000000) 6010*14414594SDavid du Colombier+ #define U9P_PERM_NONPERM(m) ((m)&0xfffffe00) 6011*14414594SDavid du Colombier+ 6012*14414594SDavid du Colombier+ /* this is too small */ 6013*14414594SDavid du Colombier+ typedef u_int32_t u9fsfh_t; 6014*14414594SDavid du Colombier+ 6015*14414594SDavid du Colombier+ struct u9fs_qid { 6016*14414594SDavid du Colombier+ u9fsfh_t path; 6017*14414594SDavid du Colombier+ u_int32_t vers; 6018*14414594SDavid du Colombier+ }; 6019*14414594SDavid du Colombier+ 6020*14414594SDavid du Colombier+ struct u9fsreq { 6021*14414594SDavid du Colombier+ TAILQ_ENTRY(u9fsreq) r_chain; 6022*14414594SDavid du Colombier+ struct u9fsreq * r_rep; 6023*14414594SDavid du Colombier+ struct mbuf * r_mrep; 6024*14414594SDavid du Colombier+ struct proc *r_procp; /* Proc that did I/O system call */ 6025*14414594SDavid du Colombier+ struct u9fsmount *r_nmp; 6026*14414594SDavid du Colombier+ 6027*14414594SDavid du Colombier+ /* actual content of the 9P message */ 6028*14414594SDavid du Colombier+ char r_type; 6029*14414594SDavid du Colombier+ short r_fid; 6030*14414594SDavid du Colombier+ u_short r_tag; 6031*14414594SDavid du Colombier+ union { 6032*14414594SDavid du Colombier+ struct { 6033*14414594SDavid du Colombier+ u_short oldtag; /* Tflush */ 6034*14414594SDavid du Colombier+ struct u9fs_qid qid; /* Rattach, Rwalk, Ropen, Rcreate */ 6035*14414594SDavid du Colombier+ char rauth[U9FS_AUTHLEN]; /* Rattach */ 6036*14414594SDavid du Colombier+ } u1; 6037*14414594SDavid du Colombier+ struct { 6038*14414594SDavid du Colombier+ char uname[U9FS_NAMELEN]; /* Tattach */ 6039*14414594SDavid du Colombier+ char aname[U9FS_NAMELEN]; /* Tattach */ 6040*14414594SDavid du Colombier+ char ticket[U9FS_TICKETLEN]; /* Tattach */ 6041*14414594SDavid du Colombier+ char auth[U9FS_AUTHLEN]; /* Tattach */ 6042*14414594SDavid du Colombier+ } u2; 6043*14414594SDavid du Colombier+ struct { 6044*14414594SDavid du Colombier+ char ename[U9FS_ERRLEN]; /* Rerror */ 6045*14414594SDavid du Colombier+ char authid[U9FS_NAMELEN]; /* Rsession */ 6046*14414594SDavid du Colombier+ char authdom[U9FS_DOMLEN]; /* Rsession */ 6047*14414594SDavid du Colombier+ char chal[U9FS_CHALLEN]; /* Tsession/Rsession */ 6048*14414594SDavid du Colombier+ } u3; 6049*14414594SDavid du Colombier+ struct { 6050*14414594SDavid du Colombier+ u_int32_t perm; /* Tcreate */ 6051*14414594SDavid du Colombier+ short newfid; /* Tclone, Tclwalk */ 6052*14414594SDavid du Colombier+ char name[U9FS_NAMELEN]; /* Twalk, Tclwalk, Tcreate */ 6053*14414594SDavid du Colombier+ char mode; /* Tcreate, Topen */ 6054*14414594SDavid du Colombier+ } u4; 6055*14414594SDavid du Colombier+ struct { 6056*14414594SDavid du Colombier+ u_int64_t offset; /* Tread, Twrite */ 6057*14414594SDavid du Colombier+ u_short count; /* Tread, Twrite, Rread */ 6058*14414594SDavid du Colombier+ char *data; /* Twrite, Rread */ 6059*14414594SDavid du Colombier+ } u5; 6060*14414594SDavid du Colombier+ char stat[U9FS_DIRLEN]; /* Twstat, Rstat */ 6061*14414594SDavid du Colombier+ } u; 6062*14414594SDavid du Colombier+ }; 6063*14414594SDavid du Colombier+ 6064*14414594SDavid du Colombier+ #define r_oldtag u.u1.oldtag 6065*14414594SDavid du Colombier+ #define r_qid u.u1.qid 6066*14414594SDavid du Colombier+ #define r_rauth u.u1.rauth 6067*14414594SDavid du Colombier+ #define r_uname u.u2.uname 6068*14414594SDavid du Colombier+ #define r_aname u.u2.aname 6069*14414594SDavid du Colombier+ #define r_ticket u.u2.ticket 6070*14414594SDavid du Colombier+ #define r_auth u.u2.auth 6071*14414594SDavid du Colombier+ #define r_ename u.u3.ename 6072*14414594SDavid du Colombier+ #define r_authid u.u3.authid 6073*14414594SDavid du Colombier+ #define r_authdom u.u3.authdom 6074*14414594SDavid du Colombier+ #define r_chal u.u3.chal 6075*14414594SDavid du Colombier+ #define r_perm u.u4.perm 6076*14414594SDavid du Colombier+ #define r_newfid u.u4.newfid 6077*14414594SDavid du Colombier+ #define r_name u.u4.name 6078*14414594SDavid du Colombier+ #define r_mode u.u4.mode 6079*14414594SDavid du Colombier+ #define r_offset u.u5.offset 6080*14414594SDavid du Colombier+ #define r_count u.u5.count 6081*14414594SDavid du Colombier+ #define r_data u.u5.data 6082*14414594SDavid du Colombier+ #define r_stat u.stat 6083*14414594SDavid du Colombier+ 6084*14414594SDavid du Colombier+ struct u9fsdir { 6085*14414594SDavid du Colombier+ char dir_name[U9FS_NAMELEN]; 6086*14414594SDavid du Colombier+ char dir_uid[U9FS_NAMELEN]; 6087*14414594SDavid du Colombier+ char dir_gid[U9FS_NAMELEN]; 6088*14414594SDavid du Colombier+ struct u9fs_qid dir_qid; 6089*14414594SDavid du Colombier+ u_int32_t dir_mode; 6090*14414594SDavid du Colombier+ u_int32_t dir_atime; 6091*14414594SDavid du Colombier+ u_int32_t dir_mtime; 6092*14414594SDavid du Colombier+ union { 6093*14414594SDavid du Colombier+ u_int64_t length; 6094*14414594SDavid du Colombier+ struct { /* little endian */ 6095*14414594SDavid du Colombier+ u_int32_t llength; 6096*14414594SDavid du Colombier+ u_int32_t hlength; 6097*14414594SDavid du Colombier+ } l; 6098*14414594SDavid du Colombier+ } u; 6099*14414594SDavid du Colombier+ u_short dir_type; 6100*14414594SDavid du Colombier+ u_short dir_dev; 6101*14414594SDavid du Colombier+ }; 6102*14414594SDavid du Colombier+ 6103*14414594SDavid du Colombier+ #define dir_length u.length 6104*14414594SDavid du Colombier+ #define dir_llength u.l.llength 6105*14414594SDavid du Colombier+ #define dir_hlength u.l.hlength 6106*14414594SDavid du Colombier+ 6107*14414594SDavid du Colombier+ enum 6108*14414594SDavid du Colombier+ { 6109*14414594SDavid du Colombier+ Tnop = 50, 6110*14414594SDavid du Colombier+ Rnop, 6111*14414594SDavid du Colombier+ Tosession = 52, /* illegal */ 6112*14414594SDavid du Colombier+ Rosession, /* illegal */ 6113*14414594SDavid du Colombier+ Terror = 54, /* illegal */ 6114*14414594SDavid du Colombier+ Rerror, 6115*14414594SDavid du Colombier+ Tflush = 56, 6116*14414594SDavid du Colombier+ Rflush, 6117*14414594SDavid du Colombier+ Toattach = 58, /* illegal */ 6118*14414594SDavid du Colombier+ Roattach, /* illegal */ 6119*14414594SDavid du Colombier+ Tclone = 60, 6120*14414594SDavid du Colombier+ Rclone, 6121*14414594SDavid du Colombier+ Twalk = 62, 6122*14414594SDavid du Colombier+ Rwalk, 6123*14414594SDavid du Colombier+ Topen = 64, 6124*14414594SDavid du Colombier+ Ropen, 6125*14414594SDavid du Colombier+ Tcreate = 66, 6126*14414594SDavid du Colombier+ Rcreate, 6127*14414594SDavid du Colombier+ Tread = 68, 6128*14414594SDavid du Colombier+ Rread, 6129*14414594SDavid du Colombier+ Twrite = 70, 6130*14414594SDavid du Colombier+ Rwrite, 6131*14414594SDavid du Colombier+ Tclunk = 72, 6132*14414594SDavid du Colombier+ Rclunk, 6133*14414594SDavid du Colombier+ Tremove = 74, 6134*14414594SDavid du Colombier+ Rremove, 6135*14414594SDavid du Colombier+ Tstat = 76, 6136*14414594SDavid du Colombier+ Rstat, 6137*14414594SDavid du Colombier+ Twstat = 78, 6138*14414594SDavid du Colombier+ Rwstat, 6139*14414594SDavid du Colombier+ Tclwalk = 80, 6140*14414594SDavid du Colombier+ Rclwalk, 6141*14414594SDavid du Colombier+ Tauth = 82, /* illegal */ 6142*14414594SDavid du Colombier+ Rauth, /* illegal */ 6143*14414594SDavid du Colombier+ Tsession = 84, 6144*14414594SDavid du Colombier+ Rsession, 6145*14414594SDavid du Colombier+ Tattach = 86, 6146*14414594SDavid du Colombier+ Rattach, 6147*14414594SDavid du Colombier+ Ttunnel = 88, 6148*14414594SDavid du Colombier+ Rtunnel, 6149*14414594SDavid du Colombier+ Tmax 6150*14414594SDavid du Colombier+ }; 6151*14414594SDavid du Colombier+ 6152*14414594SDavid du Colombier+ int u9p_m2s __P((char *ap, int n, struct u9fsreq *f)); 6153*14414594SDavid du Colombier+ int u9p_s2m __P((struct u9fsreq *f, char *ap, int copydata)); 6154*14414594SDavid du Colombier+ int u9p_m2d __P((char *ap, struct u9fsdir *f)); 6155*14414594SDavid du Colombier+ int u9p_d2m __P((struct u9fsdir *f, char *ap)); 6156*14414594SDavid du Colombier+ int u9p_type __P((char * t)); 6157*14414594SDavid du Colombier+ 6158*14414594SDavid du Colombier+ int u9p_m_m2s __P((struct mbuf **m, struct u9fsreq *f)); 6159*14414594SDavid du Colombier+ struct mbuf * u9p_m_s2m __P((struct u9fsreq *f)); 6160*14414594SDavid du Colombier+ int u9p_m_m2d __P((struct mbuf **m, struct u9fsdir *f)); 6161*14414594SDavid du Colombier+ struct mbuf * u9p_m_d2m __P((struct u9fsdir *f)); 6162*14414594SDavid du Colombier+ u_short u9p_m_tag __P((struct mbuf **m)); 6163*14414594SDavid du Colombier+ 6164*14414594SDavid du Colombier+ #endif 6165*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/9fs/bitstring.h ./9fs/bitstring.h 6166*14414594SDavid du Colombier*** /usr/src/sys/9fs/bitstring.h Wed Dec 31 19:00:00 1969 6167*14414594SDavid du Colombier--- ./9fs/bitstring.h Thu Oct 21 12:34:50 1999 6168*14414594SDavid du Colombier*************** 6169*14414594SDavid du Colombier*** 0 **** 6170*14414594SDavid du Colombier--- 1,143 ---- 6171*14414594SDavid du Colombier+ /* 6172*14414594SDavid du Colombier+ * Copyright (c) 1989, 1993 6173*14414594SDavid du Colombier+ * The Regents of the University of California. All rights reserved. 6174*14414594SDavid du Colombier+ * 6175*14414594SDavid du Colombier+ * This code is derived from software contributed to Berkeley by 6176*14414594SDavid du Colombier+ * Paul Vixie. 6177*14414594SDavid du Colombier+ * 6178*14414594SDavid du Colombier+ * Redistribution and use in source and binary forms, with or without 6179*14414594SDavid du Colombier+ * modification, are permitted provided that the following conditions 6180*14414594SDavid du Colombier+ * are met: 6181*14414594SDavid du Colombier+ * 1. Redistributions of source code must retain the above copyright 6182*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer. 6183*14414594SDavid du Colombier+ * 2. Redistributions in binary form must reproduce the above copyright 6184*14414594SDavid du Colombier+ * notice, this list of conditions and the following disclaimer in the 6185*14414594SDavid du Colombier+ * documentation and/or other materials provided with the distribution. 6186*14414594SDavid du Colombier+ * 3. All advertising materials mentioning features or use of this software 6187*14414594SDavid du Colombier+ * must display the following acknowledgement: 6188*14414594SDavid du Colombier+ * This product includes software developed by the University of 6189*14414594SDavid du Colombier+ * California, Berkeley and its contributors. 6190*14414594SDavid du Colombier+ * 4. Neither the name of the University nor the names of its contributors 6191*14414594SDavid du Colombier+ * may be used to endorse or promote products derived from this software 6192*14414594SDavid du Colombier+ * without specific prior written permission. 6193*14414594SDavid du Colombier+ * 6194*14414594SDavid du Colombier+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 6195*14414594SDavid du Colombier+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6196*14414594SDavid du Colombier+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6197*14414594SDavid du Colombier+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6198*14414594SDavid du Colombier+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6199*14414594SDavid du Colombier+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6200*14414594SDavid du Colombier+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6201*14414594SDavid du Colombier+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6202*14414594SDavid du Colombier+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6203*14414594SDavid du Colombier+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6204*14414594SDavid du Colombier+ * SUCH DAMAGE. 6205*14414594SDavid du Colombier+ * 6206*14414594SDavid du Colombier+ * @(#)bitstring.h 8.1 (Berkeley) 7/19/93 6207*14414594SDavid du Colombier+ */ 6208*14414594SDavid du Colombier+ 6209*14414594SDavid du Colombier+ #ifndef _BITSTRING_H_ 6210*14414594SDavid du Colombier+ #define _BITSTRING_H_ 6211*14414594SDavid du Colombier+ 6212*14414594SDavid du Colombier+ typedef unsigned char bitstr_t; 6213*14414594SDavid du Colombier+ 6214*14414594SDavid du Colombier+ /* internal macros */ 6215*14414594SDavid du Colombier+ /* byte of the bitstring bit is in */ 6216*14414594SDavid du Colombier+ #define _bit_byte(bit) \ 6217*14414594SDavid du Colombier+ ((bit) >> 3) 6218*14414594SDavid du Colombier+ 6219*14414594SDavid du Colombier+ /* mask for the bit within its byte */ 6220*14414594SDavid du Colombier+ #define _bit_mask(bit) \ 6221*14414594SDavid du Colombier+ (1 << ((bit)&0x7)) 6222*14414594SDavid du Colombier+ 6223*14414594SDavid du Colombier+ /* external macros */ 6224*14414594SDavid du Colombier+ /* bytes in a bitstring of nbits bits */ 6225*14414594SDavid du Colombier+ #define bitstr_size(nbits) \ 6226*14414594SDavid du Colombier+ ((((nbits) - 1) >> 3) + 1) 6227*14414594SDavid du Colombier+ 6228*14414594SDavid du Colombier+ /* allocate a bitstring */ 6229*14414594SDavid du Colombier+ #define bit_alloc(space, nbits, type, flags) \ 6230*14414594SDavid du Colombier+ MALLOC((space), bitstr_t *, \ 6231*14414594SDavid du Colombier+ (u_int)bitstr_size(nbits)*sizeof(bitstr_t), (type), (flags)) 6232*14414594SDavid du Colombier+ 6233*14414594SDavid du Colombier+ /* allocate a bitstring on the stack */ 6234*14414594SDavid du Colombier+ #define bit_decl(name, nbits) \ 6235*14414594SDavid du Colombier+ (name)[bitstr_size(nbits)] 6236*14414594SDavid du Colombier+ 6237*14414594SDavid du Colombier+ /* is bit N of bitstring name set? */ 6238*14414594SDavid du Colombier+ #define bit_test(name, bit) \ 6239*14414594SDavid du Colombier+ ((name)[_bit_byte(bit)] & _bit_mask(bit)) 6240*14414594SDavid du Colombier+ 6241*14414594SDavid du Colombier+ /* set bit N of bitstring name */ 6242*14414594SDavid du Colombier+ #define bit_set(name, bit) \ 6243*14414594SDavid du Colombier+ (name)[_bit_byte(bit)] |= _bit_mask(bit) 6244*14414594SDavid du Colombier+ 6245*14414594SDavid du Colombier+ /* clear bit N of bitstring name */ 6246*14414594SDavid du Colombier+ #define bit_clear(name, bit) \ 6247*14414594SDavid du Colombier+ (name)[_bit_byte(bit)] &= ~_bit_mask(bit) 6248*14414594SDavid du Colombier+ 6249*14414594SDavid du Colombier+ /* clear bits start ... stop in bitstring */ 6250*14414594SDavid du Colombier+ #define bit_nclear(name, start, stop) { \ 6251*14414594SDavid du Colombier+ register bitstr_t *_name = name; \ 6252*14414594SDavid du Colombier+ register int _start = start, _stop = stop; \ 6253*14414594SDavid du Colombier+ register int _startbyte = _bit_byte(_start); \ 6254*14414594SDavid du Colombier+ register int _stopbyte = _bit_byte(_stop); \ 6255*14414594SDavid du Colombier+ if (_startbyte == _stopbyte) { \ 6256*14414594SDavid du Colombier+ _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \ 6257*14414594SDavid du Colombier+ (0xff << ((_stop&0x7) + 1))); \ 6258*14414594SDavid du Colombier+ } else { \ 6259*14414594SDavid du Colombier+ _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \ 6260*14414594SDavid du Colombier+ while (++_startbyte < _stopbyte) \ 6261*14414594SDavid du Colombier+ _name[_startbyte] = 0; \ 6262*14414594SDavid du Colombier+ _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \ 6263*14414594SDavid du Colombier+ } \ 6264*14414594SDavid du Colombier+ } 6265*14414594SDavid du Colombier+ 6266*14414594SDavid du Colombier+ /* set bits start ... stop in bitstring */ 6267*14414594SDavid du Colombier+ #define bit_nset(name, start, stop) { \ 6268*14414594SDavid du Colombier+ register bitstr_t *_name = name; \ 6269*14414594SDavid du Colombier+ register int _start = start, _stop = stop; \ 6270*14414594SDavid du Colombier+ register int _startbyte = _bit_byte(_start); \ 6271*14414594SDavid du Colombier+ register int _stopbyte = _bit_byte(_stop); \ 6272*14414594SDavid du Colombier+ if (_startbyte == _stopbyte) { \ 6273*14414594SDavid du Colombier+ _name[_startbyte] |= ((0xff << (_start&0x7)) & \ 6274*14414594SDavid du Colombier+ (0xff >> (7 - (_stop&0x7)))); \ 6275*14414594SDavid du Colombier+ } else { \ 6276*14414594SDavid du Colombier+ _name[_startbyte] |= 0xff << ((_start)&0x7); \ 6277*14414594SDavid du Colombier+ while (++_startbyte < _stopbyte) \ 6278*14414594SDavid du Colombier+ _name[_startbyte] = 0xff; \ 6279*14414594SDavid du Colombier+ _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \ 6280*14414594SDavid du Colombier+ } \ 6281*14414594SDavid du Colombier+ } 6282*14414594SDavid du Colombier+ 6283*14414594SDavid du Colombier+ /* find first bit clear in name */ 6284*14414594SDavid du Colombier+ #define bit_ffc(name, nbits, value) { \ 6285*14414594SDavid du Colombier+ register bitstr_t *_name = name; \ 6286*14414594SDavid du Colombier+ register int _byte, _nbits = nbits; \ 6287*14414594SDavid du Colombier+ register int _stopbyte = _bit_byte(_nbits), _value = -1; \ 6288*14414594SDavid du Colombier+ for (_byte = 0; _byte <= _stopbyte; ++_byte) \ 6289*14414594SDavid du Colombier+ if (_name[_byte] != 0xff) { \ 6290*14414594SDavid du Colombier+ _value = _byte << 3; \ 6291*14414594SDavid du Colombier+ for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \ 6292*14414594SDavid du Colombier+ ++_value, _stopbyte >>= 1); \ 6293*14414594SDavid du Colombier+ break; \ 6294*14414594SDavid du Colombier+ } \ 6295*14414594SDavid du Colombier+ *(value) = _value; \ 6296*14414594SDavid du Colombier+ } 6297*14414594SDavid du Colombier+ 6298*14414594SDavid du Colombier+ /* find first bit set in name */ 6299*14414594SDavid du Colombier+ #define bit_ffs(name, nbits, value) { \ 6300*14414594SDavid du Colombier+ register bitstr_t *_name = name; \ 6301*14414594SDavid du Colombier+ register int _byte, _nbits = nbits; \ 6302*14414594SDavid du Colombier+ register int _stopbyte = _bit_byte(_nbits), _value = -1; \ 6303*14414594SDavid du Colombier+ for (_byte = 0; _byte <= _stopbyte; ++_byte) \ 6304*14414594SDavid du Colombier+ if (_name[_byte]) { \ 6305*14414594SDavid du Colombier+ _value = _byte << 3; \ 6306*14414594SDavid du Colombier+ for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \ 6307*14414594SDavid du Colombier+ ++_value, _stopbyte >>= 1); \ 6308*14414594SDavid du Colombier+ break; \ 6309*14414594SDavid du Colombier+ } \ 6310*14414594SDavid du Colombier+ *(value) = _value; \ 6311*14414594SDavid du Colombier+ } 6312*14414594SDavid du Colombier+ 6313*14414594SDavid du Colombier+ #endif /* !_BITSTRING_H_ */ 6314*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/conf/files ./conf/files 6315*14414594SDavid du Colombier*** /usr/src/sys/conf/files Fri Apr 30 15:32:40 1999 6316*14414594SDavid du Colombier--- ./conf/files Thu Nov 25 15:34:34 1999 6317*14414594SDavid du Colombier*************** 6318*14414594SDavid du Colombier*** 535,540 **** 6319*14414594SDavid du Colombier--- 535,541 ---- 6320*14414594SDavid du Colombier netinet/tcp_timer.c optional inet 6321*14414594SDavid du Colombier netinet/tcp_usrreq.c optional inet 6322*14414594SDavid du Colombier netinet/udp_usrreq.c optional inet 6323*14414594SDavid du Colombier+ netinet/il.c optional il 6324*14414594SDavid du Colombier netipx/ipx.c optional ipx 6325*14414594SDavid du Colombier netipx/ipx_cksum.c optional ipx 6326*14414594SDavid du Colombier netipx/ipx_input.c optional ipx 6327*14414594SDavid du Colombier*************** 6328*14414594SDavid du Colombier*** 571,576 **** 6329*14414594SDavid du Colombier--- 572,586 ---- 6330*14414594SDavid du Colombier nfs/nfs_syscalls.c optional nfs 6331*14414594SDavid du Colombier nfs/nfs_vfsops.c optional nfs 6332*14414594SDavid du Colombier nfs/nfs_vnops.c optional nfs 6333*14414594SDavid du Colombier+ 9fs/9fs_vfsops.c optional u9fs 6334*14414594SDavid du Colombier+ 9fs/9fs_vnops.c optional u9fs 6335*14414594SDavid du Colombier+ 9fs/9p.c optional u9fs 6336*14414594SDavid du Colombier+ 9fs/9auth.c optional u9fs 6337*14414594SDavid du Colombier+ 9fs/9crypt.c optional u9fs 6338*14414594SDavid du Colombier+ 9fs/9fs_subr.c optional u9fs 6339*14414594SDavid du Colombier+ 9fs/9fs_socket.c optional u9fs 6340*14414594SDavid du Colombier+ 9fs/9fs_bio.c optional u9fs 6341*14414594SDavid du Colombier+ 9fs/9fs_node.c optional u9fs 6342*14414594SDavid du Colombier nfs/bootp_subr.c optional bootp 6343*14414594SDavid du Colombier nfs/krpc_subr.c optional bootp 6344*14414594SDavid du Colombier pccard/pccard.c optional card 6345*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/conf/options ./conf/options 6346*14414594SDavid du Colombier*** /usr/src/sys/conf/options Tue May 11 01:35:28 1999 6347*14414594SDavid du Colombier--- ./conf/options Mon Oct 11 19:59:14 1999 6348*14414594SDavid du Colombier*************** 6349*14414594SDavid du Colombier*** 202,207 **** 6350*14414594SDavid du Colombier--- 202,208 ---- 6351*14414594SDavid du Colombier BRIDGE opt_bdg.h 6352*14414594SDavid du Colombier MROUTING opt_mrouting.h 6353*14414594SDavid du Colombier INET opt_inet.h 6354*14414594SDavid du Colombier+ IL opt_inet.h 6355*14414594SDavid du Colombier IPDIVERT 6356*14414594SDavid du Colombier DUMMYNET opt_ipdn.h 6357*14414594SDavid du Colombier IPFIREWALL opt_ipfw.h 6358*14414594SDavid du Colombier*************** 6359*14414594SDavid du Colombier*** 314,319 **** 6360*14414594SDavid du Colombier--- 315,322 ---- 6361*14414594SDavid du Colombier NFS_MUIDHASHSIZ opt_nfs.h 6362*14414594SDavid du Colombier NFS_NOSERVER opt_nfs.h 6363*14414594SDavid du Colombier NFS_DEBUG opt_nfs.h 6364*14414594SDavid du Colombier+ 6365*14414594SDavid du Colombier+ U9FS 6366*14414594SDavid du Colombier 6367*14414594SDavid du Colombier # give bktr an opt_bktr.h file 6368*14414594SDavid du Colombier OVERRIDE_CARD opt_bktr.h 6369*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/i386/conf/IL ./i386/conf/IL 6370*14414594SDavid du Colombier*** /usr/src/sys/i386/conf/IL Wed Dec 31 19:00:00 1969 6371*14414594SDavid du Colombier--- ./i386/conf/IL Sat Oct 23 14:01:36 1999 6372*14414594SDavid du Colombier*************** 6373*14414594SDavid du Colombier*** 0 **** 6374*14414594SDavid du Colombier--- 1,234 ---- 6375*14414594SDavid du Colombier+ # 6376*14414594SDavid du Colombier+ # GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks 6377*14414594SDavid du Colombier+ # 6378*14414594SDavid du Colombier+ # For more information read the handbook part System Administration -> 6379*14414594SDavid du Colombier+ # Configuring the FreeBSD Kernel -> The Configuration File. 6380*14414594SDavid du Colombier+ # The handbook is available in /usr/share/doc/handbook or online as 6381*14414594SDavid du Colombier+ # latest version from the FreeBSD World Wide Web server 6382*14414594SDavid du Colombier+ # <URL:http://www.FreeBSD.ORG/> 6383*14414594SDavid du Colombier+ # 6384*14414594SDavid du Colombier+ # An exhaustive list of options and more detailed explanations of the 6385*14414594SDavid du Colombier+ # device lines is present in the ./LINT configuration file. If you are 6386*14414594SDavid du Colombier+ # in doubt as to the purpose or necessity of a line, check first in LINT. 6387*14414594SDavid du Colombier+ # 6388*14414594SDavid du Colombier+ # $Id: GENERIC,v 1.143.2.2 1999/02/15 02:50:07 des Exp $ 6389*14414594SDavid du Colombier+ 6390*14414594SDavid du Colombier+ machine "i386" 6391*14414594SDavid du Colombier+ cpu "I586_CPU" 6392*14414594SDavid du Colombier+ cpu "I686_CPU" 6393*14414594SDavid du Colombier+ ident GENERIC 6394*14414594SDavid du Colombier+ maxusers 128 6395*14414594SDavid du Colombier+ 6396*14414594SDavid du Colombier+ #options DDB 6397*14414594SDavid du Colombier+ options IL # plan9's IL 6398*14414594SDavid du Colombier+ options "U9FS" # plan9's 9fs client 6399*14414594SDavid du Colombier+ options INET #InterNETworking 6400*14414594SDavid du Colombier+ options FFS #Berkeley Fast Filesystem 6401*14414594SDavid du Colombier+ options FFS_ROOT #FFS usable as root device [keep this!] 6402*14414594SDavid du Colombier+ options MFS #Memory Filesystem 6403*14414594SDavid du Colombier+ options MFS_ROOT #MFS usable as root device, "MFS" req'ed 6404*14414594SDavid du Colombier+ options NFS #Network Filesystem 6405*14414594SDavid du Colombier+ options NFS_ROOT #NFS usable as root device, "NFS" req'ed 6406*14414594SDavid du Colombier+ options "CD9660" #ISO 9660 Filesystem 6407*14414594SDavid du Colombier+ options "CD9660_ROOT" #CD-ROM usable as root. "CD9660" req'ed 6408*14414594SDavid du Colombier+ options PROCFS #Process filesystem 6409*14414594SDavid du Colombier+ options FDESC #File descriptor filesystem 6410*14414594SDavid du Colombier+ options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] 6411*14414594SDavid du Colombier+ options SCSI_DELAY=15000 #Be pessimistic about Joe SCSI device 6412*14414594SDavid du Colombier+ options UCONSOLE #Allow users to grab the console 6413*14414594SDavid du Colombier+ options FAILSAFE #Be conservative 6414*14414594SDavid du Colombier+ options USERCONFIG #boot -c editor 6415*14414594SDavid du Colombier+ options VISUAL_USERCONFIG #visual boot -c editor 6416*14414594SDavid du Colombier+ options NMBCLUSTERS=4096 6417*14414594SDavid du Colombier+ options MAXFILES=10000 6418*14414594SDavid du Colombier+ 6419*14414594SDavid du Colombier+ config kernel root on wd0 6420*14414594SDavid du Colombier+ 6421*14414594SDavid du Colombier+ # To make an SMP kernel, the next two are needed 6422*14414594SDavid du Colombier+ #options SMP # Symmetric MultiProcessor Kernel 6423*14414594SDavid du Colombier+ #options APIC_IO # Symmetric (APIC) I/O 6424*14414594SDavid du Colombier+ # Optionally these may need tweaked, (defaults shown): 6425*14414594SDavid du Colombier+ #options NCPU=2 # number of CPUs 6426*14414594SDavid du Colombier+ #options NBUS=4 # number of busses 6427*14414594SDavid du Colombier+ #options NAPIC=1 # number of IO APICs 6428*14414594SDavid du Colombier+ #options NINTR=24 # number of INTs 6429*14414594SDavid du Colombier+ 6430*14414594SDavid du Colombier+ controller isa0 6431*14414594SDavid du Colombier+ controller eisa0 6432*14414594SDavid du Colombier+ controller pci0 6433*14414594SDavid du Colombier+ 6434*14414594SDavid du Colombier+ controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 6435*14414594SDavid du Colombier+ disk fd0 at fdc0 drive 0 6436*14414594SDavid du Colombier+ disk fd1 at fdc0 drive 1 6437*14414594SDavid du Colombier+ 6438*14414594SDavid du Colombier+ options "CMD640" # work around CMD640 chip deficiency 6439*14414594SDavid du Colombier+ controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0xa0ff vector wdintr 6440*14414594SDavid du Colombier+ disk wd0 at wdc0 drive 0 6441*14414594SDavid du Colombier+ disk wd1 at wdc0 drive 1 6442*14414594SDavid du Colombier+ 6443*14414594SDavid du Colombier+ controller wdc1 at isa? port "IO_WD2" bio irq 15 flags 0xa0ff vector wdintr 6444*14414594SDavid du Colombier+ disk wd2 at wdc1 drive 0 6445*14414594SDavid du Colombier+ disk wd3 at wdc1 drive 1 6446*14414594SDavid du Colombier+ 6447*14414594SDavid du Colombier+ options ATAPI #Enable ATAPI support for IDE bus 6448*14414594SDavid du Colombier+ options ATAPI_STATIC #Don't do it as an LKM 6449*14414594SDavid du Colombier+ #device acd0 #IDE CD-ROM 6450*14414594SDavid du Colombier+ #device wfd0 #IDE Floppy (e.g. LS-120) 6451*14414594SDavid du Colombier+ 6452*14414594SDavid du Colombier+ # A single entry for any of these controllers (ncr, ahb, ahc) is 6453*14414594SDavid du Colombier+ # sufficient for any number of installed devices. 6454*14414594SDavid du Colombier+ #controller ncr0 6455*14414594SDavid du Colombier+ #controller ahb0 6456*14414594SDavid du Colombier+ #controller ahc0 6457*14414594SDavid du Colombier+ #controller isp0 6458*14414594SDavid du Colombier+ 6459*14414594SDavid du Colombier+ # This controller offers a number of configuration options, too many to 6460*14414594SDavid du Colombier+ # document here - see the LINT file in this directory and look up the 6461*14414594SDavid du Colombier+ # dpt0 entry there for much fuller documentation on this. 6462*14414594SDavid du Colombier+ controller dpt0 6463*14414594SDavid du Colombier+ 6464*14414594SDavid du Colombier+ #controller adv0 at isa? port ? cam irq ? 6465*14414594SDavid du Colombier+ #controller adw0 6466*14414594SDavid du Colombier+ #controller bt0 at isa? port ? cam irq ? 6467*14414594SDavid du Colombier+ #controller aha0 at isa? port ? cam irq ? 6468*14414594SDavid du Colombier+ #controller aic0 at isa? port 0x340 bio irq 11 6469*14414594SDavid du Colombier+ 6470*14414594SDavid du Colombier+ controller scbus0 6471*14414594SDavid du Colombier+ 6472*14414594SDavid du Colombier+ device da0 6473*14414594SDavid du Colombier+ 6474*14414594SDavid du Colombier+ device sa0 6475*14414594SDavid du Colombier+ 6476*14414594SDavid du Colombier+ device pass0 6477*14414594SDavid du Colombier+ 6478*14414594SDavid du Colombier+ device cd0 #Only need one of these, the code dynamically grows 6479*14414594SDavid du Colombier+ 6480*14414594SDavid du Colombier+ #device wt0 at isa? port 0x300 bio irq 5 drq 1 6481*14414594SDavid du Colombier+ #device mcd0 at isa? port 0x300 bio irq 10 6482*14414594SDavid du Colombier+ 6483*14414594SDavid du Colombier+ #controller matcd0 at isa? port 0x230 bio 6484*14414594SDavid du Colombier+ 6485*14414594SDavid du Colombier+ #device scd0 at isa? port 0x230 bio 6486*14414594SDavid du Colombier+ 6487*14414594SDavid du Colombier+ # atkbdc0 controlls both the keyboard and the PS/2 mouse 6488*14414594SDavid du Colombier+ controller atkbdc0 at isa? port IO_KBD tty 6489*14414594SDavid du Colombier+ device atkbd0 at isa? tty irq 1 6490*14414594SDavid du Colombier+ device psm0 at isa? tty irq 12 6491*14414594SDavid du Colombier+ 6492*14414594SDavid du Colombier+ device vga0 at isa? port ? conflicts 6493*14414594SDavid du Colombier+ 6494*14414594SDavid du Colombier+ # splash screen/screen saver 6495*14414594SDavid du Colombier+ pseudo-device splash 6496*14414594SDavid du Colombier+ 6497*14414594SDavid du Colombier+ # syscons is the default console driver, resembling an SCO console 6498*14414594SDavid du Colombier+ device sc0 at isa? tty 6499*14414594SDavid du Colombier+ # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver 6500*14414594SDavid du Colombier+ #device vt0 at isa? tty 6501*14414594SDavid du Colombier+ #options XSERVER # support for X server 6502*14414594SDavid du Colombier+ #options FAT_CURSOR # start with block cursor 6503*14414594SDavid du Colombier+ # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines 6504*14414594SDavid du Colombier+ #options PCVT_SCANSET=2 # IBM keyboards are non-std 6505*14414594SDavid du Colombier+ 6506*14414594SDavid du Colombier+ device npx0 at isa? port IO_NPX irq 13 6507*14414594SDavid du Colombier+ 6508*14414594SDavid du Colombier+ # 6509*14414594SDavid du Colombier+ # Laptop support (see LINT for more options) 6510*14414594SDavid du Colombier+ # 6511*14414594SDavid du Colombier+ device apm0 at isa? disable flags 0x31 # Advanced Power Management 6512*14414594SDavid du Colombier+ 6513*14414594SDavid du Colombier+ # PCCARD (PCMCIA) support 6514*14414594SDavid du Colombier+ #controller card0 6515*14414594SDavid du Colombier+ #device pcic0 at card? 6516*14414594SDavid du Colombier+ #device pcic1 at card? 6517*14414594SDavid du Colombier+ 6518*14414594SDavid du Colombier+ device sio0 at isa? port "IO_COM1" flags 0x10 tty irq 4 6519*14414594SDavid du Colombier+ device sio1 at isa? port "IO_COM2" tty irq 3 6520*14414594SDavid du Colombier+ device sio2 at isa? disable port "IO_COM3" tty irq 5 6521*14414594SDavid du Colombier+ device sio3 at isa? disable port "IO_COM4" tty irq 9 6522*14414594SDavid du Colombier+ 6523*14414594SDavid du Colombier+ # Parallel port 6524*14414594SDavid du Colombier+ device ppc0 at isa? port? net irq 7 6525*14414594SDavid du Colombier+ controller ppbus0 6526*14414594SDavid du Colombier+ device nlpt0 at ppbus? 6527*14414594SDavid du Colombier+ device plip0 at ppbus? 6528*14414594SDavid du Colombier+ device ppi0 at ppbus? 6529*14414594SDavid du Colombier+ #controller vpo0 at ppbus? 6530*14414594SDavid du Colombier+ 6531*14414594SDavid du Colombier+ # 6532*14414594SDavid du Colombier+ # The following Ethernet NICs are all PCI devices. 6533*14414594SDavid du Colombier+ # 6534*14414594SDavid du Colombier+ device ax0 # ASIX AX88140A 6535*14414594SDavid du Colombier+ device de0 # DEC/Intel DC21x4x (``Tulip'') 6536*14414594SDavid du Colombier+ device fxp0 # Intel EtherExpress PRO/100B (82557, 82558) 6537*14414594SDavid du Colombier+ device mx0 # Macronix 98713/98715/98725 (``PMAC'') 6538*14414594SDavid du Colombier+ device pn0 # Lite-On 82c168/82c169 (``PNIC'') 6539*14414594SDavid du Colombier+ device rl0 # RealTek 8129/8139 6540*14414594SDavid du Colombier+ device tl0 # Texas Instruments ThunderLAN 6541*14414594SDavid du Colombier+ device tx0 # SMC 9432TX (83c170 ``EPIC'') 6542*14414594SDavid du Colombier+ device vr0 # VIA Rhine, Rhine II 6543*14414594SDavid du Colombier+ device vx0 # 3Com 3c590, 3c595 (``Vortex'') 6544*14414594SDavid du Colombier+ device wb0 # Winbond W89C840F 6545*14414594SDavid du Colombier+ device xl0 # 3Com 3c90x (``Boomerang'', ``Cyclone'') 6546*14414594SDavid du Colombier+ 6547*14414594SDavid du Colombier+ # Order is important here due to intrusive probes, do *not* alphabetize 6548*14414594SDavid du Colombier+ # this list of network interfaces until the probes have been fixed. 6549*14414594SDavid du Colombier+ # Right now it appears that the ie0 must be probed before ep0. See 6550*14414594SDavid du Colombier+ # revision 1.20 of this file. 6551*14414594SDavid du Colombier+ 6552*14414594SDavid du Colombier+ #device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 6553*14414594SDavid du Colombier+ #device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 6554*14414594SDavid du Colombier+ #device ep0 at isa? port 0x300 net irq 10 6555*14414594SDavid du Colombier+ #device ex0 at isa? port? net irq? 6556*14414594SDavid du Colombier+ #device fe0 at isa? port 0x300 net irq ? 6557*14414594SDavid du Colombier+ #device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 6558*14414594SDavid du Colombier+ #device lnc0 at isa? port 0x280 net irq 10 drq 0 6559*14414594SDavid du Colombier+ #device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 6560*14414594SDavid du Colombier+ #device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 6561*14414594SDavid du Colombier+ #device cs0 at isa? port 0x300 net irq ? 6562*14414594SDavid du Colombier+ 6563*14414594SDavid du Colombier+ pseudo-device loop 6564*14414594SDavid du Colombier+ pseudo-device ether 6565*14414594SDavid du Colombier+ pseudo-device sl 1 6566*14414594SDavid du Colombier+ pseudo-device ppp 1 6567*14414594SDavid du Colombier+ pseudo-device tun 1 6568*14414594SDavid du Colombier+ pseudo-device pty 32 6569*14414594SDavid du Colombier+ pseudo-device gzip # Exec gzipped a.out's 6570*14414594SDavid du Colombier+ 6571*14414594SDavid du Colombier+ # KTRACE enables the system-call tracing facility ktrace(2). 6572*14414594SDavid du Colombier+ # This adds 4 KB bloat to your kernel, and slightly increases 6573*14414594SDavid du Colombier+ # the costs of each syscall. 6574*14414594SDavid du Colombier+ options KTRACE #kernel tracing 6575*14414594SDavid du Colombier+ 6576*14414594SDavid du Colombier+ # This provides support for System V shared memory and message queues. 6577*14414594SDavid du Colombier+ # 6578*14414594SDavid du Colombier+ options SYSVSHM 6579*14414594SDavid du Colombier+ options SYSVMSG 6580*14414594SDavid du Colombier+ 6581*14414594SDavid du Colombier+ # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be 6582*14414594SDavid du Colombier+ # aware of the legal and administrative consequences of enabling this 6583*14414594SDavid du Colombier+ # option. The number of devices determines the maximum number of 6584*14414594SDavid du Colombier+ # simultaneous BPF clients programs runnable. 6585*14414594SDavid du Colombier+ pseudo-device bpfilter 4 #Berkeley packet filter 6586*14414594SDavid du Colombier+ 6587*14414594SDavid du Colombier+ 6588*14414594SDavid du Colombier+ # USB support 6589*14414594SDavid du Colombier+ #controller uhci0 6590*14414594SDavid du Colombier+ #controller ohci0 6591*14414594SDavid du Colombier+ #controller usb0 6592*14414594SDavid du Colombier+ # 6593*14414594SDavid du Colombier+ # for the moment we have to specify the priorities of the device 6594*14414594SDavid du Colombier+ # drivers explicitly by the ordering in the list below. This will 6595*14414594SDavid du Colombier+ # be changed in the future. 6596*14414594SDavid du Colombier+ # 6597*14414594SDavid du Colombier+ #device ums0 6598*14414594SDavid du Colombier+ #device ukbd0 6599*14414594SDavid du Colombier+ #device ulpt0 6600*14414594SDavid du Colombier+ #device uhub0 6601*14414594SDavid du Colombier+ #device ucom0 6602*14414594SDavid du Colombier+ #device umodem0 6603*14414594SDavid du Colombier+ #device hid0 6604*14414594SDavid du Colombier+ #device ugen0 6605*14414594SDavid du Colombier+ 6606*14414594SDavid du Colombier+ # 6607*14414594SDavid du Colombier+ #options USB_DEBUG 6608*14414594SDavid du Colombier+ #options USBVERBOSE 6609*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/il.c ./netinet/il.c 6610*14414594SDavid du Colombier*** /usr/src/sys/netinet/il.c Wed Dec 31 19:00:00 1969 6611*14414594SDavid du Colombier--- ./netinet/il.c Tue Nov 23 19:16:13 1999 6612*14414594SDavid du Colombier*************** 6613*14414594SDavid du Colombier*** 0 **** 6614*14414594SDavid du Colombier--- 1,1147 ---- 6615*14414594SDavid du Colombier+ #include <unistd.h> 6616*14414594SDavid du Colombier+ #include <ctype.h> 6617*14414594SDavid du Colombier+ #include <sys/types.h> 6618*14414594SDavid du Colombier+ #include <sys/param.h> 6619*14414594SDavid du Colombier+ #include <sys/time.h> 6620*14414594SDavid du Colombier+ #include <sys/systm.h> 6621*14414594SDavid du Colombier+ #include <vm/vm_zone.h> 6622*14414594SDavid du Colombier+ 6623*14414594SDavid du Colombier+ #include <sys/malloc.h> 6624*14414594SDavid du Colombier+ #include <machine/param.h> 6625*14414594SDavid du Colombier+ #include <sys/mbuf.h> 6626*14414594SDavid du Colombier+ #include <sys/protosw.h> 6627*14414594SDavid du Colombier+ #include <sys/socket.h> 6628*14414594SDavid du Colombier+ #include <sys/socketvar.h> 6629*14414594SDavid du Colombier+ #include <sys/proc.h> 6630*14414594SDavid du Colombier+ #include <net/if.h> 6631*14414594SDavid du Colombier+ #include <net/route.h> 6632*14414594SDavid du Colombier+ #include <netinet/in_systm.h> 6633*14414594SDavid du Colombier+ #include <netinet/in.h> 6634*14414594SDavid du Colombier+ #include <netinet/in_var.h> 6635*14414594SDavid du Colombier+ #include <netinet/if_ether.h> 6636*14414594SDavid du Colombier+ #include <netinet/ip.h> 6637*14414594SDavid du Colombier+ #include <netinet/ip_var.h> 6638*14414594SDavid du Colombier+ #include <netinet/in_pcb.h> 6639*14414594SDavid du Colombier+ #include <errno.h> 6640*14414594SDavid du Colombier+ 6641*14414594SDavid du Colombier+ #include <netinet/il.h> 6642*14414594SDavid du Colombier+ #include <netinet/il_var.h> 6643*14414594SDavid du Colombier+ 6644*14414594SDavid du Colombier+ struct ilpcb * il_drop(struct ilpcb *ilpcb, int errno0); 6645*14414594SDavid du Colombier+ static struct ilpcb * il_close(struct ilpcb *ilpcb); 6646*14414594SDavid du Colombier+ 6647*14414594SDavid du Colombier+ /* kernel protocol states needed */ 6648*14414594SDavid du Colombier+ static struct inpcbhead ilb; 6649*14414594SDavid du Colombier+ static struct inpcbinfo ilbinfo; 6650*14414594SDavid du Colombier+ 6651*14414594SDavid du Colombier+ u_long il_sendspace = 1024*64; 6652*14414594SDavid du Colombier+ u_long il_recvspace = 1024*64; 6653*14414594SDavid du Colombier+ 6654*14414594SDavid du Colombier+ /* 6655*14414594SDavid du Colombier+ * Target size of IL PCB hash tables. Must be a power of two. 6656*14414594SDavid du Colombier+ * 6657*14414594SDavid du Colombier+ * Note that this can be overridden by the kernel environment 6658*14414594SDavid du Colombier+ * variable net.inet.tcp.tcbhashsize 6659*14414594SDavid du Colombier+ */ 6660*14414594SDavid du Colombier+ #ifndef ILBHASHSIZE 6661*14414594SDavid du Colombier+ #define ILBHASHSIZE 512 6662*14414594SDavid du Colombier+ #endif 6663*14414594SDavid du Colombier+ 6664*14414594SDavid du Colombier+ enum /* Connection state */ 6665*14414594SDavid du Colombier+ { 6666*14414594SDavid du Colombier+ ILS_CLOSED, 6667*14414594SDavid du Colombier+ ILS_SYNCER, 6668*14414594SDavid du Colombier+ ILS_SYNCEE, 6669*14414594SDavid du Colombier+ ILS_ESTABLISHED, 6670*14414594SDavid du Colombier+ ILS_LISTENING, 6671*14414594SDavid du Colombier+ ILS_CLOSING, 6672*14414594SDavid du Colombier+ ILS_OPENING, /* only for file server */ 6673*14414594SDavid du Colombier+ }; 6674*14414594SDavid du Colombier+ 6675*14414594SDavid du Colombier+ char *ilstates[] = 6676*14414594SDavid du Colombier+ { 6677*14414594SDavid du Colombier+ "Closed", 6678*14414594SDavid du Colombier+ "Syncer", 6679*14414594SDavid du Colombier+ "Syncee", 6680*14414594SDavid du Colombier+ "Established", 6681*14414594SDavid du Colombier+ "Listening", 6682*14414594SDavid du Colombier+ "Closing", 6683*14414594SDavid du Colombier+ "Opening", /* only for file server */ 6684*14414594SDavid du Colombier+ }; 6685*14414594SDavid du Colombier+ 6686*14414594SDavid du Colombier+ enum /* Packet types */ 6687*14414594SDavid du Colombier+ { 6688*14414594SDavid du Colombier+ ILT_SYNC, 6689*14414594SDavid du Colombier+ ILT_DATA, 6690*14414594SDavid du Colombier+ ILT_DATAQUERY, 6691*14414594SDavid du Colombier+ ILT_ACK, 6692*14414594SDavid du Colombier+ ILT_QUERY, 6693*14414594SDavid du Colombier+ ILT_STATE, 6694*14414594SDavid du Colombier+ ILT_CLOSE 6695*14414594SDavid du Colombier+ }; 6696*14414594SDavid du Colombier+ 6697*14414594SDavid du Colombier+ char *iltype[] = 6698*14414594SDavid du Colombier+ { 6699*14414594SDavid du Colombier+ "sync", 6700*14414594SDavid du Colombier+ "data", 6701*14414594SDavid du Colombier+ "dataquery", 6702*14414594SDavid du Colombier+ "ack", 6703*14414594SDavid du Colombier+ "query", 6704*14414594SDavid du Colombier+ "state", 6705*14414594SDavid du Colombier+ "close", 6706*14414594SDavid du Colombier+ }; 6707*14414594SDavid du Colombier+ 6708*14414594SDavid du Colombier+ /* 6709*14414594SDavid du Colombier+ * This is the actual shape of what we allocate using the zone 6710*14414594SDavid du Colombier+ * allocator. Doing it this way allows us to protect both structures 6711*14414594SDavid du Colombier+ * using the same generation count, and also eliminates the overhead 6712*14414594SDavid du Colombier+ * of allocating tcpcbs separately. By hiding the structure here, 6713*14414594SDavid du Colombier+ * we avoid changing most of the rest of the code (although it needs 6714*14414594SDavid du Colombier+ * to be changed, eventually, for greater efficiency). 6715*14414594SDavid du Colombier+ */ 6716*14414594SDavid du Colombier+ #define ALIGNMENT 32 6717*14414594SDavid du Colombier+ #define ALIGNM1 (ALIGNMENT - 1) 6718*14414594SDavid du Colombier+ struct inp_ilpcb { 6719*14414594SDavid du Colombier+ union { 6720*14414594SDavid du Colombier+ struct inpcb inp; 6721*14414594SDavid du Colombier+ char align[(sizeof(struct inpcb) + ALIGNM1) & ~ALIGNM1]; 6722*14414594SDavid du Colombier+ } inp_tp_u; 6723*14414594SDavid du Colombier+ struct ilpcb ilpcb; 6724*14414594SDavid du Colombier+ }; 6725*14414594SDavid du Colombier+ #undef ALIGNMENT 6726*14414594SDavid du Colombier+ #undef ALIGNM1 6727*14414594SDavid du Colombier+ 6728*14414594SDavid du Colombier+ static __inline struct mbuf * il_segq_top(struct ilpcb * ilpcb) 6729*14414594SDavid du Colombier+ { 6730*14414594SDavid du Colombier+ return (ilpcb->segq); 6731*14414594SDavid du Colombier+ } 6732*14414594SDavid du Colombier+ 6733*14414594SDavid du Colombier+ static __inline void il_segq_dequeue(struct ilpcb * ilpcb) 6734*14414594SDavid du Colombier+ { 6735*14414594SDavid du Colombier+ struct mbuf * m = ilpcb->segq; 6736*14414594SDavid du Colombier+ ilpcb->segq = m->m_nextpkt; 6737*14414594SDavid du Colombier+ m->m_nextpkt = 0; 6738*14414594SDavid du Colombier+ } 6739*14414594SDavid du Colombier+ 6740*14414594SDavid du Colombier+ static __inline void il_segq_insert(struct ilpcb * ilpcb, struct mbuf * m, u_long seq, struct ilhdr * il) 6741*14414594SDavid du Colombier+ { 6742*14414594SDavid du Colombier+ u_long pseq; 6743*14414594SDavid du Colombier+ struct mbuf * mp, * mq; 6744*14414594SDavid du Colombier+ 6745*14414594SDavid du Colombier+ m->m_pkthdr.header = il; 6746*14414594SDavid du Colombier+ 6747*14414594SDavid du Colombier+ mp = 0; 6748*14414594SDavid du Colombier+ mq = ilpcb->segq; 6749*14414594SDavid du Colombier+ while ( mq ) { 6750*14414594SDavid du Colombier+ il = mq->m_pkthdr.header; 6751*14414594SDavid du Colombier+ pseq = ntohl(*(u_long *)il->ilid); 6752*14414594SDavid du Colombier+ if( pseq > seq ) 6753*14414594SDavid du Colombier+ break; 6754*14414594SDavid du Colombier+ if( pseq == seq ) { /* we already got this packet */ 6755*14414594SDavid du Colombier+ m_freem(m); 6756*14414594SDavid du Colombier+ return; 6757*14414594SDavid du Colombier+ } 6758*14414594SDavid du Colombier+ mp = mq; 6759*14414594SDavid du Colombier+ mq = mq->m_nextpkt; 6760*14414594SDavid du Colombier+ } 6761*14414594SDavid du Colombier+ 6762*14414594SDavid du Colombier+ if( mp == 0 ) { 6763*14414594SDavid du Colombier+ m->m_nextpkt = ilpcb->segq; 6764*14414594SDavid du Colombier+ ilpcb->segq = m; 6765*14414594SDavid du Colombier+ return; 6766*14414594SDavid du Colombier+ } 6767*14414594SDavid du Colombier+ mp->m_nextpkt = m; 6768*14414594SDavid du Colombier+ m->m_nextpkt = mq; 6769*14414594SDavid du Colombier+ } 6770*14414594SDavid du Colombier+ 6771*14414594SDavid du Colombier+ void il_init() 6772*14414594SDavid du Colombier+ { 6773*14414594SDavid du Colombier+ LIST_INIT(&ilb); 6774*14414594SDavid du Colombier+ ilbinfo.listhead = &ilb; 6775*14414594SDavid du Colombier+ ilbinfo.hashbase = hashinit(ILBHASHSIZE, M_PCB, &ilbinfo.hashmask); 6776*14414594SDavid du Colombier+ ilbinfo.porthashbase = hashinit(ILBHASHSIZE, M_PCB, 6777*14414594SDavid du Colombier+ &ilbinfo.porthashmask); 6778*14414594SDavid du Colombier+ ilbinfo.ipi_zone = zinit("ilpcb", sizeof(struct inp_ilpcb), maxsockets, 6779*14414594SDavid du Colombier+ ZONE_INTERRUPT, 0); 6780*14414594SDavid du Colombier+ } 6781*14414594SDavid du Colombier+ 6782*14414594SDavid du Colombier+ /* fill in il header and cksum, ip src/dst addresses */ 6783*14414594SDavid du Colombier+ static int il_output(struct ilpcb * ilpcb, struct mbuf *m, int type, u_long seq, u_char spec) 6784*14414594SDavid du Colombier+ { 6785*14414594SDavid du Colombier+ struct ilhdr * il; 6786*14414594SDavid du Colombier+ struct ip * ip; 6787*14414594SDavid du Colombier+ int illen; 6788*14414594SDavid du Colombier+ struct inpcb * inp; 6789*14414594SDavid du Colombier+ struct socket * so; 6790*14414594SDavid du Colombier+ 6791*14414594SDavid du Colombier+ /* XXX: check total size is less than IP_MAXPACKET */ 6792*14414594SDavid du Colombier+ 6793*14414594SDavid du Colombier+ if( m == 0 ) { 6794*14414594SDavid du Colombier+ inp = ilpcb->inpcb; 6795*14414594SDavid du Colombier+ so = inp->inp_socket; 6796*14414594SDavid du Colombier+ m = m_copypacket(so->so_snd.sb_mb, M_DONTWAIT); 6797*14414594SDavid du Colombier+ } 6798*14414594SDavid du Colombier+ 6799*14414594SDavid du Colombier+ /* 6800*14414594SDavid du Colombier+ * Calculate data length and get a mbuf 6801*14414594SDavid du Colombier+ * for IL and IP headers. 6802*14414594SDavid du Colombier+ */ 6803*14414594SDavid du Colombier+ illen = m->m_pkthdr.len; /* size of il payload */ 6804*14414594SDavid du Colombier+ M_PREPEND(m, sizeof(struct ip) + sizeof(struct ilhdr), M_DONTWAIT); 6805*14414594SDavid du Colombier+ if( m == 0 ) 6806*14414594SDavid du Colombier+ return ENOBUFS; 6807*14414594SDavid du Colombier+ 6808*14414594SDavid du Colombier+ ip = mtod(m, struct ip *); 6809*14414594SDavid du Colombier+ il = (struct ilhdr *) (ip+1); 6810*14414594SDavid du Colombier+ bzero(ip, sizeof(*ip)); 6811*14414594SDavid du Colombier+ 6812*14414594SDavid du Colombier+ ip->ip_p = IPPROTO_IL; 6813*14414594SDavid du Colombier+ ip->ip_src = ilpcb->inpcb->inp_laddr; 6814*14414594SDavid du Colombier+ ip->ip_dst = ilpcb->inpcb->inp_faddr; 6815*14414594SDavid du Colombier+ ip->ip_len = m->m_pkthdr.len; 6816*14414594SDavid du Colombier+ ip->ip_ttl = ilpcb->inpcb->inp_ip_ttl; /* XXX */ 6817*14414594SDavid du Colombier+ ip->ip_tos = ilpcb->inpcb->inp_ip_tos; /* XXX */ 6818*14414594SDavid du Colombier+ 6819*14414594SDavid du Colombier+ *(u_short *)il->illen = htons(illen + sizeof(struct ilhdr)); 6820*14414594SDavid du Colombier+ il->iltype = type; 6821*14414594SDavid du Colombier+ il->ilspec = spec; 6822*14414594SDavid du Colombier+ *(u_short *)il->ilsrc = ilpcb->inpcb->inp_lport; 6823*14414594SDavid du Colombier+ *(u_short *)il->ildst = ilpcb->inpcb->inp_fport; 6824*14414594SDavid du Colombier+ if ( type != ILT_SYNC ) 6825*14414594SDavid du Colombier+ *(u_long *)il->ilid = htonl(seq); 6826*14414594SDavid du Colombier+ else 6827*14414594SDavid du Colombier+ *(u_long *)il->ilid = htonl(ilpcb->start); 6828*14414594SDavid du Colombier+ 6829*14414594SDavid du Colombier+ if( type != ILT_ACK && type != ILT_STATE) { 6830*14414594SDavid du Colombier+ if( ilpcb->rxt_timer == 0 ) 6831*14414594SDavid du Colombier+ ilpcb->rxt_timer = ilpcb->rxt_timer_cur; 6832*14414594SDavid du Colombier+ if( ilpcb->death_timer == 0 ) 6833*14414594SDavid du Colombier+ ilpcb->death_timer = ilpcb->death_timer_cur; 6834*14414594SDavid du Colombier+ } 6835*14414594SDavid du Colombier+ 6836*14414594SDavid du Colombier+ *(u_long *)il->ilack = htonl(ilpcb->recvd); 6837*14414594SDavid du Colombier+ il->ilsum[0] = il->ilsum[1] = 0; 6838*14414594SDavid du Colombier+ 6839*14414594SDavid du Colombier+ /* IL checksum does not cover IP header */ 6840*14414594SDavid du Colombier+ m->m_data += sizeof(struct ip); 6841*14414594SDavid du Colombier+ m->m_len -= sizeof(struct ip); 6842*14414594SDavid du Colombier+ *(u_short *)il->ilsum = in_cksum(m, illen + sizeof(struct ilhdr)); 6843*14414594SDavid du Colombier+ m->m_data -= sizeof(struct ip); 6844*14414594SDavid du Colombier+ m->m_len += sizeof(struct ip); 6845*14414594SDavid du Colombier+ 6846*14414594SDavid du Colombier+ return ip_output(m, ilpcb->inpcb->inp_options, &ilpcb->inpcb->inp_route, 6847*14414594SDavid du Colombier+ ilpcb->inpcb->inp_socket->so_options & SO_DONTROUTE ,0); 6848*14414594SDavid du Colombier+ } 6849*14414594SDavid du Colombier+ 6850*14414594SDavid du Colombier+ static int il_send_empty(struct ilpcb * ilpcb, int type, u_char spec) 6851*14414594SDavid du Colombier+ { 6852*14414594SDavid du Colombier+ struct mbuf * m0; 6853*14414594SDavid du Colombier+ 6854*14414594SDavid du Colombier+ MGETHDR(m0, M_DONTWAIT, MT_DATA); 6855*14414594SDavid du Colombier+ m0->m_len = 0; 6856*14414594SDavid du Colombier+ m0->m_pkthdr.len = 0; 6857*14414594SDavid du Colombier+ MH_ALIGN(m0, 0); /* leave space for the packet header */ 6858*14414594SDavid du Colombier+ 6859*14414594SDavid du Colombier+ return il_output(ilpcb, m0, type, ilpcb->next, spec); 6860*14414594SDavid du Colombier+ } 6861*14414594SDavid du Colombier+ 6862*14414594SDavid du Colombier+ static int il_respond(struct ilpcb * ilpcb, struct ip * ip, struct ilhdr *il, int type, u_char spec) 6863*14414594SDavid du Colombier+ { 6864*14414594SDavid du Colombier+ struct mbuf * m; 6865*14414594SDavid du Colombier+ int illen; 6866*14414594SDavid du Colombier+ struct ip * ip0; 6867*14414594SDavid du Colombier+ struct ilhdr *il0; 6868*14414594SDavid du Colombier+ struct route * ro; 6869*14414594SDavid du Colombier+ struct route sro; 6870*14414594SDavid du Colombier+ 6871*14414594SDavid du Colombier+ if( ilpcb ) { 6872*14414594SDavid du Colombier+ ro = & ilpcb->inpcb->inp_route; 6873*14414594SDavid du Colombier+ } else { 6874*14414594SDavid du Colombier+ ro = &sro; 6875*14414594SDavid du Colombier+ bzero(ro, sizeof *ro); 6876*14414594SDavid du Colombier+ } 6877*14414594SDavid du Colombier+ 6878*14414594SDavid du Colombier+ MGETHDR(m, M_DONTWAIT, MT_DATA); 6879*14414594SDavid du Colombier+ m->m_len = 0; 6880*14414594SDavid du Colombier+ m->m_pkthdr.len = 0; 6881*14414594SDavid du Colombier+ MH_ALIGN(m, 0); /* leave space for the packet header */ 6882*14414594SDavid du Colombier+ illen = m->m_pkthdr.len; /* size of il payload */ 6883*14414594SDavid du Colombier+ M_PREPEND(m, sizeof(struct ip) + sizeof(struct ilhdr), M_DONTWAIT); 6884*14414594SDavid du Colombier+ if( m == 0 ) 6885*14414594SDavid du Colombier+ return ENOBUFS; 6886*14414594SDavid du Colombier+ 6887*14414594SDavid du Colombier+ ip0 = mtod(m, struct ip *); 6888*14414594SDavid du Colombier+ il0 = (struct ilhdr *) (ip0+1); 6889*14414594SDavid du Colombier+ bzero(ip0, sizeof(*ip0)); 6890*14414594SDavid du Colombier+ 6891*14414594SDavid du Colombier+ ip0->ip_p = IPPROTO_IL; 6892*14414594SDavid du Colombier+ ip0->ip_src = ip->ip_dst; 6893*14414594SDavid du Colombier+ ip0->ip_dst = ip->ip_src; 6894*14414594SDavid du Colombier+ ip0->ip_ttl = ip_defttl; 6895*14414594SDavid du Colombier+ ip0->ip_len = sizeof(struct ip) + sizeof(struct ilhdr); 6896*14414594SDavid du Colombier+ *(u_short *)il0->illen = htons(illen + sizeof(struct ilhdr)); 6897*14414594SDavid du Colombier+ il0->iltype = type; 6898*14414594SDavid du Colombier+ il0->ilspec = spec; 6899*14414594SDavid du Colombier+ bcopy(il->ilsrc, il0->ildst, 2); 6900*14414594SDavid du Colombier+ bcopy(il->ildst, il0->ilsrc, 2); 6901*14414594SDavid du Colombier+ *(u_long *)il0->ilid = 0; 6902*14414594SDavid du Colombier+ bcopy(il->ilid, il0->ilack, 4); 6903*14414594SDavid du Colombier+ il0->ilsum[0] = il0->ilsum[1] = 0; 6904*14414594SDavid du Colombier+ 6905*14414594SDavid du Colombier+ /* IL checksum does not cover IP header */ 6906*14414594SDavid du Colombier+ m->m_data += sizeof(struct ip); 6907*14414594SDavid du Colombier+ m->m_len -= sizeof(struct ip); 6908*14414594SDavid du Colombier+ *(u_short *)il0->ilsum = in_cksum(m, illen + sizeof(struct ilhdr)); 6909*14414594SDavid du Colombier+ m->m_data -= sizeof(struct ip); 6910*14414594SDavid du Colombier+ m->m_len += sizeof(struct ip); 6911*14414594SDavid du Colombier+ 6912*14414594SDavid du Colombier+ return ip_output(m, 0, ro, 0 ,0); 6913*14414594SDavid du Colombier+ } 6914*14414594SDavid du Colombier+ 6915*14414594SDavid du Colombier+ static struct ilpcb * 6916*14414594SDavid du Colombier+ il_newconn(struct ilpcb * ilpcb, struct in_addr ti_dst, u_short ti_dport, 6917*14414594SDavid du Colombier+ struct in_addr ti_src, u_short ti_sport) 6918*14414594SDavid du Colombier+ { 6919*14414594SDavid du Colombier+ register struct ilpcb * ilpcb0; 6920*14414594SDavid du Colombier+ struct socket *so2, * so; 6921*14414594SDavid du Colombier+ struct inpcb * inp; 6922*14414594SDavid du Colombier+ struct sockaddr_in sin; 6923*14414594SDavid du Colombier+ 6924*14414594SDavid du Colombier+ so = ilpcb->inpcb->inp_socket; 6925*14414594SDavid du Colombier+ so2 = sonewconn(so, 0); 6926*14414594SDavid du Colombier+ if (so2 == 0) { 6927*14414594SDavid du Colombier+ so2 = sodropablereq(so); 6928*14414594SDavid du Colombier+ if (so2) { 6929*14414594SDavid du Colombier+ il_drop(sotoilpcb(so2), ETIMEDOUT); 6930*14414594SDavid du Colombier+ so2 = sonewconn(so, 0); 6931*14414594SDavid du Colombier+ } 6932*14414594SDavid du Colombier+ if (!so2) 6933*14414594SDavid du Colombier+ return 0; 6934*14414594SDavid du Colombier+ } 6935*14414594SDavid du Colombier+ so = so2; 6936*14414594SDavid du Colombier+ 6937*14414594SDavid du Colombier+ inp = (struct inpcb *)so->so_pcb; 6938*14414594SDavid du Colombier+ inp->inp_laddr = ti_dst; 6939*14414594SDavid du Colombier+ inp->inp_lport = ti_dport; 6940*14414594SDavid du Colombier+ if (in_pcbinshash(inp) != 0) { 6941*14414594SDavid du Colombier+ /* 6942*14414594SDavid du Colombier+ * Undo the assignments above if we failed to put 6943*14414594SDavid du Colombier+ * the PCB on the hash lists. 6944*14414594SDavid du Colombier+ */ 6945*14414594SDavid du Colombier+ inp->inp_laddr.s_addr = INADDR_ANY; 6946*14414594SDavid du Colombier+ inp->inp_lport = 0; 6947*14414594SDavid du Colombier+ 6948*14414594SDavid du Colombier+ soabort(so); 6949*14414594SDavid du Colombier+ return 0; 6950*14414594SDavid du Colombier+ } 6951*14414594SDavid du Colombier+ 6952*14414594SDavid du Colombier+ bzero((char *)&sin, sizeof(sin)); 6953*14414594SDavid du Colombier+ sin.sin_family = AF_INET; 6954*14414594SDavid du Colombier+ sin.sin_len = sizeof(sin); 6955*14414594SDavid du Colombier+ sin.sin_addr = ti_src; 6956*14414594SDavid du Colombier+ sin.sin_port = ti_sport; 6957*14414594SDavid du Colombier+ if (in_pcbconnect(inp, (struct sockaddr *)&sin, &proc0)) { 6958*14414594SDavid du Colombier+ inp->inp_laddr.s_addr = INADDR_ANY; 6959*14414594SDavid du Colombier+ soabort(so); 6960*14414594SDavid du Colombier+ return 0; 6961*14414594SDavid du Colombier+ } 6962*14414594SDavid du Colombier+ 6963*14414594SDavid du Colombier+ ilpcb0 = intoilpcb(inp); 6964*14414594SDavid du Colombier+ ilpcb0->state = ILS_LISTENING; 6965*14414594SDavid du Colombier+ 6966*14414594SDavid du Colombier+ return ilpcb0; 6967*14414594SDavid du Colombier+ } 6968*14414594SDavid du Colombier+ 6969*14414594SDavid du Colombier+ /* ack processing */ 6970*14414594SDavid du Colombier+ static void il_proc_ack(struct ilpcb * ilpcb, struct socket * so, u_long ack) 6971*14414594SDavid du Colombier+ { 6972*14414594SDavid du Colombier+ if( ack >= ilpcb->unacked ) { 6973*14414594SDavid du Colombier+ ilpcb->rxt_timer = 0; 6974*14414594SDavid du Colombier+ ilpcb->death_timer = 0; 6975*14414594SDavid du Colombier+ 6976*14414594SDavid du Colombier+ /* the rxt timer is not prop. to RTT */ 6977*14414594SDavid du Colombier+ /* reset it so that the first rxt is always 1 second */ 6978*14414594SDavid du Colombier+ ilpcb->rxt_timer_cur = 2; 6979*14414594SDavid du Colombier+ 6980*14414594SDavid du Colombier+ if( ack >= ilpcb->next ) 6981*14414594SDavid du Colombier+ ack = ilpcb->next - 1; 6982*14414594SDavid du Colombier+ while (ilpcb->unacked <= ack ) { 6983*14414594SDavid du Colombier+ sbdroprecord(&so->so_snd); 6984*14414594SDavid du Colombier+ ilpcb->unacked++; 6985*14414594SDavid du Colombier+ } 6986*14414594SDavid du Colombier+ if( ilpcb->unacked != ilpcb->next ) { 6987*14414594SDavid du Colombier+ ilpcb->rxt_timer = ilpcb->rxt_timer_cur; 6988*14414594SDavid du Colombier+ ilpcb->death_timer = ilpcb->death_timer_cur; /* do we need this here? */ 6989*14414594SDavid du Colombier+ } 6990*14414594SDavid du Colombier+ sowwakeup(so); 6991*14414594SDavid du Colombier+ } 6992*14414594SDavid du Colombier+ } 6993*14414594SDavid du Colombier+ 6994*14414594SDavid du Colombier+ static int il_proc_data(struct ilpcb * ilpcb, struct socket * so, struct mbuf * m, u_long seq, int spec) 6995*14414594SDavid du Colombier+ { 6996*14414594SDavid du Colombier+ struct mbuf * m0; 6997*14414594SDavid du Colombier+ struct ip * ip; 6998*14414594SDavid du Colombier+ int hlen = sizeof(struct ip) + sizeof(struct ilhdr); 6999*14414594SDavid du Colombier+ struct ilhdr * il; 7000*14414594SDavid du Colombier+ int needack = 0; 7001*14414594SDavid du Colombier+ 7002*14414594SDavid du Colombier+ ip = mtod(m, struct ip *); 7003*14414594SDavid du Colombier+ il = (struct ilhdr *)(ip+1); 7004*14414594SDavid du Colombier+ if( seq == ilpcb->recvd + 1 ) { 7005*14414594SDavid du Colombier+ needack = 1; 7006*14414594SDavid du Colombier+ while(1) { 7007*14414594SDavid du Colombier+ ilpcb->recvd = seq; 7008*14414594SDavid du Colombier+ 7009*14414594SDavid du Colombier+ m->m_len -= hlen; 7010*14414594SDavid du Colombier+ m->m_pkthdr.len -= hlen; 7011*14414594SDavid du Colombier+ m->m_data += hlen; 7012*14414594SDavid du Colombier+ sbappendrecord(&so->so_rcv, m); 7013*14414594SDavid du Colombier+ 7014*14414594SDavid du Colombier+ if( (m0 = il_segq_top(ilpcb)) == 0 ) 7015*14414594SDavid du Colombier+ break; 7016*14414594SDavid du Colombier+ ip = mtod(m0, struct ip *); 7017*14414594SDavid du Colombier+ il = (struct ilhdr *)(ip+1); 7018*14414594SDavid du Colombier+ seq = ntohl(*(u_long *)il->ilid); 7019*14414594SDavid du Colombier+ if( seq != ilpcb->recvd + 1 ) 7020*14414594SDavid du Colombier+ break; 7021*14414594SDavid du Colombier+ il_segq_dequeue(ilpcb); 7022*14414594SDavid du Colombier+ m = m0; 7023*14414594SDavid du Colombier+ }; 7024*14414594SDavid du Colombier+ sorwakeup(so); 7025*14414594SDavid du Colombier+ } else { 7026*14414594SDavid du Colombier+ if( seq > ilpcb->recvd ) 7027*14414594SDavid du Colombier+ il_segq_insert(ilpcb, m, seq, il); 7028*14414594SDavid du Colombier+ else 7029*14414594SDavid du Colombier+ m_freem(m); 7030*14414594SDavid du Colombier+ } 7031*14414594SDavid du Colombier+ 7032*14414594SDavid du Colombier+ return needack; 7033*14414594SDavid du Colombier+ } 7034*14414594SDavid du Colombier+ 7035*14414594SDavid du Colombier+ /* assume we only have one connection */ 7036*14414594SDavid du Colombier+ void il_input(struct mbuf * m, int iphlen) 7037*14414594SDavid du Colombier+ { 7038*14414594SDavid du Colombier+ struct ilhdr * il; 7039*14414594SDavid du Colombier+ struct ilpcb * ilpcb = 0; 7040*14414594SDavid du Colombier+ int len, type; 7041*14414594SDavid du Colombier+ u_long seq, ack; 7042*14414594SDavid du Colombier+ struct ip * ip; 7043*14414594SDavid du Colombier+ struct inpcb * inp; 7044*14414594SDavid du Colombier+ u_short sport, dport; 7045*14414594SDavid du Colombier+ struct socket * so; 7046*14414594SDavid du Colombier+ u_char spec; 7047*14414594SDavid du Colombier+ 7048*14414594SDavid du Colombier+ /* 7049*14414594SDavid du Colombier+ * Strip IP options, if any; should skip this, 7050*14414594SDavid du Colombier+ * make available to user, and use on returned packets, 7051*14414594SDavid du Colombier+ * but we don't yet have a way to check the checksum 7052*14414594SDavid du Colombier+ * with options still present. 7053*14414594SDavid du Colombier+ */ 7054*14414594SDavid du Colombier+ if (iphlen > sizeof (struct ip)) { 7055*14414594SDavid du Colombier+ ip_stripoptions(m, (struct mbuf *)0); 7056*14414594SDavid du Colombier+ iphlen = sizeof(struct ip); 7057*14414594SDavid du Colombier+ } 7058*14414594SDavid du Colombier+ 7059*14414594SDavid du Colombier+ /* 7060*14414594SDavid du Colombier+ * Get IP and IL header together in first mbuf. 7061*14414594SDavid du Colombier+ */ 7062*14414594SDavid du Colombier+ ip = mtod(m, struct ip *); 7063*14414594SDavid du Colombier+ if (m->m_len < iphlen + sizeof(struct ilhdr)) { 7064*14414594SDavid du Colombier+ if ((m = m_pullup(m, iphlen + sizeof(struct ilhdr))) == 0) { 7065*14414594SDavid du Colombier+ return; 7066*14414594SDavid du Colombier+ } 7067*14414594SDavid du Colombier+ ip = mtod(m, struct ip *); 7068*14414594SDavid du Colombier+ } 7069*14414594SDavid du Colombier+ il = (struct ilhdr *)((caddr_t)ip + iphlen); 7070*14414594SDavid du Colombier+ 7071*14414594SDavid du Colombier+ len = ntohs(*(u_short *)il->illen); 7072*14414594SDavid du Colombier+ seq = ntohl(*(u_long *)il->ilid); 7073*14414594SDavid du Colombier+ ack = ntohl(*(u_long *)il->ilack); 7074*14414594SDavid du Colombier+ sport = *(u_short *)il->ilsrc; 7075*14414594SDavid du Colombier+ dport = *(u_short *)il->ildst; 7076*14414594SDavid du Colombier+ type = il->iltype; 7077*14414594SDavid du Colombier+ spec = il->ilspec; 7078*14414594SDavid du Colombier+ 7079*14414594SDavid du Colombier+ inp = in_pcblookup_hash(&ilbinfo, ip->ip_src, sport, ip->ip_dst, dport, 1); 7080*14414594SDavid du Colombier+ if ( inp == 0 && type == ILT_SYNC ) 7081*14414594SDavid du Colombier+ goto dropwithrest; 7082*14414594SDavid du Colombier+ if( inp == 0 ) 7083*14414594SDavid du Colombier+ goto drop; 7084*14414594SDavid du Colombier+ 7085*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7086*14414594SDavid du Colombier+ if( ilpcb == 0 ) 7087*14414594SDavid du Colombier+ goto drop; 7088*14414594SDavid du Colombier+ 7089*14414594SDavid du Colombier+ so = inp->inp_socket; 7090*14414594SDavid du Colombier+ if( type == ILT_QUERY ) { /* XXX: can we use the same mbuf to send? */ 7091*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_STATE, il->ilspec); 7092*14414594SDavid du Colombier+ goto drop; 7093*14414594SDavid du Colombier+ } 7094*14414594SDavid du Colombier+ 7095*14414594SDavid du Colombier+ again: 7096*14414594SDavid du Colombier+ /* FSM transition */ 7097*14414594SDavid du Colombier+ switch( ilpcb->state ) { 7098*14414594SDavid du Colombier+ case ILS_SYNCER: 7099*14414594SDavid du Colombier+ if( ack != ilpcb->start ) 7100*14414594SDavid du Colombier+ goto drop; 7101*14414594SDavid du Colombier+ switch( type ) { 7102*14414594SDavid du Colombier+ case ILT_SYNC: 7103*14414594SDavid du Colombier+ ilpcb->unacked++; 7104*14414594SDavid du Colombier+ ilpcb->recvd = seq; 7105*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_ACK, 0); 7106*14414594SDavid du Colombier+ ilpcb->state = ILS_ESTABLISHED; 7107*14414594SDavid du Colombier+ ilpcb->rxt_timer = 0; 7108*14414594SDavid du Colombier+ ilpcb->death_timer = 0; 7109*14414594SDavid du Colombier+ soisconnected(inp->inp_socket); 7110*14414594SDavid du Colombier+ break; 7111*14414594SDavid du Colombier+ case ILT_CLOSE: 7112*14414594SDavid du Colombier+ il_drop(ilpcb, ECONNREFUSED); 7113*14414594SDavid du Colombier+ break; 7114*14414594SDavid du Colombier+ } 7115*14414594SDavid du Colombier+ break; 7116*14414594SDavid du Colombier+ 7117*14414594SDavid du Colombier+ case ILS_LISTENING: 7118*14414594SDavid du Colombier+ if( type == ILT_SYNC && ack == 0 && so->so_options & SO_ACCEPTCONN ) { 7119*14414594SDavid du Colombier+ ilpcb = il_newconn(ilpcb, ip->ip_dst, dport, ip->ip_src, sport); 7120*14414594SDavid du Colombier+ 7121*14414594SDavid du Colombier+ ilpcb->next = ilpcb->start = random(); 7122*14414594SDavid du Colombier+ ilpcb->unacked = ilpcb->next; 7123*14414594SDavid du Colombier+ ilpcb->rstart = ilpcb->recvd = seq; 7124*14414594SDavid du Colombier+ ilpcb->state = ILS_SYNCEE; 7125*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_SYNC, 0); 7126*14414594SDavid du Colombier+ ilpcb->next++; 7127*14414594SDavid du Colombier+ } else 7128*14414594SDavid du Colombier+ il_respond(ilpcb, ip, il, ILT_CLOSE, 0); 7129*14414594SDavid du Colombier+ break; 7130*14414594SDavid du Colombier+ 7131*14414594SDavid du Colombier+ case ILS_SYNCEE: 7132*14414594SDavid du Colombier+ if( ack == ilpcb->start ) { 7133*14414594SDavid du Colombier+ ilpcb->rxt_timer = 0; 7134*14414594SDavid du Colombier+ ilpcb->unacked++; 7135*14414594SDavid du Colombier+ ilpcb->state = ILS_ESTABLISHED; 7136*14414594SDavid du Colombier+ soisconnected(so); 7137*14414594SDavid du Colombier+ goto again; 7138*14414594SDavid du Colombier+ break; 7139*14414594SDavid du Colombier+ } 7140*14414594SDavid du Colombier+ if( type == ILT_SYNC && seq == ilpcb->recvd && ack == 0 ) 7141*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_SYNC, 0); 7142*14414594SDavid du Colombier+ break; 7143*14414594SDavid du Colombier+ 7144*14414594SDavid du Colombier+ case ILS_ESTABLISHED: 7145*14414594SDavid du Colombier+ il_proc_ack(ilpcb, so, ack); 7146*14414594SDavid du Colombier+ switch( type ) { 7147*14414594SDavid du Colombier+ case ILT_DATA: 7148*14414594SDavid du Colombier+ if( il_proc_data(ilpcb, so, m, seq, spec) ) 7149*14414594SDavid du Colombier+ ilpcb->flags |= ILF_NEEDACK; 7150*14414594SDavid du Colombier+ goto done; 7151*14414594SDavid du Colombier+ break; 7152*14414594SDavid du Colombier+ case ILT_DATAQUERY: 7153*14414594SDavid du Colombier+ il_proc_data(ilpcb, so, m, seq, spec); 7154*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_STATE, spec); 7155*14414594SDavid du Colombier+ goto done; 7156*14414594SDavid du Colombier+ break; 7157*14414594SDavid du Colombier+ case ILT_CLOSE: 7158*14414594SDavid du Colombier+ if( ack < ilpcb->next && ack >= ilpcb->start ) { 7159*14414594SDavid du Colombier+ if( ilpcb->recvd+1 == seq ) 7160*14414594SDavid du Colombier+ ilpcb->recvd = seq; 7161*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_CLOSE, 0); 7162*14414594SDavid du Colombier+ ilpcb->state = ILS_CLOSING; 7163*14414594SDavid du Colombier+ } 7164*14414594SDavid du Colombier+ break; 7165*14414594SDavid du Colombier+ case ILT_STATE: 7166*14414594SDavid du Colombier+ if( ack < ilpcb->rxt_max ) { 7167*14414594SDavid du Colombier+ ilpcb->rxt_max = ilpcb->next; 7168*14414594SDavid du Colombier+ il_output(ilpcb, 0, ILT_DATAQUERY, ilpcb->unacked, 1); 7169*14414594SDavid du Colombier+ } 7170*14414594SDavid du Colombier+ break; 7171*14414594SDavid du Colombier+ case ILT_SYNC: 7172*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_ACK, 0); 7173*14414594SDavid du Colombier+ break; 7174*14414594SDavid du Colombier+ } 7175*14414594SDavid du Colombier+ break; 7176*14414594SDavid du Colombier+ 7177*14414594SDavid du Colombier+ case ILS_CLOSED: 7178*14414594SDavid du Colombier+ goto drop; 7179*14414594SDavid du Colombier+ break; 7180*14414594SDavid du Colombier+ 7181*14414594SDavid du Colombier+ case ILS_CLOSING: 7182*14414594SDavid du Colombier+ if( type == ILT_CLOSE ) { 7183*14414594SDavid du Colombier+ if( ilpcb->recvd+1 == seq ) 7184*14414594SDavid du Colombier+ ilpcb->recvd = seq; 7185*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_CLOSE, 0); 7186*14414594SDavid du Colombier+ ilpcb->state = ILS_CLOSED; 7187*14414594SDavid du Colombier+ il_close(ilpcb); 7188*14414594SDavid du Colombier+ } 7189*14414594SDavid du Colombier+ break; 7190*14414594SDavid du Colombier+ } 7191*14414594SDavid du Colombier+ 7192*14414594SDavid du Colombier+ m_freem(m); 7193*14414594SDavid du Colombier+ done: 7194*14414594SDavid du Colombier+ return; 7195*14414594SDavid du Colombier+ 7196*14414594SDavid du Colombier+ dropwithrest: 7197*14414594SDavid du Colombier+ il_respond(ilpcb, ip, il, ILT_CLOSE, 0); 7198*14414594SDavid du Colombier+ drop: 7199*14414594SDavid du Colombier+ m_freem(m); 7200*14414594SDavid du Colombier+ } 7201*14414594SDavid du Colombier+ 7202*14414594SDavid du Colombier+ static void il_sendseqinit(struct ilpcb * ilpcb) 7203*14414594SDavid du Colombier+ { 7204*14414594SDavid du Colombier+ ilpcb->start = ilpcb->next = random(); 7205*14414594SDavid du Colombier+ ilpcb->unacked = ilpcb->next; 7206*14414594SDavid du Colombier+ ilpcb->state = ILS_SYNCER; 7207*14414594SDavid du Colombier+ ilpcb->next++; 7208*14414594SDavid du Colombier+ } 7209*14414594SDavid du Colombier+ 7210*14414594SDavid du Colombier+ static void il_rxt_timeout(struct ilpcb * ilpcb) 7211*14414594SDavid du Colombier+ { 7212*14414594SDavid du Colombier+ switch ( ilpcb->state ) { 7213*14414594SDavid du Colombier+ case ILS_ESTABLISHED: 7214*14414594SDavid du Colombier+ il_output(ilpcb, 0, ILT_DATAQUERY, ilpcb->unacked, 1); 7215*14414594SDavid du Colombier+ ilpcb->rxtot++; 7216*14414594SDavid du Colombier+ break; 7217*14414594SDavid du Colombier+ case ILS_SYNCER: 7218*14414594SDavid du Colombier+ case ILS_SYNCEE: 7219*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_SYNC, 0); 7220*14414594SDavid du Colombier+ break; 7221*14414594SDavid du Colombier+ case ILS_CLOSING: 7222*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_CLOSE, 0); 7223*14414594SDavid du Colombier+ break; 7224*14414594SDavid du Colombier+ } 7225*14414594SDavid du Colombier+ ilpcb->rxt_timer = ilpcb->rxt_timer_cur; 7226*14414594SDavid du Colombier+ } 7227*14414594SDavid du Colombier+ 7228*14414594SDavid du Colombier+ void il_ctlinput(int cmd, struct sockaddr *sa, void *vip) 7229*14414594SDavid du Colombier+ {} 7230*14414594SDavid du Colombier+ 7231*14414594SDavid du Colombier+ int il_ctloutput(struct socket *so, struct sockopt *sopt) 7232*14414594SDavid du Colombier+ { return 0; } 7233*14414594SDavid du Colombier+ 7234*14414594SDavid du Colombier+ void il_drain() 7235*14414594SDavid du Colombier+ {} 7236*14414594SDavid du Colombier+ 7237*14414594SDavid du Colombier+ void il_slowtimo() 7238*14414594SDavid du Colombier+ { 7239*14414594SDavid du Colombier+ struct ilpcb * ilpcb; 7240*14414594SDavid du Colombier+ struct inpcb * inp; 7241*14414594SDavid du Colombier+ int s; 7242*14414594SDavid du Colombier+ 7243*14414594SDavid du Colombier+ s = splnet(); 7244*14414594SDavid du Colombier+ for(inp = ilb.lh_first; inp; inp = inp->inp_list.le_next) { 7245*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7246*14414594SDavid du Colombier+ if(ilpcb->death_timer && --ilpcb->death_timer == 0 ) 7247*14414594SDavid du Colombier+ il_drop(ilpcb, ETIMEDOUT); 7248*14414594SDavid du Colombier+ 7249*14414594SDavid du Colombier+ if(ilpcb->rxt_timer && --ilpcb->rxt_timer == 0 ) { 7250*14414594SDavid du Colombier+ ilpcb->rxt_timer_cur <<= 1; 7251*14414594SDavid du Colombier+ il_rxt_timeout(ilpcb); 7252*14414594SDavid du Colombier+ } 7253*14414594SDavid du Colombier+ } 7254*14414594SDavid du Colombier+ splx(s); 7255*14414594SDavid du Colombier+ } 7256*14414594SDavid du Colombier+ 7257*14414594SDavid du Colombier+ void il_fasttimo() 7258*14414594SDavid du Colombier+ { 7259*14414594SDavid du Colombier+ struct ilpcb * ilpcb; 7260*14414594SDavid du Colombier+ struct inpcb * inp; 7261*14414594SDavid du Colombier+ int s; 7262*14414594SDavid du Colombier+ 7263*14414594SDavid du Colombier+ s = splnet(); 7264*14414594SDavid du Colombier+ for(inp = ilb.lh_first; inp; inp = inp->inp_list.le_next) { 7265*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7266*14414594SDavid du Colombier+ if(ilpcb->flags & ILF_NEEDACK) { 7267*14414594SDavid du Colombier+ ilpcb->flags &= ~ILF_NEEDACK; 7268*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_ACK, 0); 7269*14414594SDavid du Colombier+ } 7270*14414594SDavid du Colombier+ } 7271*14414594SDavid du Colombier+ splx(s); 7272*14414594SDavid du Colombier+ } 7273*14414594SDavid du Colombier+ 7274*14414594SDavid du Colombier+ static struct ilpcb * il_newilpcb(struct inpcb * inp) 7275*14414594SDavid du Colombier+ { 7276*14414594SDavid du Colombier+ struct inp_ilpcb *it; 7277*14414594SDavid du Colombier+ register struct ilpcb *ilpcb; 7278*14414594SDavid du Colombier+ 7279*14414594SDavid du Colombier+ it = (struct inp_ilpcb *)inp; 7280*14414594SDavid du Colombier+ ilpcb = &it->ilpcb; 7281*14414594SDavid du Colombier+ bzero((char *) ilpcb, sizeof(struct ilpcb)); 7282*14414594SDavid du Colombier+ 7283*14414594SDavid du Colombier+ ilpcb->state = ILS_CLOSED; 7284*14414594SDavid du Colombier+ ilpcb->inpcb = inp; 7285*14414594SDavid du Colombier+ ilpcb->rxt_timer_cur = 2; 7286*14414594SDavid du Colombier+ ilpcb->death_timer_cur = 20; 7287*14414594SDavid du Colombier+ 7288*14414594SDavid du Colombier+ ilpcb->inpcb = inp; /* XXX */ 7289*14414594SDavid du Colombier+ inp->inp_ip_ttl = ip_defttl; 7290*14414594SDavid du Colombier+ inp->inp_ppcb = (caddr_t)ilpcb; 7291*14414594SDavid du Colombier+ return (ilpcb); /* XXX */ 7292*14414594SDavid du Colombier+ } 7293*14414594SDavid du Colombier+ 7294*14414594SDavid du Colombier+ /* 7295*14414594SDavid du Colombier+ * Common subroutine to open a TCP connection to remote host specified 7296*14414594SDavid du Colombier+ * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local 7297*14414594SDavid du Colombier+ * port number if needed. Call in_pcbladdr to do the routing and to choose 7298*14414594SDavid du Colombier+ * a local host address (interface). If there is an existing incarnation 7299*14414594SDavid du Colombier+ * of the same connection in TIME-WAIT state and if the remote host was 7300*14414594SDavid du Colombier+ * sending CC options and if the connection duration was < MSL, then 7301*14414594SDavid du Colombier+ * truncate the previous TIME-WAIT state and proceed. 7302*14414594SDavid du Colombier+ * Initialize connection parameters and enter SYN-SENT state. 7303*14414594SDavid du Colombier+ */ 7304*14414594SDavid du Colombier+ static int 7305*14414594SDavid du Colombier+ il_connect(struct ilpcb *ilpcb, struct sockaddr *nam, struct proc *p) 7306*14414594SDavid du Colombier+ { 7307*14414594SDavid du Colombier+ struct inpcb *inp = ilpcb->inpcb, *oinp; 7308*14414594SDavid du Colombier+ struct socket *so = inp->inp_socket; 7309*14414594SDavid du Colombier+ struct sockaddr_in *sin = (struct sockaddr_in *)nam; 7310*14414594SDavid du Colombier+ struct sockaddr_in *ifaddr; 7311*14414594SDavid du Colombier+ int error; 7312*14414594SDavid du Colombier+ 7313*14414594SDavid du Colombier+ if (inp->inp_lport == 0) { 7314*14414594SDavid du Colombier+ error = in_pcbbind(inp, (struct sockaddr *)0, p); 7315*14414594SDavid du Colombier+ if (error) 7316*14414594SDavid du Colombier+ return error; 7317*14414594SDavid du Colombier+ } 7318*14414594SDavid du Colombier+ 7319*14414594SDavid du Colombier+ /* 7320*14414594SDavid du Colombier+ * Cannot simply call in_pcbconnect, because there might be an 7321*14414594SDavid du Colombier+ * earlier incarnation of this same connection still in 7322*14414594SDavid du Colombier+ * TIME_WAIT state, creating an ADDRINUSE error. 7323*14414594SDavid du Colombier+ */ 7324*14414594SDavid du Colombier+ error = in_pcbladdr(inp, nam, &ifaddr); 7325*14414594SDavid du Colombier+ if (error) 7326*14414594SDavid du Colombier+ return error; 7327*14414594SDavid du Colombier+ oinp = in_pcblookup_hash(inp->inp_pcbinfo, 7328*14414594SDavid du Colombier+ sin->sin_addr, sin->sin_port, 7329*14414594SDavid du Colombier+ inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr 7330*14414594SDavid du Colombier+ : ifaddr->sin_addr, 7331*14414594SDavid du Colombier+ inp->inp_lport, 0); 7332*14414594SDavid du Colombier+ if (oinp) { 7333*14414594SDavid du Colombier+ return EADDRINUSE; 7334*14414594SDavid du Colombier+ } 7335*14414594SDavid du Colombier+ if (inp->inp_laddr.s_addr == INADDR_ANY) 7336*14414594SDavid du Colombier+ inp->inp_laddr = ifaddr->sin_addr; 7337*14414594SDavid du Colombier+ inp->inp_faddr = sin->sin_addr; 7338*14414594SDavid du Colombier+ inp->inp_fport = sin->sin_port; 7339*14414594SDavid du Colombier+ in_pcbrehash(inp); 7340*14414594SDavid du Colombier+ 7341*14414594SDavid du Colombier+ #if 0 7342*14414594SDavid du Colombier+ ilpcb->t_template = tcp_template(tp); 7343*14414594SDavid du Colombier+ if (ilpcb->t_template == 0) { 7344*14414594SDavid du Colombier+ in_pcbdisconnect(inp); 7345*14414594SDavid du Colombier+ return ENOBUFS; 7346*14414594SDavid du Colombier+ } 7347*14414594SDavid du Colombier+ #endif 7348*14414594SDavid du Colombier+ 7349*14414594SDavid du Colombier+ soisconnecting(so); 7350*14414594SDavid du Colombier+ il_sendseqinit(ilpcb); 7351*14414594SDavid du Colombier+ 7352*14414594SDavid du Colombier+ return 0; 7353*14414594SDavid du Colombier+ } 7354*14414594SDavid du Colombier+ 7355*14414594SDavid du Colombier+ static int il_usr_send(struct socket *so, int flags, struct mbuf * m, struct sockaddr *addr, struct mbuf *control, struct proc *p) 7356*14414594SDavid du Colombier+ { 7357*14414594SDavid du Colombier+ struct ilpcb * ilpcb; 7358*14414594SDavid du Colombier+ struct inpcb * inp = sotoinpcb(so); 7359*14414594SDavid du Colombier+ int error; 7360*14414594SDavid du Colombier+ struct mbuf * m0; 7361*14414594SDavid du Colombier+ 7362*14414594SDavid du Colombier+ if (inp == 0) { 7363*14414594SDavid du Colombier+ m_freem(m); 7364*14414594SDavid du Colombier+ return EINVAL; 7365*14414594SDavid du Colombier+ } 7366*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7367*14414594SDavid du Colombier+ 7368*14414594SDavid du Colombier+ if (sbspace(&so->so_snd) < -512) { 7369*14414594SDavid du Colombier+ m_freem(m); 7370*14414594SDavid du Colombier+ error = ENOBUFS; 7371*14414594SDavid du Colombier+ goto out; 7372*14414594SDavid du Colombier+ } 7373*14414594SDavid du Colombier+ 7374*14414594SDavid du Colombier+ sbappendrecord(&so->so_snd, m); 7375*14414594SDavid du Colombier+ m0 = m_copypacket(m, M_DONTWAIT); 7376*14414594SDavid du Colombier+ error = il_output(ilpcb, m0, ILT_DATA, ilpcb->next++, 0); 7377*14414594SDavid du Colombier+ 7378*14414594SDavid du Colombier+ out: 7379*14414594SDavid du Colombier+ return error; 7380*14414594SDavid du Colombier+ } 7381*14414594SDavid du Colombier+ 7382*14414594SDavid du Colombier+ static int il_usr_attach(struct socket *so, int proto, struct proc *p) 7383*14414594SDavid du Colombier+ { 7384*14414594SDavid du Colombier+ int s = splnet(); 7385*14414594SDavid du Colombier+ int error = 0; 7386*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7387*14414594SDavid du Colombier+ struct ilpcb *ilpcb = 0; 7388*14414594SDavid du Colombier+ 7389*14414594SDavid du Colombier+ if (inp) { 7390*14414594SDavid du Colombier+ error = EISCONN; 7391*14414594SDavid du Colombier+ goto out; 7392*14414594SDavid du Colombier+ } 7393*14414594SDavid du Colombier+ 7394*14414594SDavid du Colombier+ if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 7395*14414594SDavid du Colombier+ error = soreserve(so, il_sendspace, il_recvspace); 7396*14414594SDavid du Colombier+ if (error) 7397*14414594SDavid du Colombier+ goto out; 7398*14414594SDavid du Colombier+ } 7399*14414594SDavid du Colombier+ 7400*14414594SDavid du Colombier+ error = in_pcballoc(so, &ilbinfo, p); 7401*14414594SDavid du Colombier+ 7402*14414594SDavid du Colombier+ if (error) 7403*14414594SDavid du Colombier+ goto out; 7404*14414594SDavid du Colombier+ 7405*14414594SDavid du Colombier+ inp = sotoinpcb(so); 7406*14414594SDavid du Colombier+ ilpcb = il_newilpcb(inp); 7407*14414594SDavid du Colombier+ if (ilpcb == 0) { 7408*14414594SDavid du Colombier+ int nofd = so->so_state & SS_NOFDREF; /* XXX */ 7409*14414594SDavid du Colombier+ 7410*14414594SDavid du Colombier+ so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ 7411*14414594SDavid du Colombier+ in_pcbdetach(inp); 7412*14414594SDavid du Colombier+ so->so_state |= nofd; 7413*14414594SDavid du Colombier+ error = ENOBUFS; 7414*14414594SDavid du Colombier+ goto out; 7415*14414594SDavid du Colombier+ } 7416*14414594SDavid du Colombier+ ilpcb->state = ILS_CLOSED; 7417*14414594SDavid du Colombier+ ilpcb->segq = 0; 7418*14414594SDavid du Colombier+ 7419*14414594SDavid du Colombier+ out: 7420*14414594SDavid du Colombier+ splx(s); 7421*14414594SDavid du Colombier+ return error; 7422*14414594SDavid du Colombier+ 7423*14414594SDavid du Colombier+ } 7424*14414594SDavid du Colombier+ 7425*14414594SDavid du Colombier+ static int il_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p) 7426*14414594SDavid du Colombier+ { 7427*14414594SDavid du Colombier+ int s = splnet(); 7428*14414594SDavid du Colombier+ int error = 0; 7429*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7430*14414594SDavid du Colombier+ struct ilpcb *ilpcb; 7431*14414594SDavid du Colombier+ struct sockaddr_in *sinp; 7432*14414594SDavid du Colombier+ 7433*14414594SDavid du Colombier+ if (inp == 0) { 7434*14414594SDavid du Colombier+ splx(s); 7435*14414594SDavid du Colombier+ return EINVAL; 7436*14414594SDavid du Colombier+ } 7437*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7438*14414594SDavid du Colombier+ 7439*14414594SDavid du Colombier+ /* 7440*14414594SDavid du Colombier+ * Must check for multicast addresses and disallow binding 7441*14414594SDavid du Colombier+ * to them. 7442*14414594SDavid du Colombier+ */ 7443*14414594SDavid du Colombier+ sinp = (struct sockaddr_in *)nam; 7444*14414594SDavid du Colombier+ if (sinp->sin_family == AF_INET && 7445*14414594SDavid du Colombier+ IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 7446*14414594SDavid du Colombier+ error = EAFNOSUPPORT; 7447*14414594SDavid du Colombier+ goto out; 7448*14414594SDavid du Colombier+ } 7449*14414594SDavid du Colombier+ error = in_pcbbind(inp, nam, p); 7450*14414594SDavid du Colombier+ out: splx(s); 7451*14414594SDavid du Colombier+ return error; 7452*14414594SDavid du Colombier+ } 7453*14414594SDavid du Colombier+ 7454*14414594SDavid du Colombier+ /* 7455*14414594SDavid du Colombier+ * Initiate connection to peer. 7456*14414594SDavid du Colombier+ * Create a template for use in transmissions on this connection. 7457*14414594SDavid du Colombier+ * Enter SYN_SENT state, and mark socket as connecting. 7458*14414594SDavid du Colombier+ * Start keep-alive timer, and seed output sequence space. 7459*14414594SDavid du Colombier+ * Send initial segment on connection. 7460*14414594SDavid du Colombier+ */ 7461*14414594SDavid du Colombier+ static int 7462*14414594SDavid du Colombier+ il_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p) 7463*14414594SDavid du Colombier+ { 7464*14414594SDavid du Colombier+ int s = splnet(); 7465*14414594SDavid du Colombier+ int error = 0; 7466*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7467*14414594SDavid du Colombier+ struct ilpcb *ilpcb; 7468*14414594SDavid du Colombier+ struct sockaddr_in *sinp; 7469*14414594SDavid du Colombier+ 7470*14414594SDavid du Colombier+ if (inp == 0) { 7471*14414594SDavid du Colombier+ splx(s); 7472*14414594SDavid du Colombier+ return EINVAL; 7473*14414594SDavid du Colombier+ } 7474*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7475*14414594SDavid du Colombier+ 7476*14414594SDavid du Colombier+ /* 7477*14414594SDavid du Colombier+ * Must disallow TCP ``connections'' to multicast addresses. 7478*14414594SDavid du Colombier+ */ 7479*14414594SDavid du Colombier+ sinp = (struct sockaddr_in *)nam; 7480*14414594SDavid du Colombier+ if (sinp->sin_family == AF_INET 7481*14414594SDavid du Colombier+ && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 7482*14414594SDavid du Colombier+ error = EAFNOSUPPORT; 7483*14414594SDavid du Colombier+ goto out; 7484*14414594SDavid du Colombier+ } 7485*14414594SDavid du Colombier+ 7486*14414594SDavid du Colombier+ if ((error = il_connect(ilpcb, nam, p)) != 0) 7487*14414594SDavid du Colombier+ goto out; 7488*14414594SDavid du Colombier+ 7489*14414594SDavid du Colombier+ error = il_send_empty(ilpcb, ILT_SYNC, 0); 7490*14414594SDavid du Colombier+ 7491*14414594SDavid du Colombier+ out: splx(s); 7492*14414594SDavid du Colombier+ return error; 7493*14414594SDavid du Colombier+ } 7494*14414594SDavid du Colombier+ 7495*14414594SDavid du Colombier+ /* 7496*14414594SDavid du Colombier+ * Close a TCP control block: 7497*14414594SDavid du Colombier+ * discard all space held by the tcp 7498*14414594SDavid du Colombier+ * discard internet protocol block 7499*14414594SDavid du Colombier+ * wake up any sleepers 7500*14414594SDavid du Colombier+ */ 7501*14414594SDavid du Colombier+ static struct ilpcb * 7502*14414594SDavid du Colombier+ il_close(struct ilpcb *ilpcb) 7503*14414594SDavid du Colombier+ { 7504*14414594SDavid du Colombier+ register struct mbuf *q; 7505*14414594SDavid du Colombier+ register struct mbuf *nq; 7506*14414594SDavid du Colombier+ struct inpcb *inp = ilpcb->inpcb; 7507*14414594SDavid du Colombier+ struct socket *so = inp->inp_socket; 7508*14414594SDavid du Colombier+ 7509*14414594SDavid du Colombier+ /* free the reassembly queue, if any */ 7510*14414594SDavid du Colombier+ for (q = ilpcb->segq; q; q = nq) { 7511*14414594SDavid du Colombier+ nq = q->m_nextpkt; 7512*14414594SDavid du Colombier+ ilpcb->segq = nq; 7513*14414594SDavid du Colombier+ m_freem(q); 7514*14414594SDavid du Colombier+ } 7515*14414594SDavid du Colombier+ inp->inp_ppcb = NULL; 7516*14414594SDavid du Colombier+ soisdisconnected(so); 7517*14414594SDavid du Colombier+ in_pcbdetach(inp); 7518*14414594SDavid du Colombier+ return ((struct ilpcb *)0); 7519*14414594SDavid du Colombier+ } 7520*14414594SDavid du Colombier+ 7521*14414594SDavid du Colombier+ /* 7522*14414594SDavid du Colombier+ * User issued close, and wish to trail through shutdown states: 7523*14414594SDavid du Colombier+ * if never received SYN, just forget it. If got a SYN from peer, 7524*14414594SDavid du Colombier+ * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. 7525*14414594SDavid du Colombier+ * If already got a FIN from peer, then almost done; go to LAST_ACK 7526*14414594SDavid du Colombier+ * state. In all other cases, have already sent FIN to peer (e.g. 7527*14414594SDavid du Colombier+ * after PRU_SHUTDOWN), and just have to play tedious game waiting 7528*14414594SDavid du Colombier+ * for peer to send FIN or not respond to keep-alives, etc. 7529*14414594SDavid du Colombier+ * We can let the user exit from the close as soon as the FIN is acked. 7530*14414594SDavid du Colombier+ */ 7531*14414594SDavid du Colombier+ static struct ilpcb * 7532*14414594SDavid du Colombier+ il_usrclosed(struct ilpcb *ilpcb) 7533*14414594SDavid du Colombier+ { 7534*14414594SDavid du Colombier+ 7535*14414594SDavid du Colombier+ switch (ilpcb->state) { 7536*14414594SDavid du Colombier+ case ILS_CLOSED: 7537*14414594SDavid du Colombier+ case ILS_LISTENING: 7538*14414594SDavid du Colombier+ ilpcb->state = ILS_CLOSED; 7539*14414594SDavid du Colombier+ ilpcb = il_close(ilpcb); 7540*14414594SDavid du Colombier+ break; 7541*14414594SDavid du Colombier+ 7542*14414594SDavid du Colombier+ case ILS_SYNCER: 7543*14414594SDavid du Colombier+ case ILS_SYNCEE: 7544*14414594SDavid du Colombier+ case ILS_ESTABLISHED: 7545*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_CLOSE, 0); 7546*14414594SDavid du Colombier+ ilpcb->state = ILS_CLOSING; 7547*14414594SDavid du Colombier+ break; 7548*14414594SDavid du Colombier+ 7549*14414594SDavid du Colombier+ case ILS_CLOSING: 7550*14414594SDavid du Colombier+ break; 7551*14414594SDavid du Colombier+ } 7552*14414594SDavid du Colombier+ return (ilpcb); 7553*14414594SDavid du Colombier+ } 7554*14414594SDavid du Colombier+ 7555*14414594SDavid du Colombier+ /* 7556*14414594SDavid du Colombier+ * Drop a TCP connection, reporting 7557*14414594SDavid du Colombier+ * the specified error. If connection is synchronized, 7558*14414594SDavid du Colombier+ * then send a RST to peer. 7559*14414594SDavid du Colombier+ */ 7560*14414594SDavid du Colombier+ struct ilpcb * 7561*14414594SDavid du Colombier+ il_drop(ilpcb, errno0) 7562*14414594SDavid du Colombier+ register struct ilpcb *ilpcb; 7563*14414594SDavid du Colombier+ int errno0; 7564*14414594SDavid du Colombier+ { 7565*14414594SDavid du Colombier+ struct socket *so = ilpcb->inpcb->inp_socket; 7566*14414594SDavid du Colombier+ 7567*14414594SDavid du Colombier+ panic("il_drop"); 7568*14414594SDavid du Colombier+ 7569*14414594SDavid du Colombier+ switch(ilpcb->state) { 7570*14414594SDavid du Colombier+ case ILS_SYNCEE: 7571*14414594SDavid du Colombier+ case ILS_ESTABLISHED: 7572*14414594SDavid du Colombier+ case ILS_CLOSING: 7573*14414594SDavid du Colombier+ il_send_empty(ilpcb, ILT_CLOSE, 0); 7574*14414594SDavid du Colombier+ default: 7575*14414594SDavid du Colombier+ break; 7576*14414594SDavid du Colombier+ } 7577*14414594SDavid du Colombier+ ilpcb->state = ILS_CLOSED; 7578*14414594SDavid du Colombier+ so->so_error = errno0; 7579*14414594SDavid du Colombier+ return (il_close(ilpcb)); 7580*14414594SDavid du Colombier+ } 7581*14414594SDavid du Colombier+ 7582*14414594SDavid du Colombier+ /* 7583*14414594SDavid du Colombier+ * Initiate (or continue) disconnect. 7584*14414594SDavid du Colombier+ * If embryonic state, just send reset (once). 7585*14414594SDavid du Colombier+ * If in ``let data drain'' option and linger null, just drop. 7586*14414594SDavid du Colombier+ * Otherwise (hard), mark socket disconnecting and drop 7587*14414594SDavid du Colombier+ * current input data; switch states based on user close, and 7588*14414594SDavid du Colombier+ * send segment to peer (with FIN). 7589*14414594SDavid du Colombier+ */ 7590*14414594SDavid du Colombier+ static struct ilpcb * 7591*14414594SDavid du Colombier+ il_disconnect(struct ilpcb *ilpcb) 7592*14414594SDavid du Colombier+ { 7593*14414594SDavid du Colombier+ struct socket *so = ilpcb->inpcb->inp_socket; 7594*14414594SDavid du Colombier+ 7595*14414594SDavid du Colombier+ soisdisconnecting(so); 7596*14414594SDavid du Colombier+ sbflush(&so->so_rcv); 7597*14414594SDavid du Colombier+ ilpcb = il_usrclosed(ilpcb); 7598*14414594SDavid du Colombier+ 7599*14414594SDavid du Colombier+ return (ilpcb); 7600*14414594SDavid du Colombier+ } 7601*14414594SDavid du Colombier+ 7602*14414594SDavid du Colombier+ 7603*14414594SDavid du Colombier+ /* 7604*14414594SDavid du Colombier+ * pru_detach() detaches the IL protocol from the socket. 7605*14414594SDavid du Colombier+ * If the protocol state is non-embryonic, then can't 7606*14414594SDavid du Colombier+ * do this directly: have to initiate a pru_disconnect(), 7607*14414594SDavid du Colombier+ * which may finish later; embryonic TCB's can just 7608*14414594SDavid du Colombier+ * be discarded here. 7609*14414594SDavid du Colombier+ */ 7610*14414594SDavid du Colombier+ static int 7611*14414594SDavid du Colombier+ il_usr_detach(struct socket *so) 7612*14414594SDavid du Colombier+ { 7613*14414594SDavid du Colombier+ int s = splnet(); 7614*14414594SDavid du Colombier+ int error = 0; 7615*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7616*14414594SDavid du Colombier+ struct ilpcb *ilpcb; 7617*14414594SDavid du Colombier+ 7618*14414594SDavid du Colombier+ if (inp == 0) { 7619*14414594SDavid du Colombier+ splx(s); 7620*14414594SDavid du Colombier+ return EINVAL; /* XXX */ 7621*14414594SDavid du Colombier+ } 7622*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7623*14414594SDavid du Colombier+ ilpcb = il_disconnect(ilpcb); 7624*14414594SDavid du Colombier+ splx(s); 7625*14414594SDavid du Colombier+ return error; 7626*14414594SDavid du Colombier+ } 7627*14414594SDavid du Colombier+ 7628*14414594SDavid du Colombier+ /* 7629*14414594SDavid du Colombier+ * Mark the connection as being incapable of further output. 7630*14414594SDavid du Colombier+ */ 7631*14414594SDavid du Colombier+ static int 7632*14414594SDavid du Colombier+ il_usr_shutdown(struct socket *so) 7633*14414594SDavid du Colombier+ { 7634*14414594SDavid du Colombier+ int s = splnet(); 7635*14414594SDavid du Colombier+ int error = 0; 7636*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7637*14414594SDavid du Colombier+ struct ilpcb *ilpcb; 7638*14414594SDavid du Colombier+ 7639*14414594SDavid du Colombier+ if (inp == 0) { 7640*14414594SDavid du Colombier+ splx(s); 7641*14414594SDavid du Colombier+ return EINVAL; 7642*14414594SDavid du Colombier+ } 7643*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7644*14414594SDavid du Colombier+ 7645*14414594SDavid du Colombier+ socantsendmore(so); 7646*14414594SDavid du Colombier+ ilpcb = il_usrclosed(ilpcb); 7647*14414594SDavid du Colombier+ splx(s); 7648*14414594SDavid du Colombier+ return error; 7649*14414594SDavid du Colombier+ } 7650*14414594SDavid du Colombier+ 7651*14414594SDavid du Colombier+ /* 7652*14414594SDavid du Colombier+ * Initiate disconnect from peer. 7653*14414594SDavid du Colombier+ * If connection never passed embryonic stage, just drop; 7654*14414594SDavid du Colombier+ * else if don't need to let data drain, then can just drop anyways, 7655*14414594SDavid du Colombier+ * else have to begin TCP shutdown process: mark socket disconnecting, 7656*14414594SDavid du Colombier+ * drain unread data, state switch to reflect user close, and 7657*14414594SDavid du Colombier+ * send segment (e.g. FIN) to peer. Socket will be really disconnected 7658*14414594SDavid du Colombier+ * when peer sends FIN and acks ours. 7659*14414594SDavid du Colombier+ * 7660*14414594SDavid du Colombier+ * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. 7661*14414594SDavid du Colombier+ */ 7662*14414594SDavid du Colombier+ static int 7663*14414594SDavid du Colombier+ il_usr_disconnect(struct socket *so) 7664*14414594SDavid du Colombier+ { 7665*14414594SDavid du Colombier+ int s = splnet(); 7666*14414594SDavid du Colombier+ int error = 0; 7667*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7668*14414594SDavid du Colombier+ struct ilpcb * ilpcb; 7669*14414594SDavid du Colombier+ 7670*14414594SDavid du Colombier+ if (inp == 0) { 7671*14414594SDavid du Colombier+ splx(s); 7672*14414594SDavid du Colombier+ return EINVAL; 7673*14414594SDavid du Colombier+ } 7674*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7675*14414594SDavid du Colombier+ 7676*14414594SDavid du Colombier+ il_disconnect(ilpcb); 7677*14414594SDavid du Colombier+ splx(s); 7678*14414594SDavid du Colombier+ return error; 7679*14414594SDavid du Colombier+ } 7680*14414594SDavid du Colombier+ 7681*14414594SDavid du Colombier+ /* 7682*14414594SDavid du Colombier+ * Abort the TCP. 7683*14414594SDavid du Colombier+ */ 7684*14414594SDavid du Colombier+ static int 7685*14414594SDavid du Colombier+ il_usr_abort(struct socket *so) 7686*14414594SDavid du Colombier+ { 7687*14414594SDavid du Colombier+ int s = splnet(); 7688*14414594SDavid du Colombier+ int error = 0; 7689*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7690*14414594SDavid du Colombier+ struct ilpcb * ilpcb; 7691*14414594SDavid du Colombier+ 7692*14414594SDavid du Colombier+ if (inp == 0) { 7693*14414594SDavid du Colombier+ splx(s); 7694*14414594SDavid du Colombier+ return EINVAL; 7695*14414594SDavid du Colombier+ } 7696*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7697*14414594SDavid du Colombier+ 7698*14414594SDavid du Colombier+ ilpcb = il_drop(ilpcb, ECONNABORTED); 7699*14414594SDavid du Colombier+ splx(s); 7700*14414594SDavid du Colombier+ return error; 7701*14414594SDavid du Colombier+ 7702*14414594SDavid du Colombier+ } 7703*14414594SDavid du Colombier+ 7704*14414594SDavid du Colombier+ /* 7705*14414594SDavid du Colombier+ * Prepare to accept connections. 7706*14414594SDavid du Colombier+ */ 7707*14414594SDavid du Colombier+ static int 7708*14414594SDavid du Colombier+ il_usr_listen(struct socket *so, struct proc *p) 7709*14414594SDavid du Colombier+ { 7710*14414594SDavid du Colombier+ int s = splnet(); 7711*14414594SDavid du Colombier+ int error = 0; 7712*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7713*14414594SDavid du Colombier+ struct ilpcb *ilpcb; 7714*14414594SDavid du Colombier+ 7715*14414594SDavid du Colombier+ if (inp == 0) { 7716*14414594SDavid du Colombier+ splx(s); 7717*14414594SDavid du Colombier+ return EINVAL; 7718*14414594SDavid du Colombier+ } 7719*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7720*14414594SDavid du Colombier+ 7721*14414594SDavid du Colombier+ if (inp->inp_lport == 0) 7722*14414594SDavid du Colombier+ error = in_pcbbind(inp, (struct sockaddr *)0, p); 7723*14414594SDavid du Colombier+ if (error == 0) 7724*14414594SDavid du Colombier+ ilpcb->state = ILS_LISTENING; 7725*14414594SDavid du Colombier+ 7726*14414594SDavid du Colombier+ splx(s); 7727*14414594SDavid du Colombier+ return error; 7728*14414594SDavid du Colombier+ } 7729*14414594SDavid du Colombier+ 7730*14414594SDavid du Colombier+ /* 7731*14414594SDavid du Colombier+ * Accept a connection. Essentially all the work is 7732*14414594SDavid du Colombier+ * done at higher levels; just return the address 7733*14414594SDavid du Colombier+ * of the peer, storing through addr. 7734*14414594SDavid du Colombier+ */ 7735*14414594SDavid du Colombier+ static int 7736*14414594SDavid du Colombier+ il_usr_accept(struct socket *so, struct sockaddr **nam) 7737*14414594SDavid du Colombier+ { 7738*14414594SDavid du Colombier+ int s = splnet(); 7739*14414594SDavid du Colombier+ int error = 0; 7740*14414594SDavid du Colombier+ struct inpcb *inp = sotoinpcb(so); 7741*14414594SDavid du Colombier+ struct ilpcb * ilpcb; 7742*14414594SDavid du Colombier+ 7743*14414594SDavid du Colombier+ if (inp == 0) { 7744*14414594SDavid du Colombier+ splx(s); 7745*14414594SDavid du Colombier+ return EINVAL; 7746*14414594SDavid du Colombier+ } 7747*14414594SDavid du Colombier+ ilpcb = intoilpcb(inp); 7748*14414594SDavid du Colombier+ 7749*14414594SDavid du Colombier+ in_setpeeraddr(so, nam); 7750*14414594SDavid du Colombier+ splx(s); 7751*14414594SDavid du Colombier+ return error; 7752*14414594SDavid du Colombier+ } 7753*14414594SDavid du Colombier+ 7754*14414594SDavid du Colombier+ /* xxx - should be const */ 7755*14414594SDavid du Colombier+ struct pr_usrreqs il_usrreqs = { 7756*14414594SDavid du Colombier+ il_usr_abort, il_usr_accept, il_usr_attach, il_usr_bind, 7757*14414594SDavid du Colombier+ il_usr_connect, pru_connect2_notsupp, in_control, il_usr_detach, 7758*14414594SDavid du Colombier+ il_usr_disconnect, il_usr_listen, in_setpeeraddr, pru_rcvd_notsupp, 7759*14414594SDavid du Colombier+ pru_rcvoob_notsupp, il_usr_send, pru_sense_null, il_usr_shutdown, 7760*14414594SDavid du Colombier+ in_setsockaddr, sosend, soreceive, sopoll 7761*14414594SDavid du Colombier+ }; 7762*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/il.h ./netinet/il.h 7763*14414594SDavid du Colombier*** /usr/src/sys/netinet/il.h Wed Dec 31 19:00:00 1969 7764*14414594SDavid du Colombier--- ./netinet/il.h Thu Sep 30 11:24:51 1999 7765*14414594SDavid du Colombier*************** 7766*14414594SDavid du Colombier*** 0 **** 7767*14414594SDavid du Colombier--- 1,17 ---- 7768*14414594SDavid du Colombier+ 7769*14414594SDavid du Colombier+ #ifndef NETINET_IL_H_ 7770*14414594SDavid du Colombier+ #define NETINET_IL_H_ 7771*14414594SDavid du Colombier+ 7772*14414594SDavid du Colombier+ struct ilhdr 7773*14414594SDavid du Colombier+ { 7774*14414594SDavid du Colombier+ u_char ilsum[2]; /* Checksum including header */ 7775*14414594SDavid du Colombier+ u_char illen[2]; /* Packet length */ 7776*14414594SDavid du Colombier+ u_char iltype; /* Packet type */ 7777*14414594SDavid du Colombier+ u_char ilspec; /* Special */ 7778*14414594SDavid du Colombier+ u_char ilsrc[2]; /* Src port */ 7779*14414594SDavid du Colombier+ u_char ildst[2]; /* Dst port */ 7780*14414594SDavid du Colombier+ u_char ilid[4]; /* Sequence id */ 7781*14414594SDavid du Colombier+ u_char ilack[4]; /* Acked sequence */ 7782*14414594SDavid du Colombier+ }; 7783*14414594SDavid du Colombier+ 7784*14414594SDavid du Colombier+ #endif 7785*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/il_var.h ./netinet/il_var.h 7786*14414594SDavid du Colombier*** /usr/src/sys/netinet/il_var.h Wed Dec 31 19:00:00 1969 7787*14414594SDavid du Colombier--- ./netinet/il_var.h Thu Oct 7 10:45:05 1999 7788*14414594SDavid du Colombier*************** 7789*14414594SDavid du Colombier*** 0 **** 7790*14414594SDavid du Colombier--- 1,46 ---- 7791*14414594SDavid du Colombier+ #ifndef NETINET_IL_VAR_H_ 7792*14414594SDavid du Colombier+ #define NETINET_IL_VAR_H_ 7793*14414594SDavid du Colombier+ 7794*14414594SDavid du Colombier+ struct ilpcb /* Control block */ 7795*14414594SDavid du Colombier+ { 7796*14414594SDavid du Colombier+ int state; /* Connection state */ 7797*14414594SDavid du Colombier+ struct inpcb * inpcb; /* back pointer to internet pcb */ 7798*14414594SDavid du Colombier+ u_long unacked; 7799*14414594SDavid du Colombier+ 7800*14414594SDavid du Colombier+ #define ILF_NEEDACK 1 7801*14414594SDavid du Colombier+ u_long flags; 7802*14414594SDavid du Colombier+ 7803*14414594SDavid du Colombier+ u_long rxt_max; 7804*14414594SDavid du Colombier+ int rxt_timer; /* number of ticks to the next timeout */ 7805*14414594SDavid du Colombier+ int rxt_timer_cur; /* current rxt timer period */ 7806*14414594SDavid du Colombier+ 7807*14414594SDavid du Colombier+ int death_timer; 7808*14414594SDavid du Colombier+ int death_timer_cur; 7809*14414594SDavid du Colombier+ 7810*14414594SDavid du Colombier+ u_long next; /* Id of next to send */ 7811*14414594SDavid du Colombier+ u_long recvd; /* Last packet received */ 7812*14414594SDavid du Colombier+ 7813*14414594SDavid du Colombier+ u_long start; /* Local start id */ 7814*14414594SDavid du Colombier+ u_long rstart; /* Remote start id */ 7815*14414594SDavid du Colombier+ int rxtot; /* number of retransmits on this connection */ 7816*14414594SDavid du Colombier+ 7817*14414594SDavid du Colombier+ struct mbuf * segq; 7818*14414594SDavid du Colombier+ }; 7819*14414594SDavid du Colombier+ 7820*14414594SDavid du Colombier+ #define intoilpcb(ip) ((struct ilpcb *)(ip)->inp_ppcb) 7821*14414594SDavid du Colombier+ #define sotoilpcb(so) (intoilpcb(sotoinpcb(so))) 7822*14414594SDavid du Colombier+ 7823*14414594SDavid du Colombier+ #ifdef KERNEL 7824*14414594SDavid du Colombier+ void il_init __P((void)); 7825*14414594SDavid du Colombier+ void il_input __P((struct mbuf * m, int iphlen)); 7826*14414594SDavid du Colombier+ void il_slowtimo __P((void)); 7827*14414594SDavid du Colombier+ void il_fasttimo __P((void)); 7828*14414594SDavid du Colombier+ void il_ctlinput __P((int cmd, struct sockaddr *sa, void *vip)); 7829*14414594SDavid du Colombier+ int il_ctloutput __P((struct socket *so, struct sockopt *sopt)); 7830*14414594SDavid du Colombier+ void il_drain __P((void)); 7831*14414594SDavid du Colombier+ 7832*14414594SDavid du Colombier+ extern struct pr_usrreqs il_usrreqs; 7833*14414594SDavid du Colombier+ 7834*14414594SDavid du Colombier+ #endif 7835*14414594SDavid du Colombier+ 7836*14414594SDavid du Colombier+ #endif 7837*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/netinet/in_proto.c ./netinet/in_proto.c 7838*14414594SDavid du Colombier*** /usr/src/sys/netinet/in_proto.c Sat Aug 22 23:07:14 1998 7839*14414594SDavid du Colombier--- ./netinet/in_proto.c Wed Oct 6 17:55:12 1999 7840*14414594SDavid du Colombier*************** 7841*14414594SDavid du Colombier*** 36,41 **** 7842*14414594SDavid du Colombier--- 36,42 ---- 7843*14414594SDavid du Colombier 7844*14414594SDavid du Colombier #include "opt_ipdivert.h" 7845*14414594SDavid du Colombier #include "opt_ipx.h" 7846*14414594SDavid du Colombier+ #include "opt_inet.h" 7847*14414594SDavid du Colombier 7848*14414594SDavid du Colombier #include <sys/param.h> 7849*14414594SDavid du Colombier #include <sys/kernel.h> 7850*14414594SDavid du Colombier*************** 7851*14414594SDavid du Colombier*** 71,76 **** 7852*14414594SDavid du Colombier--- 72,82 ---- 7853*14414594SDavid du Colombier #include <netns/ns_if.h> 7854*14414594SDavid du Colombier #endif 7855*14414594SDavid du Colombier 7856*14414594SDavid du Colombier+ #ifdef IL 7857*14414594SDavid du Colombier+ #include <netinet/il.h> 7858*14414594SDavid du Colombier+ #include <netinet/il_var.h> 7859*14414594SDavid du Colombier+ #endif 7860*14414594SDavid du Colombier+ 7861*14414594SDavid du Colombier extern struct domain inetdomain; 7862*14414594SDavid du Colombier static struct pr_usrreqs nousrreqs; 7863*14414594SDavid du Colombier 7864*14414594SDavid du Colombier*************** 7865*14414594SDavid du Colombier*** 161,166 **** 7866*14414594SDavid du Colombier--- 167,181 ---- 7867*14414594SDavid du Colombier 0, 7868*14414594SDavid du Colombier 0, 0, 0, 0, 7869*14414594SDavid du Colombier &rip_usrreqs 7870*14414594SDavid du Colombier+ }, 7871*14414594SDavid du Colombier+ #endif 7872*14414594SDavid du Colombier+ #ifdef IL 7873*14414594SDavid du Colombier+ { SOCK_SEQPACKET, &inetdomain, IPPROTO_IL, 7874*14414594SDavid du Colombier+ PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD|PR_ATOMIC, 7875*14414594SDavid du Colombier+ il_input, 0, il_ctlinput, il_ctloutput, 7876*14414594SDavid du Colombier+ 0, 7877*14414594SDavid du Colombier+ il_init, il_fasttimo, il_slowtimo, il_drain, 7878*14414594SDavid du Colombier+ &il_usrreqs 7879*14414594SDavid du Colombier }, 7880*14414594SDavid du Colombier #endif 7881*14414594SDavid du Colombier /* raw wildcard */ 7882*14414594SDavid du Colombierdiff -N -c -r /usr/src/sys/sys/vnode.h ./sys/vnode.h 7883*14414594SDavid du Colombier*** /usr/src/sys/sys/vnode.h Sat Mar 20 04:37:49 1999 7884*14414594SDavid du Colombier--- ./sys/vnode.h Fri Oct 15 17:44:42 1999 7885*14414594SDavid du Colombier*************** 7886*14414594SDavid du Colombier*** 62,68 **** 7887*14414594SDavid du Colombier enum vtagtype { 7888*14414594SDavid du Colombier VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PC, VT_LFS, VT_LOFS, VT_FDESC, 7889*14414594SDavid du Colombier VT_PORTAL, VT_NULL, VT_UMAP, VT_KERNFS, VT_PROCFS, VT_AFS, VT_ISOFS, 7890*14414594SDavid du Colombier! VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS, VT_VFS, VT_CODA, VT_NTFS 7891*14414594SDavid du Colombier }; 7892*14414594SDavid du Colombier 7893*14414594SDavid du Colombier /* 7894*14414594SDavid du Colombier--- 62,68 ---- 7895*14414594SDavid du Colombier enum vtagtype { 7896*14414594SDavid du Colombier VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PC, VT_LFS, VT_LOFS, VT_FDESC, 7897*14414594SDavid du Colombier VT_PORTAL, VT_NULL, VT_UMAP, VT_KERNFS, VT_PROCFS, VT_AFS, VT_ISOFS, 7898*14414594SDavid du Colombier! VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS, VT_VFS, VT_CODA, VT_NTFS, VT_U9FS 7899*14414594SDavid du Colombier }; 7900*14414594SDavid du Colombier 7901*14414594SDavid du Colombier /* 7902