M port/devenv.c => port/devenv.c +3 -0
@@ 391,6 391,8 @@ evfree(Envval *ev)
if(ev->prev)
ev->prev->next = ev->next;
+ else
+ panic("evfree");
if(ev->next)
ev->next->prev = ev->prev;
n = (ev->len + ALIGN - 1) & ~(ALIGN - 1);
@@ 399,6 401,7 @@ evfree(Envval *ev)
if(n > EVFREE)
n = EVFREE;
ev->next = envalloc.free[n];
+ ev->prev = 0;
envalloc.free[n] = ev;
}
M port/devip.c => port/devip.c +80 -74
@@ 181,7 181,7 @@ ipopen(Chan *c, int omode)
error(Eprotonosup);
if(cp->backlog == 0)
- cp->backlog = 1;
+ cp->backlog = 3;
streamopen(c, &ipinfo);
if(c->stream->devq->next->info != cp->stproto)
@@ 226,7 226,7 @@ ipclonecon(Chan *c)
base = ipconv[c->dev];
etab = &base[conf.ip];
for(new = base; new < etab; new++) {
- new = ipincoming(c->dev);
+ new = ipincoming(base);
if(new == 0)
error(Enodev);
@@ 243,11 243,10 @@ ipclonecon(Chan *c)
}
Ipconv *
-ipincoming(int dev)
+ipincoming(Ipconv *base)
{
- Ipconv *base, *new, *etab;
+ Ipconv *new, *etab;
- base = ipconv[dev];
etab = &base[conf.ip];
for(new = base; new < etab; new++) {
if(new->ref == 0 && canqlock(new)) {
@@ 335,86 334,93 @@ long
ipwrite(Chan *c, char *a, long n, ulong offset)
{
int m, backlog, type;
- char *field[5], buf[256];
- Ipconv *cp;
+ char *field[5], *ctlarg[5], buf[256];
Port port, base;
+ Ipconv *cp;
type = STREAMTYPE(c->qid.path);
if (type == Sdataqid)
return streamwrite(c, a, n, 0);
- if (type == Sctlqid) {
- cp = &ipconv[c->dev][STREAMID(c->qid.path)];
-
- strncpy(buf, a, sizeof buf);
- m = getfields(buf, field, 5, ' ');
-
- if(strcmp(field[0], "connect") == 0) {
- if((cp->stproto == &tcpinfo && cp->tcpctl.state != CLOSED) ||
- (cp->stproto == &ilinfo && cp->ilctl.state != Ilclosed))
- error(Edevbusy);
-
- if(m != 2)
- error(Ebadarg);
-
- switch(getfields(field[1], field, 5, '!')) {
- default:
- error(Ebadarg);
- case 2:
- base = PORTALLOC;
- break;
- case 3:
- if(strcmp(field[2], "r") != 0)
- error(Eperm);
- base = PRIVPORTALLOC;
- break;
- }
- cp->dst = ipparse(field[0]);
- cp->pdst = atoi(field[1]);
+ if (type != Sctlqid)
+ error(Eperm);
- /* If we have no local port assign one */
- qlock(&ipalloc);
- if(cp->psrc == 0)
- cp->psrc = nextport(ipconv[c->dev], base);
- qunlock(&ipalloc);
+ cp = &ipconv[c->dev][STREAMID(c->qid.path)];
+ m = n;
+ if(m > sizeof(buf)-1)
+ m = sizeof(buf)-1;
+ strncpy(buf, a, m);
+ buf[m] = '\0';
+
+ m = getfields(buf, field, 5, ' ');
+ if(m < 1)
+ errors("bad ip control");
+
+ if(strcmp(field[0], "connect") == 0) {
+ if((cp->stproto == &tcpinfo && cp->tcpctl.state != CLOSED) ||
+ (cp->stproto == &ilinfo && cp->ilctl.state != Ilclosed))
+ error(Edevbusy);
+
+ if(m != 2)
+ error(Ebadarg);
+
+ switch(m = getfields(field[1], ctlarg, 5, '!')) {
+ default:
+ error(Ebadarg);
+ case 2:
+ base = PORTALLOC;
+ break;
+ case 3:
+ if(strcmp(ctlarg[2], "r") != 0)
+ error(Eperm);
+ base = PRIVPORTALLOC;
+ break;
}
- else if(strcmp(field[0], "announce") == 0 ||
- strcmp(field[0], "reserve") == 0) {
- if((cp->stproto == &tcpinfo && cp->tcpctl.state != CLOSED) ||
- (cp->stproto == &ilinfo && cp->ilctl.state != Ilclosed))
- error(Edevbusy);
-
- if(m != 2)
- error(Ebadarg);
- port = atoi(field[1]);
-
- qlock(&ipalloc);
- if(portused(ipconv[c->dev], port)) {
- qunlock(&ipalloc);
- error(Einuse);
- }
- cp->psrc = port;
- cp->ptype = *field[0];
- qunlock(&ipalloc);
- }
- else if(strcmp(field[0], "backlog") == 0) {
- if(m != 2)
- error(Ebadarg);
- backlog = atoi(field[1]);
- if(backlog == 0)
- error(Ebadarg);
- if(backlog > 5)
- backlog = 5;
- cp->backlog = backlog;
- }
- else
- return streamwrite(c, a, n, 0);
+ cp->dst = ipparse(ctlarg[0]);
+ cp->pdst = atoi(ctlarg[1]);
+
+ /* If we have no local port assign one */
+ qlock(&ipalloc);
+ if(cp->psrc == 0)
+ cp->psrc = nextport(ipconv[c->dev], base);
+ qunlock(&ipalloc);
- return n;
}
+ else if(strcmp(field[0], "announce") == 0 ||
+ strcmp(field[0], "reserve") == 0) {
+ if((cp->stproto == &tcpinfo && cp->tcpctl.state != CLOSED) ||
+ (cp->stproto == &ilinfo && cp->ilctl.state != Ilclosed))
+ error(Edevbusy);
- error(Eperm);
+ if(m != 2)
+ error(Ebadarg);
+
+ port = atoi(field[1]);
+
+ qlock(&ipalloc);
+ if(portused(ipconv[c->dev], port)) {
+ qunlock(&ipalloc);
+ error(Einuse);
+ }
+ cp->psrc = port;
+ cp->ptype = *field[0];
+ qunlock(&ipalloc);
+ }
+ else if(strcmp(field[0], "backlog") == 0) {
+ if(m != 2)
+ error(Ebadarg);
+ backlog = atoi(field[1]);
+ if(backlog == 0)
+ error(Ebadarg);
+ if(backlog > 5)
+ backlog = 5;
+ cp->backlog = backlog;
+ }
+ else
+ return streamwrite(c, a, n, 0);
+
+ return n;
}
@@ 690,7 696,7 @@ iplisten(Chan *c, Ipconv *s, Ipconv *base)
pushq(c->stream, new->stproto);
new->ref--;
qunlock(&s->listenq);
-
+print("ip listener!\n");
return;
}
}
M port/ipdat.h => port/ipdat.h +3 -0
@@ 46,6 46,7 @@ struct Udphdr
uchar d[6]; /* Ethernet destination */
uchar s[6]; /* Ethernet source */
uchar type[2]; /* Ethernet packet type */
+
uchar vihl; /* Version and header length */
uchar tos; /* Type of service */
uchar length[2]; /* packet length */
@@ 72,6 73,7 @@ struct Ilhdr
uchar d[6]; /* Ethernet destination */
uchar s[6]; /* Ethernet source */
uchar type[2]; /* Ethernet packet type */
+
uchar vihl; /* Version and header length */
uchar tos; /* Type of service */
uchar length[2]; /* packet length */
@@ 265,6 267,7 @@ struct Ipconv
Ipaddr dst; /* Destination from connect */
Port psrc; /* Source port */
Port pdst; /* Destination port */
+ char ptype; /* Port type */
Ipifc *ipinterface; /* Ip protocol interface */
Queue *readq; /* Pointer to upstream read q */
M port/proc.c => port/proc.c +4 -4
@@ 521,6 521,10 @@ pexit(char *exitstr, int freemem)
if(c->fgrp)
closefgrp(c->fgrp);
+ closepgrp(c->pgrp);
+ close(u->dot);
+ if(c->egrp)
+ closeegrp(c->egrp);
if(c->kp == 0) {
wq = newwaitq();
@@ 566,10 570,6 @@ pexit(char *exitstr, int freemem)
*s = 0;
putseg(os);
}
- closepgrp(c->pgrp);
- if(c->egrp)
- closeegrp(c->egrp);
- close(u->dot);
lock(&c->exl); /* Prevent my children from leaving waits */
c->pid = 0;
M port/segment.c => port/segment.c +8 -7
@@ 265,21 265,22 @@ imagereclaim(void)
if(!canqlock(&ireclaim)) /* Somebody is already cleaning the page cache */
return;
- lock(&palloc);
- for(p = palloc.head; p; p = p->next) {
- if(p->image == 0)
- continue;
+ for(;;) {
+ lock(&palloc);
+ for(p = palloc.head; p; p = p->next)
+ if(p->image && p->ref == 0 && p->image != &swapimage)
+ break;
unlock(&palloc);
+ if(p == 0)
+ break;
+
lockpage(p);
if(p->ref == 0 && p->image != &swapimage)
uncachepage(p);
unlockpage(p);
- lock(&palloc);
}
- unlock(&palloc);
-
qunlock(&ireclaim);
}
M port/stil.c => port/stil.c +24 -6
@@ 187,8 187,9 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
int plen;
Ipconv *s, *etab, *new;
short sp, dp;
+ Ipaddr dst;
- ih = (Ilhdr *)bp;
+ ih = (Ilhdr *)bp->rptr;
plen = blen(bp);
if(plen < IL_EHSIZE+IL_HDRSIZE)
@@ 201,17 202,26 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
sp = nhgets(ih->ildst);
dp = nhgets(ih->ilsrc);
+ dst = nhgetl(ih->src);
+
+print("got packet from %d.%d.%d.%d %d %d\n", fmtaddr(dst), sp, dp);
+
etab = &ipc[conf.ip];
for(s = ipc; s < etab; s++) {
- if(s->psrc == sp && s->pdst == dp) {
+ if(s->psrc == sp && s->pdst == dp && s->dst == dst) {
ilprocess(s, ih, bp);
return;
}
}
+ if(s->curlog > s->backlog) {
+print("Backlog\n");
+ goto reset;
+ }
+
for(s = ipc; s < etab; s++) {
- if(s->ilctl.state == Illistening && s->psrc == 0) {
+ if(s->ilctl.state == Illistening && s->pdst == 0) {
/* Do the listener stuff */
new = ipincoming(ipc);
if(new == 0)
@@ 222,6 232,7 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
new->newcon = 1;
new->ipinterface = s->ipinterface;
s->ipinterface->ref++;
+ s->curlog++;
new->psrc = sp;
new->pdst = dp;
new->dst = nhgetl(ih->src);
@@ 240,6 251,8 @@ drop:
void
ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
{
+ Block *nb;
+
switch(s->ilctl.state) {
case Ilclosed:
case Ilclosing:
@@ 265,10 278,14 @@ ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
case Ildata:
ilackto(&s->ilctl, nhgetl(h->ilack));
bp->rptr += IL_EHSIZE+IL_HDRSIZE;
+/* Check and trim to length */
PUTNEXT(s->readq, bp);
break;
case Ilreset:
s->ilctl.state = Ilclosed;
+ nb = allocb(0);
+ nb->type = M_HANGUP;
+ PUTNEXT(s->readq, nb);
freeb(bp);
}
}
@@ 287,17 304,18 @@ ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, int ack)
ic = &ipc->ilctl;
/* Ip fields */
- hnputl(ih->src, Myip);
- hnputl(ih->dst, ipc->dst);
ih->proto = IP_ILPROTO;
+ hnputl(ih->src, Myip);
hnputs(ih->illen, IL_HDRSIZE);
if(inih) {
+ hnputl(ih->dst, nhgetl(inih->src));
hnputs(ih->ilsrc, nhgets(inih->ildst));
hnputs(ih->ildst, nhgets(inih->ilsrc));
hnputl(ih->ilid, nhgetl(inih->ilack));
hnputl(ih->ilack, nhgetl(inih->ilid));
}
else {
+ hnputl(ih->dst, ipc->dst);
hnputs(ih->ilsrc, ipc->psrc);
hnputs(ih->ildst, ipc->pdst);
hnputl(ih->ilid, ic->sent);
@@ 311,7 329,7 @@ ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, int ack)
if(ilcksum)
hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, IL_HDRSIZE));
- if(!ack) {
+ if(!ack && ipc) {
ic->sent++; /* Maybe needs locking */
ilackq(&ipc->ilctl, bp);
}