1*8ccd4a63SDavid du Colombier #include "u.h" 2*8ccd4a63SDavid du Colombier #include "lib.h" 3*8ccd4a63SDavid du Colombier #include "dat.h" 4*8ccd4a63SDavid du Colombier #include "fns.h" 5*8ccd4a63SDavid du Colombier #include "error.h" 6*8ccd4a63SDavid du Colombier 7*8ccd4a63SDavid du Colombier #include "devip.h" 8*8ccd4a63SDavid du Colombier 9*8ccd4a63SDavid du Colombier void hnputl(void *p, unsigned long v); 10*8ccd4a63SDavid du Colombier void hnputs(void *p, unsigned short v); 11*8ccd4a63SDavid du Colombier unsigned long nhgetl(void *p); 12*8ccd4a63SDavid du Colombier unsigned short nhgets(void *p); 13*8ccd4a63SDavid du Colombier unsigned long parseip(char *to, char *from); 14*8ccd4a63SDavid du Colombier void csclose(Chan*); 15*8ccd4a63SDavid du Colombier long csread(Chan*, void*, long, vlong); 16*8ccd4a63SDavid du Colombier long cswrite(Chan*, void*, long, vlong); 17*8ccd4a63SDavid du Colombier 18*8ccd4a63SDavid du Colombier void osipinit(void); 19*8ccd4a63SDavid du Colombier 20*8ccd4a63SDavid du Colombier enum 21*8ccd4a63SDavid du Colombier { 22*8ccd4a63SDavid du Colombier Qtopdir = 1, /* top level directory */ 23*8ccd4a63SDavid du Colombier Qcs, 24*8ccd4a63SDavid du Colombier Qprotodir, /* directory for a protocol */ 25*8ccd4a63SDavid du Colombier Qclonus, 26*8ccd4a63SDavid du Colombier Qconvdir, /* directory for a conversation */ 27*8ccd4a63SDavid du Colombier Qdata, 28*8ccd4a63SDavid du Colombier Qctl, 29*8ccd4a63SDavid du Colombier Qstatus, 30*8ccd4a63SDavid du Colombier Qremote, 31*8ccd4a63SDavid du Colombier Qlocal, 32*8ccd4a63SDavid du Colombier Qlisten, 33*8ccd4a63SDavid du Colombier 34*8ccd4a63SDavid du Colombier MAXPROTO = 4 35*8ccd4a63SDavid du Colombier }; 36*8ccd4a63SDavid du Colombier #define TYPE(x) ((int)((x).path & 0xf)) 37*8ccd4a63SDavid du Colombier #define CONV(x) ((int)(((x).path >> 4)&0xfff)) 38*8ccd4a63SDavid du Colombier #define PROTO(x) ((int)(((x).path >> 16)&0xff)) 39*8ccd4a63SDavid du Colombier #define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y)) 40*8ccd4a63SDavid du Colombier 41*8ccd4a63SDavid du Colombier typedef struct Proto Proto; 42*8ccd4a63SDavid du Colombier typedef struct Conv Conv; 43*8ccd4a63SDavid du Colombier struct Conv 44*8ccd4a63SDavid du Colombier { 45*8ccd4a63SDavid du Colombier int x; 46*8ccd4a63SDavid du Colombier Ref r; 47*8ccd4a63SDavid du Colombier int sfd; 48*8ccd4a63SDavid du Colombier int perm; 49*8ccd4a63SDavid du Colombier char owner[KNAMELEN]; 50*8ccd4a63SDavid du Colombier char* state; 51*8ccd4a63SDavid du Colombier ulong laddr; 52*8ccd4a63SDavid du Colombier ushort lport; 53*8ccd4a63SDavid du Colombier ulong raddr; 54*8ccd4a63SDavid du Colombier ushort rport; 55*8ccd4a63SDavid du Colombier int restricted; 56*8ccd4a63SDavid du Colombier char cerr[KNAMELEN]; 57*8ccd4a63SDavid du Colombier Proto* p; 58*8ccd4a63SDavid du Colombier }; 59*8ccd4a63SDavid du Colombier 60*8ccd4a63SDavid du Colombier struct Proto 61*8ccd4a63SDavid du Colombier { 62*8ccd4a63SDavid du Colombier Lock l; 63*8ccd4a63SDavid du Colombier int x; 64*8ccd4a63SDavid du Colombier int stype; 65*8ccd4a63SDavid du Colombier char name[KNAMELEN]; 66*8ccd4a63SDavid du Colombier int nc; 67*8ccd4a63SDavid du Colombier int maxconv; 68*8ccd4a63SDavid du Colombier Conv** conv; 69*8ccd4a63SDavid du Colombier Qid qid; 70*8ccd4a63SDavid du Colombier }; 71*8ccd4a63SDavid du Colombier 72*8ccd4a63SDavid du Colombier static int np; 73*8ccd4a63SDavid du Colombier static Proto proto[MAXPROTO]; 74*8ccd4a63SDavid du Colombier int eipfmt(Fmt*); 75*8ccd4a63SDavid du Colombier 76*8ccd4a63SDavid du Colombier static Conv* protoclone(Proto*, char*, int); 77*8ccd4a63SDavid du Colombier static void setladdr(Conv*); 78*8ccd4a63SDavid du Colombier 79*8ccd4a63SDavid du Colombier int 80*8ccd4a63SDavid du Colombier ipgen(Chan *c, char *nname, Dirtab *d, int nd, int s, Dir *dp) 81*8ccd4a63SDavid du Colombier { 82*8ccd4a63SDavid du Colombier Qid q; 83*8ccd4a63SDavid du Colombier Conv *cv; 84*8ccd4a63SDavid du Colombier char *p; 85*8ccd4a63SDavid du Colombier 86*8ccd4a63SDavid du Colombier USED(nname); 87*8ccd4a63SDavid du Colombier q.vers = 0; 88*8ccd4a63SDavid du Colombier q.type = 0; 89*8ccd4a63SDavid du Colombier switch(TYPE(c->qid)) { 90*8ccd4a63SDavid du Colombier case Qtopdir: 91*8ccd4a63SDavid du Colombier if(s >= 1+np) 92*8ccd4a63SDavid du Colombier return -1; 93*8ccd4a63SDavid du Colombier 94*8ccd4a63SDavid du Colombier if(s == 0){ 95*8ccd4a63SDavid du Colombier q.path = QID(s, 0, Qcs); 96*8ccd4a63SDavid du Colombier devdir(c, q, "cs", 0, "network", 0666, dp); 97*8ccd4a63SDavid du Colombier }else{ 98*8ccd4a63SDavid du Colombier s--; 99*8ccd4a63SDavid du Colombier q.path = QID(s, 0, Qprotodir); 100*8ccd4a63SDavid du Colombier q.type = QTDIR; 101*8ccd4a63SDavid du Colombier devdir(c, q, proto[s].name, 0, "network", DMDIR|0555, dp); 102*8ccd4a63SDavid du Colombier } 103*8ccd4a63SDavid du Colombier return 1; 104*8ccd4a63SDavid du Colombier case Qprotodir: 105*8ccd4a63SDavid du Colombier if(s < proto[PROTO(c->qid)].nc) { 106*8ccd4a63SDavid du Colombier cv = proto[PROTO(c->qid)].conv[s]; 107*8ccd4a63SDavid du Colombier sprint(up->genbuf, "%d", s); 108*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), s, Qconvdir); 109*8ccd4a63SDavid du Colombier q.type = QTDIR; 110*8ccd4a63SDavid du Colombier devdir(c, q, up->genbuf, 0, cv->owner, DMDIR|0555, dp); 111*8ccd4a63SDavid du Colombier return 1; 112*8ccd4a63SDavid du Colombier } 113*8ccd4a63SDavid du Colombier s -= proto[PROTO(c->qid)].nc; 114*8ccd4a63SDavid du Colombier switch(s) { 115*8ccd4a63SDavid du Colombier default: 116*8ccd4a63SDavid du Colombier return -1; 117*8ccd4a63SDavid du Colombier case 0: 118*8ccd4a63SDavid du Colombier p = "clone"; 119*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), 0, Qclonus); 120*8ccd4a63SDavid du Colombier break; 121*8ccd4a63SDavid du Colombier } 122*8ccd4a63SDavid du Colombier devdir(c, q, p, 0, "network", 0555, dp); 123*8ccd4a63SDavid du Colombier return 1; 124*8ccd4a63SDavid du Colombier case Qconvdir: 125*8ccd4a63SDavid du Colombier cv = proto[PROTO(c->qid)].conv[CONV(c->qid)]; 126*8ccd4a63SDavid du Colombier switch(s) { 127*8ccd4a63SDavid du Colombier default: 128*8ccd4a63SDavid du Colombier return -1; 129*8ccd4a63SDavid du Colombier case 0: 130*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), CONV(c->qid), Qdata); 131*8ccd4a63SDavid du Colombier devdir(c, q, "data", 0, cv->owner, cv->perm, dp); 132*8ccd4a63SDavid du Colombier return 1; 133*8ccd4a63SDavid du Colombier case 1: 134*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), CONV(c->qid), Qctl); 135*8ccd4a63SDavid du Colombier devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp); 136*8ccd4a63SDavid du Colombier return 1; 137*8ccd4a63SDavid du Colombier case 2: 138*8ccd4a63SDavid du Colombier p = "status"; 139*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), CONV(c->qid), Qstatus); 140*8ccd4a63SDavid du Colombier break; 141*8ccd4a63SDavid du Colombier case 3: 142*8ccd4a63SDavid du Colombier p = "remote"; 143*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), CONV(c->qid), Qremote); 144*8ccd4a63SDavid du Colombier break; 145*8ccd4a63SDavid du Colombier case 4: 146*8ccd4a63SDavid du Colombier p = "local"; 147*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), CONV(c->qid), Qlocal); 148*8ccd4a63SDavid du Colombier break; 149*8ccd4a63SDavid du Colombier case 5: 150*8ccd4a63SDavid du Colombier p = "listen"; 151*8ccd4a63SDavid du Colombier q.path = QID(PROTO(c->qid), CONV(c->qid), Qlisten); 152*8ccd4a63SDavid du Colombier break; 153*8ccd4a63SDavid du Colombier } 154*8ccd4a63SDavid du Colombier devdir(c, q, p, 0, cv->owner, 0444, dp); 155*8ccd4a63SDavid du Colombier return 1; 156*8ccd4a63SDavid du Colombier } 157*8ccd4a63SDavid du Colombier return -1; 158*8ccd4a63SDavid du Colombier } 159*8ccd4a63SDavid du Colombier 160*8ccd4a63SDavid du Colombier static void 161*8ccd4a63SDavid du Colombier newproto(char *name, int type, int maxconv) 162*8ccd4a63SDavid du Colombier { 163*8ccd4a63SDavid du Colombier int l; 164*8ccd4a63SDavid du Colombier Proto *p; 165*8ccd4a63SDavid du Colombier 166*8ccd4a63SDavid du Colombier if(np >= MAXPROTO) { 167*8ccd4a63SDavid du Colombier print("no %s: increase MAXPROTO", name); 168*8ccd4a63SDavid du Colombier return; 169*8ccd4a63SDavid du Colombier } 170*8ccd4a63SDavid du Colombier 171*8ccd4a63SDavid du Colombier p = &proto[np]; 172*8ccd4a63SDavid du Colombier strcpy(p->name, name); 173*8ccd4a63SDavid du Colombier p->stype = type; 174*8ccd4a63SDavid du Colombier p->qid.path = QID(np, 0, Qprotodir); 175*8ccd4a63SDavid du Colombier p->qid.type = QTDIR; 176*8ccd4a63SDavid du Colombier p->x = np++; 177*8ccd4a63SDavid du Colombier p->maxconv = maxconv; 178*8ccd4a63SDavid du Colombier l = sizeof(Conv*)*(p->maxconv+1); 179*8ccd4a63SDavid du Colombier p->conv = mallocz(l, 1); 180*8ccd4a63SDavid du Colombier if(p->conv == 0) 181*8ccd4a63SDavid du Colombier panic("no memory"); 182*8ccd4a63SDavid du Colombier } 183*8ccd4a63SDavid du Colombier 184*8ccd4a63SDavid du Colombier void 185*8ccd4a63SDavid du Colombier ipinit(void) 186*8ccd4a63SDavid du Colombier { 187*8ccd4a63SDavid du Colombier osipinit(); 188*8ccd4a63SDavid du Colombier 189*8ccd4a63SDavid du Colombier newproto("udp", S_UDP, 10); 190*8ccd4a63SDavid du Colombier newproto("tcp", S_TCP, 30); 191*8ccd4a63SDavid du Colombier 192*8ccd4a63SDavid du Colombier fmtinstall('I', eipfmt); 193*8ccd4a63SDavid du Colombier fmtinstall('E', eipfmt); 194*8ccd4a63SDavid du Colombier 195*8ccd4a63SDavid du Colombier } 196*8ccd4a63SDavid du Colombier 197*8ccd4a63SDavid du Colombier Chan * 198*8ccd4a63SDavid du Colombier ipattach(char *spec) 199*8ccd4a63SDavid du Colombier { 200*8ccd4a63SDavid du Colombier Chan *c; 201*8ccd4a63SDavid du Colombier 202*8ccd4a63SDavid du Colombier c = devattach('I', spec); 203*8ccd4a63SDavid du Colombier c->qid.path = QID(0, 0, Qtopdir); 204*8ccd4a63SDavid du Colombier c->qid.type = QTDIR; 205*8ccd4a63SDavid du Colombier c->qid.vers = 0; 206*8ccd4a63SDavid du Colombier return c; 207*8ccd4a63SDavid du Colombier } 208*8ccd4a63SDavid du Colombier 209*8ccd4a63SDavid du Colombier static Walkqid* 210*8ccd4a63SDavid du Colombier ipwalk(Chan *c, Chan *nc, char **name, int nname) 211*8ccd4a63SDavid du Colombier { 212*8ccd4a63SDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, ipgen); 213*8ccd4a63SDavid du Colombier } 214*8ccd4a63SDavid du Colombier 215*8ccd4a63SDavid du Colombier int 216*8ccd4a63SDavid du Colombier ipstat(Chan *c, uchar *dp, int n) 217*8ccd4a63SDavid du Colombier { 218*8ccd4a63SDavid du Colombier return devstat(c, dp, n, 0, 0, ipgen); 219*8ccd4a63SDavid du Colombier } 220*8ccd4a63SDavid du Colombier 221*8ccd4a63SDavid du Colombier Chan * 222*8ccd4a63SDavid du Colombier ipopen(Chan *c, int omode) 223*8ccd4a63SDavid du Colombier { 224*8ccd4a63SDavid du Colombier Proto *p; 225*8ccd4a63SDavid du Colombier ulong raddr; 226*8ccd4a63SDavid du Colombier ushort rport; 227*8ccd4a63SDavid du Colombier int perm, sfd; 228*8ccd4a63SDavid du Colombier Conv *cv, *lcv; 229*8ccd4a63SDavid du Colombier 230*8ccd4a63SDavid du Colombier omode &= 3; 231*8ccd4a63SDavid du Colombier perm = 0; 232*8ccd4a63SDavid du Colombier switch(omode) { 233*8ccd4a63SDavid du Colombier case OREAD: 234*8ccd4a63SDavid du Colombier perm = 4; 235*8ccd4a63SDavid du Colombier break; 236*8ccd4a63SDavid du Colombier case OWRITE: 237*8ccd4a63SDavid du Colombier perm = 2; 238*8ccd4a63SDavid du Colombier break; 239*8ccd4a63SDavid du Colombier case ORDWR: 240*8ccd4a63SDavid du Colombier perm = 6; 241*8ccd4a63SDavid du Colombier break; 242*8ccd4a63SDavid du Colombier } 243*8ccd4a63SDavid du Colombier 244*8ccd4a63SDavid du Colombier switch(TYPE(c->qid)) { 245*8ccd4a63SDavid du Colombier default: 246*8ccd4a63SDavid du Colombier break; 247*8ccd4a63SDavid du Colombier case Qtopdir: 248*8ccd4a63SDavid du Colombier case Qprotodir: 249*8ccd4a63SDavid du Colombier case Qconvdir: 250*8ccd4a63SDavid du Colombier case Qstatus: 251*8ccd4a63SDavid du Colombier case Qremote: 252*8ccd4a63SDavid du Colombier case Qlocal: 253*8ccd4a63SDavid du Colombier if(omode != OREAD) 254*8ccd4a63SDavid du Colombier error(Eperm); 255*8ccd4a63SDavid du Colombier break; 256*8ccd4a63SDavid du Colombier case Qclonus: 257*8ccd4a63SDavid du Colombier p = &proto[PROTO(c->qid)]; 258*8ccd4a63SDavid du Colombier cv = protoclone(p, up->user, -1); 259*8ccd4a63SDavid du Colombier if(cv == 0) 260*8ccd4a63SDavid du Colombier error(Enodev); 261*8ccd4a63SDavid du Colombier c->qid.path = QID(p->x, cv->x, Qctl); 262*8ccd4a63SDavid du Colombier c->qid.vers = 0; 263*8ccd4a63SDavid du Colombier break; 264*8ccd4a63SDavid du Colombier case Qdata: 265*8ccd4a63SDavid du Colombier case Qctl: 266*8ccd4a63SDavid du Colombier p = &proto[PROTO(c->qid)]; 267*8ccd4a63SDavid du Colombier lock(&p->l); 268*8ccd4a63SDavid du Colombier cv = p->conv[CONV(c->qid)]; 269*8ccd4a63SDavid du Colombier lock(&cv->r.lk); 270*8ccd4a63SDavid du Colombier if((perm & (cv->perm>>6)) != perm) { 271*8ccd4a63SDavid du Colombier if(strcmp(up->user, cv->owner) != 0 || 272*8ccd4a63SDavid du Colombier (perm & cv->perm) != perm) { 273*8ccd4a63SDavid du Colombier unlock(&cv->r.lk); 274*8ccd4a63SDavid du Colombier unlock(&p->l); 275*8ccd4a63SDavid du Colombier error(Eperm); 276*8ccd4a63SDavid du Colombier } 277*8ccd4a63SDavid du Colombier } 278*8ccd4a63SDavid du Colombier cv->r.ref++; 279*8ccd4a63SDavid du Colombier if(cv->r.ref == 1) { 280*8ccd4a63SDavid du Colombier memmove(cv->owner, up->user, KNAMELEN); 281*8ccd4a63SDavid du Colombier cv->perm = 0660; 282*8ccd4a63SDavid du Colombier } 283*8ccd4a63SDavid du Colombier unlock(&cv->r.lk); 284*8ccd4a63SDavid du Colombier unlock(&p->l); 285*8ccd4a63SDavid du Colombier break; 286*8ccd4a63SDavid du Colombier case Qlisten: 287*8ccd4a63SDavid du Colombier p = &proto[PROTO(c->qid)]; 288*8ccd4a63SDavid du Colombier lcv = p->conv[CONV(c->qid)]; 289*8ccd4a63SDavid du Colombier sfd = so_accept(lcv->sfd, &raddr, &rport); 290*8ccd4a63SDavid du Colombier cv = protoclone(p, up->user, sfd); 291*8ccd4a63SDavid du Colombier if(cv == 0) { 292*8ccd4a63SDavid du Colombier close(sfd); 293*8ccd4a63SDavid du Colombier error(Enodev); 294*8ccd4a63SDavid du Colombier } 295*8ccd4a63SDavid du Colombier cv->raddr = raddr; 296*8ccd4a63SDavid du Colombier cv->rport = rport; 297*8ccd4a63SDavid du Colombier setladdr(cv); 298*8ccd4a63SDavid du Colombier cv->state = "Established"; 299*8ccd4a63SDavid du Colombier c->qid.path = QID(p->x, cv->x, Qctl); 300*8ccd4a63SDavid du Colombier break; 301*8ccd4a63SDavid du Colombier } 302*8ccd4a63SDavid du Colombier c->mode = openmode(omode); 303*8ccd4a63SDavid du Colombier c->flag |= COPEN; 304*8ccd4a63SDavid du Colombier c->offset = 0; 305*8ccd4a63SDavid du Colombier return c; 306*8ccd4a63SDavid du Colombier } 307*8ccd4a63SDavid du Colombier 308*8ccd4a63SDavid du Colombier void 309*8ccd4a63SDavid du Colombier ipclose(Chan *c) 310*8ccd4a63SDavid du Colombier { 311*8ccd4a63SDavid du Colombier Conv *cc; 312*8ccd4a63SDavid du Colombier 313*8ccd4a63SDavid du Colombier switch(TYPE(c->qid)) { 314*8ccd4a63SDavid du Colombier case Qcs: 315*8ccd4a63SDavid du Colombier csclose(c); 316*8ccd4a63SDavid du Colombier break; 317*8ccd4a63SDavid du Colombier case Qdata: 318*8ccd4a63SDavid du Colombier case Qctl: 319*8ccd4a63SDavid du Colombier if((c->flag & COPEN) == 0) 320*8ccd4a63SDavid du Colombier break; 321*8ccd4a63SDavid du Colombier cc = proto[PROTO(c->qid)].conv[CONV(c->qid)]; 322*8ccd4a63SDavid du Colombier if(decref(&cc->r) != 0) 323*8ccd4a63SDavid du Colombier break; 324*8ccd4a63SDavid du Colombier strcpy(cc->owner, "network"); 325*8ccd4a63SDavid du Colombier cc->perm = 0666; 326*8ccd4a63SDavid du Colombier cc->state = "Closed"; 327*8ccd4a63SDavid du Colombier cc->laddr = 0; 328*8ccd4a63SDavid du Colombier cc->raddr = 0; 329*8ccd4a63SDavid du Colombier cc->lport = 0; 330*8ccd4a63SDavid du Colombier cc->rport = 0; 331*8ccd4a63SDavid du Colombier close(cc->sfd); 332*8ccd4a63SDavid du Colombier break; 333*8ccd4a63SDavid du Colombier } 334*8ccd4a63SDavid du Colombier } 335*8ccd4a63SDavid du Colombier 336*8ccd4a63SDavid du Colombier long 337*8ccd4a63SDavid du Colombier ipread(Chan *ch, void *a, long n, vlong offset) 338*8ccd4a63SDavid du Colombier { 339*8ccd4a63SDavid du Colombier int r; 340*8ccd4a63SDavid du Colombier Conv *c; 341*8ccd4a63SDavid du Colombier Proto *x; 342*8ccd4a63SDavid du Colombier uchar ip[4]; 343*8ccd4a63SDavid du Colombier char buf[128], *p; 344*8ccd4a63SDavid du Colombier 345*8ccd4a63SDavid du Colombier /*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/ 346*8ccd4a63SDavid du Colombier p = a; 347*8ccd4a63SDavid du Colombier switch(TYPE(ch->qid)) { 348*8ccd4a63SDavid du Colombier default: 349*8ccd4a63SDavid du Colombier error(Eperm); 350*8ccd4a63SDavid du Colombier case Qcs: 351*8ccd4a63SDavid du Colombier return csread(ch, a, n, offset); 352*8ccd4a63SDavid du Colombier case Qprotodir: 353*8ccd4a63SDavid du Colombier case Qtopdir: 354*8ccd4a63SDavid du Colombier case Qconvdir: 355*8ccd4a63SDavid du Colombier return devdirread(ch, a, n, 0, 0, ipgen); 356*8ccd4a63SDavid du Colombier case Qctl: 357*8ccd4a63SDavid du Colombier sprint(buf, "%d", CONV(ch->qid)); 358*8ccd4a63SDavid du Colombier return readstr(offset, p, n, buf); 359*8ccd4a63SDavid du Colombier case Qremote: 360*8ccd4a63SDavid du Colombier c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; 361*8ccd4a63SDavid du Colombier hnputl(ip, c->raddr); 362*8ccd4a63SDavid du Colombier sprint(buf, "%I!%d\n", ip, c->rport); 363*8ccd4a63SDavid du Colombier return readstr(offset, p, n, buf); 364*8ccd4a63SDavid du Colombier case Qlocal: 365*8ccd4a63SDavid du Colombier c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; 366*8ccd4a63SDavid du Colombier hnputl(ip, c->laddr); 367*8ccd4a63SDavid du Colombier sprint(buf, "%I!%d\n", ip, c->lport); 368*8ccd4a63SDavid du Colombier return readstr(offset, p, n, buf); 369*8ccd4a63SDavid du Colombier case Qstatus: 370*8ccd4a63SDavid du Colombier x = &proto[PROTO(ch->qid)]; 371*8ccd4a63SDavid du Colombier c = x->conv[CONV(ch->qid)]; 372*8ccd4a63SDavid du Colombier sprint(buf, "%s/%d %d %s \n", 373*8ccd4a63SDavid du Colombier c->p->name, c->x, c->r.ref, c->state); 374*8ccd4a63SDavid du Colombier return readstr(offset, p, n, buf); 375*8ccd4a63SDavid du Colombier case Qdata: 376*8ccd4a63SDavid du Colombier c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; 377*8ccd4a63SDavid du Colombier r = so_recv(c->sfd, a, n, 0); 378*8ccd4a63SDavid du Colombier if(r < 0){ 379*8ccd4a63SDavid du Colombier oserrstr(); 380*8ccd4a63SDavid du Colombier nexterror(); 381*8ccd4a63SDavid du Colombier } 382*8ccd4a63SDavid du Colombier return r; 383*8ccd4a63SDavid du Colombier } 384*8ccd4a63SDavid du Colombier } 385*8ccd4a63SDavid du Colombier 386*8ccd4a63SDavid du Colombier static void 387*8ccd4a63SDavid du Colombier setladdr(Conv *c) 388*8ccd4a63SDavid du Colombier { 389*8ccd4a63SDavid du Colombier so_getsockname(c->sfd, &c->laddr, &c->lport); 390*8ccd4a63SDavid du Colombier } 391*8ccd4a63SDavid du Colombier 392*8ccd4a63SDavid du Colombier static void 393*8ccd4a63SDavid du Colombier setlport(Conv *c) 394*8ccd4a63SDavid du Colombier { 395*8ccd4a63SDavid du Colombier if(c->restricted == 0 && c->lport == 0) 396*8ccd4a63SDavid du Colombier return; 397*8ccd4a63SDavid du Colombier 398*8ccd4a63SDavid du Colombier so_bind(c->sfd, c->restricted, c->lport); 399*8ccd4a63SDavid du Colombier } 400*8ccd4a63SDavid du Colombier 401*8ccd4a63SDavid du Colombier static void 402*8ccd4a63SDavid du Colombier setladdrport(Conv *c, char *str) 403*8ccd4a63SDavid du Colombier { 404*8ccd4a63SDavid du Colombier char *p, addr[4]; 405*8ccd4a63SDavid du Colombier 406*8ccd4a63SDavid du Colombier p = strchr(str, '!'); 407*8ccd4a63SDavid du Colombier if(p == 0) { 408*8ccd4a63SDavid du Colombier p = str; 409*8ccd4a63SDavid du Colombier c->laddr = 0; 410*8ccd4a63SDavid du Colombier } 411*8ccd4a63SDavid du Colombier else { 412*8ccd4a63SDavid du Colombier *p++ = 0; 413*8ccd4a63SDavid du Colombier parseip(addr, str); 414*8ccd4a63SDavid du Colombier c->laddr = nhgetl((uchar*)addr); 415*8ccd4a63SDavid du Colombier } 416*8ccd4a63SDavid du Colombier if(*p == '*') 417*8ccd4a63SDavid du Colombier c->lport = 0; 418*8ccd4a63SDavid du Colombier else 419*8ccd4a63SDavid du Colombier c->lport = atoi(p); 420*8ccd4a63SDavid du Colombier 421*8ccd4a63SDavid du Colombier setlport(c); 422*8ccd4a63SDavid du Colombier } 423*8ccd4a63SDavid du Colombier 424*8ccd4a63SDavid du Colombier static char* 425*8ccd4a63SDavid du Colombier setraddrport(Conv *c, char *str) 426*8ccd4a63SDavid du Colombier { 427*8ccd4a63SDavid du Colombier char *p, addr[4]; 428*8ccd4a63SDavid du Colombier 429*8ccd4a63SDavid du Colombier p = strchr(str, '!'); 430*8ccd4a63SDavid du Colombier if(p == 0) 431*8ccd4a63SDavid du Colombier return "malformed address"; 432*8ccd4a63SDavid du Colombier *p++ = 0; 433*8ccd4a63SDavid du Colombier parseip(addr, str); 434*8ccd4a63SDavid du Colombier c->raddr = nhgetl((uchar*)addr); 435*8ccd4a63SDavid du Colombier c->rport = atoi(p); 436*8ccd4a63SDavid du Colombier p = strchr(p, '!'); 437*8ccd4a63SDavid du Colombier if(p) { 438*8ccd4a63SDavid du Colombier if(strcmp(p, "!r") == 0) 439*8ccd4a63SDavid du Colombier c->restricted = 1; 440*8ccd4a63SDavid du Colombier } 441*8ccd4a63SDavid du Colombier return 0; 442*8ccd4a63SDavid du Colombier } 443*8ccd4a63SDavid du Colombier 444*8ccd4a63SDavid du Colombier long 445*8ccd4a63SDavid du Colombier ipwrite(Chan *ch, void *a, long n, vlong offset) 446*8ccd4a63SDavid du Colombier { 447*8ccd4a63SDavid du Colombier Conv *c; 448*8ccd4a63SDavid du Colombier Proto *x; 449*8ccd4a63SDavid du Colombier int r, nf; 450*8ccd4a63SDavid du Colombier char *p, *fields[3], buf[128]; 451*8ccd4a63SDavid du Colombier 452*8ccd4a63SDavid du Colombier switch(TYPE(ch->qid)) { 453*8ccd4a63SDavid du Colombier default: 454*8ccd4a63SDavid du Colombier error(Eperm); 455*8ccd4a63SDavid du Colombier case Qcs: 456*8ccd4a63SDavid du Colombier return cswrite(ch, a, n, offset); 457*8ccd4a63SDavid du Colombier case Qctl: 458*8ccd4a63SDavid du Colombier x = &proto[PROTO(ch->qid)]; 459*8ccd4a63SDavid du Colombier c = x->conv[CONV(ch->qid)]; 460*8ccd4a63SDavid du Colombier if(n > sizeof(buf)-1) 461*8ccd4a63SDavid du Colombier n = sizeof(buf)-1; 462*8ccd4a63SDavid du Colombier memmove(buf, a, n); 463*8ccd4a63SDavid du Colombier buf[n] = '\0'; 464*8ccd4a63SDavid du Colombier 465*8ccd4a63SDavid du Colombier nf = tokenize(buf, fields, 3); 466*8ccd4a63SDavid du Colombier if(strcmp(fields[0], "connect") == 0){ 467*8ccd4a63SDavid du Colombier switch(nf) { 468*8ccd4a63SDavid du Colombier default: 469*8ccd4a63SDavid du Colombier error("bad args to connect"); 470*8ccd4a63SDavid du Colombier case 2: 471*8ccd4a63SDavid du Colombier p = setraddrport(c, fields[1]); 472*8ccd4a63SDavid du Colombier if(p != 0) 473*8ccd4a63SDavid du Colombier error(p); 474*8ccd4a63SDavid du Colombier break; 475*8ccd4a63SDavid du Colombier case 3: 476*8ccd4a63SDavid du Colombier p = setraddrport(c, fields[1]); 477*8ccd4a63SDavid du Colombier if(p != 0) 478*8ccd4a63SDavid du Colombier error(p); 479*8ccd4a63SDavid du Colombier c->lport = atoi(fields[2]); 480*8ccd4a63SDavid du Colombier setlport(c); 481*8ccd4a63SDavid du Colombier break; 482*8ccd4a63SDavid du Colombier } 483*8ccd4a63SDavid du Colombier so_connect(c->sfd, c->raddr, c->rport); 484*8ccd4a63SDavid du Colombier setladdr(c); 485*8ccd4a63SDavid du Colombier c->state = "Established"; 486*8ccd4a63SDavid du Colombier return n; 487*8ccd4a63SDavid du Colombier } 488*8ccd4a63SDavid du Colombier if(strcmp(fields[0], "announce") == 0) { 489*8ccd4a63SDavid du Colombier switch(nf){ 490*8ccd4a63SDavid du Colombier default: 491*8ccd4a63SDavid du Colombier error("bad args to announce"); 492*8ccd4a63SDavid du Colombier case 2: 493*8ccd4a63SDavid du Colombier setladdrport(c, fields[1]); 494*8ccd4a63SDavid du Colombier break; 495*8ccd4a63SDavid du Colombier } 496*8ccd4a63SDavid du Colombier so_listen(c->sfd); 497*8ccd4a63SDavid du Colombier c->state = "Announced"; 498*8ccd4a63SDavid du Colombier return n; 499*8ccd4a63SDavid du Colombier } 500*8ccd4a63SDavid du Colombier if(strcmp(fields[0], "bind") == 0){ 501*8ccd4a63SDavid du Colombier switch(nf){ 502*8ccd4a63SDavid du Colombier default: 503*8ccd4a63SDavid du Colombier error("bad args to bind"); 504*8ccd4a63SDavid du Colombier case 2: 505*8ccd4a63SDavid du Colombier c->lport = atoi(fields[1]); 506*8ccd4a63SDavid du Colombier break; 507*8ccd4a63SDavid du Colombier } 508*8ccd4a63SDavid du Colombier setlport(c); 509*8ccd4a63SDavid du Colombier return n; 510*8ccd4a63SDavid du Colombier } 511*8ccd4a63SDavid du Colombier error("bad control message"); 512*8ccd4a63SDavid du Colombier case Qdata: 513*8ccd4a63SDavid du Colombier x = &proto[PROTO(ch->qid)]; 514*8ccd4a63SDavid du Colombier c = x->conv[CONV(ch->qid)]; 515*8ccd4a63SDavid du Colombier r = so_send(c->sfd, a, n, 0); 516*8ccd4a63SDavid du Colombier if(r < 0){ 517*8ccd4a63SDavid du Colombier oserrstr(); 518*8ccd4a63SDavid du Colombier nexterror(); 519*8ccd4a63SDavid du Colombier } 520*8ccd4a63SDavid du Colombier return r; 521*8ccd4a63SDavid du Colombier } 522*8ccd4a63SDavid du Colombier return n; 523*8ccd4a63SDavid du Colombier } 524*8ccd4a63SDavid du Colombier 525*8ccd4a63SDavid du Colombier static Conv* 526*8ccd4a63SDavid du Colombier protoclone(Proto *p, char *user, int nfd) 527*8ccd4a63SDavid du Colombier { 528*8ccd4a63SDavid du Colombier Conv *c, **pp, **ep; 529*8ccd4a63SDavid du Colombier 530*8ccd4a63SDavid du Colombier c = 0; 531*8ccd4a63SDavid du Colombier lock(&p->l); 532*8ccd4a63SDavid du Colombier if(waserror()) { 533*8ccd4a63SDavid du Colombier unlock(&p->l); 534*8ccd4a63SDavid du Colombier nexterror(); 535*8ccd4a63SDavid du Colombier } 536*8ccd4a63SDavid du Colombier ep = &p->conv[p->maxconv]; 537*8ccd4a63SDavid du Colombier for(pp = p->conv; pp < ep; pp++) { 538*8ccd4a63SDavid du Colombier c = *pp; 539*8ccd4a63SDavid du Colombier if(c == 0) { 540*8ccd4a63SDavid du Colombier c = mallocz(sizeof(Conv), 1); 541*8ccd4a63SDavid du Colombier if(c == 0) 542*8ccd4a63SDavid du Colombier error(Enomem); 543*8ccd4a63SDavid du Colombier lock(&c->r.lk); 544*8ccd4a63SDavid du Colombier c->r.ref = 1; 545*8ccd4a63SDavid du Colombier c->p = p; 546*8ccd4a63SDavid du Colombier c->x = pp - p->conv; 547*8ccd4a63SDavid du Colombier p->nc++; 548*8ccd4a63SDavid du Colombier *pp = c; 549*8ccd4a63SDavid du Colombier break; 550*8ccd4a63SDavid du Colombier } 551*8ccd4a63SDavid du Colombier lock(&c->r.lk); 552*8ccd4a63SDavid du Colombier if(c->r.ref == 0) { 553*8ccd4a63SDavid du Colombier c->r.ref++; 554*8ccd4a63SDavid du Colombier break; 555*8ccd4a63SDavid du Colombier } 556*8ccd4a63SDavid du Colombier unlock(&c->r.lk); 557*8ccd4a63SDavid du Colombier } 558*8ccd4a63SDavid du Colombier if(pp >= ep) { 559*8ccd4a63SDavid du Colombier unlock(&p->l); 560*8ccd4a63SDavid du Colombier poperror(); 561*8ccd4a63SDavid du Colombier return 0; 562*8ccd4a63SDavid du Colombier } 563*8ccd4a63SDavid du Colombier 564*8ccd4a63SDavid du Colombier strcpy(c->owner, user); 565*8ccd4a63SDavid du Colombier c->perm = 0660; 566*8ccd4a63SDavid du Colombier c->state = "Closed"; 567*8ccd4a63SDavid du Colombier c->restricted = 0; 568*8ccd4a63SDavid du Colombier c->laddr = 0; 569*8ccd4a63SDavid du Colombier c->raddr = 0; 570*8ccd4a63SDavid du Colombier c->lport = 0; 571*8ccd4a63SDavid du Colombier c->rport = 0; 572*8ccd4a63SDavid du Colombier c->sfd = nfd; 573*8ccd4a63SDavid du Colombier if(nfd == -1) 574*8ccd4a63SDavid du Colombier c->sfd = so_socket(p->stype); 575*8ccd4a63SDavid du Colombier 576*8ccd4a63SDavid du Colombier unlock(&c->r.lk); 577*8ccd4a63SDavid du Colombier unlock(&p->l); 578*8ccd4a63SDavid du Colombier poperror(); 579*8ccd4a63SDavid du Colombier return c; 580*8ccd4a63SDavid du Colombier } 581*8ccd4a63SDavid du Colombier 582*8ccd4a63SDavid du Colombier enum 583*8ccd4a63SDavid du Colombier { 584*8ccd4a63SDavid du Colombier Isprefix= 16, 585*8ccd4a63SDavid du Colombier }; 586*8ccd4a63SDavid du Colombier 587*8ccd4a63SDavid du Colombier uchar prefixvals[256] = 588*8ccd4a63SDavid du Colombier { 589*8ccd4a63SDavid du Colombier /*0x00*/ 0 | Isprefix, 590*8ccd4a63SDavid du Colombier 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 591*8ccd4a63SDavid du Colombier /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 592*8ccd4a63SDavid du Colombier /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 593*8ccd4a63SDavid du Colombier /*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 594*8ccd4a63SDavid du Colombier /*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 595*8ccd4a63SDavid du Colombier /*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 596*8ccd4a63SDavid du Colombier /*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 597*8ccd4a63SDavid du Colombier /*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 598*8ccd4a63SDavid du Colombier /*0x80*/ 1 | Isprefix, 599*8ccd4a63SDavid du Colombier 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600*8ccd4a63SDavid du Colombier /*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 601*8ccd4a63SDavid du Colombier /*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 602*8ccd4a63SDavid du Colombier /*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 603*8ccd4a63SDavid du Colombier /*0xC0*/ 2 | Isprefix, 604*8ccd4a63SDavid du Colombier 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 605*8ccd4a63SDavid du Colombier /*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 606*8ccd4a63SDavid du Colombier /*0xE0*/ 3 | Isprefix, 607*8ccd4a63SDavid du Colombier 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 608*8ccd4a63SDavid du Colombier /*0xF0*/ 4 | Isprefix, 609*8ccd4a63SDavid du Colombier 0, 0, 0, 0, 0, 0, 0, 610*8ccd4a63SDavid du Colombier /*0xF8*/ 5 | Isprefix, 611*8ccd4a63SDavid du Colombier 0, 0, 0, 612*8ccd4a63SDavid du Colombier /*0xFC*/ 6 | Isprefix, 613*8ccd4a63SDavid du Colombier 0, 614*8ccd4a63SDavid du Colombier /*0xFE*/ 7 | Isprefix, 615*8ccd4a63SDavid du Colombier /*0xFF*/ 8 | Isprefix, 616*8ccd4a63SDavid du Colombier }; 617*8ccd4a63SDavid du Colombier 618*8ccd4a63SDavid du Colombier int 619*8ccd4a63SDavid du Colombier eipfmt(Fmt *f) 620*8ccd4a63SDavid du Colombier { 621*8ccd4a63SDavid du Colombier char buf[5*8]; 622*8ccd4a63SDavid du Colombier static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; 623*8ccd4a63SDavid du Colombier static char *ifmt = "%d.%d.%d.%d"; 624*8ccd4a63SDavid du Colombier uchar *p, ip[16]; 625*8ccd4a63SDavid du Colombier ulong ul; 626*8ccd4a63SDavid du Colombier 627*8ccd4a63SDavid du Colombier switch(f->r) { 628*8ccd4a63SDavid du Colombier case 'E': /* Ethernet address */ 629*8ccd4a63SDavid du Colombier p = va_arg(f->args, uchar*); 630*8ccd4a63SDavid du Colombier snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); 631*8ccd4a63SDavid du Colombier return fmtstrcpy(f, buf); 632*8ccd4a63SDavid du Colombier 633*8ccd4a63SDavid du Colombier case 'I': 634*8ccd4a63SDavid du Colombier ul = va_arg(f->args, ulong); 635*8ccd4a63SDavid du Colombier hnputl(ip, ul); 636*8ccd4a63SDavid du Colombier snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]); 637*8ccd4a63SDavid du Colombier return fmtstrcpy(f, buf); 638*8ccd4a63SDavid du Colombier } 639*8ccd4a63SDavid du Colombier return fmtstrcpy(f, "(eipfmt)"); 640*8ccd4a63SDavid du Colombier } 641*8ccd4a63SDavid du Colombier 642*8ccd4a63SDavid du Colombier void 643*8ccd4a63SDavid du Colombier hnputl(void *p, unsigned long v) 644*8ccd4a63SDavid du Colombier { 645*8ccd4a63SDavid du Colombier unsigned char *a; 646*8ccd4a63SDavid du Colombier 647*8ccd4a63SDavid du Colombier a = p; 648*8ccd4a63SDavid du Colombier a[0] = v>>24; 649*8ccd4a63SDavid du Colombier a[1] = v>>16; 650*8ccd4a63SDavid du Colombier a[2] = v>>8; 651*8ccd4a63SDavid du Colombier a[3] = v; 652*8ccd4a63SDavid du Colombier } 653*8ccd4a63SDavid du Colombier 654*8ccd4a63SDavid du Colombier void 655*8ccd4a63SDavid du Colombier hnputs(void *p, unsigned short v) 656*8ccd4a63SDavid du Colombier { 657*8ccd4a63SDavid du Colombier unsigned char *a; 658*8ccd4a63SDavid du Colombier 659*8ccd4a63SDavid du Colombier a = p; 660*8ccd4a63SDavid du Colombier a[0] = v>>8; 661*8ccd4a63SDavid du Colombier a[1] = v; 662*8ccd4a63SDavid du Colombier } 663*8ccd4a63SDavid du Colombier 664*8ccd4a63SDavid du Colombier unsigned long 665*8ccd4a63SDavid du Colombier nhgetl(void *p) 666*8ccd4a63SDavid du Colombier { 667*8ccd4a63SDavid du Colombier unsigned char *a; 668*8ccd4a63SDavid du Colombier a = p; 669*8ccd4a63SDavid du Colombier return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); 670*8ccd4a63SDavid du Colombier } 671*8ccd4a63SDavid du Colombier 672*8ccd4a63SDavid du Colombier unsigned short 673*8ccd4a63SDavid du Colombier nhgets(void *p) 674*8ccd4a63SDavid du Colombier { 675*8ccd4a63SDavid du Colombier unsigned char *a; 676*8ccd4a63SDavid du Colombier a = p; 677*8ccd4a63SDavid du Colombier return (a[0]<<8)|(a[1]<<0); 678*8ccd4a63SDavid du Colombier } 679*8ccd4a63SDavid du Colombier 680*8ccd4a63SDavid du Colombier #define CLASS(p) ((*(unsigned char*)(p))>>6) 681*8ccd4a63SDavid du Colombier 682*8ccd4a63SDavid du Colombier unsigned long 683*8ccd4a63SDavid du Colombier parseip(char *to, char *from) 684*8ccd4a63SDavid du Colombier { 685*8ccd4a63SDavid du Colombier int i; 686*8ccd4a63SDavid du Colombier char *p; 687*8ccd4a63SDavid du Colombier 688*8ccd4a63SDavid du Colombier p = from; 689*8ccd4a63SDavid du Colombier memset(to, 0, 4); 690*8ccd4a63SDavid du Colombier for(i = 0; i < 4 && *p; i++){ 691*8ccd4a63SDavid du Colombier to[i] = strtoul(p, &p, 0); 692*8ccd4a63SDavid du Colombier if(*p == '.') 693*8ccd4a63SDavid du Colombier p++; 694*8ccd4a63SDavid du Colombier } 695*8ccd4a63SDavid du Colombier switch(CLASS(to)){ 696*8ccd4a63SDavid du Colombier case 0: /* class A - 1 byte net */ 697*8ccd4a63SDavid du Colombier case 1: 698*8ccd4a63SDavid du Colombier if(i == 3){ 699*8ccd4a63SDavid du Colombier to[3] = to[2]; 700*8ccd4a63SDavid du Colombier to[2] = to[1]; 701*8ccd4a63SDavid du Colombier to[1] = 0; 702*8ccd4a63SDavid du Colombier } else if (i == 2){ 703*8ccd4a63SDavid du Colombier to[3] = to[1]; 704*8ccd4a63SDavid du Colombier to[1] = 0; 705*8ccd4a63SDavid du Colombier } 706*8ccd4a63SDavid du Colombier break; 707*8ccd4a63SDavid du Colombier case 2: /* class B - 2 byte net */ 708*8ccd4a63SDavid du Colombier if(i == 3){ 709*8ccd4a63SDavid du Colombier to[3] = to[2]; 710*8ccd4a63SDavid du Colombier to[2] = 0; 711*8ccd4a63SDavid du Colombier } 712*8ccd4a63SDavid du Colombier break; 713*8ccd4a63SDavid du Colombier } 714*8ccd4a63SDavid du Colombier return nhgetl(to); 715*8ccd4a63SDavid du Colombier } 716*8ccd4a63SDavid du Colombier 717*8ccd4a63SDavid du Colombier void 718*8ccd4a63SDavid du Colombier csclose(Chan *c) 719*8ccd4a63SDavid du Colombier { 720*8ccd4a63SDavid du Colombier free(c->aux); 721*8ccd4a63SDavid du Colombier } 722*8ccd4a63SDavid du Colombier 723*8ccd4a63SDavid du Colombier long 724*8ccd4a63SDavid du Colombier csread(Chan *c, void *a, long n, vlong offset) 725*8ccd4a63SDavid du Colombier { 726*8ccd4a63SDavid du Colombier if(c->aux == nil) 727*8ccd4a63SDavid du Colombier return 0; 728*8ccd4a63SDavid du Colombier return readstr(offset, a, n, c->aux); 729*8ccd4a63SDavid du Colombier } 730*8ccd4a63SDavid du Colombier 731*8ccd4a63SDavid du Colombier static struct 732*8ccd4a63SDavid du Colombier { 733*8ccd4a63SDavid du Colombier char *name; 734*8ccd4a63SDavid du Colombier uint num; 735*8ccd4a63SDavid du Colombier } tab[] = { 736*8ccd4a63SDavid du Colombier "cs", 1, 737*8ccd4a63SDavid du Colombier "echo", 7, 738*8ccd4a63SDavid du Colombier "discard", 9, 739*8ccd4a63SDavid du Colombier "systat", 11, 740*8ccd4a63SDavid du Colombier "daytime", 13, 741*8ccd4a63SDavid du Colombier "netstat", 15, 742*8ccd4a63SDavid du Colombier "chargen", 19, 743*8ccd4a63SDavid du Colombier "ftp-data", 20, 744*8ccd4a63SDavid du Colombier "ftp", 21, 745*8ccd4a63SDavid du Colombier "ssh", 22, 746*8ccd4a63SDavid du Colombier "telnet", 23, 747*8ccd4a63SDavid du Colombier "smtp", 25, 748*8ccd4a63SDavid du Colombier "time", 37, 749*8ccd4a63SDavid du Colombier "whois", 43, 750*8ccd4a63SDavid du Colombier "dns", 53, 751*8ccd4a63SDavid du Colombier "domain", 53, 752*8ccd4a63SDavid du Colombier "uucp", 64, 753*8ccd4a63SDavid du Colombier "gopher", 70, 754*8ccd4a63SDavid du Colombier "rje", 77, 755*8ccd4a63SDavid du Colombier "finger", 79, 756*8ccd4a63SDavid du Colombier "http", 80, 757*8ccd4a63SDavid du Colombier "link", 87, 758*8ccd4a63SDavid du Colombier "supdup", 95, 759*8ccd4a63SDavid du Colombier "hostnames", 101, 760*8ccd4a63SDavid du Colombier "iso-tsap", 102, 761*8ccd4a63SDavid du Colombier "x400", 103, 762*8ccd4a63SDavid du Colombier "x400-snd", 104, 763*8ccd4a63SDavid du Colombier "csnet-ns", 105, 764*8ccd4a63SDavid du Colombier "pop-2", 109, 765*8ccd4a63SDavid du Colombier "pop3", 110, 766*8ccd4a63SDavid du Colombier "portmap", 111, 767*8ccd4a63SDavid du Colombier "uucp-path", 117, 768*8ccd4a63SDavid du Colombier "nntp", 119, 769*8ccd4a63SDavid du Colombier "netbios", 139, 770*8ccd4a63SDavid du Colombier "imap4", 143, 771*8ccd4a63SDavid du Colombier "NeWS", 144, 772*8ccd4a63SDavid du Colombier "print-srv", 170, 773*8ccd4a63SDavid du Colombier "z39.50", 210, 774*8ccd4a63SDavid du Colombier "fsb", 400, 775*8ccd4a63SDavid du Colombier "sysmon", 401, 776*8ccd4a63SDavid du Colombier "proxy", 402, 777*8ccd4a63SDavid du Colombier "proxyd", 404, 778*8ccd4a63SDavid du Colombier "https", 443, 779*8ccd4a63SDavid du Colombier "cifs", 445, 780*8ccd4a63SDavid du Colombier "ssmtp", 465, 781*8ccd4a63SDavid du Colombier "rexec", 512, 782*8ccd4a63SDavid du Colombier "login", 513, 783*8ccd4a63SDavid du Colombier "shell", 514, 784*8ccd4a63SDavid du Colombier "printer", 515, 785*8ccd4a63SDavid du Colombier "courier", 530, 786*8ccd4a63SDavid du Colombier "cscan", 531, 787*8ccd4a63SDavid du Colombier "uucp", 540, 788*8ccd4a63SDavid du Colombier "snntp", 563, 789*8ccd4a63SDavid du Colombier "9fs", 564, 790*8ccd4a63SDavid du Colombier "whoami", 565, 791*8ccd4a63SDavid du Colombier "guard", 566, 792*8ccd4a63SDavid du Colombier "ticket", 567, 793*8ccd4a63SDavid du Colombier "dlsftp", 666, 794*8ccd4a63SDavid du Colombier "fmclient", 729, 795*8ccd4a63SDavid du Colombier "imaps", 993, 796*8ccd4a63SDavid du Colombier "pop3s", 995, 797*8ccd4a63SDavid du Colombier "ingreslock", 1524, 798*8ccd4a63SDavid du Colombier "pptp", 1723, 799*8ccd4a63SDavid du Colombier "nfs", 2049, 800*8ccd4a63SDavid du Colombier "webster", 2627, 801*8ccd4a63SDavid du Colombier "weather", 3000, 802*8ccd4a63SDavid du Colombier "secstore", 5356, 803*8ccd4a63SDavid du Colombier "Xdisplay", 6000, 804*8ccd4a63SDavid du Colombier "styx", 6666, 805*8ccd4a63SDavid du Colombier "mpeg", 6667, 806*8ccd4a63SDavid du Colombier "rstyx", 6668, 807*8ccd4a63SDavid du Colombier "infdb", 6669, 808*8ccd4a63SDavid du Colombier "infsigner", 6671, 809*8ccd4a63SDavid du Colombier "infcsigner", 6672, 810*8ccd4a63SDavid du Colombier "inflogin", 6673, 811*8ccd4a63SDavid du Colombier "bandt", 7330, 812*8ccd4a63SDavid du Colombier "face", 32000, 813*8ccd4a63SDavid du Colombier "dhashgate", 11978, 814*8ccd4a63SDavid du Colombier "exportfs", 17007, 815*8ccd4a63SDavid du Colombier "rexexec", 17009, 816*8ccd4a63SDavid du Colombier "ncpu", 17010, 817*8ccd4a63SDavid du Colombier "cpu", 17013, 818*8ccd4a63SDavid du Colombier "glenglenda1", 17020, 819*8ccd4a63SDavid du Colombier "glenglenda2", 17021, 820*8ccd4a63SDavid du Colombier "glenglenda3", 17022, 821*8ccd4a63SDavid du Colombier "glenglenda4", 17023, 822*8ccd4a63SDavid du Colombier "glenglenda5", 17024, 823*8ccd4a63SDavid du Colombier "glenglenda6", 17025, 824*8ccd4a63SDavid du Colombier "glenglenda7", 17026, 825*8ccd4a63SDavid du Colombier "glenglenda8", 17027, 826*8ccd4a63SDavid du Colombier "glenglenda9", 17028, 827*8ccd4a63SDavid du Colombier "glenglenda10", 17029, 828*8ccd4a63SDavid du Colombier "flyboy", 17032, 829*8ccd4a63SDavid du Colombier "dlsftp", 17033, 830*8ccd4a63SDavid du Colombier "venti", 17034, 831*8ccd4a63SDavid du Colombier "wiki", 17035, 832*8ccd4a63SDavid du Colombier "vica", 17036, 833*8ccd4a63SDavid du Colombier 0 834*8ccd4a63SDavid du Colombier }; 835*8ccd4a63SDavid du Colombier 836*8ccd4a63SDavid du Colombier static int 837*8ccd4a63SDavid du Colombier lookupport(char *s) 838*8ccd4a63SDavid du Colombier { 839*8ccd4a63SDavid du Colombier int i; 840*8ccd4a63SDavid du Colombier char buf[10], *p; 841*8ccd4a63SDavid du Colombier 842*8ccd4a63SDavid du Colombier i = strtol(s, &p, 0); 843*8ccd4a63SDavid du Colombier if(*s && *p == 0) 844*8ccd4a63SDavid du Colombier return i; 845*8ccd4a63SDavid du Colombier 846*8ccd4a63SDavid du Colombier i = so_getservbyname(s, "tcp", buf); 847*8ccd4a63SDavid du Colombier if(i != -1) 848*8ccd4a63SDavid du Colombier return atoi(buf); 849*8ccd4a63SDavid du Colombier for(i=0; tab[i].name; i++) 850*8ccd4a63SDavid du Colombier if(strcmp(s, tab[i].name) == 0) 851*8ccd4a63SDavid du Colombier return tab[i].num; 852*8ccd4a63SDavid du Colombier return 0; 853*8ccd4a63SDavid du Colombier } 854*8ccd4a63SDavid du Colombier 855*8ccd4a63SDavid du Colombier static ulong 856*8ccd4a63SDavid du Colombier lookuphost(char *s) 857*8ccd4a63SDavid du Colombier { 858*8ccd4a63SDavid du Colombier char to[4]; 859*8ccd4a63SDavid du Colombier ulong ip; 860*8ccd4a63SDavid du Colombier 861*8ccd4a63SDavid du Colombier memset(to, 0, sizeof to); 862*8ccd4a63SDavid du Colombier parseip(to, s); 863*8ccd4a63SDavid du Colombier ip = nhgetl(to); 864*8ccd4a63SDavid du Colombier if(ip != 0) 865*8ccd4a63SDavid du Colombier return ip; 866*8ccd4a63SDavid du Colombier if((s = hostlookup(s)) == nil) 867*8ccd4a63SDavid du Colombier return 0; 868*8ccd4a63SDavid du Colombier parseip(to, s); 869*8ccd4a63SDavid du Colombier ip = nhgetl(to); 870*8ccd4a63SDavid du Colombier free(s); 871*8ccd4a63SDavid du Colombier return ip; 872*8ccd4a63SDavid du Colombier } 873*8ccd4a63SDavid du Colombier 874*8ccd4a63SDavid du Colombier long 875*8ccd4a63SDavid du Colombier cswrite(Chan *c, void *a, long n, vlong offset) 876*8ccd4a63SDavid du Colombier { 877*8ccd4a63SDavid du Colombier char *f[4]; 878*8ccd4a63SDavid du Colombier char *s, *ns; 879*8ccd4a63SDavid du Colombier ulong ip; 880*8ccd4a63SDavid du Colombier int nf, port; 881*8ccd4a63SDavid du Colombier 882*8ccd4a63SDavid du Colombier s = malloc(n+1); 883*8ccd4a63SDavid du Colombier if(s == nil) 884*8ccd4a63SDavid du Colombier error(Enomem); 885*8ccd4a63SDavid du Colombier if(waserror()){ 886*8ccd4a63SDavid du Colombier free(s); 887*8ccd4a63SDavid du Colombier nexterror(); 888*8ccd4a63SDavid du Colombier } 889*8ccd4a63SDavid du Colombier memmove(s, a, n); 890*8ccd4a63SDavid du Colombier s[n] = 0; 891*8ccd4a63SDavid du Colombier nf = getfields(s, f, nelem(f), 0, "!"); 892*8ccd4a63SDavid du Colombier if(nf != 3) 893*8ccd4a63SDavid du Colombier error("can't translate"); 894*8ccd4a63SDavid du Colombier 895*8ccd4a63SDavid du Colombier port = lookupport(f[2]); 896*8ccd4a63SDavid du Colombier if(port <= 0) 897*8ccd4a63SDavid du Colombier error("no translation for port found"); 898*8ccd4a63SDavid du Colombier 899*8ccd4a63SDavid du Colombier ip = lookuphost(f[1]); 900*8ccd4a63SDavid du Colombier if(ip == 0) 901*8ccd4a63SDavid du Colombier error("no translation for host found"); 902*8ccd4a63SDavid du Colombier 903*8ccd4a63SDavid du Colombier ns = smprint("/net/%s/clone %I!%d", f[0], ip, port); 904*8ccd4a63SDavid du Colombier if(ns == nil) 905*8ccd4a63SDavid du Colombier error(Enomem); 906*8ccd4a63SDavid du Colombier free(c->aux); 907*8ccd4a63SDavid du Colombier c->aux = ns; 908*8ccd4a63SDavid du Colombier poperror(); 909*8ccd4a63SDavid du Colombier free(s); 910*8ccd4a63SDavid du Colombier return n; 911*8ccd4a63SDavid du Colombier } 912*8ccd4a63SDavid du Colombier 913*8ccd4a63SDavid du Colombier Dev ipdevtab = 914*8ccd4a63SDavid du Colombier { 915*8ccd4a63SDavid du Colombier 'I', 916*8ccd4a63SDavid du Colombier "ip", 917*8ccd4a63SDavid du Colombier 918*8ccd4a63SDavid du Colombier devreset, 919*8ccd4a63SDavid du Colombier ipinit, 920*8ccd4a63SDavid du Colombier devshutdown, 921*8ccd4a63SDavid du Colombier ipattach, 922*8ccd4a63SDavid du Colombier ipwalk, 923*8ccd4a63SDavid du Colombier ipstat, 924*8ccd4a63SDavid du Colombier ipopen, 925*8ccd4a63SDavid du Colombier devcreate, 926*8ccd4a63SDavid du Colombier ipclose, 927*8ccd4a63SDavid du Colombier ipread, 928*8ccd4a63SDavid du Colombier devbread, 929*8ccd4a63SDavid du Colombier ipwrite, 930*8ccd4a63SDavid du Colombier devbwrite, 931*8ccd4a63SDavid du Colombier devremove, 932*8ccd4a63SDavid du Colombier devwstat, 933*8ccd4a63SDavid du Colombier }; 934*8ccd4a63SDavid du Colombier 935