static int netown(Netfile*, char*, int);
static int openfile(Netif*, int);
static char* matchtoken(char*, char*);
static char* netmulti(Netif*, Netfile*, uchar*, int);
static int parseaddr(uchar*, char*, int);
/*
* set up a new network interface
*/
void
netifinit(Netif *nif, char *name, int nfile, ulong limit)
{
if(strlen(name) >= sizeof nif->name)
panic("netifinit: name too long: %s", name);
strcpy(nif->name, name);
nif->nfile = nfile;
nif->f = xalloc(nfile*sizeof(Netfile*));
if (nif->f == nil)
panic("netifinit: no memory");
memset(nif->f, 0, nfile*sizeof(Netfile*));
nif->limit = limit;
}
/*
* generate a 3 level directory
*/
static int
netifgen(Chan *c, char*, Dirtab *vp, int, int i, Dir *dp)
{
Qid q;
Netif *nif = (Netif*)vp;
Netfile *f;
int t;
int perm;
char *o;
q.type = QTFILE;
q.vers = 0;
/* top level directory contains the name of the network */
if(c->qid.path == 0){
switch(i){
case DEVDOTDOT:
q.path = 0;
q.type = QTDIR;
devdir(c, q, ".", 0, eve, 0555, dp);
break;
case 0:
q.path = N2ndqid;
q.type = QTDIR;
strcpy(up->genbuf, nif->name);
devdir(c, q, up->genbuf, 0, eve, 0555, dp);
break;
default:
return -1;
}
return 1;
}
/* second level contains clone plus all the conversations */
t = NETTYPE(c->qid.path);
if(t == N2ndqid || t == Ncloneqid || t == Naddrqid || t == Nstatqid || t == Nifstatqid){
switch(i) {
case DEVDOTDOT:
q.type = QTDIR;
q.path = 0;
devdir(c, q, ".", 0, eve, 0555, dp);
break;
case 0:
q.path = Ncloneqid;
devdir(c, q, "clone", 0, eve, 0666, dp);
break;
case 1:
q.path = Naddrqid;
devdir(c, q, "addr", 0, eve, 0444, dp);
break;
case 2:
q.path = Nstatqid;
devdir(c, q, "stats", 0, eve, 0444, dp);
break;
case 3:
q.path = Nifstatqid;
devdir(c, q, "ifstats", 0, eve, 0444, dp);
break;
default:
i -= 4;
if(i >= nif->nfile)
return -1;
if(nif->f[i] == 0)
return 0;
q.type = QTDIR;
q.path = NETQID(i, N3rdqid);
snprint(up->genbuf, sizeof up->genbuf, "%d", i);
devdir(c, q, up->genbuf, 0, eve, 0555, dp);
break;
}
return 1;
}
/* third level */
f = nif->f[NETID(c->qid.path)];
if(f == 0)
return 0;
if(*f->owner){
o = f->owner;
perm = f->mode;
} else {
o = eve;
perm = 0666;
}
switch(i){
case DEVDOTDOT:
q.type = QTDIR;
q.path = N2ndqid;
strcpy(up->genbuf, nif->name);
devdir(c, q, up->genbuf, 0, eve, 0555, dp);
break;
case 0:
q.path = NETQID(NETID(c->qid.path), Ndataqid);
devdir(c, q, "data", 0, o, perm, dp);
break;
case 1:
q.path = NETQID(NETID(c->qid.path), Nctlqid);
devdir(c, q, "ctl", 0, o, perm, dp);
break;
case 2:
q.path = Nstatqid;
devdir(c, q, "stats", 0, eve, 0444, dp);
break;
case 3:
q.path = NETQID(NETID(c->qid.path), Ntypeqid);
devdir(c, q, "type", 0, eve, 0444, dp);
break;
case 4:
q.path = Nifstatqid;
devdir(c, q, "ifstats", 0, eve, 0444, dp);
break;
default:
return -1;
}
return 1;
}
/*
* the devxxx.c that calls us handles writing data, it knows best
*/
long
netifwrite(Netif *nif, Chan *c, void *a, long n)
{
Netfile *f;
int type;
char *p, buf[64];
uchar binaddr[Nmaxaddr];
if(NETTYPE(c->qid.path) != Nctlqid)
error(Eperm);
if(n >= sizeof(buf))
n = sizeof(buf)-1;
memmove(buf, a, n);
buf[n] = 0;
/*
* Increment the reference count of a network device.
* If id < 0, return an unused ether device.
*/
static int
openfile(Netif *nif, int id)
{
Netfile *f, **fp, **efp;