M ip/devip.c => ip/devip.c +25 -1
@@ 32,6 32,7 @@ enum
Qlocal,
Qremote,
Qstatus,
+ Qsnoop,
Logtype= 5,
Masktype= (1<<Logtype)-1,
@@ 84,7 85,7 @@ ip3gen(Chan *c, int i, Dir *dp)
devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp);
return 1;
case Qlisten:
- devdir(c, q, "listen", qlen(cv->eq), cv->owner, cv->perm, dp);
+ devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
return 1;
case Qlocal:
p = "local";
@@ 92,6 93,11 @@ ip3gen(Chan *c, int i, Dir *dp)
case Qremote:
p = "remote";
break;
+ case Qsnoop:
+ if(strcmp(cv->p->name, "ipifc") != 0)
+ return -1;
+ devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp);
+ return 1;
case Qstatus:
p = "status";
break;
@@ 235,6 241,7 @@ ipgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
case Qlocal:
case Qremote:
case Qstatus:
+ case Qsnoop:
return ip3gen(c, TYPE(c->qid), dp);
}
return -1;
@@ 391,6 398,15 @@ ipopen(Chan* c, int omode)
if(omode != OREAD)
error(Eperm);
break;
+ case Qsnoop:
+ if(omode != OREAD)
+ error(Eperm);
+ p = f->p[PROTO(c->qid)];
+ cv = p->conv[CONV(c->qid)];
+ if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
+ error(Eperm);
+ incref(&cv->snoopers);
+ break;
case Qclone:
p = f->p[PROTO(c->qid)];
qlock(p);
@@ 575,6 591,11 @@ ipclose(Chan* c)
case Qerr:
if(c->flag & COPEN)
closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
+ break;
+ case Qsnoop:
+ if(c->flag & COPEN)
+ decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
+ break;
}
free(((IPaux*)c->aux)->owner);
free(c->aux);
@@ 663,6 684,9 @@ ipread(Chan *ch, void *a, long n, vlong off)
case Qerr:
c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
return qread(c->eq, a, n);
+ case Qsnoop:
+ c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
+ return qread(c->sq, a, n);
case Qstats:
x = f->p[PROTO(ch->qid)];
if(x->stats == nil)
M ip/ip.h => ip/ip.h +2 -0
@@ 105,6 105,8 @@ struct Conv
Queue* rq; /* queued data waiting to be read */
Queue* wq; /* queued data waiting to be written */
Queue* eq; /* returned error packets */
+ Queue* sq; /* snooping queue */
+ Ref snoopers; /* number of processes with snoop open */
QLock car;
Rendez cr;
M ip/ipifc.c => ip/ipifc.c +18 -7
@@ 128,18 128,22 @@ ipifcbind(Conv *c, char **argv, int argc)
nexterror();
}
+ /* do medium specific binding */
(*m->bind)(ifc, argc, argv);
+
+ /* set the bound device name */
if(argc > 2)
strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
else
sprint(ifc->dev, "%s%d", m->name, c->x);
ifc->dev[sizeof(ifc->dev)-1] = 0;
+
+ /* set up parameters */
ifc->m = m;
ifc->minmtu = ifc->m->minmtu;
ifc->maxmtu = ifc->m->maxmtu;
if(ifc->m->unbindonclose == 0)
ifc->conv->inuse++;
-
ifc->rp.mflag = 0; // default not managed
ifc->rp.oflag = 0;
ifc->rp.maxraint = 600000; // millisecs
@@ 148,10 152,16 @@ ipifcbind(Conv *c, char **argv, int argc)
ifc->rp.reachtime = 0;
ifc->rp.rxmitra = 0;
ifc->rp.ttl = MAXTTL;
- ifc->rp.routerlt = 3*(ifc->rp.maxraint);
+ ifc->rp.routerlt = 3*(ifc->rp.maxraint);
+ /* any ancillary structures (like routes) no longer pertain */
ifc->ifcid++;
+ /* reopen all the queues closed by a previous unbind */
+ qreopen(c->rq);
+ qreopen(c->eq);
+ qreopen(c->sq);
+
wunlock(ifc);
poperror();
@@ 188,9 198,10 @@ ipifcunbind(Ipifc *ifc)
ifc->arg = nil;
ifc->reassemble = 0;
- /* hangup queues to stop queuing of packets */
- qhangup(ifc->conv->rq, "unbind");
- qhangup(ifc->conv->wq, "unbind");
+ /* close queues to stop queuing of packets */
+ qclose(ifc->conv->rq);
+ qclose(ifc->conv->wq);
+ qclose(ifc->conv->sq);
/* disassociate logical interfaces */
av[0] = "remove";
@@ 301,8 312,7 @@ ipifckick(void *x)
}
/*
- * we'll have to have a kick routine at
- * some point to deal with these
+ * called when a new ipifc structure is created
*/
static void
ipifccreate(Conv *c)
@@ 310,6 320,7 @@ ipifccreate(Conv *c)
Ipifc *ifc;
c->rq = qopen(QMAX, 0, 0, 0);
+ c->sq = qopen(2*QMAX, 0, 0, 0);
c->wq = qopen(QMAX, Qkick, ipifckick, c);
ifc = (Ipifc*)c->ptcl;
ifc->conv = c;
M ip/pktmedium.c => ip/pktmedium.c +6 -1
@@ 52,6 52,8 @@ pktbwrite(Ipifc *ifc, Block *bp, int, uchar*)
{
/* enqueue onto the conversation's rq */
bp = concatblock(bp);
+ if(ifc->conv->snoopers.ref > 0)
+ qpass(ifc->conv->sq, copyblock(bp, BLEN(bp)));
qpass(ifc->conv->rq, bp);
}
@@ 63,8 65,11 @@ pktin(Fs *f, Ipifc *ifc, Block *bp)
{
if(ifc->lifc == nil)
freeb(bp);
- else
+ else {
+ if(ifc->conv->snoopers.ref > 0)
+ qpass(ifc->conv->sq, copyblock(bp, BLEN(bp)));
ipiput4(f, ifc, bp);
+ }
}
void