M ip/ethermedium.c => ip/ethermedium.c +9 -4
@@ 115,7 115,7 @@ struct Etherarp
static void
etherbind(Ipifc *ifc, int argc, char **argv)
{
- Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6;
+ Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6, *schan;
char addr[Maxpath]; //char addr[2*KNAMELEN];
char dir[Maxpath]; //char dir[2*KNAMELEN];
char *buf;
@@ 158,9 158,14 @@ etherbind(Ipifc *ifc, int argc, char **argv)
*/
snprint(addr, sizeof(addr), "%s/stats", dir);
buf = smalloc(512);
- achan = namec(addr, Aopen, OREAD, 0);
- n = devtab[achan->type]->read(achan, buf, 511, 0);
- cclose(achan);
+ schan = namec(addr, Aopen, OREAD, 0);
+ if(waserror()){
+ cclose(schan);
+ nexterror();
+ }
+ n = devtab[schan->type]->read(schan, buf, 511, 0);
+ cclose(schan);
+ poperror();
buf[n] = 0;
ptr = strstr(buf, "addr: ");
M ip/tcp.c => ip/tcp.c +29 -22
@@ 679,23 679,19 @@ tcpmtu(Conv *s)
uchar version;
version = s->ipversion;
- mtu = 0;
ifc = findipifc(s->p->f, s->raddr, 0);
- if(ifc != nil) {
- switch(version){
- case V4:
+ switch(version){
+ default:
+ case V4:
+ mtu = DEF_MSS;
+ if(ifc != nil)
mtu = ifc->maxmtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
- break;
- case V6:
+ break;
+ case V6:
+ mtu = DEF_MSS6;
+ if(ifc != nil)
mtu = ifc->maxmtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
- break;
- default:
- panic("tcpmtu: version %d", version);
- }
- }
-
- if(mtu < 32) {
- mtu = 1280;
+ break;
}
return mtu;
@@ 1665,6 1661,19 @@ reset:
break;
}
+ if(tcb->state != Syn_received){
+ /*
+ * One DOS attack is to open connections to us and then forget about them,
+ * thereby tying up a conv at no long term cost to the attacker.
+ * This is an attempt to defeat these stateless DOS attacks. See
+ * corresponding code in tcpsendka().
+ */
+ if(seq_within(seg.ack, tcb->snd.una-(1<<31), tcb->snd.una-(1<<29))){
+ print("stateless hog %lux - %lux - %lux\n", tcb->snd.una-(1<<31), seg.ack, tcb->snd.una-(1<<29));
+ localclose(s, "stateless hog");
+ }
+ }
+
/* Cut the data to fit the receive window */
if(tcptrim(tcb, &seg, &bp, &length) == -1) {
netlog(f, Logtcp, "tcp len < 0, %lux\n", seg.seq);
@@ 2122,6 2131,10 @@ tcpoutput(Conv *s)
/*
* the BSD convention (hack?) for keep alives. resend last uchar acked.
+ *
+ * To avoid stateless Conv hogs, we pick a sequence number at random. If
+ * it that number gets acked by the other end, we shut down the connection.
+ * See the equivalent code in tcpiput().
*/
void
tcpsendka(Conv *s)
@@ 2138,7 2151,7 @@ tcpsendka(Conv *s)
seg.dest = s->rport;
seg.flags = ACK|PSH;
seg.mss = 0;
- seg.seq = tcb->snd.una-1;
+ seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
seg.ack = tcb->rcv.nxt;
seg.wnd = tcb->rcv.wnd;
tcb->last_ack = tcb->rcv.nxt;
@@ 2320,7 2333,6 @@ void
procsyn(Conv *s, Tcp *seg)
{
Tcpctl *tcb;
- int mtu;
tcb = (Tcpctl*)s->ptcl;
tcb->flags |= FORCE;
@@ 2330,14 2342,9 @@ procsyn(Conv *s, Tcp *seg)
tcb->irs = seg->seq;
tcb->snd.wnd = seg->wnd;
- if(seg->mss != 0)
+ if(seg->mss != 0 && seg->mss < tcb->mss)
tcb->mss = seg->mss;
-
tcb->max_snd = seg->wnd;
-
- mtu = tcpmtu(s);
- if(tcb->mss > mtu)
- tcb->mss = mtu;
tcb->cwind = tcb->mss;
}
M port/devrealtime.c => port/devrealtime.c +13 -11
@@ 13,6 13,7 @@
/* debugging */
extern int edfprint;
+extern Edfinterface realedf, *edf;
static Schedevent *events;
static int nevents, revent, wevent;
@@ 219,6 220,7 @@ devrtinit(void)
events = (Schedevent *)malloc(sizeof(Schedevent) * Nevents);
assert(events);
nevents = revent = wevent = 0;
+ edf = &realedf;
}
static Chan *
@@ 286,7 288,7 @@ devrtopen(Chan *c, int mode)
case Qclone:
if (mode == OREAD)
error(Eperm);
- edfinit();
+ edf->edfinit();
/* open a new task */
for (t = tasks; t< tasks + Maxtasks; t++){
qlock(t);
@@ 638,7 640,7 @@ removetask(Task *t)
Resource *r;
qlock(t);
- edfexpel(t);
+ edf->edfexpel(t);
for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
if (p = *pp)
p->task = nil;
@@ 724,7 726,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
if (e=parsetime(&time, v))
error(e);
ticks = time2ticks(time);
- edfexpel(t);
+ edf->edfexpel(t);
switch(add){
case -1:
if (ticks > t->T)
@@ 745,7 747,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
if (e=parsetime(&time, v))
error(e);
ticks = time2ticks(time);
- edfexpel(t);
+ edf->edfexpel(t);
switch(add){
case -1:
if (ticks > t->D)
@@ 764,7 766,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
if (e=parsetime(&time, v))
error(e);
ticks = time2ticks(time);
- edfexpel(t);
+ edf->edfexpel(t);
switch(add){
case -1:
if (ticks > t->C)
@@ 784,7 786,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
}else if (strcmp(a, "resources") == 0){
if (v == nil)
error("resources: value missing");
- edfexpel(t);
+ edf->edfexpel(t);
if (add == 0){
for (rp = t->res; rp < t->res + nelem(t->res); rp++)
if (*rp){
@@ 809,7 811,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
if (v == nil)
error("procs: value missing");
if (add <= 0){
- edfexpel(t);
+ edf->edfexpel(t);
}
if (add == 0){
for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
@@ 835,10 837,10 @@ devrtwrite(Chan *c, void *va, long n, vlong)
error(e);
}
}else if (strcmp(a, "admit") == 0){
- if (e = edfadmit(t))
+ if (e = edf->edfadmit(t))
error(e);
}else if (strcmp(a, "expel") == 0){
- edfexpel(t);
+ edf->edfexpel(t);
}else if (strcmp(a, "remove") == 0){
removetask(t);
return n; /* Ignore any subsequent commands */
@@ 857,8 859,8 @@ devrtwrite(Chan *c, void *va, long n, vlong)
else
t->flags |= Useblocking;
}else if (strcmp(a, "yield") == 0){
- if (isedf(up) && up->task == t){
- edfdeadline(up); /* schedule next release */
+ if (edf->isedf(up) && up->task == t){
+ edf->edfdeadline(up); /* schedule next release */
sched();
}else
error("yield outside task");
M port/edf.c => port/edf.c +25 -11
@@ 49,6 49,7 @@ enum{
static int earlierrelease(Task *t1, Task *t2) {return t1->r < t2->r;}
static int earlierdeadline(Task *t1, Task *t2) {return t1->d < t2->d;}
+static void edfrelease(Task *t);
/* Tasks waiting for release, head earliest release time */
Taskq qwaitrelease = {{0}, nil, earlierrelease};
@@ 71,7 72,7 @@ static void edfreleaseintr(Ureg *, Timer *cy);
static void edfdeadlineintr(Ureg*, Timer*);
static char * edftestschedulability(Task *thetask);
-void
+static void
edfinit(void)
{
int i;
@@ 96,13 97,13 @@ edfinit(void)
iunlock(&edflock);
}
-int
+static int
isedf(Proc *p)
{
return p && p->task && p->task->state >= EdfIdle;
}
-int
+static int
edfanyready(void)
{
return edfstack[m->machno].head || qreleased.head;
@@ 220,7 221,7 @@ edfreleasetimer(void)
timeradd(&releasetimer[m->machno]);
}
-void
+static void
edfblock(Proc *p)
{
Task *t, *pt;
@@ 284,7 285,7 @@ deadline(Proc *p, SEvent why)
edfresched(t);
}
-void
+static void
edfdeadline(Proc *p)
{
DPRINT("%d edfdeadline\n", m->machno);
@@ 295,7 296,7 @@ edfdeadline(Proc *p)
iunlock(&edflock);
}
-char *
+static char *
edfadmit(Task *t)
{
char *err;
@@ 361,7 362,7 @@ edfadmit(Task *t)
return nil;
}
-void
+static void
edfexpel(Task *t)
{
Task *tt;
@@ 492,7 493,7 @@ edfdeadlineintr(Ureg*, Timer*)
splhi();
}
-void
+static void
edfbury(Proc *p)
{
Task *t;
@@ 526,7 527,7 @@ edfbury(Proc *p)
iunlock(&edflock);
}
-void
+static void
edfready(Proc *p)
{
Task *t;
@@ 671,7 672,7 @@ edfresched(Task *t)
}
}
-void
+static void
edfrelease(Task *t)
{
DPRINT("%d edfrelease, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
@@ 685,7 686,7 @@ edfrelease(Task *t)
if(devrt) devrt(t, now, SRelease);
}
-Proc *
+static Proc *
edfrunproc(void)
{
/* Return an edf proc to run or nil */
@@ 961,3 962,16 @@ time2ticks(Time time)
assert(time >= 0);
return uvmuldiv(time, fasthz, Onesecond);
}
+
+Edfinterface realedf = {
+ .isedf = isedf,
+ .edfbury = edfbury,
+ .edfanyready = edfanyready,
+ .edfready = edfready,
+ .edfrunproc = edfrunproc,
+ .edfblock = edfblock,
+ .edfinit = edfinit,
+ .edfexpel = edfexpel,
+ .edfadmit = edfadmit,
+ .edfdeadline = edfdeadline,
+};
M port/edf.h => port/edf.h +4 -4
@@ 14,10 14,10 @@ enum {
typedef vlong Time;
typedef uvlong Ticks;
-typedef struct Task Task;
-typedef struct Resource Resource;
-typedef struct Edf Edf;
-typedef struct Taskq Taskq;
+typedef struct Task Task;
+typedef struct Resource Resource;
+typedef struct Edf Edf;
+typedef struct Taskq Taskq;
enum Edfstate {
EdfUnused, /* task structure not in use */
M port/nulledf.c => port/nulledf.c +39 -6
@@ 6,36 6,69 @@
#include "../port/error.h"
#include "../port/edf.h"
-int
+static int
isedf(Proc*)
{
return 0;
}
-void
+static void
edfbury(Proc*)
{
}
-int
+static int
edfanyready(void)
{
return 0;
}
-void
+static void
edfready(Proc*)
{
}
-Proc*
+static Proc*
edfrunproc(void)
{
return nil;
}
-void
+static void
edfblock(Proc*)
{
}
+static void
+edfinit(void)
+{
+}
+
+static void
+edfexpel(Task*)
+{
+}
+
+static char *
+edfadmit(Task*)
+{
+ return "No edf";
+}
+
+static void
+edfdeadline(Proc*)
+{
+}
+
+Edfinterface nulledf = {
+ .isedf = isedf,
+ .edfbury = edfbury,
+ .edfanyready = edfanyready,
+ .edfready = edfready,
+ .edfrunproc = edfrunproc,
+ .edfblock = edfblock,
+ .edfinit = edfinit,
+ .edfexpel = edfexpel,
+ .edfadmit = edfadmit,
+ .edfdeadline = edfdeadline,
+};
M port/portclock.c => port/portclock.c +1 -1
@@ 122,7 122,7 @@ hzclock(Ureg *ur)
return;
/* i.e. don't deschedule an EDF process here! */
- if(anyready() && !isedf(up)){
+ if(anyready() && !edf->isedf(up)){
sched();
splhi();
}
M port/portdat.h => port/portdat.h +16 -0
@@ 6,6 6,7 @@ typedef struct Cmdtab Cmdtab;
typedef struct Cname Cname;
typedef struct Dev Dev;
typedef struct Dirtab Dirtab;
+typedef struct Edfinterface Edfinterface;
typedef struct Egrp Egrp;
typedef struct Evalue Evalue;
typedef struct Fgrp Fgrp;
@@ 846,6 847,21 @@ struct Timer
ulong period;
};
+struct Edfinterface {
+ int (*isedf)(Proc*);
+ void (*edfbury)(Proc*);
+ int (*edfanyready)(void);
+ void (*edfready)(Proc*);
+ Proc* (*edfrunproc)(void);
+ void (*edfblock)(Proc*);
+ void (*edfinit)(void);
+ void (*edfexpel)(Task *t);
+ char * (*edfadmit)(Task *t);
+ void (*edfdeadline)(Proc *p);
+};
+
+extern Edfinterface *edf;
+
#define DEVDOTDOT -1
#pragma varargck argpos print 1
M port/portfns.h => port/portfns.h +0 -12
@@ 87,17 87,6 @@ void dumpstack(void);
Fgrp* dupfgrp(Fgrp*);
void duppage(Page*);
void dupswap(Page*);
-void edfdeadline(Proc*);
-void edfrelease(Task*);
-char* edfadmit(Task*);
-void edfexpel(Task*);
-void edfbury(Proc*);
-void edfsched(Task*);
-int edfanyready(void);
-void edfready(Proc*);
-Proc* edfrunproc(void);
-void edfblock(Proc*);
-void edfinit(void);
int emptystr(char*);
int encrypt(void*, void*, int);
void envcpy(Egrp*, Egrp*);
@@ 140,7 129,6 @@ int incref(Ref*);
void initseg(void);
int iprint(char*, ...);
void isdir(Chan*);
-int isedf(Proc*);
int iseve(void);
int islo(void);
Segment* isoverlap(Proc*, ulong, int);
M port/proc.c => port/proc.c +18 -14
@@ 22,6 22,10 @@ static struct Procalloc
static Schedq runq[Nrq];
+extern Edfinterface nulledf;
+
+Edfinterface *edf = &nulledf;
+
char *statename[] =
{ /* BUG: generate automatically */
"Dead",
@@ 57,8 61,8 @@ schedinit(void) /* never returns */
break;
case Moribund:
up->state = Dead;
- if (isedf(up))
- edfbury(up);
+ if (edf->isedf(up))
+ edf->edfbury(up);
/*
* Holding locks from pexit:
@@ 122,7 126,7 @@ sched(void)
int
anyready(void)
{
- return nrdy || edfanyready();
+ return nrdy || edf->edfanyready();
}
int
@@ 153,8 157,8 @@ ready(Proc *p)
s = splhi();
- if(isedf(p)){
- edfready(p);
+ if(edf->isedf(p)){
+ edf->edfready(p);
splx(s);
return;
}
@@ 208,7 212,7 @@ runproc(void)
Proc *p, *l;
ulong rt;
- if ((p = edfrunproc()) != nil)
+ if ((p = edf->edfrunproc()) != nil)
return p;
loop:
@@ 503,8 507,8 @@ sleep(Rendez *r, int (*f)(void*), void *arg)
unlock(r);
// Behind unlock, we may call wakeup on ourselves.
- if (isedf(up))
- edfblock(up);
+ if (edf->isedf(up))
+ edf->edfblock(up);
gotolabel(&m->sched);
}
@@ 713,8 717,8 @@ addbroken(Proc *p)
broken.p[broken.n++] = p;
qunlock(&broken);
- if (isedf(up))
- edfbury(up);
+ if (edf->isedf(up))
+ edf->edfbury(up);
p->state = Broken;
p->psstate = 0;
sched();
@@ 884,8 888,8 @@ pexit(char *exitstr, int freemem)
lock(&procalloc);
lock(&palloc);
- if (isedf(up))
- edfbury(up);
+ if (edf->isedf(up))
+ edf->edfbury(up);
up->state = Moribund;
sched();
panic("pexit");
@@ 1139,8 1143,8 @@ procctl(Proc *p)
qunlock(&p->debug);
splhi();
p->state = Stopped;
- if (isedf(up))
- edfblock(up);
+ if (edf->isedf(up))
+ edf->edfblock(up);
sched();
p->psstate = state;
splx(s);
M port/qlock.c => port/qlock.c +6 -6
@@ 43,8 43,8 @@ qlock(QLock *q)
up->state = Queueing;
up->qpc = getcallerpc(&q);
unlock(&q->use);
- if(isedf(up))
- edfblock(up);
+ if(edf->isedf(up))
+ edf->edfblock(up);
sched();
}
@@ 107,8 107,8 @@ rlock(RWlock *q)
up->qnext = 0;
up->state = QueueingR;
unlock(&q->use);
- if (isedf(up))
- edfblock(up);
+ if (edf->isedf(up))
+ edf->edfblock(up);
sched();
}
@@ 164,8 164,8 @@ wlock(RWlock *q)
up->qnext = 0;
up->state = QueueingW;
unlock(&q->use);
- if (isedf(up))
- edfblock(up);
+ if (edf->isedf(up))
+ edf->edfblock(up);
sched();
}
M port/sysproc.c => port/sysproc.c +2 -2
@@ 839,8 839,8 @@ sysrendezvous(ulong *arg)
*l = up;
up->state = Rendezvous;
unlock(up->rgrp);
- if (isedf(up))
- edfblock(up);
+ if (edf->isedf(up))
+ edf->edfblock(up);
sched();