From 0eda2a9c26fce9efca9185306e14fe4e4cadf637 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 24 Apr 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-04-24 --- ip/devip.c | 3 +++ ip/icmp.c | 1 + ip/il.c | 1 + ip/ip.h | 3 ++- ip/tcp.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- ip/udp.c | 1 + 6 files changed, 61 insertions(+), 3 deletions(-) diff --git a/ip/devip.c b/ip/devip.c index 5829142959de5e69aea57d622247c6b24af4c5a7..256b2fe31539f8d2dfbbeb07ddb69cd3fc059eac 100644 --- a/ip/devip.c +++ b/ip/devip.c @@ -1084,6 +1084,7 @@ Fsprotoclone(Proto *p, char *user) { Conv *c, **pp, **ep; +retry: c = nil; ep = &p->conv[p->nc]; for(pp = p->conv; pp < ep; pp++) { @@ -1120,6 +1121,8 @@ Fsprotoclone(Proto *p, char *user) } } if(pp >= ep) { + if(p->gc != nil && (*p->gc)(p)) + goto retry; return nil; } diff --git a/ip/icmp.c b/ip/icmp.c index 6a515f0cc6a4f4e81360a2933d5d7d6b628468f7..7df64cfbf11dc95a73c5f188bf3aeaf5538e48b3 100644 --- a/ip/icmp.c +++ b/ip/icmp.c @@ -465,6 +465,7 @@ icmpinit(Fs *fs) icmp->stats = icmpstats; icmp->ctl = nil; icmp->advise = icmpadvise; + icmp->gc = nil; icmp->ipproto = IP_ICMPPROTO; icmp->nc = 16; icmp->ptclsize = 0; diff --git a/ip/il.c b/ip/il.c index 33391b729a4fdc83f6939aca7b579f8beaa7d85b..33ec6df9a770f9fe1550bafddccc2a1c328808d7 100644 --- a/ip/il.c +++ b/ip/il.c @@ -1341,6 +1341,7 @@ ilinit(Fs *f) il->advise = iladvise; il->stats = ilxstats; il->inuse = ilinuse; + il->gc = nil; il->ipproto = IP_ILPROTO; il->nc = Nchans; il->ptclsize = sizeof(Ilcb); diff --git a/ip/ip.h b/ip/ip.h index e10fc09806fe9239161a1210873ec4037a130090..ef1b2f8887d5a75aa63c2437bf44e6048af48923 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -27,7 +27,7 @@ enum Maxproto= 20, Nhash= 64, Maxincall= 5, - Nchans= 256, + Nchans= 512, MAClen= 16, /* longest mac address */ MAXTTL= 255, @@ -218,6 +218,7 @@ struct Proto int (*local)(Conv*, char*, int); int (*remote)(Conv*, char*, int); int (*inuse)(Conv*); + int (*gc)(Proto*); /* returns true if any conversations are freed */ Fs *f; /* file system this proto is part of */ Conv **conv; /* array of conversations */ diff --git a/ip/tcp.c b/ip/tcp.c index 0c65ef3024a0874c4ef659b77e0b2e80a9b61466..33051c536dc30355b346690c3a7789a5a34f9c40 100644 --- a/ip/tcp.c +++ b/ip/tcp.c @@ -123,7 +123,7 @@ struct Tcp ushort wnd; ushort urg; ushort mss; - ushort len; /* size of data */ + ushort len; /* size of data */ }; typedef struct Reseq Reseq; @@ -188,6 +188,7 @@ struct Tcpctl int mdev; /* Mean deviation of round trip */ int kacounter; /* count down for keep alive */ uint sndsyntime; /* time syn sent */ + ulong time; /* time Finwait2 or Syn_received was sent */ Tcphdr protohdr; /* prototype header */ }; @@ -1340,6 +1341,7 @@ tcpiput(Proto *tcp, uchar*, Block *bp) if(seg.flags & SYN) { procsyn(s, &seg); tcpsndsyn(tcb); + tcb->time = msec; tcpsetstate(s, Syn_received); if(length != 0 || (seg.flags & FIN)) break; @@ -1365,8 +1367,10 @@ tcpiput(Proto *tcp, uchar*, Block *bp) tcpsynackrtt(s); tcpsetstate(s, Established); } - else + else { + tcb->time = msec; tcpsetstate(s, Syn_received); + } if(length != 0 || (seg.flags & FIN)) break; @@ -1460,6 +1464,7 @@ tcpiput(Proto *tcp, uchar*, Block *bp) tcphalt(tpriv, &tcb->rtt_timer); tcphalt(tpriv, &tcb->acktimer); tcpsetkacounter(tcb); + tcb->time = msec; tcpsetstate(s, Finwait2); tcb->katimer.start = MSL2 * (1000 / MSPTICK); tcpgo(tpriv, &tcb->katimer); @@ -2238,6 +2243,51 @@ tcpstats(Proto *tcp, char *buf, int len) tpriv->tstats.OutRsts); } +/* + * garbage collect any stale conversations: + * - SYN received but no SYN-ACK after 5 seconds (could be the SYN attack) + * - Finwait2 after 5 minutes + * + * this is called whenever we run out of channels. Both checks are + * of questionable validity so we try to use them only when we're + * up against the wall. + */ +int +tcpgc(Proto *tcp) +{ + Conv *c, **pp, **ep; + int n; + Tcpctl *tcb; + + + n = 0; + ep = &tcp->conv[tcp->nc]; + for(pp = tcp->conv; pp < ep; pp++) { + c = *pp; + if(c == nil) + break; + if(!canqlock(c)) + continue; + tcb = (Tcpctl*)c->ptcl; + switch(tcb->state){ + case Syn_received: + if(msec - tcb->time > 5000){ + localclose(c, "timed out"); + n++; + } + break; + case Finwait2: + if(msec - tcb->time > 5*60*1000){ + localclose(c, "timed out"); + n++; + } + break; + } + qunlock(c); + } + return n; +} + void tcpinit(Fs *fs) { @@ -2258,6 +2308,7 @@ tcpinit(Fs *fs) tcp->advise = tcpadvise; tcp->stats = tcpstats; tcp->inuse = tcpinuse; + tcp->gc = tcpgc; tcp->ipproto = IP_TCPPROTO; tcp->nc = Nchans; tcp->ptclsize = sizeof(Tcpctl); diff --git a/ip/udp.c b/ip/udp.c index d7eff2ae775dffcedee4b0b6113cbd2cda9db46e..ea3217654b193fa2320cb873dce3aa588177e813 100644 --- a/ip/udp.c +++ b/ip/udp.c @@ -497,6 +497,7 @@ udpinit(Fs *fs) udp->rcv = udpiput; udp->advise = udpadvise; udp->stats = udpstats; + udp->gc = nil; udp->ipproto = IP_UDPPROTO; udp->nc = Nchans; udp->ptclsize = sizeof(Udpcb);