From bd91522ad0a9b938efd0d416755ed5de85d3fd8b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 4 Aug 1993 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1993-08-04 --- port/arp.h | 45 -- port/bootp.h | 29 - port/devarp.c | 489 -------------- port/devdk.c | 1636 --------------------------------------------- port/devip.c | 1206 --------------------------------- port/deviproute.c | 377 ----------- port/ipdat.h | 533 --------------- port/proc.c | 1 - port/qio.c | 25 +- port/stasync.c | 477 ------------- port/stfcall.c | 172 ----- port/stil.c | 877 ------------------------ port/stip.c | 635 ------------------ port/streboot.c | 48 -- port/stsplice.c | 80 --- port/sturp.c | 1072 ----------------------------- port/tcpif.c | 108 --- port/tcpinput.c | 1026 ---------------------------- port/tcpoutput.c | 273 -------- port/tcptimer.c | 125 ---- 20 files changed, 16 insertions(+), 9218 deletions(-) delete mode 100644 port/arp.h delete mode 100644 port/bootp.h delete mode 100644 port/devarp.c delete mode 100644 port/devdk.c delete mode 100644 port/devip.c delete mode 100644 port/deviproute.c delete mode 100644 port/ipdat.h delete mode 100644 port/stasync.c delete mode 100644 port/stfcall.c delete mode 100644 port/stil.c delete mode 100644 port/stip.c delete mode 100644 port/streboot.c delete mode 100644 port/stsplice.c delete mode 100644 port/sturp.c delete mode 100644 port/tcpif.c delete mode 100644 port/tcpinput.c delete mode 100644 port/tcpoutput.c delete mode 100644 port/tcptimer.c diff --git a/port/arp.h b/port/arp.h deleted file mode 100644 index 17a71fb142b10ada312c720636e87cfa2314b7e7..0000000000000000000000000000000000000000 --- a/port/arp.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * this file used by (at least) the kernel, arpd, snoopy, tboot - */ -typedef struct Arppkt Arppkt; -typedef struct Arpentry Arpentry; -typedef struct Arpstats Arpstats; - -/* Format of ethernet arp request */ -struct Arppkt { - uchar d[6]; - uchar s[6]; - uchar type[2]; - uchar hrd[2]; - uchar pro[2]; - uchar hln; - uchar pln; - uchar op[2]; - uchar sha[6]; - uchar spa[4]; - uchar tha[6]; - uchar tpa[4]; - }; - -#define ARPSIZE 42 - -/* Format of request from starp to user level arpd */ -struct Arpentry { - uchar etaddr[6]; - uchar ipaddr[4]; - }; - -/* Arp cache statistics */ -struct Arpstats { - int hit; - int miss; - int failed; - }; - -#define ET_ARP 0x0806 -#define ET_RARP 0x8035 - -#define ARP_REQUEST 1 -#define ARP_REPLY 2 -#define RARP_REQUEST 3 -#define RARP_REPLY 4 diff --git a/port/bootp.h b/port/bootp.h deleted file mode 100644 index 8a1dd2128796a7b9e378a6263434adb87ac4a6d1..0000000000000000000000000000000000000000 --- a/port/bootp.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * this file used by (at least) snoopy, tboot and bootp - */ -enum -{ - Bootrequest = 1, - Bootreply = 2, -}; - -typedef struct Bootp Bootp; -struct Bootp -{ - uchar op; /* opcode */ - uchar htype; /* hardware type */ - uchar hlen; /* hardware address len */ - uchar hops; /* hops */ - uchar xid[4]; /* a random number */ - uchar secs[2]; /* elapsed snce client started booting */ - uchar pad[2]; - uchar ciaddr[4]; /* client IP address (client tells server) */ - uchar yiaddr[4]; /* client IP address (server tells client) */ - uchar siaddr[4]; /* server IP address */ - uchar giaddr[4]; /* gateway IP address */ - uchar chaddr[16]; /* client hardware address */ - char sname[64]; /* server host name (optional) */ - char file[128]; /* boot file name */ - char vend[128]; /* vendor-specific goo */ -}; - diff --git a/port/devarp.c b/port/devarp.c deleted file mode 100644 index fd9595c117b0b3a6bd90634373093fb5dc17f3e1..0000000000000000000000000000000000000000 --- a/port/devarp.c +++ /dev/null @@ -1,489 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -#include "devtab.h" - -#define ARP_FREE 0 -#define ARP_OK 1 -#define ARP_ASKED 2 -#define ARP_TEMP 0 -#define ARP_PERM 1 -#define Arphashsize 32 -#define ARPHASH(p) arphash[((p[2]^p[3])%Arphashsize)] - -typedef struct Arpcache Arpcache; -struct Arpcache -{ - uchar status; - uchar type; - uchar eip[4]; - uchar et[6]; - Arpcache *hash; - Arpcache **hashhd; - Arpcache *frwd; - Arpcache *prev; -}; - -Arpstats arpstats; -Arpcache *arplruhead, *arplrutail; -Arpcache *arp, **arphash; -Queue *Servq; -Lock larphash; - -void arpiput(Queue *, Block *); -void arpoput(Queue *, Block *); -void arpopn(Queue *, Stream *); -void arpcls(Queue *); -void arpenter(Arpentry*, int); -void arpflush(void); -int arpdelete(char*); -void arplinkhead(Arpcache*); -int arplookup(uchar*, uchar*); - -Qinfo arpinfo = { arpiput, arpoput, arpopn, arpcls, "arp" }; - -#define ARP_ENTRYLEN 50 -char *padstr = " "; - -enum{ - arpdirqid, - arpdir2qid, - arpstatqid, - arpctlqid, - arpdataqid, -}; - -Dirtab arptab[]={ - "stats", {arpstatqid}, 0, 0444, - "ctl", {arpctlqid}, 0, 0664, - "data", {arpdataqid}, 0, 0664, -}; -#define Narptab (sizeof(arptab)/sizeof(Dirtab)) - -/* - * create a 2-level directory - */ -int -arpgen(Chan *c, void *vp, int ntab, int i, Dir *dp) -{ - Qid q; - - USED(vp); - USED(ntab); - - q.vers = 0; - - /* top level directory contains the directory arp */ - if(c->qid.path == CHDIR){ - if(i) - return -1; - q.path = CHDIR | arpdir2qid; - devdir(c, q, "arp", 0, eve, 0555, dp); - return 1; - } - - /* next level uses table */ - return devgen(c, arptab, Narptab, i, dp); -} - -void -arpreset(void) -{ - Arpcache *ap, *ep; - - arp = xalloc(sizeof(Arpcache) * conf.arp); - arphash = (Arpcache **)xalloc(sizeof(Arpcache *) * Arphashsize); - - ep = &arp[conf.arp]; - for(ap = arp; ap < ep; ap++) { - ap->frwd = ap+1; - ap->prev = ap-1; - ap->type = ARP_FREE; - ap->status = ARP_TEMP; - } - - arp[0].prev = 0; - arplruhead = arp; - ap = &arp[conf.arp-1]; - ap->frwd = 0; - arplrutail = ap; - newqinfo(&arpinfo); -} - -void -arpinit(void) -{ -} - -Chan * -arpattach(char *spec) -{ - return devattach('a', spec); -} - -Chan * -arpclone(Chan *c, Chan *nc) -{ - return devclone(c, nc); -} - -int -arpwalk(Chan *c, char *name) -{ - return devwalk(c, name, 0, 0, arpgen); -} - -void -arpstat(Chan *c, char *db) -{ - devstat(c, db, 0, 0, arpgen); -} - -Chan * -arpopen(Chan *c, int omode) -{ - if(c->qid.path&CHDIR){ - if(omode != OREAD) - error(Eperm); - } - - switch(STREAMTYPE(c->qid.path)) { - case arpdataqid: - break; - case arpstatqid: - if(omode != OREAD) - error(Ebadarg); - break; - case arpctlqid: - break; - } - - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -void -arpcreate(Chan *c, char *name, int omode, ulong perm) -{ - USED(c, name, omode, perm); - error(Eperm); -} - -void -arpremove(Chan *c) -{ - USED(c); - error(Eperm); -} - -void -arpwstat(Chan *c, char *dp) -{ - USED(c, dp); - error(Eperm); -} - -void -arpclose(Chan *c) -{ - streamclose(c); -} - -long -arpread(Chan *c, void *a, long n, ulong offset) -{ - char buf[100]; - Arpcache *ap; - int part, bytes, size; - char *ststr; - - if(c->qid.path&CHDIR) - return devdirread(c, a, n, arptab, Narptab, arpgen); - - switch((int)(c->qid.path&~CHDIR)){ - case arpdataqid: - bytes = c->offset; - while(bytes < conf.arp*ARP_ENTRYLEN && n) { - ap = &arp[bytes/ARP_ENTRYLEN]; - part = bytes%ARP_ENTRYLEN; - - if(ap->status != ARP_OK) - ststr = "invalid"; - else - ststr = (ap->type == ARP_TEMP ? "temp" : "perm"); - - sprint(buf,"%d.%d.%d.%d to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s%s", - ap->eip[0], ap->eip[1], ap->eip[2], ap->eip[3], - ap->et[0], ap->et[1], ap->et[2], ap->et[3], - ap->et[4], ap->et[5], - ststr, padstr); - - buf[ARP_ENTRYLEN-1] = '\n'; - - size = ARP_ENTRYLEN - part; - size = MIN(n, size); - memmove(a, buf+part, size); - - a = (void *)((int)a + size); - n -= size; - bytes += size; - } - return bytes - c->offset; - break; - case arpstatqid: - sprint(buf, "hits: %d miss: %d failed: %d\n", - arpstats.hit, arpstats.miss, arpstats.failed); - - return readstr(offset, a, n, buf); - default: - n=0; - break; - } - return n; -} - -long -arpwrite(Chan *c, char *a, long n, ulong offset) -{ - Arpentry entry; - char buf[20], *field[5]; - int m; - - USED(offset); - - switch(STREAMTYPE(c->qid.path)) { - case arpctlqid: - - strncpy(buf, a, sizeof buf); - m = getfields(buf, field, 5, ' '); - - if(strncmp(field[0], "flush", 5) == 0) - arpflush(); - else - if(strcmp(field[0], "delete") == 0) { - if(m != 2) - error(Ebadarg); - - if(arpdelete(field[1]) < 0) - error(Enetaddr); - } - break; - - case arpdataqid: - if(n != sizeof(Arpentry)) - error(Emsgsize); - memmove(&entry, a, sizeof(Arpentry)); - arpenter(&entry, ARP_TEMP); - break; - - default: - error(Ebadusefd); - } - - return n; -} - -void -arpopn(Queue *q, Stream *s) -{ - USED(q, s); -} - -void -arpcls(Queue *q) -{ - if(q == Servq) - Servq = 0; -} - -void -arpiput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} - -void -arpoput(Queue *q, Block *bp) -{ - uchar ip[4]; - Etherhdr *eh; - Ipaddr addr; - static int dropped; - - if(bp->type != M_DATA) { - if(Servq == 0 && streamparse("arpd", bp)) { - Servq = RD(q); - freeb(bp); - } - else - PUTNEXT(q, bp); - return; - } - - eh = (Etherhdr *)bp->rptr; - if(nhgets(eh->type) != ET_IP) { - PUTNEXT(q, bp); - return; - } - - /* if ip broadcast, use ether bcast address */ - addr = nhgetl(eh->dst); - if(Myip[Myself] == 0 || addr == Myip[Mybcast] || addr == Myip[Mynet] - || ((addr & Mymask) == Myip[Mynet+1] && (addr & ~Mynetmask) == ~Mynetmask)){ - memset(eh->d, 0xff, sizeof(eh->d)); - PUTNEXT(q, bp); - return; - } - - iproute(eh->dst, ip); - - /* if a known ip addr, send downstream to the ethernet */ - if(arplookup(ip, eh->d)) { - PUTNEXT(q, bp); - return; - } - - /* Push the packet up to the arp server for address resolution */ - if(!Servq) { - if((dropped++ % 1000) == 0) - print("arp: No server, packet dropped %d.%d.%d.%d\n", - eh->dst[0], eh->dst[1], eh->dst[2], eh->dst[3]); - freeb(bp); - return; - } - memmove(eh->d, ip, sizeof(ip)); - PUTNEXT(Servq, bp); -} - -int -arplookup(uchar *ip, uchar *et) -{ - Arpcache *ap; - - lock(&larphash); - for(ap = ARPHASH(ip); ap; ap = ap->hash) { - if(ap->status == ARP_OK && memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) { - memmove(et, ap->et, sizeof(ap->et)); - arplinkhead(ap); - unlock(&larphash); - arpstats.hit++; - return 1; - } - } - arpstats.miss++; - unlock(&larphash); - return 0; -} - -void -arpflush(void) -{ - Arpcache *ap, *ep; - - ep = &arp[conf.arp]; - for(ap = arp; ap < ep; ap++) - ap->status = ARP_FREE; -} - -void -arpenter(Arpentry *ape, int type) -{ - Arpcache *ap, **l, *d; - - - /* Update an entry if we have one already */ - l = &ARPHASH(ape->ipaddr); - lock(&larphash); - for(ap = *l; ap; ap = ap->hash) { - if(ap->status == ARP_OK && memcmp(ap->eip, ape->ipaddr, sizeof(ap->eip)) == 0) { - if(ap->type != ARP_PERM) { - ap->type = type; - memmove(ap->et, ape->etaddr, sizeof(ap->et)); - ap->status = ARP_OK; - } - unlock(&larphash); - return; - } - } - - /* Find an entry to replace */ - for(ap = arplrutail; ap && ap->type == ARP_PERM; ap = ap->prev) - ; - - if(!ap) { - print("arp: too many permanent entries\n"); - unlock(&larphash); - return; - } - - if(ap->hashhd) { - for(d = *ap->hashhd; d; d = d->hash) { - if(d == ap) { - *(ap->hashhd) = ap->hash; - break; - } - ap->hashhd = &d->hash; - } - } - - ap->type = type; - ap->status = ARP_OK; - memmove(ap->eip, ape->ipaddr, sizeof(ape->ipaddr)); - memmove(ap->et, ape->etaddr, sizeof(ape->etaddr)); - ap->hashhd = l; - ap->hash = *l; - *l = ap; - arplinkhead(ap); - unlock(&larphash); -} - -int -arpdelete(char *addr) -{ - Arpcache *ap; - uchar ip[4]; - Ipaddr i; - int rv; - - rv = -1; - i = ipparse(addr); - hnputl(ip, i); - lock(&larphash); - for(ap = arplruhead; ap; ap = ap->frwd) { - if(memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) { - ap->status = ARP_FREE; - rv = 0; - break; - } - } - unlock(&larphash); - return rv; -} - -void -arplinkhead(Arpcache *ap) -{ - if(ap != arplruhead) { - if(ap->prev) - ap->prev->frwd = ap->frwd; - else - arplruhead = ap->frwd; - - if(ap->frwd) - ap->frwd->prev = ap->prev; - else - arplrutail = ap->prev; - - ap->frwd = arplruhead; - ap->prev = 0; - arplruhead = ap; - } -} diff --git a/port/devdk.c b/port/devdk.c deleted file mode 100644 index 28a70420277efb6b72144388e764fc3abb681360..0000000000000000000000000000000000000000 --- a/port/devdk.c +++ /dev/null @@ -1,1636 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define DPRINT if(0) print - -#define NOW (MACHP(0)->ticks) - -typedef struct Dkmsg Dkmsg; -typedef struct Line Line; -typedef struct Dk Dk; - -enum { - Maxdk = 4, -}; - -/* - * types of possible dkcalls - */ -enum { - Dial, - Announce, - Redial -}; - -/* - * format of messages to/from the datakit controller on the common - * signalling line - */ -struct Dkmsg { - uchar type; - uchar srv; - uchar param0l; - uchar param0h; - uchar param1l; - uchar param1h; - uchar param2l; - uchar param2h; - uchar param3l; - uchar param3h; - uchar param4l; - uchar param4h; -}; - -/* - * message codes (T_xxx == dialin.type, D_xxx == dialin.srv) - */ -#define T_SRV 1 /* service request */ -#define D_SERV 1 /* (host to dkmux) announce a service */ -#define D_DIAL 2 /* (host to dkmux) connect to a service */ -#define D_XINIT 7 /* (dkmux to host) line has been spliced */ -#define T_REPLY 2 /* reply to T_SRV/D_SERV or T_SRV/D_DIAL */ -#define D_OK 1 /* not used */ -#define D_OPEN 2 /* (dkmux to host) connection established */ -#define D_FAIL 3 /* (dkmux to host) connection failed */ -#define T_CHG 3 /* change the status of a connection */ -#define D_CLOSE 1 /* close the connection */ -#define D_ISCLOSED 2 /* (dkmux to host) confirm a close */ -#define D_CLOSEALL 3 /* (dkmux to host) close all connections */ -#define D_REDIAL 6 /* (host to dkmux) redial a call */ -#define T_ALIVE 4 /* (host to dkmux) keep alive message */ -#define D_CONTINUE 0 /* host has not died since last msg */ -#define D_RESTART 1 /* host has restarted */ -#define D_MAXCHAN 2 /* request maximum line number */ -#define T_RESTART 8 /* (dkmux to host) datakit restarted */ - -/* - * macros for cracking/forming the window negotiation parameter - */ -#define MIN(x,y) (x < y ? x : y) -#define W_WINDOW(o,d,t) ((o<<8) | (d<<4) | t | 0100000) -#define W_VALID(x) ((x) & 0100000) -#define W_ORIG(x) (((x)>>8) & 017) -#define W_DEST(x) (((x)>>4) & 017) -#define W_TRAF(x) ((x) & 017) -#define W_DESTMAX(x,y) (W_WINDOW(W_ORIG(x),MIN(W_DEST(x),y),W_TRAF(x))) -#define W_LIMIT(x,y) (W_WINDOW(MIN(W_ORIG(x),y),MIN(W_DEST(x),y),W_TRAF(x))) -#define W_VALUE(x) (1<<((x)+4)) - -struct Line { - QLock; - Netprot; /* stat info */ - int lineno; - Rendez r; /* wait here for dial */ - int state; /* dial state */ - int err; /* dialing error (if non zero) */ - int window; /* negotiated window */ - int timestamp; /* timestamp of last call received on this line */ - int calltolive; /* multiple of 15 seconds for dialing state to last */ - Queue *rq; - char addr[64]; - char raddr[64]; - char ruser[32]; - Dk *dp; /* interface contianing this line */ -}; - -/* - * a dkmux dk. one exists for every stream that a - * dkmux line discipline is pushed onto. - */ -struct Dk -{ - QLock netlock; - Network net; /* stat info */ - Line **linep; /* array of line structures */ - - QLock csclock; - Chan *csc; - - char name[64]; /* dk name */ - Queue *wq; /* dk output queue */ - int ncsc; /* csc line number */ - int lines; /* number of lines */ - int restart; - int urpwindow; - Rendez timer; - int closeall; /* set when we receive a closeall message */ - Rendez closeallr; /* wait here for a closeall */ -}; -Lock dklock; -Dk *dk[Maxdk]; - -/* - * conversation states (for Line.state) - */ -typedef enum { - Lclosed=0, - Lopened, /* opened but no call out */ - Lconnected, /* opened and a call set up on htis line */ - Lrclose, /* remote end has closed down */ - Llclose, /* local end has closed down */ - Ldialing, /* dialing a new call */ - Llistening, /* this line listening for calls */ - Lackwait, /* incoming call waiting for ack/nak */ - Laccepting, /* waiting for user to accept or reject the call */ -} Lstate; -char *dkstate[] = -{ - [Lclosed] "Closed", - [Lopened] "Opened", - [Lconnected] "Established", - [Lrclose] "Rclose", - [Llclose] "Lclose", - [Ldialing] "Dialing", - [Llistening] "Listen", - [Lackwait] "Ackwait", - [Laccepting] "Accepting", -}; - -/* - * map datakit error to errno - */ -enum { - DKok, - DKbusy, - DKnetotl, - DKdestotl, - DKbadnet, - DKnetbusy, - DKinuse, - DKreject, -}; -char* dkerr[]={ - [DKok] "", - [DKbusy] "devdk: destination busy", - [DKnetotl] "devdk: network not answering", - [DKdestotl] "devdk: destination not answering", - [DKbadnet] "devdk: unknown address", - [DKnetbusy] "devdk: network busy", - [DKinuse] "devdk: service in use", - [DKreject] "devdk: connection refused", -}; -#define DKERRS sizeof(dkerr)/sizeof(char*) - -/* - * imported - */ -extern Qinfo urpinfo; - -/* - * predeclared - */ -Chan* dkattach(char*); -static void dkmuxconfig(Queue*, Block*); -static Chan* dkopenline(Dk*, int); -static Chan* dkopencsc(Dk*); -static int dkmesg(Chan*, int, int, int, int); -static void dkcsckproc(void*); -static void dkanswer(Chan*, int, int); -static void dkwindow(Chan*); -static void dkcall(int, Chan*, char*, char*, char*); -static void dktimer(void*); -static void dkchgmesg(Chan*, Dk*, Dkmsg*, int); -static void dkreplymesg(Dk*, Dkmsg*, int); -Chan* dkopen(Chan*, int); -static void dkhangup(Line*); - -/* - * for standard network interface (net.c) - */ -static int dkcloneline(Chan*); -static int dklisten(Chan*); -static void dkfilladdr(Chan*, char*, int); -static void dkfillraddr(Chan*, char*, int); -static void dkfillruser(Chan*, char*, int); -static void dkfillstatus(Chan*, char*, int); - -extern Qinfo dkinfo; - -/* - * the datakit multiplexor stream module definition - */ -static Streamopen dkmuxopen; -static Streamput dkmuxoput; -static Streamput dkmuxiput; -Qinfo dkmuxinfo = -{ - dkmuxiput, - dkmuxoput, - dkmuxopen, - 0, - "dkmux" -}; - -/* - * allocate a line if it doesn't exist - */ -static Line* -linealloc(Dk *dp, int lineno, int dolock) -{ - Line *lp; - - if(dolock) - qlock(&dp->netlock); - if(lineno > dp->lines) - panic("linealloc"); - lp = dp->linep[lineno]; - if(lp == 0){ - lp = smalloc(sizeof(Line)); - lp->lineno = lineno; - netadd(&dp->net, lp, lineno); - dp->linep[lineno] = lp; - } - if(dolock) - qunlock(&dp->netlock); - return lp; -} - -/* - * a new dkmux. hold the stream in place so it can never be closed down. - */ -static void -dkmuxopen(Queue *q, Stream *s) -{ - RD(q)->ptr = 0; - WR(q)->ptr = 0; - - naildownstream(s); -} - -/* - * handle configuration - */ -static void -dkmuxoput(Queue *q, Block *bp) -{ - if(bp->type != M_DATA){ - if(streamparse("config", bp)) - dkmuxconfig(q, bp); - else - PUTNEXT(q, bp); - return; - } - PUTNEXT(q, bp); -} - -/* - * gather a message and send it up the appropriate stream - * - * The first two bytes of each message contains the channel - * number, low order byte first. - * - * Simplifying assumption: one put == one message && the channel number - * is in the first block. If this isn't true, demultiplexing will not - * work. - */ -static void -dkmuxiput(Queue *q, Block *bp) -{ - Dk *dp; - Line *lp; - int line; - - /* - * not configured yet - */ - if(q->other->ptr == 0){ - freeb(bp); - return; - } - - dp = (Dk *)q->ptr; - if(bp->type != M_DATA){ - PUTNEXT(q, bp); - return; - } - - line = bp->rptr[0] | (bp->rptr[1]<<8); - bp->rptr += 2; - if(line<0 || line>=dp->lines){ - DPRINT("dkmuxiput bad line %d\n", line); - freeb(bp); - return; - } - - lp = linealloc(dp, line, 1); - if(lp && canqlock(lp)){ - if(lp->rq) - PUTNEXT(lp->rq, bp); - else{ - DPRINT("dkmuxiput unopened line %d\n", line); - freeb(bp); - } - qunlock(lp); - } else { - DPRINT("dkmuxiput unopened line %d\n", line); - freeb(bp); - } -} - -/* - * the datakit line stream module definition - */ -static Streamopen dkstopen; -static Streamclose dkstclose; -static Streamput dkoput, dkiput; -Qinfo dkinfo = -{ - dkiput, - dkoput, - dkstopen, - dkstclose, - "dk" -}; - -/* - * open and save a pointer to the conversation - */ -static void -dkstopen(Queue *q, Stream *s) -{ - Dk *dp; - Line *lp; - - dp = dk[s->dev]; - q->other->ptr = q->ptr = lp = dp->linep[s->id]; - lp->dp = dp; - lp->rq = q; - if(lp->state==Lclosed) - lp->state = Lopened; -} - -/* - * close down a datakit conversation - */ -static void -dkstclose(Queue *q) -{ - Dk *dp; - Line *lp; - Chan *c; - - lp = (Line *)q->ptr; - dp = lp->dp; - - /* - * if we never got going, we're done - */ - if(lp->rq == 0){ - lp->state = Lclosed; - return; - } - - /* - * these states don't need the datakit - */ - switch(lp->state){ - case Lclosed: - case Llclose: - case Lopened: - lp->state = Lclosed; - goto out; - } - - c = 0; - if(waserror()){ - lp->state = Lclosed; - if(c) - close(c); - goto out; - } - c = dkopencsc(dp); - - /* - * shake hands with dk - */ - switch(lp->state){ - case Lrclose: - dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); - lp->state = Lclosed; - break; - - case Lackwait: - dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); - lp->state = Llclose; - break; - - case Llistening: - dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); - lp->state = Llclose; - break; - - case Lconnected: - dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); - lp->state = Llclose; - break; - } - poperror(); - close(c); - -out: - qlock(lp); - lp->rq = 0; - qunlock(lp); - - netdisown(lp); - lp->window = 0; -} - -/* - * this is only called by hangup - */ -static void -dkiput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} - -/* - * we assume that each put is a message. - * - * add a 2 byte channel number to the start of each message, - * low order byte first. Make sure the first block contains - * both the 2 channel bytes and the control byte. - */ -static void -dkoput(Queue *q, Block *bp) -{ - Line *lp; - Dk *dp; - int line; - - if(bp->type != M_DATA){ - freeb(bp); - error(Ebadarg); - } - - lp = (Line *)q->ptr; - dp = lp->dp; - line = lp->lineno; - - bp = padb(bp, 2); - bp->rptr[0] = line; - bp->rptr[1] = line>>8; - - FLOWCTL(dp->wq, bp); -} - -/* - * configure a datakit multiplexor. this takes 5 arguments separated - * by spaces: - * the line number of the common signalling channel (must be > 0) - * the number of lines in the device (optional) - * the word `restart' or `norestart' (optional/default==restart) - * the name of the dk (default==dk) - * the urp window size (default==2048) - * - * we can configure only once - */ -static int -haveca(void *arg) -{ - Dk *dp; - - dp = arg; - return dp->closeall; -} -static void -dkmuxconfig(Queue *q, Block *bp) -{ - Dk *dp; - char *fields[5]; - int n; - char buf[64]; - char name[NAMELEN]; - int lines; - int ncsc; - int restart; - int window; - - if(WR(q)->ptr){ - freeb(bp); - error(Egreg); - } - - /* - * defaults - */ - ncsc = 1; - restart = 1; - lines = 16; - window = 2048; - strcpy(name, "dk"); - - /* - * parse - */ - n = getfields((char *)bp->rptr, fields, 5, ' '); - switch(n){ - case 5: - window = strtoul(fields[4], 0, 0); - if(window < 16) - window = 1<<(window+4); - case 4: - strncpy(name, fields[3], sizeof(name)); - name[sizeof(name)-1] = 0; - case 3: - if(strcmp(fields[2], "restart")!=0) - restart = 0; - case 2: - lines = strtoul(fields[1], 0, 0); - case 1: - ncsc = strtoul(fields[0], 0, 0); - break; - default: - freeb(bp); - error(Ebadarg); - } - freeb(bp); - if(ncsc <= 0 || lines <= ncsc) - error(Ebadarg); - - /* - * find a free dk slot. it name is already configured - * or no slots are left, error. - */ - lock(&dklock); - if(waserror()){ - unlock(&dklock); - nexterror(); - } - for(n = 0; n < Maxdk; n++){ - dp = dk[n]; - if(dp == 0) - break; - if(strcmp(name, dp->name) == 0) - error(Einuse); - } - if(n == Maxdk) - error(Enoifc); - - /* - * allocate both a dk structure and an array of pointers to line - * structures - */ - dp = smalloc(sizeof(Dk)); - dp->ncsc = ncsc; - dp->lines = lines; - dp->linep = smalloc(sizeof(Line*) * dp->lines); - strcpy(dp->name, name); - dp->net.name = dp->name; - dp->net.nconv = dp->lines; - dp->net.devp = &dkinfo; - dp->net.protop = &urpinfo; - dp->net.listen = dklisten; - dp->net.clone = dkcloneline; - dp->net.ninfo = 5; - dp->net.info[0].name = "local"; - dp->net.info[0].fill = dkfilladdr; - dp->net.info[1].name = "remote"; - dp->net.info[1].fill = dkfillraddr; - dp->net.info[2].name = "ruser"; - dp->net.info[2].fill = dkfillruser; - dp->net.info[3].name = "urpstats"; - dp->net.info[3].fill = urpfillstats; - dp->net.info[4].name = "status"; - dp->net.info[4].fill = dkfillstatus; - dp->restart = restart; - dp->urpwindow = window; - dp->wq = WR(q); - q->ptr = q->other->ptr = dp; - dk[n] = dp; - unlock(&dklock); - poperror(); - - /* - * open csc here so that boot, dktimer, and dkcsckproc aren't - * all fighting for it at once. - */ - dkopencsc(dp); - - /* - * start a process to listen to csc messages - */ - sprint(buf, "csc.%s.%d", dp->name, dp->ncsc); - kproc(buf, dkcsckproc, dp); - - /* - * tell datakit we've rebooted. It should close all channels. - * do this here to get it done before trying to open a channel. - */ - if(dp->restart) { - DPRINT("dktimer: restart %s\n", dp->name); - dp->closeall = 0; - dkmesg(dp->csc, T_ALIVE, D_RESTART, 0, 0); - } - tsleep(&dp->closeallr, haveca, dp, 15000); - - /* - * start a keepalive process - */ - sprint(buf, "timer.%s.%d", dp->name, dp->ncsc); - kproc(buf, dktimer, dp); -} - -void -dkreset(void) -{ - newqinfo(&dkmuxinfo); -} - -void -dkinit(void) -{ -} - -Chan* -dkattach(char *spec) -{ - Chan *c; - Dk *dp; - int dev; - - /* - * find a multiplexor with the same name (default dk) - */ - if(*spec == 0) - spec = "dk"; - for(dev = 0; dev < Maxdk; dev++){ - dp = dk[dev]; - if(dp && strcmp(dp->name, spec) == 0) - break; - } - if(dev == Maxdk) - error(Enoifc); - - /* - * return the new channel - */ - c = devattach('k', spec); - c->dev = dev; - return c; -} - -Chan* -dkclone(Chan *c, Chan *nc) -{ - return devclone(c, nc); -} - -int -dkwalk(Chan *c, char *name) -{ - return netwalk(c, name, &dk[c->dev]->net); -} - -void -dkstat(Chan *c, char *dp) -{ - netstat(c, dp, &dk[c->dev]->net); -} - -Chan* -dkopen(Chan *c, int omode) -{ - Dk *dp; - - dp = dk[c->dev]; - linealloc(dp, STREAMID(c->qid.path), 1); - return netopen(c, omode, &dp->net); -} - -void -dkcreate(Chan *c, char *name, int omode, ulong perm) -{ - USED(c); - USED(name); - USED(omode); - USED(perm); - error(Eperm); -} - -void -dkclose(Chan *c) -{ - if(c->stream) - streamclose(c); -} - -long -dkread(Chan *c, void *a, long n, ulong offset) -{ - return netread(c, a, n, offset, &dk[c->dev]->net); -} - -long -dkwrite(Chan *c, void *a, long n, ulong offset) -{ - int t; - char buf[256]; - char *field[5]; - int m; - - USED(offset); - t = STREAMTYPE(c->qid.path); - - /* - * get data dispatched as quickly as possible - */ - if(t == Sdataqid) - return streamwrite(c, a, n, 0); - - /* - * easier to do here than in dkoput - */ - if(t == Sctlqid){ - if(n > sizeof buf - 1) - n = sizeof buf - 1; - strncpy(buf, a, n); - buf[n] = '\0'; - m = getfields(buf, field, 5, ' '); - if(strcmp(field[0], "connect")==0){ - if(m < 2) - error(Ebadarg); - dkcall(Dial, c, field[1], 0, 0); - } else if(strcmp(field[0], "announce")==0){ - if(m < 2) - error(Ebadarg); - dkcall(Announce, c, field[1], 0, 0); - } else if(strcmp(field[0], "redial")==0){ - if(m < 4) - error(Ebadarg); - dkcall(Redial, c, field[1], field[2], field[3]); - } else if(strcmp(field[0], "accept")==0){ - if(m < 2) - error(Ebadarg); - dkanswer(c, strtoul(field[1], 0, 0), 0); - } else if(strcmp(field[0], "reject")==0){ - if(m < 3) - error(Ebadarg); - for(m = 0; m < DKERRS-1; m++) - if(strcmp(field[2], dkerr[m]) == 0) - break; - dkanswer(c, strtoul(field[1], 0, 0), m); - } else - return streamwrite(c, a, n, 0); - return n; - } - - error(Eperm); - return -1; /* never reached */ -} - -void -dkremove(Chan *c) -{ - USED(c); - error(Eperm); -} - -void -dkwstat(Chan *c, char *dp) -{ - netwstat(c, dp, &dk[c->dev]->net); -} - -/* - * return the number of an unused line (reserve it) - */ -static int -dkcloneline(Chan *c) -{ - Line *lp; - Dk *dp; - int line; - - dp = dk[c->dev]; - /* - * get an unused device and open its control file - */ - qlock(&dp->netlock); - for(line = dp->ncsc+1; line < dp->lines; line++){ - lp = dp->linep[line]; - if(lp == 0 || lp->state == Lclosed){ - lp = linealloc(dp, line, 0); - lp->state = Lopened; - - /* current user becomes owner */ - netown(lp, up->user, 0); - - qunlock(&dp->netlock); - return lp->lineno; - } - } - qunlock(&dp->netlock); - error(Enodev); - return -1; /* never reached */ -} - -static Chan* -dkopenline(Dk *dp, int line) -{ - Chan *c; - - c = 0; - if(waserror()){ - if(c) - close(c); - nexterror(); - } - c = dkattach(dp->name); - c->qid.path = STREAMQID(line, Sdataqid); - dkopen(c, ORDWR); - poperror(); - - return c; -} - -/* - * open the common signalling channel (dp->csc's reference count never goes below 1) - */ -static Chan* -dkopencsc(Dk *dp) -{ - qlock(&dp->csclock); - if(dp->csc == 0) - dp->csc = dkopenline(dp, dp->ncsc); - incref(dp->csc); - qunlock(&dp->csclock); - return dp->csc; -} - -/* - * return the contents of the info files - */ -void -dkfilladdr(Chan *c, char *buf, int len) -{ - if(len < sizeof(dk[0]->linep[0]->addr)+2) - error(Ebadarg); - sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->addr); -} -void -dkfillraddr(Chan *c, char *buf, int len) -{ - if(len < sizeof(dk[0]->linep[0]->raddr)+2) - error(Ebadarg); - sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->raddr); -} -void -dkfillruser(Chan *c, char *buf, int len) -{ - if(len < sizeof(dk[0]->linep[0]->ruser)+2) - error(Ebadarg); - sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->ruser); -} -void -dkfillstatus(Chan *c, char *buf, int len) -{ - Dk *dp; - Line *lp; - int line; - char lbuf[65]; - - line = STREAMID(c->qid.path); - dp = dk[c->dev]; - lp = linealloc(dp, line, 1); - sprint(lbuf, "%s/%d %d %s window %d\n", dp->name, line, - lp->state != Lclosed ? 1 : 0, dkstate[lp->state], lp->window); - strncpy(buf, lbuf, len); -} - -/* - * send a message to the datakit on the common signaling line - */ -static int -dkmesg(Chan *c, int type, int srv, int p0, int p1) -{ - Dkmsg d; - - if(waserror()){ - print("dkmesg: error\n"); - return -1; - } - d.type = type; - d.srv = srv; - d.param0l = p0; - d.param0h = p0>>8; - d.param1l = p1; - d.param1h = p1>>8; - d.param2l = 0; - d.param2h = 0; - d.param3l = 0; - d.param3h = 0; - d.param4l = 0; - d.param4h = 0; - streamwrite(c, (char *)&d, sizeof(Dkmsg), 1); - poperror(); - return 0; -} - -/* - * call out on a datakit - */ -static int -calldone(void *a) -{ - Line *lp; - - lp = (Line *)a; - return lp->state != Ldialing; -} -static void -dkcall(int type, Chan *c, char *addr, char *nuser, char *machine) -{ - char dialstr[66]; - int line, win; - char dialtone; - int t_val, d_val; - Dk *dp; - Line *lp; - Chan *dc; - Chan *csc; - char *bang, *dot; - - line = STREAMID(c->qid.path); - dp = dk[c->dev]; - lp = linealloc(dp, line, 1); - - /* - * only dial on virgin lines - */ - if(lp->state != Lopened) - error(Ebadarg); - - DPRINT("dkcall(line=%d, type=%d, dest=%s)\n", line, type, addr); - - /* - * build dial string - * - guard against new lines - * - change ! into . to delimit service - */ - if(strchr(addr, '\n')) - error(Ebadarg); - if(strlen(addr)+strlen(up->user)+2 >= sizeof(dialstr)) - error(Ebadarg); - strcpy(dialstr, addr); - bang = strchr(dialstr, '!'); - if(bang){ - dot = strchr(dialstr, '.'); - if(dot==0 || dot > bang) - *bang = '.'; - } - switch(type){ - case Dial: - t_val = T_SRV; - d_val = D_DIAL; - strcat(dialstr, "\n"); - strcat(dialstr, up->user); - strcat(dialstr, "\n"); - break; - case Announce: - t_val = T_SRV; - d_val = D_SERV; - break; - case Redial: - t_val = T_CHG; - d_val = D_REDIAL; - strcat(dialstr, "\n"); - strcat(dialstr, nuser); - strcat(dialstr, "\n"); - strcat(dialstr, machine); - strcat(dialstr, "\n"); - break; - default: - t_val = 0; - d_val = 0; - panic("bad dial type"); - } - - /* - * open the data file - */ - dc = dkopenline(dp, line); - if(waserror()){ - close(dc); - nexterror(); - } - lp->calltolive = 4; - lp->state = Ldialing; - - /* - * tell the controller we want to make a call - */ - DPRINT("dialout\n"); - csc = dkopencsc(dp); - if(waserror()){ - close(csc); - nexterror(); - } - for(win = 0; ; win++) - if(W_VALUE(win) >= dp->urpwindow || win == 15) - break; - dkmesg(csc, t_val, d_val, line, W_WINDOW(win, win, 2)); - poperror(); - close(csc); - - /* - * if redial, wait for a dial tone (otherwise we might send - * the dialstr to the previous other end and not the controller) - */ - if(type==Redial){ - if(streamread(dc, &dialtone, 1L) != 1L){ - lp->state = Lconnected; - error(Ebadarg); - } - } - - /* - * make the call - */ - DPRINT("dialstr %s\n", dialstr); - streamwrite(dc, dialstr, (long)strlen(dialstr), 1); - close(dc); - poperror(); - - /* - * redial's never get a reply, assume it worked - */ - if(type == Redial) { - lp->state = Lconnected; - return; - } - - /* - * wait for a reply - */ - DPRINT("reply wait\n"); - sleep(&lp->r, calldone, lp); - - /* - * if there was an error, translate it to a plan 9 - * errno and report it to the user. - */ - DPRINT("got reply %d\n", lp->state); - if(lp->state != Lconnected) { - if(lp->err >= DKERRS) - error(dkerr[0]); - else - error(dkerr[lp->err]); - } - - /* - * change state if serving - */ - if(type == D_SERV){ - lp->state = Llistening; - } - DPRINT("connected!\n"); - - /* - * decode the window size - */ - if (W_VALID(lp->window)){ - /* - * a 1127 window negotiation - */ - lp->window = W_VALUE(W_DEST(lp->window)); - } else if(lp->window>2 && lp->window<31){ - /* - * a generic window negotiation - */ - lp->window = 1<window; - } else - lp->window = 0; - - /* - * tag the connection - */ - strncpy(lp->addr, addr, sizeof(lp->addr)-1); - strncpy(lp->raddr, addr, sizeof(lp->raddr)-1); - - /* - * reset the protocol - */ - dkwindow(c); -} - -/* - * listen for a call, reflavor the - */ -static int -dklisten(Chan *c) -{ - char dialstr[512]; - char *line[12]; - char *field[8]; - Line *lp; - Dk *dp; - int n, lineno, ts, window; - int from; - Chan *dc; - static int dts; - char *cp; - - dp = dk[c->dev]; - from = STREAMID(c->qid.path); - - /* - * open the data file - */ - dc = dkopenline(dp, STREAMID(c->qid.path)); - if(waserror()){ - close(dc); - nexterror(); - } - - /* - * wait for a call in - */ - for(;;){ - /* - * read the dialstring and null terminate it - */ - n = streamread(dc, dialstr, sizeof(dialstr)-1); - DPRINT("returns %d\n", n); - if(n <= 0) - error(Eio); - dialstr[n] = 0; - DPRINT("dialstr = %s\n", dialstr); - - /* - * break the dial string into lines - */ - n = getfields(dialstr, line, 12, '\n'); - if (n < 2) { - DPRINT("bad dialstr from dk (1 line)\n"); - error(Eio); - } - - /* - * line 0 is `line.tstamp.traffic[.urpparms.window]' - */ - window = 0; - switch(getfields(line[0], field, 5, '.')){ - case 5: - /* - * generic way of passing window - */ - window = strtoul(field[4], 0, 0); - if(window > 0 && window <31) - window = 1<= dp->lines){ - print("dklisten: illegal line %d\n", lineno); - continue; - } - lp = linealloc(dp, lineno, 1); - ts = strtoul(field[1], 0, 0); - - /* - * this could be a duplicate request - */ - if(ts == lp->timestamp){ - if((dts++ % 1000) == 0) - print("dklisten: repeat timestamp %d\n", lineno); - if(lp->state != Lconnected) - dkanswer(c, lineno, DKbusy); - continue; - } - - /* - * take care of glare (datakit picked an inuse channel - * for the call to come in on). - */ - if(!canqlock(lp)){ - DPRINT("DKbusy1\n"); - dkanswer(c, lineno, DKbusy); - continue; - } else { - if(lp->state != Lclosed){ - qunlock(lp); - DPRINT("DKbusy2 %ux\n", lp->state); - dkanswer(c, lineno, DKbusy); - continue; - } - } - lp->window = window; - - /* - * Line 1 is `my-dk-name.service[.more-things]'. - * Special characters are escaped by '\'s. Convert to - * a plan 9 address, i.e. system!service. - */ - strncpy(lp->addr, line[1], sizeof(lp->addr)-1); - if(cp = strchr(lp->addr, '.')){ - *cp = '!'; - if(cp = strchr(cp, '.')) - *cp = 0; - } - - /* - * the rest is variable length - */ - switch(n) { - case 2: - /* no more lines */ - lp->ruser[0] = 0; - lp->raddr[0] = 0; - break; - case 3: - /* line 2 is `source.user.param1.param2' */ - getfields(line[2], field, 3, '.'); - strncpy(lp->raddr, field[0], sizeof(lp->raddr)-1); - strncpy(lp->ruser, field[1], sizeof(lp->ruser)-1); - break; - case 4: - /* line 2 is `user.param1.param2' */ - getfields(line[2], field, 2, '.'); - strncpy(lp->ruser, field[0], sizeof(lp->ruser)-1); - - /* line 3 is `source.node.mod.line' */ - strncpy(lp->raddr, line[3], sizeof(lp->raddr)-1); - break; - default: - print("bad message from dk(>4 line)\n"); - qunlock(lp); - error(Ebadarg); - } - - DPRINT("src(%s)user(%s)dest(%s)w(%d)\n", lp->raddr, lp->ruser, - lp->addr, W_TRAF(lp->window)); - - lp->timestamp = ts; - lp->state = Lconnected; - - /* listener becomes owner */ - netown(lp, dp->linep[from]->owner, 0); - - qunlock(lp); - close(dc); - poperror(); - DPRINT("dklisten returns %d\n", lineno); - return lineno; - } - panic("dklisten terminates strangely\n"); - return -1; /* never reached */ -} - -/* - * answer a call - */ -static void -dkanswer(Chan *c, int line, int code) -{ - char reply[64]; - Chan *dc; - Line *lp; - Dk *dp; - - dp = dk[c->dev]; - lp = linealloc(dp, line, 1); - - /* - * open the data file (c is a control file) - */ - dc = dkattach(dp->name); - if(waserror()){ - close(dc); - nexterror(); - } - dc->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); - dkopen(dc, ORDWR); - - /* - * send the reply - */ - sprint(reply, "%ud.%ud.%ud", line, lp->timestamp, code); - DPRINT("dkanswer %s\n", reply); - streamwrite(dc, reply, strlen(reply), 1); - close(dc); - poperror(); - - /* - * set window size - */ - if(code == 0){ - if(waserror()){ - close(dc); - nexterror(); - } - sprint(reply, "init %d %d", lp->window, Streamhi); - dc = dkopenline(dp, line); - dc->qid.path = STREAMQID(line, Sctlqid); - streamwrite(dc, reply, strlen(reply), 1); - close(dc); - poperror(); - } -} - -/* - * set the window size and reset the protocol - */ -static void -dkwindow(Chan *c) -{ - char buf[64]; - Line *lp; - - lp = linealloc(dk[c->dev], STREAMID(c->qid.path), 1); - if(lp->window == 0) - lp->window = 64; - sprint(buf, "init %d %d", lp->window, Streamhi); - streamwrite(c, buf, strlen(buf), 1); -} - -/* - * hangup a datakit connection - */ -static void -dkhangup(Line *lp) -{ - Block *bp; - - qlock(lp); - if(lp->rq){ - bp = allocb(0); - bp->type = M_HANGUP; - PUTNEXT(lp->rq, bp); - } - qunlock(lp); -} - -/* - * A process which listens to all input on a csc line - */ -static void -dkcsckproc(void *a) -{ - long n; - Dk *dp; - Dkmsg d; - int line; - - dp = a; - - if(waserror()){ - close(dp->csc); - return; - } - DPRINT("dkcsckproc: %d\n", dp->ncsc); - - /* - * loop forever listening - */ - for(;;){ - n = streamread(dp->csc, (char *)&d, (long)sizeof(d)); - if(n != sizeof(d)){ - if(n == 0) - error(Ehungup); - print("strange csc message %d\n", n); - continue; - } - line = (d.param0h<<8) + d.param0l; - DPRINT("t(%d)s(%d)l(%d)\n", d.type, d.srv, line); - switch (d.type) { - - case T_CHG: /* controller wants to close a line */ - dkchgmesg(dp->csc, dp, &d, line); - break; - - case T_REPLY: /* reply to a dial request */ - dkreplymesg(dp, &d, line); - break; - - case T_SRV: /* ignore it, it's useless */ -/* print("dksrvmesg(%d)\n", line); /**/ - break; - - case T_RESTART: /* datakit reboot */ - if(line >=0 && linelines) - dp->lines = line+1; - break; - - default: - print("unrecognized csc message %o.%o(%o)\n", - d.type, d.srv, line); - break; - } - } -} - -/* - * datakit requests or confirms closing a line - */ -static void -dkchgmesg(Chan *c, Dk *dp, Dkmsg *dialp, int line) -{ - Line *lp; - - switch (dialp->srv) { - - case D_CLOSE: /* remote shutdown */ - if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) { - /* tell controller this line is not in use */ - dkmesg(c, T_CHG, D_CLOSE, line, 0); - return; - } - switch (lp->state) { - - case Ldialing: - /* simulate a failed connection */ - dkreplymesg(dp, (Dkmsg *)0, line); - lp->state = Lrclose; - break; - - case Lrclose: - case Lconnected: - case Llistening: - case Lackwait: - dkhangup(lp); - lp->state = Lrclose; - break; - - case Lopened: - dkmesg(c, T_CHG, D_CLOSE, line, 0); - break; - - case Llclose: - case Lclosed: - dkhangup(lp); - dkmesg(c, T_CHG, D_CLOSE, line, 0); - lp->state = Lclosed; - break; - } - break; - - case D_ISCLOSED: /* acknowledging a local shutdown */ - if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) - return; - switch (lp->state) { - case Llclose: - case Lclosed: - lp->state = Lclosed; - break; - - case Lrclose: - case Lconnected: - case Llistening: - case Lackwait: - break; - } - break; - - case D_CLOSEALL: - /* - * datakit wants us to close all lines - */ - for(line = dp->ncsc+1; line < dp->lines; line++){ - lp = dp->linep[line]; - if(lp == 0) - continue; - switch (lp->state) { - - case Ldialing: - /* simulate a failed connection */ - dkreplymesg(dp, (Dkmsg *)0, line); - lp->state = Lrclose; - break; - - case Lrclose: - case Lconnected: - case Llistening: - case Lackwait: - lp->state = Lrclose; - dkhangup(lp); - break; - - case Lopened: - break; - - case Llclose: - case Lclosed: - lp->state = Lclosed; - break; - } - } - dp->closeall = 1; - wakeup(&dp->closeallr); - break; - - default: - print("unrecognized T_CHG\n"); - } -} - -/* - * datakit replies to a dialout. capture reply code and traffic parameters - */ -static void -dkreplymesg(Dk *dp, Dkmsg *dialp, int line) -{ - Line *lp; - - DPRINT("dkreplymesg(%d)\n", line); - - if(line < 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) - return; - - if(lp->state != Ldialing) - return; - - if(dialp){ - /* - * a reply from the dk - */ - lp->state = (dialp->srv==D_OPEN) ? Lconnected : Lrclose; - lp->err = (dialp->param1h<<8) + dialp->param1l; - lp->window = lp->err; - DPRINT("dkreplymesg: %d\n", lp->state); - } else { - /* - * a local abort - */ - lp->state = Lrclose; - lp->err = 0; - } - - if(lp->state==Lrclose){ - dkhangup(lp); - } - wakeup(&lp->r); -} - -/* - * send a I'm alive message every 7.5 seconds and remind the dk of - * any closed channels it hasn't acknowledged. - */ -static void -dktimer(void *a) -{ - int i; - Dk *dp; - Line *lp; - Chan *c; - - dp = (Dk *)a; - c = dkopencsc(dp); - - while(waserror()); - - for(;;){ - /* - * send keep alive - */ - DPRINT("keep alive\n"); - dkmesg(c, T_ALIVE, D_CONTINUE, 0, 0); - - /* - * remind controller of dead lines and - * timeout calls that take to long - */ - for (i=dp->ncsc+1; ilines; i++){ - lp = dp->linep[i]; - if(lp == 0) - continue; - switch(lp->state){ - case Llclose: - dkmesg(c, T_CHG, D_CLOSE, i, 0); - break; - - case Ldialing: - if(lp->calltolive==0 || --lp->calltolive!=0) - break; - dkreplymesg(dp, (Dkmsg *)0, i); - break; - } - } - tsleep(&dp->timer, return0, 0, 7500); - } -} diff --git a/port/devip.c b/port/devip.c deleted file mode 100644 index 29c3fd8910db629cf938aab5dd98ee4f6636ae77..0000000000000000000000000000000000000000 --- a/port/devip.c +++ /dev/null @@ -1,1206 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -#include "devtab.h" - -enum -{ - Nrprotocol = 3, /* Number of protocols supported by this driver */ - Nipsubdir = 4, /* Number of subdirectory entries per connection */ - Nfrag = 32, /* Ip reassembly queue entries */ - Nifc = 4, /* max interfaces */ -}; - -int udpsum = 1; -Queue *Ipoutput; /* Control message stream for tcp/il */ -Ipifc *ipifc[Nrprotocol+1]; -QLock ipalloc; /* Protocol port allocation lock */ -Ipconv **tcpbase; - -Streamput udpstiput, udpstoput, tcpstiput, tcpstoput; -Streamput iliput, iloput, bsdiput, bsdoput; -Streamopen udpstopen, tcpstopen, ilopen, bsdopen; -Streamclose udpstclose, tcpstclose, ilclose, bsdclose; - -Qinfo tcpinfo = { tcpstiput, tcpstoput, tcpstopen, tcpstclose, "tcp", 0, 1 }; -Qinfo udpinfo = { udpstiput, udpstoput, udpstopen, udpstclose, "udp" }; -Qinfo ilinfo = { iliput, iloput, ilopen, ilclose, "il" }; -Qinfo bsdinfo = { bsdiput, bsdoput, bsdopen, bsdclose, "bsd", 0, 1 }; - -Qinfo *protocols[] = { &tcpinfo, &udpinfo, &ilinfo, 0 }; - -void -ipinitifc(Ipifc *ifc, Qinfo *stproto) -{ - ifc->conv = xalloc(Nipconv * sizeof(Ipconv*)); - ifc->protop = stproto; - ifc->nconv = Nipconv; - ifc->devp = &ipinfo; - if(stproto != &udpinfo) - ifc->listen = iplisten; - ifc->clone = ipclonecon; - ifc->ninfo = 3; - ifc->info[0].name = "remote"; - ifc->info[0].fill = ipremotefill; - ifc->info[1].name = "local"; - ifc->info[1].fill = iplocalfill; - ifc->info[2].name = "status"; - ifc->info[2].fill = ipstatusfill; - ifc->name = stproto->name; -} - -void -ipreset(void) -{ - int i; - - for(i = 0; protocols[i]; i++) { - ipifc[i] = xalloc(sizeof(Ipifc)); - ipinitifc(ipifc[i], protocols[i]); - newqinfo(protocols[i]); - } - - initfrag(Nfrag); -} - -void -ipinit(void) -{ -} - -Chan * -ipattach(char *spec) -{ - int i; - Chan *c; - - /* fail if ip is not yet configured */ - if(Ipoutput == 0) - error(Enoproto); - - for(i = 0; protocols[i]; i++) { - if(strcmp(spec, protocols[i]->name) == 0) { - c = devattach('I', spec); - c->dev = i; - - return (c); - } - } - - error(Enoproto); - return 0; /* not reached */ -} - -Chan * -ipclone(Chan *c, Chan *nc) -{ - return devclone(c, nc); -} - -int -ipwalk(Chan *c, char *name) -{ - return netwalk(c, name, ipifc[c->dev]); -} - -void -ipstat(Chan *c, char *db) -{ - netstat(c, db, ipifc[c->dev]); -} - -Chan * -ipopen(Chan *c, int omode) -{ - return netopen(c, omode, ipifc[c->dev]); -} - -int -ipclonecon(Chan *c) -{ - Ipconv *new; - - new = ipincoming(ipifc[c->dev], 0); - if(new == 0) - error(Enodev); - return new->id; -} - -/* - * create a new conversation structure if none exists for this conversation slot - */ -Ipconv* -ipcreateconv(Ipifc *ifc, int id) -{ - Ipconv **p; - Ipconv *new; - - p = &ifc->conv[id]; - if(*p) - return *p; - qlock(ifc); - p = &ifc->conv[id]; - if(*p){ - qunlock(ifc); - return *p; - } - if(waserror()){ - qunlock(ifc); - nexterror(); - } - new = smalloc(sizeof(Ipconv)); - new->ifc = ifc; - netadd(ifc, new, p - ifc->conv); - new->ref = 1; - *p = new; - qunlock(ifc); - poperror(); - return new; -} - -/* - * allocate a conversation structure. - */ -Ipconv* -ipincoming(Ipifc *ifc, Ipconv *from) -{ - Ipconv *new; - Ipconv **p, **etab; - - /* look for an unused existing conversation */ - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; p < etab; p++) { - new = *p; - if(new == 0) - break; - if(new->ref == 0 && canqlock(new)) { - if(new->ref || ipconbusy(new)) { - qunlock(new); - continue; - } - if(from) /* copy ownership from listening channel */ - netown(new, from->owner, 0); - else /* current user becomes owner */ - netown(new, up->user, 0); - - new->ref = 1; - qunlock(new); - return new; - } - } - - /* create one */ - qlock(ifc); - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; ; p++){ - if(p == etab){ - qunlock(ifc); - return 0; - } - if(*p == 0) - break; - } - if(waserror()){ - qunlock(ifc); - nexterror(); - } - new = smalloc(sizeof(Ipconv)); - new->ifc = ifc; - netadd(ifc, new, p - ifc->conv); - qlock(new); - *p = new; - qunlock(ifc); - poperror(); - if(from) /* copy ownership from listening channel */ - netown(new, from->owner, 0); - else /* current user becomes owner */ - netown(new, up->user, 0); - new->ref = 1; - qunlock(new); - return new; -} - -void -ipcreate(Chan *c, char *name, int omode, ulong perm) -{ - USED(c, name, omode, perm); - error(Eperm); -} - -void -ipremove(Chan *c) -{ - USED(c); - error(Eperm); -} - -void -ipwstat(Chan *c, char *dp) -{ - netwstat(c, dp, ipifc[c->dev]); -} - -void -ipclose(Chan *c) -{ - if(c->stream) - streamclose(c); -} - -long -ipread(Chan *c, void *a, long n, ulong offset) -{ - return netread(c, a, n, offset, ipifc[c->dev]); -} - -long -ipwrite(Chan *c, char *a, long n, ulong offset) -{ - int m, backlog, type, priv; - char *field[5], *ctlarg[5], buf[256]; - Port port; - Ipconv *cp; - - USED(offset); - type = STREAMTYPE(c->qid.path); - if (type == Sdataqid) - return streamwrite(c, a, n, 0); - - if (type != Sctlqid) - error(Eperm); - - cp = ipcreateconv(ipifc[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) - error(Ebadarg); - - if(strcmp(field[0], "connect") == 0) { - if(ipconbusy(cp)) - error(Enetbusy); - - if(m != 2) - error(Ebadarg); - - switch(getfields(field[1], ctlarg, 5, '!')) { - default: - error(Eneedservice); - case 2: - priv = 0; - break; - case 3: - if(strcmp(ctlarg[2], "r") != 0) - error(Eperm); - priv = 1; - break; - } - cp->dst = ipparse(ctlarg[0]); - cp->pdst = atoi(ctlarg[1]); - - /* If we have no local port assign one */ - if(cp->psrc == 0){ - qlock(&ipalloc); - cp->psrc = nextport(ipifc[c->dev], priv); - qunlock(&ipalloc); - } - - if(cp->ifc->protop == &tcpinfo) - tcpstart(cp, TCP_ACTIVE, Streamhi, 0); - else if(cp->ifc->protop == &ilinfo) - ilstart(cp, IL_ACTIVE, 20); - - /* - * stupid hack for BSD port's 512, 513, & 514 - * to make it harder for user to lie about his - * identity. -- presotto - */ - switch(cp->pdst){ - case 512: - case 513: - case 514: - pushq(c->stream, &bsdinfo); - break; - } - } - else if(strcmp(field[0], "disconnect") == 0) { - if(cp->ifc->protop != &udpinfo) - error(Eperm); - - cp->dst = 0; - cp->pdst = 0; - } - else if(strcmp(field[0], "announce") == 0) { - if(ipconbusy(cp)) - error(Enetbusy); - - if(m != 2) - error(Ebadarg); - - port = atoi(field[1]); - - if(port){ - qlock(&ipalloc); - if(portused(ipifc[c->dev], port)) { - qunlock(&ipalloc); - error(Einuse); - } - cp->psrc = port; - qunlock(&ipalloc); - } else if(*field[1] != '*'){ - qlock(&ipalloc); - cp->psrc = nextport(ipifc[c->dev], 0); - qunlock(&ipalloc); - } else - cp->psrc = 0; - - if(cp->ifc->protop == &tcpinfo) - tcpstart(cp, TCP_PASSIVE, Streamhi, 0); - else if(cp->ifc->protop == &ilinfo) - ilstart(cp, IL_PASSIVE, 10); - - if(cp->backlog == 0) - cp->backlog = 3; - } - 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 if(strcmp(field[0], "headers") == 0) { - cp->headers = 1; /* include addr/port in user packet */ - } - else - return streamwrite(c, a, n, 0); - - return n; -} - -int -ipconbusy(Ipconv *cp) -{ - if(cp->ifc->protop == &tcpinfo) - if(cp->tcpctl.state != Closed) - return 1; - - if(cp->ifc->protop == &ilinfo) - if(cp->ilctl.state != Ilclosed) - return 1; - - return 0; -} - -void -udpstiput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} - -/* - * udprcvmsg - called by stip to multiplex udp ports onto conversations - */ -void -udprcvmsg(Ipifc *ifc, Block *bp) -{ - Ipconv *cp, **p, **etab; - Udphdr *uh; - Port dport, sport; - ushort sum, len; - Ipaddr addr; - Block *nbp; - - uh = (Udphdr *)(bp->rptr); - - /* Put back pseudo header for checksum */ - uh->Unused = 0; - len = nhgets(uh->udplen); - hnputs(uh->udpplen, len); - - addr = nhgetl(uh->udpsrc); - - if(udpsum && nhgets(uh->udpcksum)) { - if(sum = ptcl_csum(bp, UDP_EHSIZE, len+UDP_PHDRSIZE)) { - print("udp: checksum error %x (%d.%d.%d.%d)\n", - sum, fmtaddr(addr)); - - freeb(bp); - return; - } - } - - dport = nhgets(uh->udpdport); - sport = nhgets(uh->udpsport); - - /* Look for a conversation structure for this port */ - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; p < etab; p++) { - cp = *p; - if(cp == 0) - break; - if(cp->ref) - if(cp->psrc == dport) - if(cp->pdst == 0 || cp->pdst == sport) { - /* Trim the packet down to data size */ - len = len - (UDP_HDRSIZE-UDP_PHDRSIZE); - bp = btrim(bp, UDP_EHSIZE+UDP_HDRSIZE, len); - if(bp == 0) - return; - - if(cp->headers){ - /* pass the src address to the stream head */ - nbp = allocb(Udphdrsize); - nbp->next = bp; - bp = nbp; - hnputl(bp->wptr, addr); - bp->wptr += 4; - hnputs(bp->wptr, sport); - bp->wptr += 2; - } else { - /* save the src address in the conversation struct */ - cp->dst = addr; - cp->pdst = sport; - } - PUTNEXT(cp->readq, bp); - return; - } - } - - freeb(bp); -} - -void -udpstoput(Queue *q, Block *bp) -{ - Ipconv *cp; - Udphdr *uh; - int dlen, ptcllen, newlen; - Ipaddr addr; - Port port; - - if(bp->type == M_CTL) { - PUTNEXT(q, bp); - return; - } - - cp = (Ipconv *)(q->ptr); - if(cp->psrc == 0) - error(Enoport); - - if(bp->type != M_DATA) { - freeb(bp); - error(Ebadctl); - } - - /* Only allow atomic udp writes to form datagrams */ - if(!(bp->flags & S_DELIM)) { - freeb(bp); - error(Emsgsize); - } - - /* - * if we're in header mode, rip off the first 64 bytes as the - * destination. The destination is in ascii in the form - * %d.%d.%d.%d!%d - */ - if(cp->headers){ - /* get user specified addresses */ - bp = pullup(bp, Udphdrsize); - if(bp == 0){ - freeb(bp); - error(Emsgsize); - } - addr = nhgetl(bp->rptr); - bp->rptr += 4; - port = nhgets(bp->rptr); - bp->rptr += 2; - } else - addr = port = 0; - - /* Round packet up to even number of bytes and check we can - * send it - */ - dlen = blen(bp); - if(dlen > UDP_DATMAX) { - freeb(bp); - error(Emsgsize); - } - newlen = bround(bp, 1); - - /* Make space to fit udp & ip & ethernet header */ - bp = padb(bp, UDP_EHSIZE + UDP_HDRSIZE); - - uh = (Udphdr *)(bp->rptr); - - ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE); - uh->Unused = 0; - uh->udpproto = IP_UDPPROTO; - uh->frag[0] = 0; - uh->frag[1] = 0; - hnputs(uh->udpplen, ptcllen); - hnputl(uh->udpsrc, Myip[Myself]); - hnputs(uh->udpsport, cp->psrc); - if(cp->headers) { - hnputl(uh->udpdst, addr); - hnputs(uh->udpdport, port); - } - else { - hnputl(uh->udpdst, cp->dst); - hnputs(uh->udpdport, cp->pdst); - } - hnputs(uh->udplen, ptcllen); - uh->udpcksum[0] = 0; - uh->udpcksum[1] = 0; - - hnputs(uh->udpcksum, ptcl_csum(bp, UDP_EHSIZE, newlen+UDP_HDRSIZE)); - PUTNEXT(q, bp); -} - -void -udpstclose(Queue *q) -{ - Ipconv *ipc; - - ipc = (Ipconv *)(q->ptr); - - ipc->headers = 0; - ipc->psrc = 0; - ipc->pdst = 0; - ipc->dst = 0; -} - -void -udpstopen(Queue *q, Stream *s) -{ - Ipconv *ipc; - - ipc = ipcreateconv(ipifc[s->dev], s->id); - initipifc(ipifc[s->dev], IP_UDPPROTO, udprcvmsg, 1500, 512, ETHER_HDR); - - ipc->readq = RD(q); - RD(q)->ptr = (void *)ipc; - WR(q)->next->ptr = (void *)ipc->ifc; - WR(q)->ptr = (void *)ipc; -} - -void -tcpstiput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} - -tcproominq(void *a) -{ - return !((Tcpctl *)a)->sndfull; -} - -void -tcpstoput(Queue *q, Block *bp) -{ - Ipconv *s; - Tcpctl *tcb; - Block *f; - - s = (Ipconv *)(q->ptr); - tcb = &s->tcpctl; - - if(bp->type == M_CTL) { - PUTNEXT(q, bp); - return; - } - - if(s->psrc == 0) - error(Enoport); - - /* Report asynchronous errors */ - if(s->err) - error(s->err); - - switch(tcb->state) { - case Listen: - tcb->flags |= ACTIVE; - tcpsndsyn(tcb); - tcpsetstate(s, Syn_sent); - - /* No break */ - case Syn_sent: - case Syn_received: - case Established: - case Close_wait: - /* - * Process flow control - */ - if(tcb->sndfull){ - qlock(&tcb->sndrlock); - if(waserror()) { - qunlock(&tcb->sndrlock); - nexterror(); - } - sleep(&tcb->sndr, tcproominq, tcb); - poperror(); - qunlock(&tcb->sndrlock); - } - - /* - * Push data - */ - qlock(tcb); - if(waserror()) { - qunlock(tcb); - nexterror(); - } - tcb->sndcnt += blen(bp); - if(tcb->sndcnt > Streamhi) - tcb->sndfull = 1; - if(tcb->sndq == 0) - tcb->sndq = bp; - else { - for(f = tcb->sndq; f->next; f = f->next) - ; - f->next = bp; - } - tcprcvwin(s); - tcpoutput(s); - poperror(); - qunlock(tcb); - break; - - default: - freeb(bp); - error(Ehungup); - } -} - -void -tcpstopen(Queue *q, Stream *s) -{ - Ipconv *ipc; - Ipifc *ifc; - Tcpctl *tcb; - Block *bp; - static int tcpkprocs; - - if(!Ipoutput) { - Ipoutput = WR(q); - s->opens++; - s->inuse++; - } - - /* Flow control and tcp timer processes */ - if(tcpkprocs == 0) { - tcpkprocs = 1; - kproc("tcpack", tcpackproc, 0); - kproc("tcpflow", tcpflow, ipifc[s->dev]); - - } - - if(tcpbase == 0) - tcpbase = ipifc[s->dev]->conv; - ifc = ipifc[s->dev]; - initipifc(ifc, IP_TCPPROTO, tcpinput, 1500, 512, ETHER_HDR); - ipc = ipcreateconv(ifc, s->id); - - ipc->readq = RD(q); - ipc->readq->rp = &tcpflowr; - ipc->err = 0; - - RD(q)->ptr = (void *)ipc; - WR(q)->next->ptr = (void *)ipc->ifc; - WR(q)->ptr = (void *)ipc; - - /* pass any waiting data upstream */ - tcb = &ipc->tcpctl; - qlock(tcb); - while(bp = getb(&tcb->rcvq)) - PUTNEXT(ipc->readq, bp); - qunlock(tcb); -} - -void -ipremotefill(Chan *c, char *buf, int len) -{ - Ipconv *cp; - - if(len < 32) - error(Etoosmall); - cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path)); - sprint(buf, "%d.%d.%d.%d!%d\n", fmtaddr(cp->dst), cp->pdst); -} - -void -iplocalfill(Chan *c, char *buf, int len) -{ - Ipconv *cp; - - if(len < 32) - error(Etoosmall); - cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path)); - sprint(buf, "%d.%d.%d.%d!%d\n", fmtaddr(Myip[Myself]), cp->psrc); -} - -void -ipstatusfill(Chan *c, char *buf, int len) -{ - Ipconv *cp; - int connection; - - if(len < 64) - error(Ebadarg); - connection = STREAMID(c->qid.path); - cp = ipcreateconv(ipifc[c->dev], connection); - if(cp->ifc->protop == &tcpinfo) - sprint(buf, "tcp/%d %d %s %s\n", connection, cp->ref, - tcpstate[cp->tcpctl.state], - cp->tcpctl.flags & CLONE ? "listen" : "connect"); - else if(cp->ifc->protop == &ilinfo) - sprint(buf, "il/%d %d %s rtt %d ms %d csum\n", connection, cp->ref, - ilstate[cp->ilctl.state], cp->ilctl.rtt, - cp->ifc ? cp->ifc->chkerrs : 0); - else - sprint(buf, "%s/%d %d Datagram\n", - cp->ifc->protop->name, connection, cp->ref); -} - -int -iphavecon(Ipconv *s) -{ - return s->curlog; -} - -int -iplisten(Chan *c) -{ - Ipconv *s; - int connection; - Ipconv **p, **etab, *new; - - connection = STREAMID(c->qid.path); - s = ipcreateconv(ipifc[c->dev], connection); - - if(s->ifc->protop == &tcpinfo) - if(s->tcpctl.state != Listen) - error(Enolisten); - - if(s->ifc->protop == &ilinfo) - if(s->ilctl.state != Illistening) - error(Enolisten); - - for(;;) { - qlock(&s->listenq); /* single thread for the sleep */ - if(waserror()) { - qunlock(&s->listenq); - nexterror(); - } - sleep(&s->listenr, iphavecon, s); - poperror(); - etab = &ipifc[c->dev]->conv[Nipconv]; - for(p = ipifc[c->dev]->conv; p < etab; p++) { - new = *p; - if(new == 0) - break; - if(new->newcon == s) { - qlock(s); - s->curlog--; - qunlock(s); - new->newcon = 0; - qunlock(&s->listenq); - return new->id; - } - } - qunlock(&s->listenq); - print("iplisten: no newcon\n"); - } - return -1; /* not reached */ -} - -void -tcpstclose(Queue *q) -{ - Ipconv *s; - Ipconv **etab, **p; - Tcpctl *tcb; - - s = (Ipconv *)(q->ptr); - tcb = &s->tcpctl; - - /* Not interested in data anymore */ - qlock(s); - s->readq = 0; - qunlock(s); - - switch(tcb->state){ - case Listen: - /* - * reset any incoming calls to this listener - */ - qlock(s); - s->backlog = 0; - s->curlog = 0; - etab = &tcpbase[Nipconv]; - for(p = tcpbase; p < etab && *p; p++){ - if((*p)->newcon == s) { - (*p)->newcon = 0; - tcpflushincoming(*p); - } - } - qunlock(s); - - qlock(tcb); - localclose(s, 0); - qunlock(tcb); - break; - - case Closed: - case Syn_sent: - qlock(tcb); - localclose(s, 0); - qunlock(tcb); - break; - - case Syn_received: - case Established: - tcb->sndcnt++; - tcb->snd.nxt++; - tcpsetstate(s, Finwait1); - goto output; - - case Close_wait: - tcb->sndcnt++; - tcb->snd.nxt++; - tcpsetstate(s, Last_ack); - output: - qlock(tcb); - if(waserror()) { - qunlock(tcb); - nexterror(); - } - tcpoutput(s); - poperror(); - qunlock(tcb); - break; - } -} - - -static short endian = 1; -static char* aendian = (char*)&endian; -#define LITTLE *aendian - -ushort -ptcl_bsum(uchar *addr, int len) -{ - ulong losum, hisum, mdsum, x; - ulong t1, t2; - - losum = 0; - hisum = 0; - mdsum = 0; - - x = 0; - if((ulong)addr & 1) { - if(len) { - hisum += addr[0]; - len--; - addr++; - } - x = 1; - } - while(len >= 16) { - t1 = *(ushort*)(addr+0); - t2 = *(ushort*)(addr+2); mdsum += t1; - t1 = *(ushort*)(addr+4); mdsum += t2; - t2 = *(ushort*)(addr+6); mdsum += t1; - t1 = *(ushort*)(addr+8); mdsum += t2; - t2 = *(ushort*)(addr+10); mdsum += t1; - t1 = *(ushort*)(addr+12); mdsum += t2; - t2 = *(ushort*)(addr+14); mdsum += t1; - mdsum += t2; - len -= 16; - addr += 16; - } - while(len >= 2) { - mdsum += *(ushort*)addr; - len -= 2; - addr += 2; - } - if(x) { - if(len) - losum += addr[0]; - if(LITTLE) - losum += mdsum; - else - hisum += mdsum; - } else { - if(len) - hisum += addr[0]; - if(LITTLE) - hisum += mdsum; - else - losum += mdsum; - } - - losum += hisum >> 8; - losum += (hisum & 0xff) << 8; - while(hisum = losum>>16) - losum = hisum + (losum & 0xffff); - - return losum & 0xffff; -} - -ushort -ptcl_csum(Block *bp, int offset, int len) -{ - uchar *addr; - ulong losum, hisum; - ushort csum; - int odd, blen, x; - - /* Correct to front of data area */ - while(bp && offset && offset >= BLEN(bp)) { - offset -= BLEN(bp); - bp = bp->next; - } - if(bp == 0) - return 0; - - addr = bp->rptr + offset; - blen = BLEN(bp) - offset; - - if(bp->next == 0) - return ~ptcl_bsum(addr, MIN(len, blen)) & 0xffff; - - losum = 0; - hisum = 0; - - odd = 0; - while(len) { - x = MIN(len, blen); - csum = ptcl_bsum(addr, x); - if(odd) - hisum += csum; - else - losum += csum; - odd = (odd+x) & 1; - len -= x; - - bp = bp->next; - if(bp == 0) - break; - blen = BLEN(bp); - addr = bp->rptr; - } - - losum += hisum>>8; - losum += (hisum&0xff)<<8; - while((csum = losum>>16) != 0) - losum = csum + (losum & 0xffff); - - return ~losum & 0xffff; -} - -Block * -btrim(Block *bp, int offset, int len) -{ - Block *nb, *startb; - ulong l; - - if(blen(bp) < offset+len) { - freeb(bp); - return 0; - } - - while((l = BLEN(bp)) < offset) { - offset -= l; - nb = bp->next; - bp->next = 0; - freeb(bp); - bp = nb; - } - - startb = bp; - bp->rptr += offset; - - while((l = BLEN(bp)) < len) { - len -= l; - bp = bp->next; - } - - bp->wptr -= (BLEN(bp) - len); - bp->flags |= S_DELIM; - - if(bp->next) { - freeb(bp->next); - bp->next = 0; - } - - return(startb); -} - -Ipconv * -portused(Ipifc *ifc, Port port) -{ - Ipconv **p, **etab; - Ipconv *cp; - - if(port == 0) - return 0; - - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; p < etab; p++){ - cp = *p; - if(cp == 0) - break; - if(cp->psrc == port) - return cp; - } - - return 0; -} - -static Port lastport[2] = { PORTALLOC-1, PRIVPORTALLOC-1 }; - -Port -nextport(Ipifc *ifc, int priv) -{ - Port base; - Port max; - Port *p; - Port i; - - if(priv){ - base = PRIVPORTALLOC; - max = UNPRIVPORTALLOC; - p = &lastport[1]; - } else { - base = PORTALLOC; - max = PORTMAX; - p = &lastport[0]; - } - - for(i = *p + 1; i < max; i++) - if(!portused(ifc, i)) - return(*p = i); - for(i = base ; i <= *p; i++) - if(!portused(ifc, i)) - return(*p = i); - - return(0); -} - -/* NEEDS HASHING ! */ - -Ipconv* -ip_conn(Ipifc *ifc, Port dst, Port src, Ipaddr dest) -{ - Ipconv **p, *s, **etab; - - /* Look for a conversation structure for this port */ - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; p < etab; p++) { - s = *p; - if(s == 0) - break; - if(s->psrc == dst) - if(s->pdst == src) - if(s->dst == dest || dest == 0) - return s; - } - - return 0; -} - -/* - * Fuck me sideways with a bargepole!!! -- philw - * - * BSD authentication protocol, used on ports 512, 513, & 514. - * This makes sure that a user can only write the REAL user id. - * - * q->ptr is number of nulls seen - */ -void -bsdopen(Queue *q, Stream *s) -{ - USED(s); - RD(q)->ptr = q; - WR(q)->ptr = q; -} -void -bsdclose(Queue *q) -{ - Block *bp; - - bp = allocb(0); - bp->type = M_HANGUP; - PUTNEXT(q->other, bp); -} -void -bsdiput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} -void -bsdoput(Queue *q, Block *bp) -{ - uchar *luser; - Block *nbp; - - /* just pass it on if we've done authentication */ - if(q->ptr == 0 || bp->type != M_DATA){ - PUTNEXT(q, bp); - return; - } - - /* collect into a single block */ - qlock(&q->rlock); - if(q->first == 0) - q->first = pullup(bp, blen(bp)); - else{ - nbp = q->first; - nbp->next = bp; - q->first = pullup(nbp, blen(nbp)); - } - bp = q->first; - if(bp == 0){ - qunlock(&q->rlock); - bsdclose(q); - return; - } - - /* look for 2 nulls to indicate stderr port and local user */ - luser = memchr(bp->rptr, 0, BLEN(bp)); - if(luser == 0){ - qunlock(&q->rlock); - return; - } - luser++; - if(memchr(luser, 0, bp->wptr - luser) == 0){ - qunlock(&q->rlock); - return; - } - - /* if luser is a lie, hangup */ - if(memcmp(luser, up->user, strlen(up->user)+1) != 0) - bsdclose(q); - - /* mark queue as authenticated and pass data to remote side */ - q->ptr = 0; - q->first = 0; - bp->flags |= S_DELIM; - PUTNEXT(q, bp); - qunlock(&q->rlock); -} diff --git a/port/deviproute.c b/port/deviproute.c deleted file mode 100644 index 806860a097fa06b3392d72e7ee44236cd1b7c8ab..0000000000000000000000000000000000000000 --- a/port/deviproute.c +++ /dev/null @@ -1,377 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -#include "devtab.h" - -/* - * All ip numbers and masks are stored as ulongs. - * All interfaces to this code uses the standard byte - * string representation. - */ - -typedef struct Iproute Iproute; -typedef struct Iprtab Iprtab; - -enum -{ - Nroutes= 256, -}; - -/* - * routes - */ -struct Iproute { - ulong dst; - ulong gate; - ulong mask; - Iproute *next; - int inuse; -}; -struct Iprtab { - Lock; - int n; /* number of valid routes */ - Iproute *first; /* list of valid routes */ - Iproute r[Nroutes]; /* all routes */ -}; -Iprtab iprtab; - -/* - * The chosen route is the one obeys the constraint - * r->mask & dst == r->dst - * - * If there are several matches, the one whose mask has the most - * leading ones (and hence is the most specific) wins. This is - * forced by storing the routes in decreasing number of ones order - * and returning the first match. The default gateway has no ones - * in the mask and is thus the last matched. - */ -void -iproute(uchar *dst, uchar *gate) -{ - Iproute *r; - ulong udst; - - udst = nhgetl(dst); - if((udst&Mynetmask) == (Myip[Myself]&Mynetmask)){ - memmove(gate, dst, 4); - return; - } - - /* - * first check routes - */ - for(r = iprtab.first; r; r = r->next){ - if((r->mask&udst) == r->dst){ - hnputl(gate, r->gate); - return; - } - } - - /* - * else just return the same address - */ - memmove(gate, dst, 4); -} - -/* - * Add a route, create a mask if the first mask is 0. - * - * All routes are stored sorted by the length of leading - * ones in the mask. - * - * NOTE: A default route has an all zeroes mask and dst. - */ -void -ipaddroute(ulong dst, ulong mask, ulong gate) -{ - Iproute *r, *e, *free; - - /* - * filter out impossible requests - */ - if((dst&mask) != dst) - error(Enetaddr); - - /* - * see if we already have a route for - * the destination - */ - lock(&iprtab); - free = 0; - for(r = iprtab.r; r < &iprtab.r[Nroutes]; r++){ - if(r->inuse == 0){ - free = r; - continue; - } - if(dst==r->dst && mask==r->mask){ - r->gate = gate; - unlock(&iprtab); - return; - } - } - if(free == 0){ - unlock(&iprtab); - exhausted("routes"); - } - - /* - * add the new route in sorted order - */ - free->dst = dst; - free->mask = mask; - free->gate = gate; - free->inuse = 1; - for(r = e = iprtab.first; r; r = r->next){ - if(mask > r->mask) - break; - e = r; - } - free->next = r; - if(r == iprtab.first) - iprtab.first = free; - else - e->next = free; - iprtab.n++; - unlock(&iprtab); -} - -/* - * remove a route - */ -void -ipremroute(ulong dst, ulong mask) -{ - Iproute *r, *e; - - lock(&iprtab); - for(r = e = iprtab.first; r; r = r->next){ - if(dst==r->dst && mask==r->mask){ - if(r == iprtab.first) - iprtab.first = r->next; - else - e->next = r->next; - r->inuse = 0; - iprtab.n--; - break; - } - e = r; - } - unlock(&iprtab); -} - -/* - * remove all routes - */ -void -ipflushroute(void) -{ - Iproute *r; - - lock(&iprtab); - for(r = iprtab.first; r; r = r->next) - r->inuse = 0; - iprtab.first = 0; - iprtab.n = 0; - unlock(&iprtab); -} - -/* - * device interface - */ -enum{ - Qdir, - Qdata, -}; -Dirtab iproutetab[]={ - "iproute", {Qdata}, 0, 0666, -}; -#define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) - -void -iproutereset(void) -{ -} - -void -iprouteinit(void) -{ -} - -Chan * -iprouteattach(char *spec) -{ - return devattach('P', spec); -} - -Chan * -iprouteclone(Chan *c, Chan *nc) -{ - return devclone(c, nc); -} - -int -iproutewalk(Chan *c, char *name) -{ - return devwalk(c, name, iproutetab, (long)Niproutetab, devgen); -} - -void -iproutestat(Chan *c, char *db) -{ - devstat(c, db, iproutetab, (long)Niproutetab, devgen); -} - -Chan * -iprouteopen(Chan *c, int omode) -{ - if(c->qid.path == CHDIR){ - if(omode != OREAD) - error(Eperm); - } - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -void -iproutecreate(Chan *c, char *name, int omode, ulong perm) -{ - USED(c, name, omode, perm); - error(Eperm); -} - -void -iprouteremove(Chan *c) -{ - USED(c); - error(Eperm); -} - -void -iproutewstat(Chan *c, char *dp) -{ - USED(c, dp); - error(Eperm); -} - -void -iprouteclose(Chan *c) -{ - USED(c); -} - -#define IPR_ENTRYLEN 54 -#define PAD " " - -long -iprouteread(Chan *c, void *a, long n, ulong offset) -{ - char buf[IPR_ENTRYLEN*3]; - Iproute *r; - int part, bytes, size; - uchar dst[4], mask[4], gate[4]; - - switch((int)(c->qid.path&~CHDIR)){ - case Qdir: - return devdirread(c, a, n, iproutetab, Niproutetab, devgen); - case Qdata: - lock(&iprtab); - part = offset/IPR_ENTRYLEN; - for(r = iprtab.first; part && r; r = r->next) - part--; - bytes = offset; - while(r && bytes < iprtab.n*IPR_ENTRYLEN && n){ - part = bytes%IPR_ENTRYLEN; - - hnputl(dst, r->dst); - hnputl(mask, r->mask); - hnputl(gate, r->gate); - sprint(buf,"%d.%d.%d.%d & %d.%d.%d.%d -> %d.%d.%d.%d%s", - dst[0], dst[1], dst[2], dst[3], - mask[0], mask[1], mask[2], mask[3], - gate[0], gate[1], gate[2], gate[3], - PAD); - - buf[IPR_ENTRYLEN-1] = '\n'; - - size = IPR_ENTRYLEN - part; - if(size > n) - size = n; - memmove(a, buf+part, size); - - a = (void *)((int)a + size); - n -= size; - bytes += size; - r = r->next; - } - unlock(&iprtab); - return bytes - offset; - break; - default: - n=0; - break; - } - return n; -} - -long -iproutewrite(Chan *c, char *a, long n, ulong offset) -{ - char buf[IPR_ENTRYLEN]; - char *field[4]; - Ipaddr mask, dst, gate; - int m; - - USED(offset); - - switch((int)(c->qid.path&~CHDIR)){ - case Qdata: - strncpy(buf, a, sizeof buf); - m = getfields(buf, field, 4, ' '); - - if(strncmp(field[0], "flush", 5) == 0) - ipflushroute(); - else if(strcmp(field[0], "add") == 0){ - switch(m){ - case 4: - dst = ipparse(field[1]); - mask = ipparse(field[2]); - gate = ipparse(field[3]); - ipaddroute(dst, mask, gate); - break; - case 3: - dst = ipparse(field[1]); - gate = ipparse(field[2]); - ipaddroute(dst, classmask[dst>>30], gate); - break; - default: - error(Ebadarg); - } - } else if(strcmp(field[0], "delete") == 0){ - switch(m){ - case 3: - dst = ipparse(field[1]); - mask = ipparse(field[2]); - ipremroute(dst, mask); - break; - case 2: - dst = ipparse(field[1]); - ipremroute(dst, classmask[dst>>30]); - break; - default: - error(Ebadarg); - } - } - break; - default: - error(Ebadusefd); - } - return n; -} diff --git a/port/ipdat.h b/port/ipdat.h deleted file mode 100644 index 7ec2de425198ef4de2c7cedec6bfb581dc43d37b..0000000000000000000000000000000000000000 --- a/port/ipdat.h +++ /dev/null @@ -1,533 +0,0 @@ -typedef struct Etherhdr Etherhdr; -typedef struct Fragq Fragq; -typedef struct Ilcb Ilcb; -typedef struct Ilhdr Ilhdr; -typedef ulong Ipaddr; -typedef struct Ipconv Ipconv; -typedef struct Ipfrag Ipfrag; -typedef struct Ipifc Ipifc; -typedef ushort Port; -typedef struct Reseq Reseq; -typedef struct Tcp Tcp; -typedef struct Tcpctl Tcpctl; -typedef struct Tcphdr Tcphdr; -typedef struct Timer Timer; -typedef struct Udphdr Udphdr; - -struct Etherhdr -{ -#define ETHER_HDR 14 - uchar d[6]; - uchar s[6]; - uchar type[2]; - - /* Now we have the ip fields */ -#define ETHER_IPHDR 20 - uchar vihl; /* Version and header length */ - uchar tos; /* Type of service */ - uchar length[2]; /* packet length */ - uchar id[2]; /* Identification */ - uchar frag[2]; /* Fragment information */ - uchar ttl; /* Time to live */ - uchar proto; /* Protocol */ - uchar cksum[2]; /* Header checksum */ - uchar src[4]; /* Ip source */ - uchar dst[4]; /* Ip destination */ -}; - -/* Ethernet packet types */ -#define ET_IP 0x0800 - -struct Udphdr -{ -#define UDP_EHSIZE 22 - 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 */ - uchar id[2]; /* Identification */ - uchar frag[2]; /* Fragment information */ - - /* Udp pseudo ip really starts here */ -#define UDP_PHDRSIZE 12 -#define UDP_HDRSIZE 20 - uchar Unused; - uchar udpproto; /* Protocol */ - uchar udpplen[2]; /* Header plus data length */ - uchar udpsrc[4]; /* Ip source */ - uchar udpdst[4]; /* Ip destination */ - uchar udpsport[2]; /* Source port */ - uchar udpdport[2]; /* Destination port */ - uchar udplen[2]; /* data length */ - uchar udpcksum[2]; /* Checksum */ -}; - -struct Ilhdr -{ -#define IL_EHSIZE 34 - 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 */ - uchar id[2]; /* Identification */ - uchar frag[2]; /* Fragment information */ - uchar ttl; /* Time to live */ - uchar proto; /* Protocol */ - uchar cksum[2]; /* Header checksum */ - uchar src[4]; /* Ip source */ - uchar dst[4]; /* Ip destination */ -#define IL_HDRSIZE 18 - uchar ilsum[2]; /* Checksum including header */ - uchar illen[2]; /* Packet length */ - uchar iltype; /* Packet type */ - uchar ilspec; /* Special */ - uchar ilsrc[2]; /* Src port */ - uchar ildst[2]; /* Dst port */ - uchar ilid[4]; /* Sequence id */ - uchar ilack[4]; /* Acked sequence */ -}; - -struct Ilcb /* Control block */ -{ - int state; /* Connection state */ - - Rendez syncer; /* where syncer waits for a connect */ - - QLock ackq; /* Unacknowledged queue */ - Block *unacked; - Block *unackedtail; - - QLock outo; /* Out of order packet queue */ - Block *outoforder; - - Lock nxl; - ulong next; /* Id of next to send */ - ulong recvd; /* Last packet received */ - ulong start; /* Local start id */ - ulong rstart; /* Remote start id */ - - int timeout; /* Time out counter */ - int slowtime; /* Slow time counter */ - int fasttime; /* Retransmission timer */ - int acktime; /* Acknowledge timer */ - int querytime; /* Query timer */ - int deathtime; /* Time to kill connection */ - - int rtt; /* Average round trip time */ - ulong rttack; /* The ack we are waiting for */ - ulong ackms; /* Time we issued */ - - int window; /* Maximum receive window */ -}; - -enum /* Packet types */ -{ - Ilsync, - Ildata, - Ildataquery, - Ilack, - Ilquerey, - Ilstate, - Ilclose, -}; - -enum /* Connection state */ -{ - Ilclosed, - Ilsyncer, - Ilsyncee, - Ilestablished, - Illistening, - Ilclosing, -}; - -#define TCP_PKT (TCP_EHSIZE+TCP_IPLEN+TCP_PHDRSIZE) - -struct Tcphdr -{ -#define TCP_EHSIZE 14 - uchar d[6]; /* Ethernet destination */ - uchar s[6]; /* Ethernet source */ - uchar type[2]; /* Ethernet packet type */ -#define TCP_IPLEN 8 - uchar vihl; /* Version and header length */ - uchar tos; /* Type of service */ - uchar length[2]; /* packet length */ - uchar id[2]; /* Identification */ - uchar frag[2]; /* Fragment information */ - -#define TCP_PHDRSIZE 12 - uchar Unused; - uchar proto; - uchar tcplen[2]; - uchar tcpsrc[4]; - uchar tcpdst[4]; - -#define TCP_HDRSIZE 20 - uchar tcpsport[2]; - uchar tcpdport[2]; - uchar tcpseq[4]; - uchar tcpack[4]; - uchar tcpflag[2]; - uchar tcpwin[2]; - uchar tcpcksum[2]; - uchar tcpurg[2]; - - /* Options segment */ - uchar tcpopt[2]; - uchar tcpmss[2]; -}; - -enum -{ - TimerOFF = 0, - TimerON = 1, - TimerDONE = 2, -}; - -struct Timer -{ - Timer *next; - Timer *prev; - int state; - int start; - int count; - void (*func)(void*); - void *arg; -}; - -struct Tctl -{ - uchar state; /* Connection state */ - uchar type; /* Listening or active connection */ - uchar code; /* Icmp code */ - struct { - int una; /* Unacked data pointer */ - int nxt; /* Next sequence expected */ - int ptr; /* Data pointer */ - ushort wnd; /* Tcp send window */ - int up; /* Urgent data pointer */ - int wl1; - int wl2; - } snd; - struct { - int nxt; /* Receive pointer to next byte slot */ - ushort wnd; /* Receive window incoming */ - int up; /* Urgent pointer */ - } rcv; - int iss; /* Initial sequence number */ - ushort cwind; /* Congestion window */ - ushort ssthresh; /* Slow start threshold */ - int resent; /* Bytes just resent */ - int irs; /* Initial received squence */ - ushort mss; /* Mean segment size */ - int rerecv; /* Overlap of data rerecevived */ - ushort window; /* Recevive window */ - int max_snd; /* Max send */ - int last_ack; /* Last acknowledege received */ - char backoff; /* Exponential backoff counter */ - char flags; /* State flags */ - char tos; /* Type of service */ - - Blist rcvq; /* Received data */ - ulong rcvcnt; /* Bytes queued for upstream */ - - Block *sndq; /* List of data going out */ - ulong sndcnt; /* Amount of data in send queue */ - Rendez sndr; /* process flow control */ - QLock sndrlock; - int sndfull; - - Reseq *reseq; /* Resequencing queue */ - Timer timer; /* Activity timer */ - Timer acktimer; /* Acknoledge timer */ - Timer rtt_timer; /* Round trip timer */ - int rttseq; /* Round trip sequence */ - int srtt; /* Shortened round trip */ - int mdev; /* Mean deviation of round trip */ -}; - -struct Tcpctl -{ - QLock; - Rendez syner; - struct Tctl; -}; - -struct Tcp -{ - Port source; - Port dest; - int seq; - int ack; - char flags; - ushort wnd; - ushort up; - ushort mss; -}; - -struct Reseq -{ - Reseq *next; - Tcp seg; - Block *bp; - ushort length; - char tos; -}; - -/* An ip interface used for UDP/TCP/IL */ -struct Ipconv -{ - QLock; /* Ref count lock */ - Netprot; /* stat info */ - int ref; - Ipaddr dst; /* Destination from connect */ - Port psrc; /* Source port */ - Port pdst; /* Destination port */ - - Ipifc *ifc; /* Ip protocol interface */ - Queue *readq; /* Pointer to upstream read q */ - QLock listenq; /* List of people waiting incoming cons */ - Rendez listenr; /* Some where to sleep while waiting */ - - char *err; /* Async protocol error */ - int backlog; /* Maximum number of waiting connections */ - int headers; /* include header in packet */ - int curlog; /* Number of waiting connections */ - Ipconv *newcon; /* This is the start of a connection */ - - union { - Tcpctl tcpctl; /* Tcp control block */ - Ilcb ilctl; /* Il control block */ - }; -}; - -enum -{ - MAX_TIME = (1<<20), /* Forever */ - TCP_ACK = 200, /* Timed ack sequence every 200ms */ - - URG = 0x20, /* Data marked urgent */ - ACK = 0x10, /* Aknowledge is valid */ - PSH = 0x08, /* Whole data pipe is pushed */ - RST = 0x04, /* Reset connection */ - SYN = 0x02, /* Pkt. is synchronise */ - FIN = 0x01, /* Start close down */ - - EOL_KIND = 0, - NOOP_KIND = 1, - MSS_KIND = 2, - - MSS_LENGTH = 4, /* Mean segment size */ - MSL2 = 10, - MSPTICK = 100, /* Milliseconds per timer tick */ - DEF_MSS = 1024, /* Default mean segment */ - DEF_RTT = 1000, /* Default round trip */ - - TCP_PASSIVE = 0, /* Listen connection */ - TCP_ACTIVE = 1, /* Outgoing connection */ - IL_PASSIVE = 0, - IL_ACTIVE = 1, - - MAXBACKOFF = 5, - FORCE = 1, - CLONE = 2, - RETRAN = 4, - ACTIVE = 8, - SYNACK = 16, - AGAIN = 8, - DGAIN = 4, -}; - -#define set_timer(t,x) (((t)->start) = (x)/MSPTICK) -#define run_timer(t) ((t)->state == TimerON) - -enum /* Tcp connection states */ -{ - Closed = 0, - Listen, - Syn_sent, - Syn_received, - Established, - Finwait1, - Finwait2, - Close_wait, - Closing, - Last_ack, - Time_wait -}; - -enum -{ - Nipconv= 512, /* max conversations per interface */ - Udphdrsize= 6, /* size if a to/from user Udp header */ -}; - -/* - * Ip interface structure. We have one for each active protocol driver - */ -struct Ipifc -{ - QLock; - Network; /* user level network interface */ - Ipifc *next; - int inited; - uchar protocol; /* Ip header protocol number */ - void (*iprcv) (Ipifc*, Block*); /* Receive demultiplexor */ - int maxmtu; /* Maximum transfer unit */ - int minmtu; /* Minumum tranfer unit */ - int hsize; /* Media header size */ - ulong chkerrs; /* checksum errors */ - Ipconv **conv; /* conversations */ -}; - - -struct Fragq -{ - QLock; - Block *blist; - Fragq *next; - Ipaddr src; - Ipaddr dst; - ushort id; - ulong age; -}; - -struct Ipfrag -{ - ushort foff; - ushort flen; -}; - -enum { - IP_VER = 0x40, /* Using IP version 4 */ - IP_HLEN = 0x05, /* Header length in characters */ - IP_DF = 0x4000, /* Don't fragment */ - IP_MF = 0x2000, /* More fragments */ - - /* Sizes */ - IP_MAX = (32*1024), /* Maximum Internet packet size */ - UDP_MAX = (IP_MAX-ETHER_IPHDR), /* Maximum UDP datagram size */ - UDP_DATMAX = (UDP_MAX-UDP_HDRSIZE),/* Maximum amount of udp data */ - IL_DATMAX = (IP_MAX-IL_HDRSIZE), /* Maximum IL data in one ip packet */ - - /* Protocol numbers */ - IP_UDPPROTO = 17, - IP_TCPPROTO = 6, - IP_ILPROTO = 40, - - /* Protocol port numbers */ - PORTALLOC = 5000, /* First automatic allocated port */ - PRIVPORTALLOC = 600, /* First priveleged port allocated */ - UNPRIVPORTALLOC = 1024, /* First unpriveleged port allocated */ - PORTMAX = 30000, /* Last port to allocte */ -}; - -void add_reseq(Tcpctl *, char, Tcp *, Block *, ushort); -int arp_lookup(uchar*, uchar*); -int backoff(int); -Block* btrim(Block*, int, int); -void localclose(Ipconv *, char []); -int dupb(Block **, Block *, int, int); -void extract_oob(Block **, Block **, Tcp *); -void get_reseq(Tcpctl *, char *, Tcp *, Block **, ushort *); -void hnputl(uchar*, ulong); -void hnputs(uchar*, ushort); -Block* htontcp(Tcp *, Block *, Tcphdr *); -Block* htontcp(Tcp *, Block *, Tcphdr *); -void iloutoforder(Ipconv*, Ilhdr*, Block*); -void ilstart(Ipconv *, int, int); -int inb_window(Tcpctl *, int); -void init_tcpctl(Ipconv *); -void initfrag(int); -void initipifc(Ipifc*, uchar, void (*)(Ipifc*, Block*), int, int, int); -Ipconv* ip_conn(Ipifc*, Port, Port, Ipaddr dest); -ushort ip_csum(uchar*); -Block* ip_reassemble(int, Block*, Etherhdr*); -int ipclonecon(Chan *); -int ipconbusy(Ipconv*); -Ipconv* ipcreateconv(Ipifc*, int); -int ipforme(uchar*); -Fragq* ipfragallo(void); -void ipfragfree(Fragq*, int); -Ipconv* ipincoming(Ipifc*, Ipconv*); -int iplisten(Chan *); -void iplocalfill(Chan*, char*, int); -void ipmkdir(Qinfo *, Dirtab *, Ipconv *); -Ipaddr ipparse(char*); -void ipremotefill(Chan*, char*, int); -void iproute(uchar*, uchar*); -void ipsetaddrs(void); -void ipstatusfill(Chan*, char*, int); -Port nextport(Ipifc*, int); -ushort nhgets(uchar*); -ulong nhgetl(uchar*); -int ntohtcp(Tcp *, Block **); -int ntohtcp(Tcp*, Block**); -Ipconv* portused(Ipifc*, Port); -void ppkt(Block*); -void proc_syn(Ipconv*, char, Tcp*); -ushort ptcl_csum(Block*bp, int, int); -int pullb(Block **, int); -void reset(Ipaddr, Ipaddr, char, ushort, Tcp*); -void tcpsndsyn(Tcpctl*); -int seq_ge(int, int); -int seq_gt(int, int); -int seq_gt(int, int); -int seq_le(int, int); -int seq_lt(int, int); -int seq_within(int, int, int); -int seq_within(int, int, int); -void tcpsetstate(Ipconv *, char); -void tcpgo(Timer *); -void tcphalt(Timer *); -void tcpxstate(Ipconv*, char oldstate, char newstate); -void tcpacktimer(void *); -void tcpinput(Ipifc*, Block *); -void tcpoutput(Ipconv*); -void tcptimeout(void *); -void tcpackproc(void*); -void tcpflow(void*); -void tcpflushincoming(Ipconv*); -void tcprcvwin(Ipconv *); -void tcpstart(Ipconv *, int, ushort, char); -int trim(Tcpctl *, Tcp *, Block **, ushort *); -void udprcvmsg(Ipifc*, Block*); -void update(Ipconv *, Tcp *); - -#define fmtaddr(xx) (xx>>24)&0xff,(xx>>16)&0xff,(xx>>8)&0xff,xx&0xff -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define BLKIP(xp) ((Etherhdr *)((xp)->rptr)) -#define BLKFRAG(xp) ((Ipfrag *)((xp)->base)) -#define PREC(x) ((x)>>5 & 7) - -extern Ipaddr Myip[7]; -extern Ipaddr Mymask; -extern Ipaddr Mynetmask; -extern Ipaddr classmask[4]; -extern Ipifc *ipifc[]; -extern char *tcpstate[]; -extern char *ilstate[]; -extern Rendez tcpflowr; -extern Qinfo tcpinfo; -extern Qinfo ipinfo; -extern Qinfo udpinfo; -extern Qinfo ilinfo; -extern Qinfo arpinfo; -extern Queue *Ipoutput; - -/* offsets into Myip */ -enum -{ - Myself = 0, - Mybcast = 1, - Mynet = 3, - Mysubnet = 5, -}; diff --git a/port/proc.c b/port/proc.c index 91c9304badfe55c9d14c5d9e78e89944de825d83..26af50ad3dd84cd436795672150219c699fa3ac5 100644 --- a/port/proc.c +++ b/port/proc.c @@ -84,7 +84,6 @@ schedinit(void) /* never returns */ void sched(void) { - kmapinval(); if(up) { splhi(); m->cs++; diff --git a/port/qio.c b/port/qio.c index a3a9706e8aa603c0708a1efa70a2892233499629..e1731e5fe86df7872918117a7dac9948d03de235 100644 --- a/port/qio.c +++ b/port/qio.c @@ -115,9 +115,10 @@ iallockproc(void *arg) unlock(cl); splx(x); - for(; first; first = p){ + while(first != 0) { p = first->next; free(first); + first = p; } } @@ -146,10 +147,12 @@ iallockproc(void *arg) first = 0; l = &first; - for(i = x = cl->goal - cl->have; x > 0; x--){ + i = cl->goal - cl->have; + for(x = i; x > 0; x--){ p = malloc(1<next; } @@ -190,7 +193,7 @@ iallocb(int size) Block *b; size += sizeof(Block); - for(pow = Minpow; pow <= Maxpow; pow++) + for(pow = Minpow; pow <= Maxpow; pow++){ if(size <= (1<base = (uchar*)(b+1); - b->wp = b->rp = b->base; + b->wp = b->base; + b->rp = b->base; b->lim = b->base + (1<base = (uchar*)(b+1); - b->rp = b->wp = b->base; + b->rp = b->base; + b->wp = b->base; b->lim = b->base + size; b->flag = 0; @@ -549,9 +555,10 @@ qclose(Queue *q) splx(x); /* free queued blocks */ - while(b = bfirst){ - bfirst = b->next; - free(b); + while(bfirst){ + b = bfirst->next; + free(bfirst); + bfirst = b; } /* wake up readers/writers */ diff --git a/port/stasync.c b/port/stasync.c deleted file mode 100644 index 8baa27f9b43867b1051876af55cbad7246cf8d49..0000000000000000000000000000000000000000 --- a/port/stasync.c +++ /dev/null @@ -1,477 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define DPRINT if(asyncdebug)kprint - -/* - * configuration - */ -enum { - MAXFRAME= 256, /* also known to tsm8 code */ -}; - -/* input states */ -enum -{ - Hunt, - Framing, - Framed, - Data, - Escape -}; - -typedef struct Async Async; -struct Async -{ - QLock; - Async *list; - int id; - - int inuse; - Queue *wq; - - /* output state */ - QLock xmit; /* transmit lock */ - int chan; /* current urp channel */ - Block *bp; /* current output buffer */ - int count; - ushort crc; - - /* input state */ - int state; /* input state */ - uchar buf[MAXFRAME]; /* current input buffer */ - int icount; - ushort icrc; - - /* statistics */ - ulong chan0; - ulong toolong; - ulong tooshort; - ulong badcrc; - ulong badescape; - ulong in; /* bytes in */ - ulong out; /* bytes out */ -}; - -int nasync; - -/* list of allocated async structures (never freed) */ -struct -{ - Lock; - Async *async; -} asyncalloc; - -/* - * async stream module definition - */ -static void asynciput(Queue*, Block*); -static void asyncoput(Queue*, Block*); -static void asyncopen(Queue*, Stream*); -static void asyncclose(Queue*); -static void asyncreset(void); -Qinfo asyncinfo = -{ - asynciput, - asyncoput, - asyncopen, - asyncclose, - "async", - asyncreset -}; - -static int debugcount = 6; -int asyncdebug; -int asyncerror; - -static ushort crc_table[256] = { -#include "../port/crc_16.h" -}; - -#define BOT 0050 /* begin trailer */ -#define BOTM 0051 /* begin trailer, more data follows */ -#define BOTS 0052 /* seq update alg. on this trailer */ - -#define FRAME 0x7e -#define STUF 0x9d - -#define CRCSTART (crc_table[0xff]) -#define CRCFUNC(crc,x) (crc_table[((crc)^(x))&0xff]^((crc)>>8)) - -/* - * create the async structures - */ -static void -asyncreset(void) -{ -} - -/* - * allocate an async structure - */ -static void -asyncopen(Queue *q, Stream *s) -{ - Async *ap; - - DPRINT("asyncopen %d\n", s->dev); - - for(ap = asyncalloc.async; ap; ap = ap->list){ - qlock(ap); - if(ap->inuse == 0) - break; - qunlock(ap); - } - if(ap == 0){ - ap = smalloc(sizeof(Async)); - qlock(ap); - lock(&asyncalloc); - ap->list = asyncalloc.async; - asyncalloc.async = ap; - ap->id = nasync++; - unlock(&asyncalloc); - } - q->ptr = q->other->ptr = ap; - - ap->inuse = 1; - ap->bp = 0; - ap->chan = -1; - ap->count = 0; - ap->toolong = 0; - ap->tooshort = 0; - ap->badcrc = 0; - ap->badescape = 0; - ap->chan0 = 0; - ap->in = 0; - ap->out = 0; - ap->wq = WR(q); - ap->state = Hunt; - qunlock(ap); -} - -static void -asyncclose(Queue * q) -{ - Async *ap = (Async *)q->ptr; - - DPRINT("asyncstclose %d\n", ap->id); - qlock(ap); - ap->inuse = 0; - qunlock(ap); -} - -/* - * free all blocks of a message in `q', `bp' is the first block - * of the message - */ -static void -freemsg(Queue *q, Block *bp) -{ - for(; bp; bp = getq(q)){ - if(bp->flags & S_DELIM){ - freeb(bp); - return; - } - freeb(bp); - } -} - -static void -showframe(char *t, Async *ap, uchar *buf, int n) -{ - kprint("a%d %s [", ap->id, t); - while (--n >= 0) - kprint(" %2.2ux", *buf++); - kprint(" ]\n"); -} - -void -aswrite(Async *ap) -{ - if(ap->bp->rptr == ap->bp->wptr) - return; - FLOWCTL(ap->wq, ap->bp); - ap->bp = 0; -} - -void -asputf(Async *ap) -{ - uchar *p; - int c; - - p = ap->bp->wptr; - if(ap->count > 0) { - if(asyncerror) - ap->crc^=1, asyncerror=0; - *p++ = c = ap->crc&0xff; - if(c == FRAME) - *p++ = 0x00; - *p++ = c = (ap->crc>>8)&0xff; - if(c == FRAME) - *p++ = 0x00; - ap->count = 0; - } - *p++ = FRAME; - *p++ = FRAME; - ap->bp->wptr = p; - if(asyncdebug > 2) - showframe("out", ap, ap->bp->rptr, BLEN(ap->bp)); - aswrite(ap); -} - -void -asputc(Async *ap, int c) -{ - int d; - uchar *p; - - if(ap->bp == 0) - ap->bp = allocb(MAXFRAME+4); - p = ap->bp->wptr; - if(ap->count <= 0) { - *p++ = d = 0x80|((ap->chan>>5)&0x7e); - ap->crc = CRCFUNC(CRCSTART, d); - *p++ = d = 0x80|((ap->chan<<1)&0x7e); - ap->crc = CRCFUNC(ap->crc, d); - } - *p++ = c; - if(c == FRAME) - *p++ = 0x00; - ap->crc = CRCFUNC(ap->crc, c); - ap->bp->wptr = p; - if(++ap->count >= MAXFRAME-4) - asputf(ap); - else if(ap->bp->lim - p < 8) - aswrite(ap); -} - -/* - * output a block - * - * the first 2 bytes of every message are the channel number, - * low order byte first. the third is a possible trailing control - * character. - */ -void -asyncoput(Queue *q, Block *bp) -{ - Async *ap = (Async *)q->ptr; - int c, chan, ctl; - Block *msg; - - if(bp->type != M_DATA){ - if(streamparse("debug", bp)){ - asyncdebug = 3; - freeb(bp); - } else { - PUTNEXT(q, bp); - } - return; - } - - /* - * each datakit message has a 2 byte channel number followed by - * one control byte - */ - msg = pullup(bp, 3); - if(msg == 0){ - print("asyncoput msglen < 3\n"); - return; - } - chan = msg->rptr[0] | (msg->rptr[1]<<8); - ctl = msg->rptr[2]; - msg->rptr += 3; - - qlock(&ap->xmit); - if(waserror()){ - qunlock(&ap->xmit); - freeb(msg); - nexterror(); - } - - /* - * new frame if the channel number has changed - */ - if(chan != ap->chan && ap->count > 0) - asputf(ap); - ap->chan = chan; - - if(asyncdebug > 1) - kprint("a%d->(%d)%3.3uo %d\n", - ap->id, chan, ctl, bp->wptr-bp->rptr); - - /* - * send the 8 bit data - */ - for(bp = msg; bp; bp = bp->next){ - while (bp->rptr < bp->wptr) { - asputc(ap, c = *bp->rptr++); - if(c == STUF) - asputc(ap, 0); - } - } - - /* - * send the control byte if there is one - */ - if(ctl){ - asputc(ap, STUF); - asputc(ap, ctl); - switch (ctl) { - case BOT: - case BOTM: - case BOTS: - break; - default: - asputf(ap); - } - } - if(debugcount > 0 && --debugcount == 0) - asyncdebug = 1; - - freeb(msg); - qunlock(&ap->xmit); - poperror(); - return; -} - -/* - * Read bytes from the raw input. - */ - -void -asdeliver(Queue *q, Async *ap) -{ - int chan, c; - Block *bp = 0; - uchar *p = ap->buf; - int n = ap->icount; - - chan = *p++ & 0x7e; - chan = (chan<<5)|((*p++ & 0x7e)>>1); - if(chan==0) { - DPRINT("a%d deliver chan 0\n", ap->id); - ap->chan0++; - return; - } - for (n-=4; n>0; n--) { - if(!bp) { - bp = allocb(n+2); - bp->flags |= S_DELIM; - bp->wptr[0] = chan; - bp->wptr[1] = chan>>8; - bp->wptr[2] = 0; - bp->wptr += 3; - } - if((c = *p++) == STUF) { - --n; - if((c = *p++) != 0) { - bp->rptr[2] = c; - if(asyncdebug > 1) - kprint("a%d<-(%d)%3.3uo %d\n", - ap->id, chan, bp->rptr[2], - bp->wptr - bp->rptr - 3); - PUTNEXT(q, bp); - bp = 0; - continue; - } else - c = STUF; - } - *bp->wptr++ = c; - } - if(bp) { - if(asyncdebug > 1) - kprint("a%d<-(%d)%3.3uo %d\n", - ap->id, chan, bp->rptr[2], - bp->wptr - bp->rptr - 3); - PUTNEXT(q, bp); - } -} - -static void -asynciput(Queue *q, Block *bp) -{ - int c; - Async *ap = q->ptr; - int state = ap->state; - - while(bp->wptr > bp->rptr){ - c = *bp->rptr++; - switch(state) { - case Hunt: /* wait for framing byte */ - if(c == FRAME) - state = Framing; - break; - - case Framing: /* saw 1 framing byte after Hunt */ - if(c == FRAME) - state = Framed; - else - state = Hunt; - break; - - case Framed: /* saw 2 or more framing bytes */ - if(c == FRAME) - break; - state = Data; - ap->icrc = CRCSTART; - ap->icount = 0; - goto Datachar; - - case Data: /* mid-frame */ - if(c == FRAME) { - state = Escape; - break; - } - Datachar: - if(ap->icount >= MAXFRAME) { - DPRINT("a%d pkt too long\n", ap->id); - ap->toolong++; - state = Hunt; - break; - } - ap->icrc = CRCFUNC(ap->icrc, c); - ap->buf[ap->icount++] = c; - break; - - case Escape: /* saw framing byte in Data */ - switch (c) { - case FRAME: - if(asyncdebug > 2) - showframe("in", ap, ap->buf, ap->icount); - if(ap->icount < 5) { - DPRINT("a%d pkt too short\n", ap->id); - if(asyncdebug && asyncdebug<=2) - showframe("shortin", ap, ap->buf, ap->icount); - ap->tooshort++; - } else if(ap->icrc != 0) { - DPRINT("a%d bad crc\n", ap->id); - if(asyncdebug && asyncdebug<=2) - showframe("badin", ap, ap->buf, ap->icount); - ap->badcrc++; - } else { - asdeliver(q, ap); - } - state = Framed; - break; - case 0: - c = FRAME; - state = Data; - goto Datachar; - default: - DPRINT("a%d bad escape\n", ap->id); - ap->badescape++; - state = Hunt; - break; - } - break; - } - } - ap->state = state; - freeb(bp); -} diff --git a/port/stfcall.c b/port/stfcall.c deleted file mode 100644 index 54d3a24263b6995e16306c557f3cd78ef2a5784a..0000000000000000000000000000000000000000 --- a/port/stfcall.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -enum -{ - Twritehdr = 16, /* Min bytes for Twrite */ - Rreadhdr = 8, /* Min bytes for Rread */ - Twritecnt = 13, /* Offset in byte stream of write count */ - Rreadcnt = 5, /* Offset for Readcnt */ -}; - -static void fcalliput(Queue*, Block*); -static void fcalloput(Queue*, Block*); -static void fcallopen(Queue*, Stream*); -static void fcallclose(Queue*); -static void fcallreset(void); -Qinfo fcallinfo = { fcalliput, fcalloput, fcallopen, fcallclose, "fcall", fcallreset }; - -static uchar msglen[256] = -{ - [Tnop] 3, - [Rnop] 3, - [Tsession] 3, - [Rsession] 3, - [Terror] 0, - [Rerror] 67, - [Tflush] 5, - [Rflush] 3, - [Tattach] 89, - [Rattach] 13, - [Tclone] 7, - [Rclone] 5, - [Twalk] 33, - [Rwalk] 13, - [Topen] 6, - [Ropen] 13, - [Tcreate] 38, - [Rcreate] 13, - [Tread] 15, - [Rread] 8, - [Twrite] 16, - [Rwrite] 7, - [Tclunk] 5, - [Rclunk] 5, - [Tremove] 5, - [Rremove] 5, - [Tstat] 5, - [Rstat] 121, - [Twstat] 121, - [Rwstat] 5, - [Tclwalk] 35, - [Rclwalk] 13, - [Tauth] 69, - [Rauth] 35, -}; - -static void -fcallreset(void) -{ -} - -static void -fcallopen(Queue *q, Stream *s) -{ - USED(q, s); -} - -static void -fcallclose(Queue * q) -{ - USED(q); -} - -void -fcalloput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} - -void -upstream(Queue *q, ulong len) -{ - Block *bl, **tail, *bp; - ulong l; - - tail = &bl; - while(len) { - l = BLEN(q->first); - if(l > len) - break; - bp = getq(q); /* Consume all of block */ - *tail = bp; - tail = &bp->next; - len -= l; - } - if(len) { /* Consume partial block */ - lock(q); - *tail = copyb(q->first, len); - q->first->rptr += len; - q->len -= len; - unlock(q); - } - for(bp = bl; bp->next; bp = bp->next) - ; - bp->flags |= S_DELIM; - PUTNEXT(q, bl); -} - -static void -fcalliput(Queue *q, Block *bp) -{ - ulong len, need, off; - - if(bp->type != M_DATA) { - PUTNEXT(q, bp); - return; - } - if(BLEN(bp) == 0) { - freeb(bp); - return; - } - - /* Stash the data */ - bp->flags &= ~S_DELIM; - putq(q, bp); - - for(;;) { - bp = q->first; - if(bp == 0) - return; - switch(bp->rptr[0]) { /* This is the type */ - default: - len = msglen[bp->rptr[0]]; - if(len == 0){ - bp = allocb(0); - bp->type = M_HANGUP; - PUTNEXT(q, bp); - return; - } - if(q->len < len) - return; - - upstream(q, len); - continue; - - case Twrite: /* Fmt: TGGFFOOOOOOOOCC */ - len = Twritehdr; /* T = type, G = tag, F = fid */ - off = Twritecnt; /* O = offset, C = count */ - break; - - case Rread: /* Fmt: TGGFFCC */ - len = Rreadhdr; - off = Rreadcnt; - break; - } - - if(q->len < len) - return; - - pullup(q->first, len); - bp = q->first; - need = len+bp->rptr[off]+(bp->rptr[off+1]<<8); - if(q->len < need) - return; - - upstream(q, need); - } -} diff --git a/port/stil.c b/port/stil.c deleted file mode 100644 index 0fd95f962420ffc30ed6e79041707c11ba72fe47..0000000000000000000000000000000000000000 --- a/port/stil.c +++ /dev/null @@ -1,877 +0,0 @@ -/* - * stil - Internet link protocol - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -#define DBG if(0)print -int ilcksum = 1; -static int initseq = 26000; -static Rendez ilackr; - -char *ilstate[] = -{ - "Closed", - "Syncer", - "Syncee", - "Established", - "Listening", - "Closing" -}; - -char *iltype[] = -{ - "sync", - "data", - "dataquerey", - "ack", - "querey", - "state", - "close" -}; -static char *etime = "connection timed out"; - -/* Always Acktime < Fasttime < Slowtime << Ackkeepalive */ -enum -{ - Iltickms = 100, - Slowtime = 200*Iltickms, - Fasttime = 4*Iltickms, - Acktime = 2*Iltickms, - Ackkeepalive = 6000*Iltickms, - Querytime = 60*Iltickms, /* time between queries */ - Keepalivetime = 10*Querytime, /* keep alive time */ - Defaultwin = 20, - ILgain = 8, -}; - -#define Starttimer(s) {(s)->timeout = 0; \ - (s)->fasttime = (Fasttime*(s)->rtt)/Iltickms; \ - (s)->slowtime = (Slowtime*(s)->rtt)/Iltickms; } - -void ilrcvmsg(Ipifc*, Block*); -void ilackproc(void*); -void ilsendctl(Ipconv*, Ilhdr*, int, ulong, ulong); -void ilackq(Ilcb*, Block*); -void ilprocess(Ipconv*, Ilhdr*, Block*); -void ilpullup(Ipconv*); -void ilhangup(Ipconv*, char *); -void ilfreeq(Ilcb*); -void ilrexmit(Ilcb*); -void ilbackoff(Ilcb*); - -void -ilopen(Queue *q, Stream *s) -{ - Ipconv *ipc; - static int ilkproc; - - if(!Ipoutput) { - Ipoutput = WR(q); - s->opens++; - s->inuse++; - } - - if(ilkproc == 0) { - ilkproc = 1; - kproc("ilack", ilackproc, ipifc[s->dev]); - } - - ipc = ipcreateconv(ipifc[s->dev], s->id); - initipifc(ipc->ifc, IP_ILPROTO, ilrcvmsg, 1500, 60, ETHER_HDR); - - ipc->readq = RD(q); - RD(q)->ptr = (void *)ipc; - WR(q)->next->ptr = (void *)ipc->ifc; - WR(q)->ptr = (void *)ipc; -} - -void -ilclose(Queue *q) -{ - Ipconv *s; - Ilcb *ic; - - s = (Ipconv *)(q->ptr); - ic = &s->ilctl; - qlock(s); - s->readq = 0; - qunlock(s); - - switch(ic->state) { - case Ilclosing: - case Ilclosed: - break; - case Ilsyncer: - case Ilsyncee: - case Ilestablished: - ilfreeq(ic); - ic->state = Ilclosing; - ilsendctl(s, 0, Ilclose, ic->next, ic->recvd); - break; - case Illistening: - ic->state = Ilclosed; - s->psrc = 0; - s->pdst = 0; - s->dst = 0; - break; - } -} - -void -iloput(Queue *q, Block *bp) -{ - Ipconv *ipc; - Ilhdr *ih; - Ilcb *ic; - int dlen; - Block *f; - ulong id; - - ipc = (Ipconv *)(q->ptr); - if(ipc->psrc == 0) - error(Enoport); - - ic = &ipc->ilctl; - switch(ic->state) { - case Ilclosed: - case Illistening: - case Ilclosing: - error(Ehungup); - } - - if(bp->type != M_DATA) { - freeb(bp); - error(Ebadctl); - } - - /* Only allow atomic Il writes to form datagrams */ - for(f = bp; f->next; f = f->next) - ; - if((f->flags & S_DELIM) == 0) { - freeb(bp); - error(Emsgsize); - } - - dlen = blen(bp); - if(dlen > IL_DATMAX) { - freeb(bp); - error(Emsgsize); - } - - /* Make space to fit il & ip & ethernet header */ - bp = padb(bp, IL_EHSIZE+IL_HDRSIZE); - ih = (Ilhdr *)(bp->rptr); - - /* Ip fields */ - ih->frag[0] = 0; - ih->frag[1] = 0; - hnputl(ih->src, Myip[Myself]); - hnputl(ih->dst, ipc->dst); - ih->proto = IP_ILPROTO; - /* Il fields */ - hnputs(ih->illen, dlen+IL_HDRSIZE); - hnputs(ih->ilsrc, ipc->psrc); - hnputs(ih->ildst, ipc->pdst); - - lock(&ic->nxl); - id = ic->next++; - unlock(&ic->nxl); - hnputl(ih->ilid, id); - - hnputl(ih->ilack, ic->recvd); - ih->iltype = Ildata; - ih->ilspec = 0; - ih->ilsum[0] = 0; - ih->ilsum[1] = 0; - - /* Checksum of ilheader plus data (not ip & no pseudo header) */ - if(ilcksum) - hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, dlen+IL_HDRSIZE)); - ilackq(ic, bp); - - /* Start the round trip timer for this packet if the timer is free */ - if(ic->rttack == 0) { - ic->rttack = id; - ic->ackms = MACHP(0)->ticks; - } - ic->acktime = Ackkeepalive; - - PUTNEXT(q, bp); -} - -void -ilackq(Ilcb *ic, Block *bp) -{ - Block *np; - - /* Enqueue a copy on the unacked queue in case this one gets lost */ - np = copyb(bp, blen(bp)); - qlock(&ic->ackq); - if(ic->unacked) - ic->unackedtail->list = np; - else { - /* Start timer since we may have been idle for some time */ - Starttimer(ic); - ic->unacked = np; - } - ic->unackedtail = np; - np->list = 0; - qunlock(&ic->ackq); -} - -void -ilackto(Ilcb *ic, ulong ackto) -{ - Ilhdr *h; - Block *bp; - ulong id, t; - - if(ic->rttack == ackto) { - t = TK2MS(MACHP(0)->ticks - ic->ackms); - /* Guard against the ulong zero wrap if MACP->ticks */ - if(t < 100*ic->rtt) - ic->rtt = (ic->rtt*(ILgain-1)+t)/ILgain; - if(ic->rtt < Iltickms) - ic->rtt = Iltickms; - } - - /* Cancel if we lost the packet we were interested in */ - if(ic->rttack <= ackto) - ic->rttack = 0; - - qlock(&ic->ackq); - while(ic->unacked) { - h = (Ilhdr *)ic->unacked->rptr; - id = nhgetl(h->ilid); - if(ackto < id) - break; - - bp = ic->unacked; - ic->unacked = bp->list; - bp->list = 0; - freeb(bp); - } - qunlock(&ic->ackq); -} - -void -iliput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} - -void -ilrcvmsg(Ipifc *ifc, Block *bp) -{ - Ilhdr *ih; - Ilcb *ic; - int plen, illen; - Ipconv *s, **p, **etab, *new, *spec, *gen; - short sp, dp; - Ipaddr dst; - - ih = (Ilhdr *)bp->rptr; - plen = blen(bp); - if(plen < IL_EHSIZE+IL_HDRSIZE) - goto drop; - - illen = nhgets(ih->illen); - if(illen+IL_EHSIZE > plen) - goto drop; - - sp = nhgets(ih->ildst); - dp = nhgets(ih->ilsrc); - dst = nhgetl(ih->src); - - if(ilcksum && ptcl_csum(bp, IL_EHSIZE, illen) != 0) { - ifc->chkerrs++; -/* st = (ih->iltype < 0 || ih->iltype > Ilclose) ? "?" : iltype[ih->iltype]; - print("il: cksum error, pkt(%s id %lud ack %lud %d.%d.%d.%d/%d->%d)\n", - st, nhgetl(ih->ilid), nhgetl(ih->ilack), fmtaddr(dst), sp, dp); /**/ - goto drop; - } - - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; p < etab; p++) { - s = *p; - if(s == 0) - break; - if(s->psrc == sp) - if(s->pdst == dp) - if(s->dst == dst) { - ilprocess(s, ih, bp); - return; - } - } - - if(ih->iltype != Ilsync) - goto drop; - - gen = 0; - spec = 0; - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; p < etab && *p; p++) { - s = *p; - if(s->ilctl.state == Illistening) - if(s->pdst == 0) - if(s->dst == 0) { - if(s->psrc == sp){ - spec = s; - break; - } - if(s->psrc == 0) - gen = s; - } - } - - if(spec) - s = spec; - else if(gen) - s = gen; - else - goto drop; - - if(s->curlog > s->backlog) - goto reset; - - new = ipincoming(ifc, s); - if(new == 0) - goto reset; - - new->newcon = s; - new->ifc = s->ifc; - new->psrc = sp; - new->pdst = dp; - new->dst = nhgetl(ih->src); - - ic = &new->ilctl; - ic->state = Ilsyncee; - initseq += TK2MS(MACHP(0)->ticks); - ic->start = initseq & 0xffffff; - ic->next = ic->start+1; - ic->recvd = 0; - ic->rstart = nhgetl(ih->ilid); - ic->slowtime = Slowtime; - ic->rtt = Iltickms; - ic->querytime = Keepalivetime; - ic->deathtime = Keepalivetime; - ic->window = Defaultwin; - ilprocess(new, ih, bp); - - s->curlog++; - wakeup(&s->listenr); - return; - -drop: - freeb(bp); - return; -reset: - ilsendctl(0, ih, Ilclose, 0, 0); - freeb(bp); -} - -void -_ilprocess(Ipconv *s, Ilhdr *h, Block *bp) -{ - Ilcb *ic; - ulong id, ack; - - id = nhgetl(h->ilid); - ack = nhgetl(h->ilack); - ic = &s->ilctl; - - ic->querytime = Keepalivetime; - ic->deathtime = Keepalivetime; - switch(ic->state) { - default: - panic("il unknown state"); - case Ilclosed: - freeb(bp); - break; - case Ilsyncer: - switch(h->iltype) { - default: - break; - case Ilsync: - if(ack != ic->start) - ilhangup(s, "connection rejected"); - else { - ic->recvd = id; - ic->rstart = id; - ilsendctl(s, 0, Ilack, ic->next, ic->recvd); - ic->state = Ilestablished; - wakeup(&ic->syncer); - ilpullup(s); - Starttimer(ic); - } - break; - case Ilclose: - if(ack == ic->start) - ilhangup(s, "remote close"); - break; - } - freeb(bp); - break; - case Ilsyncee: - switch(h->iltype) { - default: - break; - case Ilsync: - if(id != ic->rstart || ack != 0) - ic->state = Ilclosed; - else { - ic->recvd = id; - ilsendctl(s, 0, Ilsync, ic->start, ic->recvd); - Starttimer(ic); - } - break; - case Ilack: - if(ack == ic->start) { - ic->state = Ilestablished; - ilpullup(s); - Starttimer(ic); - } - break; - case Ilclose: - if(id == ic->next) - ilhangup(s, "remote close"); - break; - } - freeb(bp); - break; - case Ilestablished: - switch(h->iltype) { - case Ilsync: - if(id != ic->rstart) - ilhangup(s, "remote close"); - else { - ilsendctl(s, 0, Ilack, ic->next, ic->rstart); - Starttimer(ic); - } - freeb(bp); - break; - case Ildata: - Starttimer(ic); - ilackto(ic, ack); - ic->acktime = Acktime; - iloutoforder(s, h, bp); - ilpullup(s); - break; - case Ildataquery: - Starttimer(ic); - ilackto(ic, ack); - ic->acktime = Acktime; - iloutoforder(s, h, bp); - ilpullup(s); - ilsendctl(s, 0, Ilstate, ic->next, ic->recvd); - break; - case Ilack: - ilackto(ic, ack); - Starttimer(ic); - freeb(bp); - break; - case Ilquerey: - ilackto(ic, ack); - ilsendctl(s, 0, Ilstate, ic->next, ic->recvd); - Starttimer(ic); - freeb(bp); - break; - case Ilstate: - ilackto(ic, ack); - ilrexmit(ic); - Starttimer(ic); - freeb(bp); - break; - case Ilclose: - freeb(bp); - if(ack < ic->start || ack > ic->next) - break; - ilsendctl(s, 0, Ilclose, ic->next, ic->recvd); - ic->state = Ilclosing; - ilfreeq(ic); - Starttimer(ic); - break; - } - break; - case Illistening: - freeb(bp); - break; - case Ilclosing: - switch(h->iltype) { - case Ilclose: - ic->recvd = id; - ilsendctl(s, 0, Ilclose, ic->next, ic->recvd); - if(ack == ic->next) - ilhangup(s, 0); - Starttimer(ic); - break; - default: - break; - } - freeb(bp); - break; - } -} - -void -ilrexmit(Ilcb *ic) -{ - Block *nb; - Ilhdr *h; - - nb = 0; - qlock(&ic->ackq); - if(ic->unacked) - nb = copyb(ic->unacked, blen(ic->unacked)); - qunlock(&ic->ackq); - - if(nb == 0) - return; - - h = (Ilhdr*)nb->rptr; - DBG("rxmit %d.", nhgetl(h->ilid)); - - h->iltype = Ildataquery; - hnputl(h->ilack, ic->recvd); - h->ilsum[0] = 0; - h->ilsum[1] = 0; - if(ilcksum) - hnputs(h->ilsum, ptcl_csum(nb, IL_EHSIZE, nhgets(h->illen))); - - PUTNEXT(Ipoutput, nb); -} - -/* DEBUG */ -void -ilprocess(Ipconv *s, Ilhdr *h, Block *bp) -{ - Ilcb *ic = &s->ilctl; - - USED(ic); - DBG("%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ", - ilstate[ic->state], ic->rstart, ic->recvd, ic->start, ic->next, - iltype[h->iltype], nhgetl(h->ilid), nhgetl(h->ilack), - nhgets(h->ilsrc), nhgets(h->ildst)); - - _ilprocess(s, h, bp); - - DBG("%11s rcv %d snt %d\n", ilstate[ic->state], ic->recvd, ic->next); -} - -void -ilhangup(Ipconv *s, char *msg) -{ - Block *nb; - int l; - Ilcb *ic; - int callout; - - DBG("hangup! %s %d/%d\n", msg ? msg : "??", s->psrc, s->pdst); - - ic = &s->ilctl; - callout = ic->state == Ilsyncer; - ic->state = Ilclosed; - qlock(s); - if(s->readq) { - if(msg) { - l = strlen(msg); - nb = allocb(l); - strcpy((char*)nb->wptr, msg); - nb->wptr += l; - } - else - nb = allocb(0); - nb->type = M_HANGUP; - nb->flags |= S_DELIM; - PUTNEXT(s->readq, nb); - } - qunlock(s); - if(callout) - wakeup(&ic->syncer); - - s->psrc = 0; -} - -void -ilpullup(Ipconv *s) -{ - Ilcb *ic; - Ilhdr *oh; - Block *bp; - ulong oid, dlen; - - if(s->readq == 0) - return; - - ic = &s->ilctl; - if(ic->state != Ilestablished) - return; - - qlock(&ic->outo); - while(ic->outoforder) { - bp = ic->outoforder; - oh = (Ilhdr*)bp->rptr; - oid = nhgetl(oh->ilid); - if(oid <= ic->recvd) { - ic->outoforder = bp->list; - freeb(bp); - continue; - } - if(oid != ic->recvd+1) - break; - - ic->recvd = oid; - ic->outoforder = bp->list; - - qunlock(&ic->outo); - bp->list = 0; - dlen = nhgets(oh->illen)-IL_HDRSIZE; - bp = btrim(bp, IL_EHSIZE+IL_HDRSIZE, dlen); - PUTNEXT(s->readq, bp); - qlock(&ic->outo); - } - qunlock(&ic->outo); -} - -void -iloutoforder(Ipconv *s, Ilhdr *h, Block *bp) -{ - Block *f, **l; - Ilcb *ic; - ulong id; - uchar *lid; - - ic = &s->ilctl; - bp->list = 0; - - - id = nhgetl(h->ilid); - /* Window checks */ - if(id <= ic->recvd || id > ic->recvd+ic->window) { - freeb(bp); - return; - } - - /* Packet is acceptable so sort onto receive queue for pullup */ - qlock(&ic->outo); - if(ic->outoforder == 0) - ic->outoforder = bp; - else { - l = &ic->outoforder; - for(f = *l; f; f = f->list) { - lid = ((Ilhdr*)(f->rptr))->ilid; - if(id < nhgetl(lid)) { - bp->list = f; - *l = bp; - qunlock(&ic->outo); - return; - } - l = &f->list; - } - *l = bp; - } - qunlock(&ic->outo); -} - -void -ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, ulong id, ulong ack) -{ - Ilhdr *ih; - Ilcb *ic; - Block *bp; - - bp = allocb(IL_EHSIZE+IL_HDRSIZE); - bp->wptr += IL_EHSIZE+IL_HDRSIZE; - bp->flags |= S_DELIM; - - ih = (Ilhdr *)(bp->rptr); - ic = &ipc->ilctl; - - /* Ip fields */ - ih->proto = IP_ILPROTO; - hnputl(ih->src, Myip[Myself]); - hnputs(ih->illen, IL_HDRSIZE); - ih->frag[0] = 0; - ih->frag[1] = 0; - 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, id); - hnputl(ih->ilack, ack); - ic->acktime = Ackkeepalive; - } - ih->iltype = type; - ih->ilspec = 0; - ih->ilsum[0] = 0; - ih->ilsum[1] = 0; - - if(ilcksum) - hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, IL_HDRSIZE)); - -/* DBG("\nctl(%s id %d ack %d %d->%d)\n", - iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack), - nhgets(ih->ilsrc), nhgets(ih->ildst)); -*/ - PUTNEXT(Ipoutput, bp); -} - -void -ilackproc(void *a) -{ - Ipifc *ifc; - Ipconv **base, **p, **end, *s; - Ilcb *ic; - - ifc = (Ipifc*)a; - base = ifc->conv; - end = &base[Nipconv]; - - for(;;) { - tsleep(&ilackr, return0, 0, Iltickms); - for(p = base; p < end && *p; p++) { - s = *p; - ic = &s->ilctl; - ic->timeout += Iltickms; - switch(ic->state) { - case Ilclosed: - case Illistening: - break; - case Ilclosing: - if(ic->timeout >= ic->fasttime) { - ilsendctl(s, 0, Ilclose, ic->next, ic->recvd); - ilbackoff(ic); - } - if(ic->timeout >= ic->slowtime) - ilhangup(s, 0); - break; - case Ilsyncee: - case Ilsyncer: - if(ic->timeout >= ic->fasttime) { - ilsendctl(s, 0, Ilsync, ic->start, ic->recvd); - ilbackoff(ic); - } - if(ic->timeout >= ic->slowtime) - ilhangup(s, etime); - break; - case Ilestablished: - ic->acktime -= Iltickms; - if(ic->acktime <= 0) - ilsendctl(s, 0, Ilack, ic->next, ic->recvd); - - ic->querytime -= Iltickms; - if(ic->querytime <= 0){ - ic->deathtime -= Querytime; - if(ic->deathtime < 0){ - ilhangup(s, etime); - break; - } - ilsendctl(s, 0, Ilquerey, ic->next, ic->recvd); - ic->querytime = Querytime; - } - if(ic->unacked == 0) { - ic->timeout = 0; - break; - } - if(ic->timeout >= ic->fasttime) { - ilrexmit(ic); - ilbackoff(ic); - } - if(ic->timeout >= ic->slowtime) { - ilhangup(s, etime); - break; - } - break; - } - } - } -} - -void -ilbackoff(Ilcb *ic) -{ - if(ic->fasttime < Slowtime/2) - ic->fasttime += Fasttime; - else - ic->fasttime = (ic->fasttime)*3/2; -} - -static int -notsyncer(void *ic) -{ - Ilcb *i; - - i = ic; - return i->state != Ilsyncer; -} - -void -ilstart(Ipconv *ipc, int type, int window) -{ - Ilcb *ic = &ipc->ilctl; - - if(ic->state != Ilclosed) - return; - - ic->unacked = 0; - ic->outoforder = 0; - ic->slowtime = Slowtime; - ic->rtt = Iltickms; - Starttimer(ic); - - initseq += TK2MS(MACHP(0)->ticks); - ic->start = initseq & 0xffffff; - ic->next = ic->start+1; - ic->recvd = 0; - ic->window = window; - - switch(type) { - case IL_PASSIVE: - ic->state = Illistening; - break; - case IL_ACTIVE: - ic->state = Ilsyncer; - ilsendctl(ipc, 0, Ilsync, ic->start, ic->recvd); - sleep(&ic->syncer, notsyncer, ic); - if(ic->state == Ilclosed) - error(Etimedout); - break; - } -} - -void -ilfreeq(Ilcb *ic) -{ - Block *bp, *next; - - qlock(&ic->ackq); - for(bp = ic->unacked; bp; bp = next) { - next = bp->list; - freeb(bp); - } - ic->unacked = 0; - qunlock(&ic->ackq); - - qlock(&ic->outo); - for(bp = ic->outoforder; bp; bp = next) { - next = bp->list; - freeb(bp); - } - ic->outoforder = 0; - qunlock(&ic->outo); -} diff --git a/port/stip.c b/port/stip.c deleted file mode 100644 index 2c0c2bd696984b04362134078616ac7e0779e4c3..0000000000000000000000000000000000000000 --- a/port/stip.c +++ /dev/null @@ -1,635 +0,0 @@ -/* - * ethernet specific multiplexor for ip - * - * this line discipline gets pushed onto an ethernet channel - * to demultiplex/multiplex ip conversations. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -#define DPRINT if(pip)print -int pip = 0; -int ipcksum = 1; -int Id = 1; - -Fragq *flisthead; -Fragq *fragfree; -QLock fraglock; - -Queue *Etherq; - -Ipaddr Myip[7]; -Ipaddr Mymask; -Ipaddr Mynetmask; -uchar Netmyip[4]; /* In Network byte order */ -uchar bcast[4] = { 0xff, 0xff, 0xff, 0xff }; - -/* Predeclaration */ -static void ipetherclose(Queue*); -static void ipetheriput(Queue*, Block*); -static void ipetheropen(Queue*, Stream*); -static void ipetheroput(Queue*, Block*); - -/* - * the ethernet multiplexor stream module definition - */ -Qinfo ipinfo = -{ - ipetheriput, - ipetheroput, - ipetheropen, - ipetherclose, - "internet" -}; - -void -initfrag(int size) -{ - Fragq *fq, *eq; - - fragfree = (Fragq*)xalloc(sizeof(Fragq) * size); - - eq = &fragfree[size]; - for(fq = fragfree; fq < eq; fq++) - fq->next = fq+1; - - fragfree[size-1].next = 0; -} - -/* - * set up an ether interface - */ -static void -ipetheropen(Queue *q, Stream *s) -{ - Ipconv *ipc; - - /* First open is by ipconfig and sets up channel - * to ethernet - */ - if(!Etherq) { - Etherq = WR(q); - s->opens++; /* Hold this queue in place */ - s->inuse++; - ipsetaddrs(); - } else { - ipc = ipcreateconv(ipifc[s->dev], s->id); - RD(q)->ptr = (void *)ipc; - WR(q)->ptr = (void *)ipc; - ipc->ref = 1; - } - - DPRINT("ipetheropen EQ %lux dev=%d id=%d RD %lux WR %lux\n", - Etherq, s->dev, s->id, RD(q), WR(q)); -} - -/* - * initipifc - set parameters of an ip protocol interface - */ -void -initipifc(Ipifc *ifc, uchar ptcl, void (*recvfun)(Ipifc*, Block *bp), int max, - int min, int hdrsize) -{ - qlock(ifc); - ifc->iprcv = recvfun; - - /* If media supports large transfer units limit maxmtu - * to max ip size */ - if(max > IP_MAX) - max = IP_MAX; - ifc->maxmtu = max; - ifc->minmtu = min; - ifc->hsize = hdrsize; - - ifc->protocol = ptcl; - ifc->inited = 1; - - qunlock(ifc); -} - -static void -ipetherclose(Queue *q) -{ - Ipconv *ipc; - - ipc = (Ipconv *)(q->ptr); - if(ipc){ - netdisown(ipc); - ipc->ref = 0; - } -} - -static void -ipetheroput(Queue *q, Block *bp) -{ - Etherhdr *eh, *feh; - int lid, len, seglen, chunk, dlen, blklen, offset; - Ipifc *ifp; - ushort fragoff; - Block *xp, *nb; - uchar *ptr; - - if(bp->type != M_DATA){ - /* Allow one setting of the ip address */ - if(streamparse("setip", bp)) { - if(strncmp(eve, up->user, sizeof(eve)) != 0) - error(Eperm); - ptr = bp->rptr; - Myip[Myself] = ipparse((char *)ptr); - Netmyip[0] = (Myip[Myself]>>24)&0xff; - Netmyip[1] = (Myip[Myself]>>16)&0xff; - Netmyip[2] = (Myip[Myself]>>8)&0xff; - Netmyip[3] = Myip[Myself]&0xff; - Mymask = classmask[Myip[Myself]>>30]; - while(*ptr != ' ' && *ptr) - ptr++; - if(*ptr) - Mynetmask = ipparse((char *)ptr); - else - Mynetmask = Mymask; - freeb(bp); - ipsetaddrs(); - } - else - PUTNEXT(Etherq, bp); - return; - } - - ifp = (Ipifc *)(q->ptr); - - /* Number of bytes in ip and media header to write */ - len = blen(bp); - - /* Fill out the ip header */ - eh = (Etherhdr *)(bp->rptr); - eh->vihl = IP_VER|IP_HLEN; - eh->tos = 0; - eh->ttl = 255; - - /* If we dont need to fragment just send it */ - if(len <= ifp->maxmtu) { - hnputs(eh->length, len-ETHER_HDR); - hnputs(eh->id, Id++); - eh->frag[0] = 0; - eh->frag[1] = 0; - eh->cksum[0] = 0; - eh->cksum[1] = 0; - hnputs(eh->cksum, ip_csum(&eh->vihl)); - - /* Finally put in the type and pass down to the arp layer */ - hnputs(eh->type, ET_IP); - PUTNEXT(Etherq, bp); - return; - } - - if(eh->frag[0] & (IP_DF>>8)) - goto drop; - - seglen = (ifp->maxmtu - (ETHER_HDR+ETHER_IPHDR)) & ~7; - if(seglen < 8) - goto drop; - - /* Make prototype output header */ - hnputs(eh->type, ET_IP); - - dlen = len - (ETHER_HDR+ETHER_IPHDR); - xp = bp; - lid = Id++; - - offset = ETHER_HDR+ETHER_IPHDR; - while(xp && offset && offset >= BLEN(xp)) { - offset -= BLEN(xp); - xp = xp->next; - } - xp->rptr += offset; - - for(fragoff = 0; fragoff < dlen; fragoff += seglen) { - nb = allocb(ETHER_HDR+ETHER_IPHDR+seglen); - feh = (Etherhdr *)(nb->rptr); - - memmove(nb->wptr, eh, ETHER_HDR+ETHER_IPHDR); - nb->wptr += ETHER_HDR+ETHER_IPHDR; - - if((fragoff + seglen) >= dlen) { - seglen = dlen - fragoff; - hnputs(feh->frag, fragoff>>3); - } - else { - hnputs(feh->frag, (fragoff>>3)|IP_MF); - } - - hnputs(feh->length, seglen + ETHER_IPHDR); - hnputs(feh->id, lid); - - /* Copy up the data area */ - chunk = seglen; - while(chunk) { - if(!xp) { - freeb(nb); - goto drop; - } - blklen = MIN(BLEN(xp), chunk); - memmove(nb->wptr, xp->rptr, blklen); - nb->wptr += blklen; - xp->rptr += blklen; - chunk -= blklen; - if(xp->rptr == xp->wptr) - xp = xp->next; - } - - feh->cksum[0] = 0; - feh->cksum[1] = 0; - hnputs(feh->cksum, ip_csum(&feh->vihl)); - nb->flags |= S_DELIM; - PUTNEXT(Etherq, nb); - } -drop: - freeb(bp); -} - - -/* - * Input a packet and use the ip protocol to select the correct - * device to pass it to. - * - */ -static void -ipetheriput(Queue *q, Block *bp) -{ - Ipifc *ifc, **ifp; - Etherhdr *h; - ushort frag; - - if(bp->type != M_DATA){ - PUTNEXT(q, bp); - return; - } - - h = (Etherhdr *)(bp->rptr); - - /* Ensure we have enough data to process */ - if(BLEN(bp) < (ETHER_HDR+ETHER_IPHDR)) { - bp = pullup(bp, ETHER_HDR+ETHER_IPHDR); - if(bp == 0) - return; - } - - /* Look to see if its for me before we waste time checksuming it */ - if(ipforme(h->dst) == 0) - goto drop; - - - if(ipcksum && ip_csum(&h->vihl)) { - print("ip: checksum error (from %d.%d.%d.%d ?)\n", - h->src[0], h->src[1], h->src[2], h->src[3]); - goto drop; - } - - /* Check header length and version */ - if(h->vihl != (IP_VER|IP_HLEN)) - goto drop; - - frag = nhgets(h->frag); - if(frag) { - h->tos = frag & IP_MF ? 1 : 0; - bp = ip_reassemble(frag, bp, h); - if(!bp) - return; - } - - /* - * Look for an ip interface attached to this protocol - */ - for(ifp = ipifc; ; ifp++){ - ifc = *ifp; - if(ifc == 0) - break; - if(ifc->protocol == h->proto) { - (*ifc->iprcv)(ifc, bp); - return; - } - } - -drop: - freeb(bp); -} - -void -ipsetaddrs(void) -{ - Myip[Mybcast] = ~0; /* local broadcast */ - Myip[2] = 0; /* local broadcast - old */ - Myip[Mysubnet] = Myip[Myself] | ~Mynetmask; /* subnet broadcast */ - Myip[Mysubnet+1] = Myip[Myself] & Mynetmask; /* subnet broadcast - old */ - Myip[Mynet] = Myip[Myself] | ~Mymask; /* net broadcast */ - Myip[Mynet+1] = Myip[Myself] & Mymask; /* net broadcast - old */ -} - -int -ipforme(uchar *addr) -{ - Ipaddr haddr; - Ipaddr *p; - - haddr = nhgetl(addr); - - /* try my address plus all the forms of ip broadcast */ - for(p = Myip; p < &Myip[7]; p++) - if(haddr == *p); - return 1; - - /* if we haven't set an address yet, accept anything we get */ - if(Myip[Myself] == 0) - return 1; - - return 0; -} - -typedef struct Fragstat Fragstat; -struct Fragstat -{ - ulong prev; - ulong prevall; - ulong succ; - ulong succall; -}; -Fragstat fragstat; - -Block * -ip_reassemble(int offset, Block *bp, Etherhdr *ip) -{ - Fragq *f; - Ipaddr src, dst; - ushort id; - Block *bl, **l, *last, *prev; - int ovlap, len, fragsize, pktposn; - int end; - - /* Check ethrnet has handed us a contiguous buffer */ - if(bp->next) - panic("ip: reass ?"); - - src = nhgetl(ip->src); - dst = nhgetl(ip->dst); - id = nhgets(ip->id); - - /* - * find a reassembly queue for this fragment - */ - qlock(&fraglock); - for(f = flisthead; f; f = f->next) - if(f->src == src && f->dst == dst && f->id == id) - break; - qunlock(&fraglock); - - /* - * if this isn't a fragmented packet, accept it - * and get rid of any fragments that might go - * with it. - */ - if(!ip->tos && (offset & ~(IP_MF|IP_DF)) == 0) { - if(f != 0) { - qlock(f); - ipfragfree(f, 1); - } - return bp; - } - - BLKFRAG(bp)->foff = offset<<3; - BLKFRAG(bp)->flen = nhgets(ip->length) - ETHER_IPHDR; /* Ip data length */ - bp->flags &= ~S_DELIM; - - /* First fragment allocates a reassembly queue */ - if(f == 0) { - f = ipfragallo(); - qlock(f); - f->id = id; - f->src = src; - f->dst = dst; - - f->blist = bp; - - qunlock(f); - return 0; - } - qlock(f); - - /* - * find the new fragment's position in the queue - */ - prev = 0; - l = &f->blist; - for(bl = f->blist; bl && BLKFRAG(bp)->foff > BLKFRAG(bl)->foff; bl = bl->next) { - prev = bl; - l = &bl->next; - } - - /* Check overlap of a previous fragment - trim away as necessary */ - if(prev) { - ovlap = BLKFRAG(prev)->foff + BLKFRAG(prev)->flen - BLKFRAG(bp)->foff; - if(ovlap > 0) { - fragstat.prev++; - if(ovlap >= BLKFRAG(bp)->flen) { - fragstat.prevall++; - freeb(bp); - qunlock(f); - return 0; - } - BLKFRAG(prev)->flen -= ovlap; - } - } - - /* Link onto assembly queue */ - bp->next = *l; - *l = bp; - - /* Check to see if succeeding segments overlap */ - if(bp->next) { - l = &bp->next; - end = BLKFRAG(bp)->foff + BLKFRAG(bp)->flen; - /* Take completely covered segements out */ - while(*l){ - ovlap = end - BLKFRAG(*l)->foff; - if(ovlap <= 0) - break; - fragstat.succ++; - if(ovlap < BLKFRAG(*l)->flen) { - fragstat.succall++; - BLKFRAG(*l)->flen -= ovlap; - BLKFRAG(*l)->foff += ovlap; - /* move up ether+ip hdrs */ - memmove((*l)->rptr + ovlap, (*l)->rptr, - ETHER_HDR+ETHER_IPHDR); - (*l)->rptr += ovlap; - break; - } - last = (*l)->next; - (*l)->next = 0; - freeb(*l); - *l = last; - } - } - - /* - * look for a complete packet. if we get to a fragment - * without IP_MF set, we're done. - */ - pktposn = 0; - for(bl = f->blist; bl; bl = bl->next) { - if(BLKFRAG(bl)->foff != pktposn) - break; - if((BLKIP(bl)->frag[0]&(IP_MF>>8)) == 0) - goto complete; - - pktposn += BLKFRAG(bl)->flen; - } - qunlock(f); - return 0; - -complete: - bl = f->blist; - last = bl; - len = nhgets(BLKIP(bl)->length); - bl->wptr = bl->rptr + len + ETHER_HDR; - - /* Pullup all the fragment headers and return a complete packet */ - for(bl = bl->next; bl; bl = bl->next) { - fragsize = BLKFRAG(bl)->flen; - len += fragsize; - bl->rptr += (ETHER_HDR+ETHER_IPHDR); - bl->wptr = bl->rptr + fragsize; - last = bl; - } - - last->flags |= S_DELIM; - bl = f->blist; - f->blist = 0; - ipfragfree(f, 1); - - ip = BLKIP(bl); - hnputs(ip->length, len); - - return(bl); -} - -/* - * ipfragfree - Free a list of fragments, fragment list must be locked - */ - -void -ipfragfree(Fragq *frag, int lockq) -{ - Fragq *fl, **l; - - if(frag->blist) - freeb(frag->blist); - - frag->src = 0; - frag->id = 0; - frag->blist = 0; - qunlock(frag); - - if(lockq) - qlock(&fraglock); - - l = &flisthead; - for(fl = *l; fl; fl = fl->next) { - if(fl == frag) { - *l = frag->next; - break; - } - l = &fl->next; - } - - frag->next = fragfree; - fragfree = frag; - - if(lockq) - qunlock(&fraglock); -} - -/* - * ipfragallo - allocate a reassembly queue - */ -Fragq * -ipfragallo(void) -{ - Fragq *f; - - qlock(&fraglock); - while(fragfree == 0) { - for(f = flisthead; f; f = f->next) - if(canqlock(f)) { - ipfragfree(f, 0); - break; - } - } - f = fragfree; - fragfree = f->next; - f->next = flisthead; - flisthead = f; - f->age = TK2MS(MACHP(0)->ticks) + 30000; - - qunlock(&fraglock); - return f; -} - -/* - * ip_csum - Compute internet header checksums - */ -ushort -ip_csum(uchar *addr) -{ - int len; - ulong sum = 0; - - len = (addr[0]&0xf)<<2; - - while(len > 0) { - sum += addr[0]<<8 | addr[1] ; - len -= 2; - addr += 2; - } - - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - return (sum^0xffff); -} - -/* - * ipparse - Parse an ip address out of a string - */ - -Ipaddr classmask[4] = { - 0xff000000, - 0xff000000, - 0xffff0000, - 0xffffff00 -}; - -Ipaddr -ipparse(char *ipa) -{ - Ipaddr address = 0; - int shift; - Ipaddr net; - - shift = 24; - - while(shift >= 0 && ipa != (char *)1) { - address |= atoi(ipa) << shift; - shift -= 8; - ipa = strchr(ipa, '.')+1; - } - net = address & classmask[address>>30]; - - shift += 8; - return net | ((address & ~classmask[address>>30])>>shift); -} diff --git a/port/streboot.c b/port/streboot.c deleted file mode 100644 index 536c60e822cb6bbd10e55d392635e1a722973336..0000000000000000000000000000000000000000 --- a/port/streboot.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -/* - * reboot stream module definition - */ -static void rebootopen(Queue*, Stream*); -static void rebootiput(Queue*, Block*); -static void rebootoput(Queue*, Block*); -static void rebootreset(void); -Qinfo rebootinfo = -{ - rebootiput, - rebootoput, - rebootopen, - 0, - "reboot", - 0 -}; - -static void -rebootopen(Queue *q, Stream *s) -{ - USED(q); - USED(s); - if(strcmp(up->user, eve) != 0) - error(Eperm); -} - -void -rebootoput(Queue *q, Block *bp) -{ - PUTNEXT(q, bp); -} - -static void -rebootiput(Queue *q, Block *bp) -{ - if(bp->type == M_HANGUP){ - print("lost connection to fs, rebooting"); - exit(0); - } - PUTNEXT(q, bp); -} diff --git a/port/stsplice.c b/port/stsplice.c deleted file mode 100644 index f5de37dabd88805f33f1ebcb276d12f46f73a01a..0000000000000000000000000000000000000000 --- a/port/stsplice.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define splicedebug 1 - -#define DPRINT if(splicedebug)kprint - -/* - * Splice line discipline. - */ - -static void spliceopen(Queue*, Stream*); -static void spliceclose(Queue*); -static void spliceoput(Queue*, Block*); -static void spliceiput(Queue*, Block*); -Qinfo spliceinfo = -{ - spliceiput, - spliceoput, - spliceopen, - spliceclose, - "splice" -}; - -static void -spliceopen(Queue *q, Stream *s) -{ - DPRINT("spliceopen q=0x%ux s=0x%ux\n", q, s); - - WR(q)->ptr = s; /* pointer to ourselves */ - RD(q)->ptr = 0; /* pointer to other side */ -} - -static void -spliceclose(Queue *q) -{ - DPRINT("spliceclose q=0x%ux us=0x%ux them=0x%ux\n", - q, WR(q)->ptr, RD(q)->ptr); - - RD(q)->ptr = 0; - WR(q)->ptr = 0; -} - -static void -spliceoput(Queue *q, Block *bp) -{ - int fd; - Chan *c; - Stream *s; - - if(bp->type != M_CTL){ - PUTNEXT(q, bp); - return; - } - fd = strtol((char *)bp->rptr, 0, 0); - freeb(bp); - if(RD(q)->ptr) - error("stream already spliced"); - c = fdtochan(fd, ORDWR, 0, 0); - s = c->stream; - if(s == 0) - error("splice attempt on non-stream"); - pushq(s, &spliceinfo); - RD(q)->ptr = s; - RD(s->procq->next)->ptr = WR(q)->ptr; -} - -static void -spliceiput(Queue *q, Block *bp) -{ - if(bp->type == M_HANGUP) - PUTNEXT(q, bp); - else - FLOWCTL(((Stream *)q->ptr)->procq, bp); -} diff --git a/port/sturp.c b/port/sturp.c deleted file mode 100644 index 2ad25375e7d01f2224f264314601de01e14bdf76..0000000000000000000000000000000000000000 --- a/port/sturp.c +++ /dev/null @@ -1,1072 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -enum { - MSrexmit= 1000, - Nmask= 0x7, -}; - -#define DPRINT if(q->flag&QDEBUG)kprint - -typedef struct Urp Urp; - -#define NOW (MACHP(0)->ticks*MS2HZ) - -/* - * URP status - */ -struct urpstat { - ulong input; /* bytes read from urp */ - ulong output; /* bytes output to urp */ - ulong rexmit; /* retransmit rejected urp msg */ - ulong rjtrs; /* reject, trailer size */ - ulong rjpks; /* reject, packet size */ - ulong rjseq; /* reject, sequence number */ - ulong levelb; /* unknown level b */ - ulong enqsx; /* enqs sent */ - ulong enqsr; /* enqs rcved */ -} urpstat; - -struct Urp { - QLock; - Urp *list; /* list of all urp structures */ - short state; /* flags */ - Rendez r; /* process waiting for output to finish */ - - /* input */ - QLock ack; /* ack lock */ - Queue *rq; /* input queue */ - uchar iseq; /* last good input sequence number */ - uchar lastecho; /* last echo/rej sent */ - uchar trbuf[3]; /* trailer being collected */ - short trx; /* # bytes in trailer being collected */ - int blocks; - - /* output */ - QLock xmit; /* output lock, only one process at a time */ - Queue *wq; /* output queue */ - int maxout; /* maximum outstanding unacked blocks */ - int maxblock; /* max block size */ - int next; /* next block to send */ - int unechoed; /* first unechoed block */ - int unacked; /* first unacked block */ - int nxb; /* next xb to use */ - Block *xb[8]; /* the xmit window buffer */ - QLock xl[8]; - ulong timer; /* timeout for xmit */ - int rexmit; -}; - -/* list of allocated urp structures (never freed) */ -struct -{ - Lock; - Urp *urp; -} urpalloc; - -Rendez urpkr; -QLock urpkl; -int urpkstarted; - -#define WINDOW(u) ((u)->unechoed>(u)->next ? (u)->unechoed+(u)->maxout-(u)->next-8 :\ - (u)->unechoed+(u)->maxout-(u)->next) -#define IN(x, f, n) (f<=n ? (x>=f && x=f)) -#define NEXT(x) (((x)+1)&Nmask) - -/* - * Protocol control bytes - */ -#define SEQ 0010 /* sequence number, ends trailers */ -#undef ECHO -#define ECHO 0020 /* echos, data given to next queue */ -#define REJ 0030 /* rejections, transmission error */ -#define ACK 0040 /* acknowledgments */ -#define BOT 0050 /* beginning of trailer */ -#define BOTM 0051 /* beginning of trailer, more data follows */ -#define BOTS 0052 /* seq update algorithm on this trailer */ -#define SOU 0053 /* start of unsequenced trailer */ -#define EOU 0054 /* end of unsequenced trailer */ -#define ENQ 0055 /* xmitter requests flow/error status */ -#define CHECK 0056 /* xmitter requests error status */ -#define INITREQ 0057 /* request initialization */ -#define INIT0 0060 /* disable trailer processing */ -#define INIT1 0061 /* enable trailer procesing */ -#define AINIT 0062 /* response to INIT0/INIT1 */ -#undef DELAY -#define DELAY 0100 /* real-time printing delay */ -#define BREAK 0110 /* Send/receive break (new style) */ - -#define REJECTING 0x1 -#define INITING 0x2 -#define HUNGUP 0x4 -#define OPEN 0x8 -#define CLOSING 0x10 - -/* - * predeclared - */ -static void urpreset(void); -static void urpciput(Queue*, Block*); -static void urpiput(Queue*, Block*); -static void urpoput(Queue*, Block*); -static void urpopen(Queue*, Stream*); -static void urpclose(Queue *); -static void output(Urp*); -static void sendblock(Urp*, int); -static void rcvack(Urp*, int); -static void flushinput(Urp*); -static void sendctl(Urp*, int); -static void sendack(Urp*); -static void sendrej(Urp*); -static void initoutput(Urp*, int); -static void initinput(Urp*); -static void urpkproc(void *arg); -static void urpvomit(char*, Urp*); -static void tryoutput(Urp*); - -Qinfo urpinfo = -{ - urpciput, - urpoput, - urpopen, - urpclose, - "urp", - urpreset -}; - -static void -urpreset(void) -{ -} - -static void -urpopen(Queue *q, Stream *s) -{ - Urp *urp; - - USED(s); - if(!urpkstarted){ - qlock(&urpkl); - if(!urpkstarted){ - urpkstarted = 1; - kproc("urpkproc", urpkproc, 0); - } - qunlock(&urpkl); - } - - /* - * find an unused urp structure - */ - for(urp = urpalloc.urp; urp; urp = urp->list){ - if(urp->state == 0){ - qlock(urp); - if(urp->state == 0) - break; - qunlock(urp); - } - } - if(urp == 0){ - /* - * none available, create a new one, they are never freed - */ - urp = smalloc(sizeof(Urp)); - qlock(urp); - lock(&urpalloc); - urp->list = urpalloc.urp; - urpalloc.urp = urp; - unlock(&urpalloc); - } - q->ptr = q->other->ptr = urp; - q->rp = &urpkr; - urp->rq = q; - urp->wq = q->other; - urp->state = OPEN; - qunlock(urp); - initinput(urp); - initoutput(urp, 0); -} - -/* - * Shut down the connection and kill off the kernel process - */ -static int -isflushed(void *a) -{ - Urp *urp; - - urp = (Urp *)a; - return (urp->state&HUNGUP) || (urp->unechoed==urp->nxb && urp->wq->len==0); -} -static void -urpclose(Queue *q) -{ - Urp *urp; - int i; - - urp = (Urp *)q->ptr; - if(urp == 0) - return; - - /* - * wait for all outstanding messages to drain, tell kernel - * process we're closing. - * - * if 2 minutes elapse, give it up - */ - urp->state |= CLOSING; - if(!waserror()){ - tsleep(&urp->r, isflushed, urp, 2*60*1000); - poperror(); - } - urp->state |= HUNGUP; - - qlock(&urp->xmit); - /* - * ack all outstanding messages - */ - i = urp->next - 1; - if(i < 0) - i = 7; - rcvack(urp, ECHO+i); - - /* - * free all staged but unsent messages - */ - for(i = 0; i < 7; i++) - if(urp->xb[i]){ - freeb(urp->xb[i]); - urp->xb[i] = 0; - } - qunlock(&urp->xmit); - - qlock(urp); - urp->state = 0; - qunlock(urp); -} - -/* - * upstream control messages - */ -static void -urpctliput(Urp *urp, Queue *q, Block *bp) -{ - switch(bp->type){ - case M_HANGUP: - urp->state |= HUNGUP; - wakeup(&urp->r); - break; - } - PUTNEXT(q, bp); -} - -/* - * character mode input. - * - * the first byte in every message is a ctl byte (which belongs at the end). - */ -void -urpciput(Queue *q, Block *bp) -{ - Urp *urp; - int i; - int ctl; - - urp = (Urp *)q->ptr; - if(urp == 0) - return; - if(bp->type != M_DATA){ - urpctliput(urp, q, bp); - return; - } - - /* - * get the control character - */ - ctl = *bp->rptr++; - if(ctl < 0) - return; - - /* - * take care of any data - */ - if(BLEN(bp)>0 && q->next->len<2*Streamhi && q->next->nb<2*Streambhi){ - bp->flags |= S_DELIM; - urpstat.input += BLEN(bp); - PUTNEXT(q, bp); - } else - freeb(bp); - - /* - * handle the control character - */ - switch(ctl){ - case 0: - break; - case ENQ: - DPRINT("rENQ(c)\n"); - urpstat.enqsr++; - sendctl(urp, urp->lastecho); - sendctl(urp, ACK+urp->iseq); - break; - - case CHECK: - DPRINT("rCHECK(c)\n"); - sendctl(urp, ACK+urp->iseq); - break; - - case AINIT: - DPRINT("rAINIT(c)\n"); - urp->state &= ~INITING; - flushinput(urp); - tryoutput(urp); - break; - - case INIT0: - case INIT1: - DPRINT("rINIT%d(c)\n", ctl-INIT0); - sendctl(urp, AINIT); - if(ctl == INIT1) - q->put = urpiput; - initinput(urp); - break; - - case INITREQ: - DPRINT("rINITREQ(c)\n"); - initoutput(urp, 0); - break; - - case BREAK: - break; - - case REJ+0: case REJ+1: case REJ+2: case REJ+3: - case REJ+4: case REJ+5: case REJ+6: case REJ+7: - DPRINT("rREJ%d(c)\n", ctl-REJ); - rcvack(urp, ctl); - break; - - case ACK+0: case ACK+1: case ACK+2: case ACK+3: - case ACK+4: case ACK+5: case ACK+6: case ACK+7: - case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3: - case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7: - DPRINT("%s%d(c)\n", (ctl&ECHO)?"rECHO":"rACK", ctl&7); - rcvack(urp, ctl); - break; - - case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3: - case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: - DPRINT("rSEQ%d(c)\n", ctl-SEQ); - qlock(&urp->ack); - i = ctl & Nmask; - if(!QFULL(q->next)) - sendctl(urp, urp->lastecho = ECHO+i); - urp->iseq = i; - qunlock(&urp->ack); - break; - } -} - -/* - * block mode input. - * - * the first byte in every message is a ctl byte (which belongs at the end). - * - * Simplifying assumption: one put == one message && the control byte - * is in the first block. If this isn't true, strange bytes will be - * used as control bytes. - * - * There's no input lock. The channel could be closed while we're - * processing a message. - */ -void -urpiput(Queue *q, Block *bp) -{ - Urp *urp; - int i, len; - int ctl; - - urp = (Urp *)q->ptr; - if(urp == 0) - return; - if(bp->type != M_DATA){ - urpctliput(urp, q, bp); - return; - } - - /* - * get the control character - */ - ctl = *bp->rptr++; - - /* - * take care of any block count(trx) - */ - while(urp->trx){ - if(BLEN(bp)<=0) - break; - switch (urp->trx) { - case 1: - case 2: - urp->trbuf[urp->trx++] = *bp->rptr++; - continue; - default: - urp->trx = 0; - break; - } - } - - /* - * queue the block(s) - */ - if(BLEN(bp) > 0){ - bp->flags &= ~S_DELIM; - putq(q, bp); - if(q->len > 4*1024){ - flushinput(urp); - return; - } - } else - freeb(bp); - - /* - * handle the control character - */ - switch(ctl){ - case 0: - break; - case ENQ: - DPRINT("rENQ %d %uo %uo\n", urp->blocks, urp->lastecho, ACK+urp->iseq); - urp->blocks = 0; - urpstat.enqsr++; - sendctl(urp, urp->lastecho); - sendctl(urp, ACK+urp->iseq); - flushinput(urp); - break; - - case CHECK: - DPRINT("rCHECK\n"); - sendctl(urp, ACK+urp->iseq); - break; - - case AINIT: - DPRINT("rAINIT\n"); - urp->state &= ~INITING; - flushinput(urp); - tryoutput(urp); - break; - - case INIT0: - case INIT1: - DPRINT("rINIT%d\n", ctl-INIT0); - sendctl(urp, AINIT); - if(ctl == INIT0) - q->put = urpciput; - initinput(urp); - break; - - case INITREQ: - DPRINT("rINITREQ\n"); - initoutput(urp, 0); - break; - - case BREAK: - break; - - case BOT: - case BOTM: - case BOTS: - DPRINT("rBOT%c...", " MS"[ctl-BOT]); - urp->trx = 1; - urp->trbuf[0] = ctl; - break; - - case REJ+0: case REJ+1: case REJ+2: case REJ+3: - case REJ+4: case REJ+5: case REJ+6: case REJ+7: - DPRINT("rREJ%d\n", ctl-REJ); - rcvack(urp, ctl); - break; - - case ACK+0: case ACK+1: case ACK+2: case ACK+3: - case ACK+4: case ACK+5: case ACK+6: case ACK+7: - case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3: - case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7: - DPRINT("%s%d\n", (ctl&ECHO)?"rECHO":"rACK", ctl&7); - rcvack(urp, ctl); - break; - - /* - * if the sequence number is the next expected - * and the trailer length == 3 - * and the block count matches the bytes received - * then send the bytes upstream. - */ - case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3: - case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: - len = urp->trbuf[1] + (urp->trbuf[2]<<8); - DPRINT("rSEQ%d(%d,%d,%d)...", ctl-SEQ, urp->trx, len, q->len); - i = ctl & Nmask; - if(urp->trx != 3){ - urpstat.rjtrs++; - sendrej(urp); - break; - }else if(q->len != len){ - urpstat.rjpks++; - sendrej(urp); - break; - }else if(i != ((urp->iseq+1)&Nmask)){ - urpstat.rjseq++; - sendrej(urp); - break; - }else if(q->next->len > (3*Streamhi)/2 - || q->next->nb > (3*Streambhi)/2){ - DPRINT("next->len=%d, next->nb=%d\n", - q->next->len, q->next->nb); - flushinput(urp); - break; - } - DPRINT("accept %d\n", q->len); - - /* - * send data upstream - */ - if(q->first) { - if(urp->trbuf[0] != BOTM) - q->last->flags |= S_DELIM; - while(bp = getq(q)){ - urpstat.input += BLEN(bp); - PUTNEXT(q, bp); - } - } else { - bp = allocb(0); - if(urp->trbuf[0] != BOTM) - bp->flags |= S_DELIM; - PUTNEXT(q, bp); - } - urp->trx = 0; - - /* - * acknowledge receipt - */ - qlock(&urp->ack); - urp->iseq = i; - if(!QFULL(q->next)) - sendctl(urp, urp->lastecho = ECHO|i); - qunlock(&urp->ack); - break; - } -} - -/* - * downstream control - */ -static void -urpctloput(Urp *urp, Queue *q, Block *bp) -{ - char *fields[2]; - int outwin; - - switch(bp->type){ - case M_CTL: - if(streamparse("break", bp)){ - /* - * send a break as part of the data stream - */ - urpstat.output++; - bp->wptr = bp->lim; - bp->rptr = bp->wptr - 1; - *bp->rptr = BREAK; - putq(q, bp); - output(urp); - return; - } - if(streamparse("init", bp)){ - outwin = strtoul((char*)bp->rptr, 0, 0); - initoutput(urp, outwin); - freeb(bp); - return; - } - if(streamparse("debug", bp)){ - switch(getfields((char *)bp->rptr, fields, 2, ' ')){ - case 1: - if (strcmp(fields[0], "on") == 0) { - q->flag |= QDEBUG; - q->other->flag |= QDEBUG; - } - if (strcmp(fields[0], "off") == 0) { - q->flag &= ~QDEBUG; - q->other->flag &= ~QDEBUG; - } - } - freeb(bp); - return; - } - } - PUTNEXT(q, bp); -} - -/* - * accept data from a writer - */ -static void -urpoput(Queue *q, Block *bp) -{ - Urp *urp; - - urp = (Urp *)q->ptr; - - if(bp->type != M_DATA){ - urpctloput(urp, q, bp); - return; - } - - urpstat.output += BLEN(bp); - putq(q, bp); - output(urp); -} - -/* - * start output - */ -static void -output(Urp *urp) -{ - Block *bp, *nbp; - ulong now; - Queue *q; - int i; - - if(!canqlock(&urp->xmit)) - return; - - if(waserror()){ - print("urp output error\n"); - qunlock(&urp->xmit); - nexterror(); - } - - /* - * if still initing and it's time to rexmit, send an INIT1 - */ - now = NOW; - if(urp->state & INITING){ - if(now > urp->timer){ - q = urp->wq; - DPRINT("INITING timer (%d, %d): ", now, urp->timer); - sendctl(urp, INIT1); - urp->timer = now + MSrexmit; - } - goto out; - } - - /* - * fill the transmit buffers, `nxb' can never overtake `unechoed' - */ - q = urp->wq; - i = NEXT(urp->nxb); - if(i != urp->unechoed) { - for(bp = getq(q); bp && i!=urp->unechoed; i = NEXT(i)){ - if(urp->xb[urp->nxb] != 0) - urpvomit("output", urp); - if(BLEN(bp) > urp->maxblock){ - nbp = urp->xb[urp->nxb] = allocb(0); - nbp->rptr = bp->rptr; - nbp->wptr = bp->rptr = bp->rptr + urp->maxblock; - } else { - urp->xb[urp->nxb] = bp; - bp = getq(q); - } - urp->nxb = i; - } - if(bp) - putbq(q, bp); - } - - /* - * retransmit cruft - */ - if(urp->rexmit){ - /* - * if a retransmit is requested, move next back to - * the unacked blocks - */ - urpstat.rexmit++; - urp->rexmit = 0; - urp->next = urp->unacked; - } else if(urp->unechoed!=urp->next && NOW>urp->timer){ - /* - * if a retransmit time has elapsed since a transmit, - * send an ENQ - */ - DPRINT("OUTPUT timer (%d, %d): ", NOW, urp->timer); - urp->timer = NOW + MSrexmit; - urp->state &= ~REJECTING; - urpstat.enqsx++; - sendctl(urp, ENQ); - goto out; - } - - /* - * if there's a window open, push some blocks out - * - * the lock is to synchronize with acknowledges that free - * blocks. - */ - while(WINDOW(urp)>0 && urp->next!=urp->nxb){ - i = urp->next; - qlock(&urp->xl[i]); - if(waserror()){ - qunlock(&urp->xl[i]); - nexterror(); - } - sendblock(urp, i); - qunlock(&urp->xl[i]); - urp->next = NEXT(urp->next); - poperror(); - } -out: - qunlock(&urp->xmit); - poperror(); -} - -/* - * try output, this is called by an input process - */ -void -tryoutput(Urp *urp) -{ - if(!waserror()){ - output(urp); - poperror(); - } -} - -/* - * send a control byte, put the byte at the end of the allocated - * space in case a lower layer needs header room. - */ -static void -sendctl(Urp *urp, int ctl) -{ - Block *bp; - Queue *q; - - q = urp->wq; - if(QFULL(q->next)) - return; - bp = allocb(1); - bp->wptr = bp->lim; - bp->rptr = bp->lim-1; - *bp->rptr = ctl; - bp->flags |= S_DELIM; - DPRINT("sCTL %ulx\n", ctl); - PUTNEXT(q, bp); -} - -/* - * send a reject - */ -static void -sendrej(Urp *urp) -{ - Queue *q = urp->wq; - flushinput(urp); - qlock(&urp->ack); - if((urp->lastecho&~Nmask) == ECHO){ - DPRINT("REJ %d\n", urp->iseq); - sendctl(urp, urp->lastecho = REJ|urp->iseq); - } - qunlock(&urp->ack); -} - -/* - * send an acknowledge - */ -static void -sendack(Urp *urp) -{ - /* - * check the precondition for acking - */ - if(QFULL(urp->rq->next) || (urp->lastecho&Nmask)==urp->iseq) - return; - - if(!canqlock(&urp->ack)) - return; - - /* - * check again now that we've locked - */ - if(QFULL(urp->rq->next) || (urp->lastecho&Nmask)==urp->iseq){ - qunlock(&urp->ack); - return; - } - - /* - * send the ack - */ - { Queue *q = urp->wq; DPRINT("sendack: "); } - sendctl(urp, urp->lastecho = ECHO|urp->iseq); - qunlock(&urp->ack); -} - -/* - * send a block. - */ -static void -sendblock(Urp *urp, int bn) -{ - int n; - Queue *q; - Block *bp, *m, *nbp; - - q = urp->wq; - urp->timer = NOW + MSrexmit; - if(QFULL(q->next)) - return; - - /* - * message 1, the BOT and the data - */ - bp = urp->xb[bn]; - if(bp == 0) - return; - m = allocb(1); - m->rptr = m->lim - 1; - m->wptr = m->lim; - *m->rptr = (bp->flags & S_DELIM) ? BOT : BOTM; - nbp = allocb(0); - nbp->rptr = bp->rptr; - nbp->wptr = bp->wptr; - nbp->base = bp->base; - nbp->lim = bp->lim; - nbp->flags |= S_DELIM; - if(bp->type == M_CTL){ - PUTNEXT(q, nbp); - m->flags |= S_DELIM; - PUTNEXT(q, m); - } else { - m->next = nbp; - PUTNEXT(q, m); - } - - /* - * message 2, the block length and the SEQ - */ - m = allocb(3); - m->rptr = m->lim - 3; - m->wptr = m->lim; - n = BLEN(bp); - m->rptr[0] = SEQ | bn; - m->rptr[1] = n; - m->rptr[2] = n<<8; - m->flags |= S_DELIM; - PUTNEXT(q, m); - DPRINT("sb %d (%d)\n", bn, urp->timer); -} - -/* - * receive an acknowledgement - */ -static void -rcvack(Urp *urp, int msg) -{ - int seqno; - int next; - int i; - - seqno = msg&Nmask; - next = NEXT(seqno); - - /* - * release any acknowledged blocks - */ - if(IN(seqno, urp->unacked, urp->next)){ - for(; urp->unacked != next; urp->unacked = NEXT(urp->unacked)){ - i = urp->unacked; - qlock(&urp->xl[i]); - if(urp->xb[i]) - freeb(urp->xb[i]); - else - urpvomit("rcvack", urp); - urp->xb[i] = 0; - qunlock(&urp->xl[i]); - } - } - - switch(msg & 0370){ - case ECHO: - if(IN(seqno, urp->unechoed, urp->next)) { - urp->unechoed = next; - } - /* - * the next reject at the start of a window starts a - * retransmission. - */ - urp->state &= ~REJECTING; - break; - case REJ: - if(IN(seqno, urp->unechoed, urp->next)) - urp->unechoed = next; - /* - * ... FALL THROUGH ... - */ - case ACK: - /* - * start a retransmission if we aren't retransmitting - * and this is the start of a window. - */ - if(urp->unechoed==next && !(urp->state & REJECTING)){ - urp->state |= REJECTING; - urp->rexmit = 1; - } - break; - } - - tryoutput(urp); - if(urp->state & CLOSING) - wakeup(&urp->r); -} - -/* - * throw away any partially collected input - */ -static void -flushinput(Urp *urp) -{ - Block *bp; - - while (bp = getq(urp->rq)) - freeb(bp); - urp->trx = 0; -} - -/* - * initialize output - */ -static void -initoutput(Urp *urp, int window) -{ - int i; - - /* - * set output window - */ - urp->maxblock = window/4; - if(urp->maxblock < 64) - urp->maxblock = 64; - urp->maxblock -= 4; - urp->maxout = 4; - - /* - * set sequence varialbles - */ - urp->unechoed = 1; - urp->unacked = 1; - urp->next = 1; - urp->nxb = 1; - urp->rexmit = 0; - - /* - * free any outstanding blocks - */ - for(i = 0; i < 8; i++){ - qlock(&urp->xl[i]); - if(urp->xb[i]) - freeb(urp->xb[i]); - urp->xb[i] = 0; - qunlock(&urp->xl[i]); - } - - /* - * tell the other side we've inited - */ - urp->state |= INITING; - urp->timer = NOW + MSrexmit; - { Queue *q = urp->wq; DPRINT("initoutput (%d): ", urp->timer); } - sendctl(urp, INIT1); -} - -/* - * initialize input - */ -static void -initinput(Urp *urp) -{ - /* - * restart all sequence parameters - */ - urp->blocks = 0; - urp->trx = 0; - urp->iseq = 0; - urp->lastecho = ECHO+0; - flushinput(urp); -} - -static void -urpkproc(void *arg) -{ - Urp *urp; - - USED(arg); - - if(waserror()) - ; - - for(;;){ - for(urp = urpalloc.urp; urp; urp = urp->list){ - if(urp->state==0 || (urp->state&HUNGUP)) - continue; - if(!canqlock(urp)) - continue; - if(waserror()){ - qunlock(urp); - continue; - } - if(urp->state==0 || (urp->state&HUNGUP)){ - qunlock(urp); - poperror(); - continue; - } - if(urp->iseq!=(urp->lastecho&7) && !QFULL(urp->rq->next)) - sendack(urp); - output(urp); - qunlock(urp); - poperror(); - } - tsleep(&urpkr, return0, 0, 500); - } -} - -/* - * urp got very confused, complain - */ -static void -urpvomit(char *msg, Urp* urp) -{ - print("urpvomit: %s %ux next %d unechoed %d unacked %d nxb %d\n", - msg, urp, urp->next, urp->unechoed, urp->unacked, urp->nxb); - print("\txb: %ux %ux %ux %ux %ux %ux %ux %ux\n", - urp->xb[0], urp->xb[1], urp->xb[2], urp->xb[3], urp->xb[4], - urp->xb[5], urp->xb[6], urp->xb[7]); - print("\tiseq: %uo lastecho: %uo trx: %d trbuf: %uo %uo %uo\n", - urp->iseq, urp->lastecho, urp->trx, urp->trbuf[0], urp->trbuf[1], - urp->trbuf[2]); - print("\tupq: %ux %d %d\n", &urp->rq->next->r, urp->rq->next->nb, - urp->rq->next->len); -} - -void -urpfillstats(Chan *c, char *buf, int len) -{ - char b[256]; - - USED(c); - sprint(b, "in: %d\nout: %d\nrexmit: %d\nrjtrs: %d\nrjpks: %d\nrjseq: %d\nenqsx: %d\nenqsr: %d\n", - urpstat.input, urpstat.output, urpstat.rexmit, urpstat.rjtrs, - urpstat.rjpks, urpstat.rjseq, urpstat.enqsx, urpstat.enqsr); - strncpy(buf, b, len); -} diff --git a/port/tcpif.c b/port/tcpif.c deleted file mode 100644 index d5e75d486e3db0d3e9f887541580fd73bd5a3a38..0000000000000000000000000000000000000000 --- a/port/tcpif.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -extern int tcpdbg; -#define DPRINT if(tcpdbg) print - -void -tcpxstate(Ipconv *s, char oldstate, char newstate) -{ - int len; - Block *bp; - Tcpctl *tcb; - - if(oldstate == newstate) - return; - - tcb = &s->tcpctl; - switch(newstate) { - case Closed: - s->psrc = 0; /* This connection is toast */ - s->pdst = 0; - s->dst = 0; - - case Close_wait: /* Remote closes */ - if(s->err) { - len = strlen(s->err); - bp = allocb(len); - strcpy((char *)bp->wptr, s->err); - bp->wptr += len; - } - else - bp = allocb(0); - - bp->flags |= S_DELIM; - bp->type = M_HANGUP; - qlock(s); - if(waserror()) { - qunlock(s); - nexterror(); - } - if(s->readq == 0) { - if(newstate == Close_wait) - putb(&tcb->rcvq, bp); - else - freeb(bp); - } else - PUTNEXT(s->readq, bp); - poperror(); - qunlock(s); - break; - } - - if(oldstate == Syn_sent) - wakeup(&tcb->syner); -} - -static int -notsyner(void *ic) -{ - return ((Tcpctl*)ic)->state != Syn_sent; -} - -void -tcpstart(Ipconv *s, int mode, ushort window, char tos) -{ - Tcpctl *tcb; - - tcb = &s->tcpctl; - if(tcb->state != Closed) - return; - - init_tcpctl(s); - - tcb->window = window; - tcb->rcv.wnd = window; - tcb->tos = tos; - - switch(mode){ - case TCP_PASSIVE: - tcb->flags |= CLONE; - tcpsetstate(s, Listen); - break; - - case TCP_ACTIVE: - /* Send SYN, go into SYN_SENT state */ - tcb->flags |= ACTIVE; - qlock(tcb); - if(waserror()) { - qunlock(tcb); - nexterror(); - } - tcpsndsyn(tcb); - tcpsetstate(s, Syn_sent); - tcpoutput(s); - poperror(); - qunlock(tcb); - tsleep(&tcb->syner, notsyner, tcb, 120*1000); - if(tcb->state != Established && tcb->state != Syn_received) - error(Etimedout); - break; - } -} diff --git a/port/tcpinput.c b/port/tcpinput.c deleted file mode 100644 index 8ccfa69af86ca86b932659cfb93b697a6a9b3036..0000000000000000000000000000000000000000 --- a/port/tcpinput.c +++ /dev/null @@ -1,1026 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -int tcpdbg = 0; -ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent with SYN */ -int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ - -#define DPRINT if(tcpdbg) print -#define LPRINT if(tcpdbg) print - -char *tcpstate[] = -{ - "Closed", "Listen", "Syn_sent", "Syn_received", - "Established", "Finwait1", "Finwait2", "Close_wait", - "Closing", "Last_ack", "Time_wait" -}; - -void -sndrst(Ipaddr source, Ipaddr dest, ushort length, Tcp *seg) -{ - Block *hbp; - Port tmp; - char rflags; - Tcphdr ph; - - if(seg->flags & RST) - return; - - hnputl(ph.tcpsrc, dest); - hnputl(ph.tcpdst, source); - ph.proto = IP_TCPPROTO; - hnputs(ph.tcplen, TCP_HDRSIZE); - - /* Swap port numbers */ - tmp = seg->dest; - seg->dest = seg->source; - seg->source = tmp; - - rflags = RST; - - /* convince the other end that this reset is in band */ - if(seg->flags & ACK) { - seg->seq = seg->ack; - seg->ack = 0; - } - else { - rflags |= ACK; - seg->ack = seg->seq; - seg->seq = 0; - if(seg->flags & SYN) - seg->ack++; - seg->ack += length; - if(seg->flags & FIN) - seg->ack++; - } - seg->flags = rflags; - seg->wnd = 0; - seg->up = 0; - seg->mss = 0; - if((hbp = htontcp(seg, 0, &ph)) == 0) - return; - - PUTNEXT(Ipoutput, hbp); -} - -/* - * flush an incoming call; send a reset to the remote side and close the - * conversation - */ -void -tcpflushincoming(Ipconv *s) -{ - Tcp seg; - Tcpctl *tcb; - - tcb = &s->tcpctl; - seg.source = s->pdst; - seg.dest = s->psrc; - seg.flags = ACK; - seg.seq = tcb->snd.ptr; - seg.ack = tcb->last_ack = tcb->rcv.nxt; - - sndrst(s->dst, Myip[Myself], 0, &seg); - localclose(s, 0); -} - -static void -tcpmove(struct Tctl *to, struct Tctl *from) -{ - memmove(to, from, sizeof(struct Tctl)); -} - -Ipconv* -tcpincoming(Ipifc *ifc, Ipconv *s, Tcp *segp, Ipaddr source) -{ - Ipconv *new; - - qlock(s); - if(s->curlog >= s->backlog){ - qunlock(s); - return 0; - } - - new = ipincoming(ifc, s); - if(new == 0){ - qunlock(s); - return 0; - } - - s->curlog++; - qunlock(s); - new->psrc = segp->dest; - new->pdst = segp->source; - new->dst = source; - tcpmove(&new->tcpctl, &s->tcpctl); - new->tcpctl.flags &= ~CLONE; - new->tcpctl.timer.arg = new; - new->tcpctl.timer.state = TimerOFF; - new->tcpctl.acktimer.arg = new; - new->tcpctl.acktimer.state = TimerOFF; - new->newcon = s; - - wakeup(&s->listenr); - return new; -} - -void -tcpinput(Ipifc *ifc, Block *bp) -{ - Tcp seg; - char tos; - Tcphdr *h; - int hdrlen; - Tcpctl *tcb; - ushort length; - Ipconv *spec, *gen; - Ipaddr source, dest; - Ipconv *s, **p, **etab; - - h = (Tcphdr *)(bp->rptr); - dest = nhgetl(h->tcpdst); - source = nhgetl(h->tcpsrc); - - tos = h->tos; - length = nhgets(h->length); - - h->Unused = 0; - hnputs(h->tcplen, length - (TCP_IPLEN+TCP_PHDRSIZE)); - if(ptcl_csum(bp, TCP_EHSIZE+TCP_IPLEN, length - TCP_IPLEN)) { - freeb(bp); - return; - } - - if((hdrlen = ntohtcp(&seg, &bp)) < 0) - return; - - /* trim the packet to the size claimed by the datagram */ - length -= (hdrlen+TCP_IPLEN+TCP_PHDRSIZE); - bp = btrim(bp, hdrlen+TCP_PKT, length); - if(bp == 0) - return; - - /* Look for a connection. failing that look for a listener. */ - s = ip_conn(ifc, seg.dest, seg.source, source); - if (s == 0) { - if(seg.flags & SYN){ - /* - * find a listener specific to this port (spec) or, - * failing that, a general one (gen) - */ - spec = 0; - gen = 0; - etab = &ifc->conv[Nipconv]; - for(p = ifc->conv; p < etab && *p; p++) { - s = *p; - if(s->tcpctl.state == Listen) - if(s->pdst == 0) - if(s->dst == 0) { - if(s->psrc == seg.dest){ - spec = s; - break; - } - if(s->psrc == 0) - gen = s; - } - } - if(spec) - s = tcpincoming(ifc, spec, &seg, source); - else if(gen) - s = tcpincoming(ifc, gen, &seg, source); - else - s = 0; - } - if(s == 0){ - freeb(bp); - sndrst(source, dest, length, &seg); - return; - } - } - - /* The rest of the input state machine is run with the control block - * locked and implements the state machine directly out of the RFC - * Out-of-band data is ignored - it was always a bad idea. - */ - tcb = &s->tcpctl; - qlock(tcb); - - switch(tcb->state) { - case Closed: - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - case Listen: - if(seg.flags & RST) { - freeb(bp); - goto done; - } - if(seg.flags & ACK) { - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - } - if(seg.flags & SYN) { - proc_syn(s, tos, &seg); - tcpsndsyn(tcb); - tcpsetstate(s, Syn_received); - if(length != 0 || (seg.flags & FIN)) - break; - freeb(bp); - goto output; - } - freeb(bp); - goto done; - case Syn_sent: - if(seg.flags & ACK) { - if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) { - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - } - } - if(seg.flags & RST) { - if(seg.flags & ACK) - localclose(s, Econrefused); - freeb(bp); - goto done; - } - - if(seg.flags & ACK) - if(PREC(tos) != PREC(tcb->tos)){ - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - } - - if(seg.flags & SYN) { - proc_syn(s, tos, &seg); - if(seg.flags & ACK){ - update(s, &seg); - tcpsetstate(s, Established); - } - else - tcpsetstate(s, Syn_received); - - if(length != 0 || (seg.flags & FIN)) - break; - - freeb(bp); - goto output; - } - else - freeb(bp); - goto done; - } - - /* Cut the data to fit the receive window */ - if(trim(tcb, &seg, &bp, &length) == -1) { - if(!(seg.flags & RST)) { - tcb->flags |= FORCE; - goto output; - } - goto done; - } - - /* Cannot accept so answer with a rst */ - if(length) - if(s->readq == 0) - if(tcb->state == Closed) { - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - } - - /* The segment is beyond the current receive pointer so - * queue the data in the resequence queue - */ - if(seg.seq != tcb->rcv.nxt) - if(length != 0 || (seg.flags & (SYN|FIN))) { - add_reseq(tcb, tos, &seg, bp, length); - tcb->flags |= FORCE; - goto output; - } - - for(;;) { - if(seg.flags & RST) { - if(tcb->state == Syn_received - && !(tcb->flags & (CLONE|ACTIVE))) - tcpsetstate(s, Listen); - else - localclose(s, Econrefused); - - freeb(bp); - goto done; - } - - /* This tos stuff should be removed */ - if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){ - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - } - - if(!(seg.flags & ACK)) { - freeb(bp); - goto done; - } - - switch(tcb->state) { - case Syn_received: - if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){ - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - } - update(s, &seg); - tcpsetstate(s, Established); - case Established: - case Close_wait: - update(s, &seg); - break; - case Finwait1: - update(s, &seg); - if(tcb->sndcnt == 0) - tcpsetstate(s, Finwait2); - break; - case Finwait2: - update(s, &seg); - break; - case Closing: - update(s, &seg); - if(tcb->sndcnt == 0) { - tcpsetstate(s, Time_wait); - tcb->timer.start = MSL2 * (1000 / MSPTICK); - tcpgo(&tcb->timer); - } - break; - case Last_ack: - update(s, &seg); - if(tcb->sndcnt == 0) { - freeb(bp); - localclose(s, Enoerror); - goto done; - } - case Time_wait: - tcb->flags |= FORCE; - tcpgo(&tcb->timer); - } - - if((seg.flags&URG) && seg.up) { - if(seq_gt(seg.up + seg.seq, tcb->rcv.up)) { - tcb->rcv.up = seg.up + seg.seq; - pullb(&bp, seg.up); - } - } - else if(seq_gt(tcb->rcv.nxt, tcb->rcv.up)) - tcb->rcv.up = tcb->rcv.nxt; - - if(length == 0){ - if(bp) - freeb(bp); - } - else { - switch(tcb->state){ - default: - /* Ignore segment text */ - if(bp) - freeb(bp); - break; - - case Syn_received: - case Established: - case Finwait1: - /* If we still have some data place on receive queue */ - tcb->rcvcnt += blen(bp); - if(bp){ - if(s->readq) - PUTNEXT(s->readq, bp); - else - putb(&tcb->rcvq, bp); - bp = 0; - } - tcb->rcv.nxt += length; - - tcprcvwin(s); - - tcpgo(&tcb->acktimer); - - if(tcb->max_snd <= tcb->rcv.nxt-tcb->last_ack) - tcb->flags |= FORCE; - break; - case Finwait2: - /* no process to read the data, send a reset */ - if(bp) - freeb(bp); - sndrst(source, dest, length, &seg); - goto done; - } - } - - if(seg.flags & FIN) { - tcb->flags |= FORCE; - - switch(tcb->state) { - case Syn_received: - case Established: - tcb->rcv.nxt++; - tcpsetstate(s, Close_wait); - break; - case Finwait1: - tcb->rcv.nxt++; - if(tcb->sndcnt == 0) { - tcpsetstate(s, Time_wait); - tcb->timer.start = MSL2 * (1000/MSPTICK); - tcpgo(&tcb->timer); - } - else - tcpsetstate(s, Closing); - break; - case Finwait2: - tcb->rcv.nxt++; - tcpsetstate(s, Time_wait); - tcb->timer.start = MSL2 * (1000/MSPTICK); - tcpgo(&tcb->timer); - break; - case Close_wait: - case Closing: - case Last_ack: - break; - case Time_wait: - tcpgo(&tcb->timer); - break; - } - } - - while(tcb->reseq) { - if(seq_ge(tcb->rcv.nxt, tcb->reseq->seg.seq) == 0) - break; - - get_reseq(tcb, &tos, &seg, &bp, &length); - - if(trim(tcb, &seg, &bp, &length) == 0) - break; - } - break; - } -output: - tcpoutput(s); -done: - qunlock(tcb); -} - -void -update(Ipconv *s, Tcp *seg) -{ - int rtt; - ushort acked; - ushort expand; - Tcpctl *tcb = &s->tcpctl; - - if(seq_gt(seg->ack, tcb->snd.nxt)) { - tcb->flags |= FORCE; - return; - } - - if(seq_ge(seg->ack,tcb->snd.wl2)) - if(seq_gt(seg->seq,tcb->snd.wl1) || (seg->seq == tcb->snd.wl1)) { - if(seg->wnd != 0) - if(tcb->snd.wnd == 0) - tcb->snd.ptr = tcb->snd.una; - - tcb->snd.wnd = seg->wnd; - tcb->snd.wl1 = seg->seq; - tcb->snd.wl2 = seg->ack; - } - - if(!seq_gt(seg->ack, tcb->snd.una)) - return; - - /* Compute the new send window size */ - acked = seg->ack - tcb->snd.una; - if(tcb->cwind < tcb->snd.wnd) { - if(tcb->cwind < tcb->ssthresh) - expand = MIN(acked,tcb->mss); - else - expand = ((long)tcb->mss * tcb->mss) / tcb->cwind; - - if(tcb->cwind + expand < tcb->cwind) - expand = 65535 - tcb->cwind; - if(tcb->cwind + expand > tcb->snd.wnd) - expand = tcb->snd.wnd - tcb->cwind; - if(expand != 0) - tcb->cwind += expand; - } - - /* Adjust the timers acorrding to the round trip time */ - if(run_timer(&tcb->rtt_timer)) - if(seq_ge(seg->ack, tcb->rttseq)) { - tcphalt(&tcb->rtt_timer); - if((tcb->flags&RETRAN) == 0) { - tcb->backoff = 0; - rtt = tcb->rtt_timer.start - tcb->rtt_timer.count; - rtt *= MSPTICK; - if(rtt > tcb->srtt && - (tcb->state == Syn_sent || tcb->state == Syn_received)) - tcb->srtt = rtt; - else { - tcb->srtt = ((AGAIN-1)*tcb->srtt + rtt) / AGAIN; - rtt = abs(rtt - tcb->srtt); - tcb->mdev = ((DGAIN-1)*tcb->mdev + rtt) / DGAIN; - } - } - } - - if((tcb->flags & SYNACK) == 0){ - tcb->flags |= SYNACK; - acked--; - tcb->sndcnt--; - } - - pullb(&tcb->sndq, acked); - - tcb->sndcnt -= acked; - tcb->snd.una = seg->ack; - if(seq_gt(seg->ack, tcb->snd.up)) - tcb->snd.up = seg->ack; - - tcphalt(&tcb->timer); - if(tcb->snd.una != tcb->snd.nxt) - tcpgo(&tcb->timer); - - if(seq_lt(tcb->snd.ptr, tcb->snd.una)) - tcb->snd.ptr = tcb->snd.una; - - tcb->flags &= ~RETRAN; - tcb->backoff = 0; - - if(tcb->sndfull && tcb->sndcnt < Streamhi/2){ - wakeup(&tcb->sndr); - tcb->sndfull = 0; - } -} - -int -in_window(Tcpctl *tcb, int seq) -{ - return seq_within(seq, tcb->rcv.nxt, (int)(tcb->rcv.nxt+tcb->rcv.wnd-1)); -} - -void -proc_syn(Ipconv *s, char tos, Tcp *seg) -{ - Tcpctl *tcb = &s->tcpctl; - ushort mtu; - - - tcb->flags |= FORCE; - - if(PREC(tos) > PREC(tcb->tos)) - tcb->tos = tos; - - tcb->rcv.up = tcb->rcv.nxt = seg->seq + 1; - tcb->snd.wl1 = tcb->irs = seg->seq; - tcb->snd.wnd = seg->wnd; - - if(seg->mss != 0) - tcb->mss = seg->mss; - - tcb->max_snd = seg->wnd; - if((mtu = s->ifc->maxmtu) != 0) { - mtu -= TCP_HDRSIZE + TCP_EHSIZE + TCP_PHDRSIZE; - tcb->cwind = tcb->mss = MIN(mtu, tcb->mss); - } -} - -/* Generate an initial sequence number and put a SYN on the send queue */ -void -tcpsndsyn(Tcpctl *tcb) -{ - static int start; - - start += 250000; - tcb->iss = start; - tcb->rttseq = tcb->iss; - tcb->snd.wl2 = tcb->iss; - tcb->snd.una = tcb->iss; - tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq; - tcb->sndcnt++; - tcb->flags |= FORCE; -} - -void -add_reseq(Tcpctl *tcb, char tos, Tcp *seg, Block *bp, ushort length) -{ - Reseq *rp, *rp1; - - rp = malloc(sizeof(Reseq)); - if(rp == 0){ - freeb(bp); /* bp always consumed by add_reseq */ - return; - } - - rp->seg = *seg; - rp->tos = tos; - rp->bp = bp; - rp->length = length; - - /* Place on reassembly list sorting by starting seq number */ - rp1 = tcb->reseq; - if(rp1 == 0 || seq_lt(seg->seq, rp1->seg.seq)) { - rp->next = rp1; - tcb->reseq = rp; - return; - } - - for(;;) { - if(rp1->next == 0 || seq_lt(seg->seq, rp1->next->seg.seq)) { - rp->next = rp1->next; - rp1->next = rp; - break; - } - rp1 = rp1->next; - } -} - -void -get_reseq(Tcpctl *tcb, char *tos, Tcp *seg, Block **bp, ushort *length) -{ - Reseq *rp; - - rp = tcb->reseq; - if(rp == 0) - return; - - tcb->reseq = rp->next; - - *tos = rp->tos; - *seg = rp->seg; - *bp = rp->bp; - *length = rp->length; - - free(rp); -} - -int -trim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length) -{ - Block *nbp; - long dupcnt; - long excess; - ushort len; - char accept; - - accept = 0; - len = *length; - if(seg->flags & SYN) - len++; - if(seg->flags & FIN) - len++; - - if(tcb->rcv.wnd == 0) { - if(len == 0) - if(seg->seq == tcb->rcv.nxt) - return 0; - } - else { - /* Some part of the segment should be in the window */ - if(in_window(tcb,seg->seq)) - accept++; - else - if(len != 0) { - if(in_window(tcb, (int)(seg->seq+len-1)) || - seq_within(tcb->rcv.nxt, seg->seq,(int)(seg->seq+len-1))) - accept++; - } - } - if(!accept) { - freeb(*bp); - return -1; - } - dupcnt = tcb->rcv.nxt - seg->seq; - if(dupcnt > 0){ - tcb->rerecv += dupcnt; - if(seg->flags & SYN){ - seg->flags &= ~SYN; - seg->seq++; - - if (seg->up > 1) - seg->up--; - else - seg->flags &= ~URG; - dupcnt--; - } - if(dupcnt > 0){ - pullb(bp, (ushort)dupcnt); - seg->seq += dupcnt; - *length -= dupcnt; - - if (seg->up > dupcnt) - seg->up -= dupcnt; - else { - seg->flags &= ~URG; - seg->up = 0; - } - } - } - excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd); - if(excess > 0) { - tcb->rerecv += excess; - *length -= excess; - nbp = copyb(*bp, *length); - freeb(*bp); - *bp = nbp; - seg->flags &= ~FIN; - } - return 0; -} - -int -pullb(Block **bph, int count) -{ - int n, bytes; - Block *bp; - - bytes = 0; - if(bph == 0) - return 0; - - while(*bph && count != 0) { - bp = *bph; - n = MIN(count, BLEN(bp)); - bytes += n; - count -= n; - bp->rptr += n; - if(BLEN(bp) == 0) { - *bph = bp->next; - bp->next = 0; - freeb(bp); - } - } - return bytes; -} - -int -dupb(Block **hp, Block *bp, int offset, int count) -{ - int i, blen, bytes = 0; - uchar *addr; - - *hp = allocb(count); - if(*hp == 0) - return 0; - - /* Correct to front of data area */ - while(bp && offset && offset >= BLEN(bp)) { - offset -= BLEN(bp); - bp = bp->next; - } - if(bp == 0) - return 0; - - addr = bp->rptr + offset; - blen = BLEN(bp) - offset; - - while(count) { - i = MIN(count, blen); - memmove((*hp)->wptr, addr, i); - (*hp)->wptr += i; - bytes += i; - count -= i; - bp = bp->next; - if(!bp) - break; - blen = BLEN(bp); - addr = bp->rptr; - } - - return bytes; -} - -static void -cleartcp(struct Tctl *a) -{ - memset(a, 0, sizeof(struct Tctl)); -} - -void -init_tcpctl(Ipconv *s) -{ - - Tcpctl *tcb = &s->tcpctl; - - cleartcp(tcb); - - tcb->cwind = tcb->mss = tcp_mss; - tcb->ssthresh = 65535; - tcb->srtt = tcp_irtt; - - tcb->timer.start = tcb->srtt / MSPTICK; - tcb->timer.func = tcptimeout; - tcb->timer.arg = s; - tcb->rtt_timer.start = MAX_TIME; - tcb->acktimer.start = TCP_ACK / MSPTICK; - tcb->acktimer.func = tcpacktimer; - tcb->acktimer.arg = s; -} - -/* - * called with tcb locked - */ -void -localclose(Ipconv *s, char reason[]) -{ - Reseq *rp,*rp1; - Tcpctl *tcb = &s->tcpctl; - Block *bp; - - tcphalt(&tcb->timer); - tcphalt(&tcb->rtt_timer); - s->err = reason; - - /* flush receive queue */ - while(bp = getb(&tcb->rcvq)) - freeb(bp); - - /* Flush reassembly queue; nothing more can arrive */ - for(rp = tcb->reseq;rp != 0;rp = rp1){ - rp1 = rp->next; - freeb(rp->bp); - free(rp); - } - - tcb->reseq = 0; - s->err = reason; - tcpsetstate(s, Closed); -} - -int -seq_within(int x, int low, int high) -{ - if(low <= high){ - if(low <= x && x <= high) - return 1; - } - else { - if(low >= x && x >= high) - return 1; - } - return 0; -} - -int -seq_lt(int x, int y) -{ - return (long)(x-y) < 0; -} - -int -seq_le(int x, int y) -{ - return (long)(x-y) <= 0; -} - -int -seq_gt(int x, int y) -{ - return (long)(x-y) > 0; -} - -int -seq_ge(int x, int y) -{ - return (long)(x-y) >= 0; -} - -void -tcpsetstate(Ipconv *s, char newstate) -{ - Tcpctl *tcb; - char oldstate; - - tcb = &s->tcpctl; - - oldstate = tcb->state; - tcb->state = newstate; - tcpxstate(s, oldstate, newstate); -} - -Block * -htontcp(Tcp *tcph, Block *data, Tcphdr *ph) -{ - int dlen; - Tcphdr *h; - Block *bp; - ushort csum; - ushort hdrlen; - - hdrlen = TCP_HDRSIZE; - if(tcph->mss) - hdrlen += MSS_LENGTH; - - if(data) { - dlen = blen(data); - data = padb(data, hdrlen + TCP_PKT); - if(data == 0) - return 0; - /* If we collected blocks delimit the end of the chain */ - for(bp = data; bp->next; bp = bp->next) - bp->flags &= ~S_DELIM; - bp->flags |= S_DELIM; - } - else { - dlen = 0; - data = allocb(hdrlen + TCP_PKT); - if(data == 0) - return 0; - data->wptr += hdrlen + TCP_PKT; - data->flags |= S_DELIM; - } - - - memmove(data->rptr, ph, TCP_PKT); - - h = (Tcphdr *)(data->rptr); - h->proto = IP_TCPPROTO; - h->frag[0] = 0; - h->frag[1] = 0; - hnputs(h->tcplen, hdrlen + dlen); - hnputs(h->tcpsport, tcph->source); - hnputs(h->tcpdport, tcph->dest); - hnputl(h->tcpseq, tcph->seq); - hnputl(h->tcpack, tcph->ack); - hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags); - hnputs(h->tcpwin, tcph->wnd); - h->tcpcksum[0] = 0; - h->tcpcksum[1] = 0; - h->Unused = 0; - hnputs(h->tcpurg, tcph->up); - - if(tcph->mss != 0){ - h->tcpopt[0] = MSS_KIND; - h->tcpopt[1] = MSS_LENGTH; - hnputs(h->tcpmss, tcph->mss); - } - csum = ptcl_csum(data, TCP_EHSIZE+TCP_IPLEN, hdrlen+dlen+TCP_PHDRSIZE); - hnputs(h->tcpcksum, csum); - - return data; -} - -int -ntohtcp(Tcp *tcph, Block **bpp) -{ - ushort hdrlen; - ushort i, optlen; - Tcphdr *h; - uchar *optr; - - *bpp = pullup(*bpp, TCP_PKT+TCP_HDRSIZE); - if(*bpp == 0) - return -1; - - h = (Tcphdr *)((*bpp)->rptr); - tcph->source = nhgets(h->tcpsport); - tcph->dest = nhgets(h->tcpdport); - tcph->seq = nhgetl(h->tcpseq); - tcph->ack = nhgetl(h->tcpack); - - hdrlen = (h->tcpflag[0] & 0xf0) >> 2; - if(hdrlen < TCP_HDRSIZE) { - freeb(*bpp); - return -1; - } - - tcph->flags = h->tcpflag[1]; - tcph->wnd = nhgets(h->tcpwin); - tcph->up = nhgets(h->tcpurg); - tcph->mss = 0; - - *bpp = pullup(*bpp, hdrlen+TCP_PKT); - if(!*bpp) - return -1; - - optr = h->tcpopt; - for(i = TCP_HDRSIZE; i < hdrlen;) { - switch(*optr++){ - case EOL_KIND: - return hdrlen; - case NOOP_KIND: - i++; - break; - case MSS_KIND: - optlen = *optr++; - if(optlen == MSS_LENGTH) - tcph->mss = nhgets(optr); - i += optlen; - break; - } - } - return hdrlen; -} diff --git a/port/tcpoutput.c b/port/tcpoutput.c deleted file mode 100644 index bbb1f7ee60ef5fcb87b5451289f506914e517077..0000000000000000000000000000000000000000 --- a/port/tcpoutput.c +++ /dev/null @@ -1,273 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -#define DPRINT if(tcpdbg) print - -extern int tcpdbg; -extern ushort tcp_mss; - int tcptimertype; - -void -tcpoutput(Ipconv *s) -{ - Tcp seg; - int qlen; - Tcphdr ph; - Tcpctl *tcb; - Block *hbp,*dbp, *sndq; - ushort ssize, dsize, usable, sent; - - tcb = &s->tcpctl; - - switch(tcb->state) { - case Listen: - case Closed: - return; - } - - for(;;) { - qlen = tcb->sndcnt; - sent = tcb->snd.ptr - tcb->snd.una; - sndq = tcb->sndq; - - /* Don't send anything else until our SYN has been acked */ - if(sent != 0) - if((tcb->flags & SYNACK) == 0) - break; - - /* Compute usable segment based on offered window and limit - * window probes to one - */ - if(tcb->snd.wnd == 0){ - if(sent != 0) { - if (tcb->flags&FORCE) - tcb->snd.ptr = tcb->snd.una; - else - break; - } - usable = 1; - } - else { - usable = MIN(tcb->snd.wnd,tcb->cwind) - sent; - if(sent != 0) - if(qlen - sent < tcb->mss) - usable = 0; - } - - ssize = MIN(qlen - sent, usable); - ssize = MIN(ssize, tcb->mss); - dsize = ssize; - seg.up = 0; - - if(ssize == 0) - if((tcb->flags&FORCE) == 0) - break; - - tcphalt(&tcb->acktimer); - - tcb->flags &= ~FORCE; - tcprcvwin(s); - - /* By default we will generate an ack */ - seg.source = s->psrc; - seg.dest = s->pdst; - seg.flags = ACK; - seg.mss = 0; - - switch(tcb->state){ - case Syn_sent: - seg.flags = 0; - /* No break */ - case Syn_received: - if(tcb->snd.ptr == tcb->iss){ - seg.flags |= SYN; - dsize--; - seg.mss = tcp_mss; - } - break; - } - seg.seq = tcb->snd.ptr; - seg.ack = tcb->last_ack = tcb->rcv.nxt; - seg.wnd = tcb->rcv.wnd; - - /* Pull out data to send */ - dbp = 0; - if(dsize != 0){ - if(dupb(&dbp, sndq, sent, dsize) != dsize) { - seg.flags |= FIN; - dsize--; - } - DPRINT("dupb: %d\n", dbp->rptr[0]); - } - - if(sent+dsize == qlen) - seg.flags |= PSH; - - /* - * keep track of balance of resent data */ - if(tcb->snd.ptr < tcb->snd.nxt) - tcb->resent += MIN((int)tcb->snd.nxt - (int)tcb->snd.ptr,(int)ssize); - - tcb->snd.ptr += ssize; - - /* Pull up the send pointer so we can accept acks for this window */ - if(seq_gt(tcb->snd.ptr,tcb->snd.nxt)) - tcb->snd.nxt = tcb->snd.ptr; - - /* Fill in fields of pseudo IP header */ - hnputl(ph.tcpdst, s->dst); - hnputl(ph.tcpsrc, Myip[Myself]); - hnputs(ph.tcpsport, s->psrc); - hnputs(ph.tcpdport, s->pdst); - - /* Build header, link data and compute cksum */ - if((hbp = htontcp(&seg, dbp, &ph)) == 0) { - freeb(dbp); - return; - } - - /* Start the transmission timers if there is new data and we - * expect acknowledges - */ - if(ssize != 0){ - tcb->timer.start = backoff(tcb->backoff) * - (2 * tcb->mdev + tcb->srtt + MSPTICK) / MSPTICK; - if(!run_timer(&tcb->timer)) - tcpgo(&tcb->timer); - - /* If round trip timer isn't running, start it */ - if(!run_timer(&tcb->rtt_timer)){ - tcpgo(&tcb->rtt_timer); - tcb->rttseq = tcb->snd.ptr; - } - } - PUTNEXT(Ipoutput, hbp); - } -} - -void -tcprxmit(Ipconv *s) -{ - Tcpctl *tcb; - - tcb = &s->tcpctl; - qlock(tcb); - tcb->flags |= RETRAN|FORCE; - tcb->snd.ptr = tcb->snd.una; - - /* Pull window down to a single packet and halve the slow - * start threshold - */ - tcb->ssthresh = tcb->cwind / 2; - tcb->ssthresh = MAX(tcb->ssthresh, tcb->mss); - - tcb->cwind = tcb->mss; - tcpoutput(s); - qunlock(tcb); -} - -void -tcptimeout(void *arg) -{ - Tcpctl *tcb; - Ipconv *s; - - s = (Ipconv *)arg; - tcb = &s->tcpctl; - switch(tcb->state){ - default: - tcb->backoff++; - if (tcb->backoff >= MAXBACKOFF && tcb->snd.wnd > 0) { - localclose(s, Etimedout); - break; - } - tcprxmit(s); - break; - - case Time_wait: - localclose(s, 0); - break; - } -} - -int -backoff(int n) -{ - if(tcptimertype == 1) - return n+1; - - if(n <= 4) - return 1 << n; - - return n*n; -} - -void -tcpacktimer(Ipconv *s) -{ - Tcpctl *tcb = &s->tcpctl; - - qlock(tcb); - tcb->flags |= FORCE; - tcprcvwin(s); - tcpoutput(s); - qunlock(tcb); -} - -void -tcprcvwin(Ipconv *s) /* Call with tcb locked */ -{ - int w; - Tcpctl *tcb; - - tcb = &s->tcpctl; - qlock(s); - if(s->readq) { - w = Streamhi - s->readq->next->len; - if(w < 0) - tcb->rcv.wnd = 0; - else - tcb->rcv.wnd = w; - } - else - tcb->rcv.wnd = Streamhi; - qunlock(s); -} - -/* - * Network byte order functions - */ - -void -hnputs(uchar *ptr, ushort val) -{ - ptr[0] = val>>8; - ptr[1] = val; -} - -void -hnputl(uchar *ptr, ulong val) -{ - ptr[0] = val>>24; - ptr[1] = val>>16; - ptr[2] = val>>8; - ptr[3] = val; -} - -ulong -nhgetl(uchar *ptr) -{ - return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]); -} - -ushort -nhgets(uchar *ptr) -{ - return ((ptr[0]<<8) | ptr[1]); -} diff --git a/port/tcptimer.c b/port/tcptimer.c deleted file mode 100644 index 6ce0df195068c1a0827405f7452543c732578321..0000000000000000000000000000000000000000 --- a/port/tcptimer.c +++ /dev/null @@ -1,125 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "arp.h" -#include "ipdat.h" - -static Timer *timers; /* List of active timers */ -static QLock tl; /* Protect timer list */ -static Rendez Tcpack; -Rendez tcpflowr; - -static void -deltimer(Timer *t) -{ - if(timers == t) - timers = t->next; - - if(t->next) - t->next->prev = t->prev; - - if(t->prev) - t->prev->next = t->next; -} - -/* - * Poke each tcp connection to recompute window size and - * acknowledgement timer - */ - -void -tcpflow(void *x) -{ - Ipifc *ifc; - Ipconv *cp, **p, **etab; - - ifc = x; - etab = &ifc->conv[Nipconv]; - - for(;;) { - sleep(&tcpflowr, return0, 0); - - for(p = ifc->conv; p < etab; p++) { - cp = *p; - if(cp == 0) - break; - if(cp->readq && cp->ref != 0 && !QFULL(cp->readq->next)) { - tcprcvwin(cp); - tcpacktimer(cp); - } - } - } -} - -void -tcpackproc(void *junk) -{ - Timer *t, *tp, *timeo; - - USED(junk); - for(;;) { - timeo = 0; - - qlock(&tl); - for(t = timers;t != 0; t = tp) { - tp = t->next; - if(t->state == TimerON) { - t->count--; - if(t->count == 0) { - deltimer(t); - t->state = TimerDONE; - t->next = timeo; - timeo = t; - } - } - } - qunlock(&tl); - - for(;;) { - t = timeo; - if(t == 0) - break; - - timeo = t->next; - if(t->state == TimerDONE) - if(t->func) - (*t->func)(t->arg); - } - tsleep(&Tcpack, return0, 0, MSPTICK); - } -} - -void -tcpgo(Timer *t) -{ - if(t == 0 || t->start == 0) - return; - - qlock(&tl); - t->count = t->start; - if(t->state != TimerON) { - t->state = TimerON; - t->prev = 0; - t->next = timers; - if(t->next) - t->next->prev = t; - timers = t; - } - qunlock(&tl); -} - -void -tcphalt(Timer *t) -{ - if(t == 0) - return; - - qlock(&tl); - if(t->state == TimerON) - deltimer(t); - t->state = TimerOFF; - qunlock(&tl); -}