159cc4ca5SDavid du Colombier #include "u.h" 259cc4ca5SDavid du Colombier #include "../port/lib.h" 359cc4ca5SDavid du Colombier #include "mem.h" 459cc4ca5SDavid du Colombier #include "dat.h" 559cc4ca5SDavid du Colombier #include "fns.h" 659cc4ca5SDavid du Colombier #include "../port/error.h" 759cc4ca5SDavid du Colombier 859cc4ca5SDavid du Colombier #include "ip.h" 959cc4ca5SDavid du Colombier 1059cc4ca5SDavid du Colombier static void netdevbind(Ipifc *ifc, int argc, char **argv); 1159cc4ca5SDavid du Colombier static void netdevunbind(Ipifc *ifc); 1259cc4ca5SDavid du Colombier static void netdevbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); 1359cc4ca5SDavid du Colombier static void netdevread(void *a); 1459cc4ca5SDavid du Colombier 1559cc4ca5SDavid du Colombier typedef struct Netdevrock Netdevrock; 1659cc4ca5SDavid du Colombier struct Netdevrock 1759cc4ca5SDavid du Colombier { 1859cc4ca5SDavid du Colombier Fs *f; /* file system we belong to */ 1959cc4ca5SDavid du Colombier Proc *readp; /* reading process */ 2059cc4ca5SDavid du Colombier Chan *mchan; /* Data channel */ 2159cc4ca5SDavid du Colombier }; 2259cc4ca5SDavid du Colombier 2359cc4ca5SDavid du Colombier Medium netdevmedium = 2459cc4ca5SDavid du Colombier { 2559cc4ca5SDavid du Colombier .name= "netdev", 2659cc4ca5SDavid du Colombier .hsize= 0, 2759cc4ca5SDavid du Colombier .minmtu= 0, 2859cc4ca5SDavid du Colombier .maxmtu= 64000, 2959cc4ca5SDavid du Colombier .maclen= 0, 3059cc4ca5SDavid du Colombier .bind= netdevbind, 3159cc4ca5SDavid du Colombier .unbind= netdevunbind, 3259cc4ca5SDavid du Colombier .bwrite= netdevbwrite, 3359cc4ca5SDavid du Colombier .unbindonclose= 0, 3459cc4ca5SDavid du Colombier }; 3559cc4ca5SDavid du Colombier 3659cc4ca5SDavid du Colombier /* 3759cc4ca5SDavid du Colombier * called to bind an IP ifc to a generic network device 3859cc4ca5SDavid du Colombier * called with ifc qlock'd 3959cc4ca5SDavid du Colombier */ 4059cc4ca5SDavid du Colombier static void 4159cc4ca5SDavid du Colombier netdevbind(Ipifc *ifc, int argc, char **argv) 4259cc4ca5SDavid du Colombier { 4359cc4ca5SDavid du Colombier Chan *mchan; 4459cc4ca5SDavid du Colombier Netdevrock *er; 4559cc4ca5SDavid du Colombier 4659cc4ca5SDavid du Colombier if(argc < 2) 4759cc4ca5SDavid du Colombier error(Ebadarg); 4859cc4ca5SDavid du Colombier 4980ee5cbfSDavid du Colombier mchan = namec(argv[2], Aopen, ORDWR, 0); 5059cc4ca5SDavid du Colombier 5159cc4ca5SDavid du Colombier er = smalloc(sizeof(*er)); 5259cc4ca5SDavid du Colombier er->mchan = mchan; 5359cc4ca5SDavid du Colombier er->f = ifc->conv->p->f; 5459cc4ca5SDavid du Colombier 5559cc4ca5SDavid du Colombier ifc->arg = er; 5659cc4ca5SDavid du Colombier 5759cc4ca5SDavid du Colombier kproc("netdevread", netdevread, ifc); 5859cc4ca5SDavid du Colombier } 5959cc4ca5SDavid du Colombier 6059cc4ca5SDavid du Colombier /* 6159cc4ca5SDavid du Colombier * called with ifc wlock'd 6259cc4ca5SDavid du Colombier */ 6359cc4ca5SDavid du Colombier static void 6459cc4ca5SDavid du Colombier netdevunbind(Ipifc *ifc) 6559cc4ca5SDavid du Colombier { 6659cc4ca5SDavid du Colombier Netdevrock *er = ifc->arg; 6759cc4ca5SDavid du Colombier 6859cc4ca5SDavid du Colombier if(er->readp != nil) 6959cc4ca5SDavid du Colombier postnote(er->readp, 1, "unbind", 0); 7059cc4ca5SDavid du Colombier 7159cc4ca5SDavid du Colombier /* wait for readers to die */ 7259cc4ca5SDavid du Colombier while(er->readp != nil) 7359cc4ca5SDavid du Colombier tsleep(&up->sleep, return0, 0, 300); 7459cc4ca5SDavid du Colombier 7559cc4ca5SDavid du Colombier if(er->mchan != nil) 7659cc4ca5SDavid du Colombier cclose(er->mchan); 7759cc4ca5SDavid du Colombier 7859cc4ca5SDavid du Colombier free(er); 7959cc4ca5SDavid du Colombier } 8059cc4ca5SDavid du Colombier 8159cc4ca5SDavid du Colombier /* 8259cc4ca5SDavid du Colombier * called by ipoput with a single block to write 8359cc4ca5SDavid du Colombier */ 8459cc4ca5SDavid du Colombier static void 8559cc4ca5SDavid du Colombier netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*) 8659cc4ca5SDavid du Colombier { 8759cc4ca5SDavid du Colombier Netdevrock *er = ifc->arg; 8859cc4ca5SDavid du Colombier 8959cc4ca5SDavid du Colombier if(bp->next) 9059cc4ca5SDavid du Colombier bp = concatblock(bp); 9159cc4ca5SDavid du Colombier if(BLEN(bp) < ifc->minmtu) 9259cc4ca5SDavid du Colombier bp = adjustblock(bp, ifc->minmtu); 9359cc4ca5SDavid du Colombier 9459cc4ca5SDavid du Colombier devtab[er->mchan->type]->bwrite(er->mchan, bp, 0); 9559cc4ca5SDavid du Colombier ifc->out++; 9659cc4ca5SDavid du Colombier } 9759cc4ca5SDavid du Colombier 9859cc4ca5SDavid du Colombier /* 9959cc4ca5SDavid du Colombier * process to read from the device 10059cc4ca5SDavid du Colombier */ 10159cc4ca5SDavid du Colombier static void 10259cc4ca5SDavid du Colombier netdevread(void *a) 10359cc4ca5SDavid du Colombier { 10459cc4ca5SDavid du Colombier Ipifc *ifc; 10559cc4ca5SDavid du Colombier Block *bp; 10659cc4ca5SDavid du Colombier Netdevrock *er; 10759cc4ca5SDavid du Colombier char *argv[1]; 10859cc4ca5SDavid du Colombier 10959cc4ca5SDavid du Colombier ifc = a; 11059cc4ca5SDavid du Colombier er = ifc->arg; 11159cc4ca5SDavid du Colombier er->readp = up; /* hide identity under a rock for unbind */ 11259cc4ca5SDavid du Colombier if(waserror()){ 11359cc4ca5SDavid du Colombier er->readp = nil; 11459cc4ca5SDavid du Colombier pexit("hangup", 1); 11559cc4ca5SDavid du Colombier } 11659cc4ca5SDavid du Colombier for(;;){ 11759cc4ca5SDavid du Colombier bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0); 11859cc4ca5SDavid du Colombier if(bp == nil){ 11959cc4ca5SDavid du Colombier /* 12059cc4ca5SDavid du Colombier * get here if mchan is a pipe and other side hangs up 12159cc4ca5SDavid du Colombier * clean up this interface & get out 12259cc4ca5SDavid du Colombier ZZZ is this a good idea? 12359cc4ca5SDavid du Colombier */ 12459cc4ca5SDavid du Colombier poperror(); 12559cc4ca5SDavid du Colombier er->readp = nil; 12659cc4ca5SDavid du Colombier argv[0] = "unbind"; 12759cc4ca5SDavid du Colombier if(!waserror()) 12859cc4ca5SDavid du Colombier ifc->conv->p->ctl(ifc->conv, argv, 1); 12959cc4ca5SDavid du Colombier pexit("hangup", 1); 13059cc4ca5SDavid du Colombier } 13159cc4ca5SDavid du Colombier if(!canrlock(ifc)){ 13259cc4ca5SDavid du Colombier freeb(bp); 13359cc4ca5SDavid du Colombier continue; 13459cc4ca5SDavid du Colombier } 13559cc4ca5SDavid du Colombier if(waserror()){ 13659cc4ca5SDavid du Colombier runlock(ifc); 13759cc4ca5SDavid du Colombier nexterror(); 13859cc4ca5SDavid du Colombier } 13959cc4ca5SDavid du Colombier ifc->in++; 14059cc4ca5SDavid du Colombier if(ifc->lifc == nil) 14159cc4ca5SDavid du Colombier freeb(bp); 14259cc4ca5SDavid du Colombier else 143*3ff48bf5SDavid du Colombier ipiput4(er->f, ifc, bp); 14459cc4ca5SDavid du Colombier runlock(ifc); 14559cc4ca5SDavid du Colombier poperror(); 14659cc4ca5SDavid du Colombier } 14759cc4ca5SDavid du Colombier } 14859cc4ca5SDavid du Colombier 14959cc4ca5SDavid du Colombier void 15059cc4ca5SDavid du Colombier netdevmediumlink(void) 15159cc4ca5SDavid du Colombier { 15259cc4ca5SDavid du Colombier addipmedium(&netdevmedium); 15359cc4ca5SDavid du Colombier } 154