From a1e5d4c3ad80b17f1989ec008b4eb25cb2e1315a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 13 Mar 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-03-13 --- ip/arp.c | 79 ++++++------ ip/devip.c | 191 ++++++++++++++++++---------- ip/ethermedium.c | 34 ++--- ip/gre.c | 70 ++++++----- ip/icmp.c | 132 ++++++++++--------- ip/il.c | 177 +++++++++++++++----------- ip/inferno.c | 46 +++++++ ip/ip.c | 321 ++++++++++++++++++++++++++++++----------------- ip/ip.h | 149 ++++++++++++++-------- ip/ipaux.c | 2 + ip/ipifc.c | 222 ++++++++++++++++---------------- ip/iproute.c | 152 +++++++++++----------- ip/netlog.c | 158 ++++++++++++----------- ip/pktmedium.c | 8 +- ip/tcp.c | 320 ++++++++++++++++++++++++++++------------------ ip/udp.c | 214 +++++++++++++++++++++---------- 16 files changed, 1370 insertions(+), 905 deletions(-) create mode 100644 ip/inferno.c diff --git a/ip/arp.c b/ip/arp.c index 74fb26e845cb044a3067f54fb8e224925b060bf3..9cc9a20de76b0879111a5f4176a1c6a517b89c15 100644 --- a/ip/arp.c +++ b/ip/arp.c @@ -27,30 +27,38 @@ char *arpstate[] = "WAIT", }; -typedef struct Arpcache Arpcache; -struct Arpcache +/* + * one per Fs + */ +struct Arp { QLock; - Arpent* hash[NHASH]; + Fs *f; + Arpent *hash[NHASH]; Arpent cache[NCACHE]; }; -Arpcache arp; - char *Ebadarp = "bad arp"; #define haship(s) ((s)[IPaddrlen-1]%NHASH) +void +arpinit(Fs *f) +{ + f->arp = smalloc(sizeof(Arp)); + f->arp->f = f; +} + static Arpent* -newarp(uchar *ip, Medium *m) +newarp(Arp *arp, uchar *ip, Medium *m) { uint t; Block *next, *xp; Arpent *a, *e, *f, **l; /* find oldest entry */ - e = &arp.cache[NCACHE]; - a = arp.cache; + e = &arp->cache[NCACHE]; + a = arp->cache; t = a->used; for(f = a; f < e; f++){ if(f->used < t){ @@ -69,7 +77,7 @@ newarp(uchar *ip, Medium *m) } /* take out of current chain */ - l = &arp.hash[haship(a->ip)]; + l = &arp->hash[haship(a->ip)]; for(f = *l; f; f = f->hash){ if(f == a) { *l = a->hash; @@ -79,7 +87,7 @@ newarp(uchar *ip, Medium *m) } /* insert into new chain */ - l = &arp.hash[haship(ip)]; + l = &arp->hash[haship(ip)]; a->hash = *l; *l = a; memmove(a->ip, ip, sizeof(a->ip)); @@ -91,7 +99,7 @@ newarp(uchar *ip, Medium *m) } Arpent* -arpget(Block *bp, int version, Medium *type, uchar *ip, uchar *mac) +arpget(Arp *arp, Block *bp, int version, Medium *type, uchar *ip, uchar *mac) { int hash; Arpent *a; @@ -102,16 +110,16 @@ arpget(Block *bp, int version, Medium *type, uchar *ip, uchar *mac) ip = v6ip; } - qlock(&arp); + qlock(arp); hash = haship(ip); - for(a = arp.hash[hash]; a; a = a->hash) { + for(a = arp->hash[hash]; a; a = a->hash) { if(memcmp(ip, a->ip, sizeof(a->ip)) == 0) if(type == a->type) break; } if(a == nil){ - a = newarp(ip, type); + a = newarp(arp, ip, type); a->state = AWAIT; } a->used = msec; @@ -126,7 +134,7 @@ arpget(Block *bp, int version, Medium *type, uchar *ip, uchar *mac) } memmove(mac, a->mac, a->type->maclen); - qunlock(&arp); + qunlock(arp); return nil; } @@ -134,16 +142,16 @@ arpget(Block *bp, int version, Medium *type, uchar *ip, uchar *mac) * called with arp locked */ void -arprelease(Arpent*) +arprelease(Arp *arp, Arpent*) { - qunlock(&arp); + qunlock(arp); } /* * called with arp locked */ Block* -arpresolve(Arpent *a, Medium *type, uchar *mac) +arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac) { Block *bp; @@ -153,13 +161,13 @@ arpresolve(Arpent *a, Medium *type, uchar *mac) a->used = msec; bp = a->hold; a->hold = nil; - qunlock(&arp); + qunlock(arp); return bp; } void -arpenter(Ipifc *ifc, int version, uchar *ip, uchar *mac, Medium *type, int refresh) +arpenter(Arp *arp, Ipifc *ifc, int version, uchar *ip, uchar *mac, Medium *type, int refresh) { Arpent *a; Block *bp, *next; @@ -170,8 +178,8 @@ arpenter(Ipifc *ifc, int version, uchar *ip, uchar *mac, Medium *type, int refre ip = v6ip; } - qlock(&arp); - for(a = arp.hash[haship(ip)]; a; a = a->hash) { + qlock(arp); + for(a = arp->hash[haship(ip)]; a; a = a->hash) { if(a->type != type || (a->state != AWAIT && a->state != AOK)) continue; @@ -182,7 +190,7 @@ arpenter(Ipifc *ifc, int version, uchar *ip, uchar *mac, Medium *type, int refre a->hold = nil; if(version == V4) ip += IPv4off; - qunlock(&arp); + qunlock(arp); while(bp) { next = bp->list; if(ifc != nil){ @@ -206,19 +214,18 @@ arpenter(Ipifc *ifc, int version, uchar *ip, uchar *mac, Medium *type, int refre } } - /* if nil, we're adding a new entry */ if(refresh == 0){ - a = newarp(ip, type); + a = newarp(arp, ip, type); a->state = AOK; a->type = type; memmove(a->mac, mac, type->maclen); } - qunlock(&arp); + qunlock(arp); } int -arpwrite(char *s, int len) +arpwrite(Arp *arp, char *s, int len) { int n; Block *bp; @@ -238,8 +245,8 @@ arpwrite(char *s, int len) n = parsefields(buf, f, 4, " "); if(strcmp(f[0], "flush") == 0){ - qlock(&arp); - for(a = arp.cache; a < &arp.cache[NCACHE]; a++){ + qlock(arp); + for(a = arp->cache; a < &arp->cache[NCACHE]; a++){ memset(a->ip, 0, sizeof(a->ip)); memset(a->mac, 0, sizeof(a->mac)); a->hash = nil; @@ -251,8 +258,8 @@ arpwrite(char *s, int len) a->hold = bp; } } - memset(arp.hash, 0, sizeof(arp.hash)); - qunlock(&arp); + memset(arp->hash, 0, sizeof(arp->hash)); + qunlock(arp); } else if(strcmp(f[0], "add") == 0){ if(n != 4) error(Ebadarp); @@ -261,7 +268,7 @@ arpwrite(char *s, int len) error(Ebadarp); parseip(ip, f[2]); parsemac(mac, f[3], m->maclen); - arpenter(nil, V6, ip, mac, m, 0); + arpenter(arp, nil, V6, ip, mac, m, 0); } else error(Ebadarp); @@ -283,7 +290,7 @@ convmac(char *p, uchar *mac, int n) } int -arpread(char *p, ulong offset, int len) +arpread(Arp *arp, char *p, ulong offset, int len) { Arpent *a; int n; @@ -296,7 +303,7 @@ arpread(char *p, ulong offset, int len) len = len/Alinelen; n = 0; - for(a = arp.cache; len > 0 && a < &arp.cache[NCACHE]; a++){ + for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){ if(a->state == 0) continue; if(offset > 0){ @@ -304,10 +311,10 @@ arpread(char *p, ulong offset, int len) continue; } len--; - qlock(&arp); + qlock(arp); convmac(mac, a->mac, a->type->maclen); n += sprint(p+n, aformat, a->type->name, arpstate[a->state], a->ip, mac); - qunlock(&arp); + qunlock(arp); } return n; diff --git a/ip/devip.c b/ip/devip.c index ffc12be53c3b1354a7b288a459dc05e220706e5a..65efca548c780d229af2055fc6e589979cb6ca43 100644 --- a/ip/devip.c +++ b/ip/devip.c @@ -6,14 +6,12 @@ #include "../port/error.h" #include "../ip/ip.h" -Fs fs; -Queue* qlog; - enum { Qtopdir= 1, /* top level directory */ Qtopbase, Qarp= Qtopbase, + Qbootp, Qiproute, Qiprouter, Qipselftab, @@ -33,14 +31,29 @@ enum Qlocal, Qremote, Qstatus, + + Logtype= 5, + Masktype= (1<> 5)&0xfff) -#define PROTO(x) (((x).path >> 17)&0xff) -#define QID(p, c, y) (((p)<<17) | ((c)<<5) | (y)) +#define TYPE(x) ( (x).path & Masktype ) +#define CONV(x) ( ((x).path >> Shiftconv) & Maskconv ) +#define PROTO(x) ( ((x).path >> Shiftproto) & Maskproto ) +#define QID(p, c, y) ( ((p)<<(Shiftproto)) | ((c)<qid)]->conv[CONV(c->qid)]; + cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)]; switch(i) { default: return -1; @@ -118,6 +131,10 @@ ip1gen(Chan *c, int i, Dir *dp) p = "arp"; q = (Qid){QID(0, 0, Qarp), 0}; break; + case Qbootp: + p = "bootp"; + q = (Qid){QID(0, 0, Qbootp), 0}; + break; case Qiproute: p = "iproute"; q = (Qid){QID(0, 0, Qiproute), 0}; @@ -146,33 +163,37 @@ ipgen(Chan *c, Dirtab*, int, int s, Dir *dp) Qid q; Conv *cv; char name[16]; + Fs *f; + + f = ipfs[c->dev]; switch(TYPE(c->qid)) { case Qtopdir: - if(s < fs.np) { - if(fs.p[s]->connect == nil) + if(s < f->np) { + if(f->p[s]->connect == nil) return 0; /* protocol with no user interface */ q = (Qid){QID(s, 0, Qprotodir)|CHDIR, 0}; - devdir(c, q, fs.p[s]->name, 0, network, CHDIR|0555, dp); + devdir(c, q, f->p[s]->name, 0, network, CHDIR|0555, dp); return 1; } - s -= fs.np; + s -= f->np; return ip1gen(c, s+Qtopbase, dp); case Qarp: + case Qbootp: case Qlog: case Qiproute: case Qiprouter: case Qipselftab: return ip1gen(c, TYPE(c->qid), dp); case Qprotodir: - if(s < fs.p[PROTO(c->qid)]->ac) { - cv = fs.p[PROTO(c->qid)]->conv[s]; + if(s < f->p[PROTO(c->qid)]->ac) { + cv = f->p[PROTO(c->qid)]->conv[s]; sprint(name, "%d", s); q = (Qid){QID(PROTO(c->qid), s, Qconvdir)|CHDIR, 0}; devdir(c, q, name, 0, cv->owner, CHDIR|0555, dp); return 1; } - s -= fs.p[PROTO(c->qid)]->ac; + s -= f->p[PROTO(c->qid)]->ac; return ip2gen(c, s+Qprotobase, dp); case Qclone: case Qstats: @@ -199,12 +220,6 @@ ipreset(void) static void ipinit(void) { - int i; - extern void (*ipprotoinit[])(Fs*); - - initfrag(100); - for(i = 0; ipprotoinit[i]; i++) - ipprotoinit[i](&fs); fmtinstall('i', eipconv); fmtinstall('I', eipconv); fmtinstall('E', eipconv); @@ -212,13 +227,45 @@ ipinit(void) fmtinstall('M', eipconv); } +static Fs* +ipgetfs(int dev) +{ + extern void (*ipprotoinit[])(Fs*); + Fs *f; + int i; + + if(dev >= Nfs) + return nil; + + qlock(&fslock); + if(ipfs[dev] == nil){ + f = smalloc(sizeof(Fs)); + ip_init(f); + arpinit(f); + netloginit(f); + for(i = 0; ipprotoinit[i]; i++) + ipprotoinit[i](f); + ipfs[dev] = f; + } + qunlock(&fslock); + + return ipfs[dev]; +} + static Chan* ipattach(char* spec) { Chan *c; + int dev; + + dev = atoi(spec); + if(dev >= 16) + error("bad specification"); + ipgetfs(dev); c = devattach('I', spec); c->qid = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0}; + c->dev = dev; return c; } @@ -281,18 +328,21 @@ ipopen(Chan* c, int omode) Conv *cv, *nc; Proto *p; int perm; + Fs *f; omode &= 3; perm = m2p[omode]; + f = ipfs[c->dev]; + switch(TYPE(c->qid)) { default: break; case Qlog: - netlogopen(); + netlogopen(f); break; case Qiprouter: - iprouteropen(); + iprouteropen(f); break; case Qiproute: memmove(c->tag, "none", sizeof(c->tag)); @@ -304,13 +354,14 @@ ipopen(Chan* c, int omode) case Qremote: case Qlocal: case Qstats: + case Qbootp: case Qipselftab: if(omode != OREAD) error(Eperm); break; case Qclone: - p = fs.p[PROTO(c->qid)]; - cv = Fsprotoclone(p, up->user); + p = f->p[PROTO(c->qid)]; + cv = Fsprotoclone(p, commonuser()); if(cv == nil) { error(Enodev); break; @@ -320,7 +371,7 @@ ipopen(Chan* c, int omode) case Qdata: case Qctl: case Qerr: - p = fs.p[PROTO(c->qid)]; + p = f->p[PROTO(c->qid)]; qlock(p); cv = p->conv[CONV(c->qid)]; lock(cv); @@ -330,7 +381,7 @@ ipopen(Chan* c, int omode) nexterror(); } if((perm & (cv->perm>>6)) != perm) { - if(strcmp(up->user, cv->owner) != 0) + if(strcmp(commonuser(), cv->owner) != 0) error(Eperm); if((perm & cv->perm) != perm) error(Eperm); @@ -338,7 +389,7 @@ ipopen(Chan* c, int omode) } cv->inuse++; if(cv->inuse == 1){ - memmove(cv->owner, up->user, NAMELEN); + memmove(cv->owner, commonuser(), NAMELEN); cv->perm = 0660; } unlock(cv); @@ -346,7 +397,7 @@ ipopen(Chan* c, int omode) poperror(); break; case Qlisten: - cv = fs.p[PROTO(c->qid)]->conv[CONV(c->qid)]; + cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)]; if(cv->state != Announced) error("not announced"); @@ -365,7 +416,7 @@ ipopen(Chan* c, int omode) if(nc != nil){ cv->incall = nc->next; c->qid = (Qid){QID(PROTO(c->qid), nc->x, Qctl), 0}; - memmove(cv->owner, up->user, NAMELEN); + memmove(cv->owner, commonuser(), NAMELEN); } unlock(cv); @@ -430,22 +481,25 @@ closeconv(Conv *cv) static void ipclose(Chan* c) { + Fs *f; + + f = ipfs[c->dev]; switch(TYPE(c->qid)) { default: break; case Qlog: if(c->flag & COPEN) - netlogclose(); + netlogclose(f); break; case Qiprouter: if(c->flag & COPEN) - iprouterclose(); + iprouterclose(f); break; case Qdata: case Qctl: case Qerr: if(c->flag & COPEN) - closeconv(fs.p[PROTO(c->qid)]->conv[CONV(c->qid)]); + closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]); } } @@ -461,6 +515,9 @@ ipread(Chan *ch, void *a, long n, ulong offset) Proto *x; char *buf, *p; long m, rv; + Fs *f; + + f = ipfs[ch->dev]; p = a; switch(TYPE(ch->qid)) { @@ -471,13 +528,15 @@ ipread(Chan *ch, void *a, long n, ulong offset) case Qconvdir: return devdirread(ch, a, n, 0, 0, ipgen); case Qarp: - return arpread(a, offset, n); + return arpread(f->arp, a, offset, n); + case Qbootp: + return bootpread(a, offset, n); case Qiproute: - return routeread(a, offset, n); + return routeread(f, a, offset, n); case Qipselftab: - return ipselftabread(a, offset, n); + return ipselftabread(f, a, offset, n); case Qlog: - return netlogread(a, offset, n); + return netlogread(f, a, offset, n); case Qctl: buf = smalloc(16); sprint(buf, "%d", CONV(ch->qid)); @@ -486,14 +545,14 @@ ipread(Chan *ch, void *a, long n, ulong offset) return rv; case Qremote: buf = smalloc(Statelen); - c = fs.p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; + c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; sprint(buf, "%I!%d\n", c->raddr, c->rport); rv = readstr(offset, p, n, buf); free(buf); return rv; case Qlocal: buf = smalloc(Statelen); - x = fs.p[PROTO(ch->qid)]; + x = f->p[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; if(x->local == nil) { sprint(buf, "%I!%d\n", c->laddr, c->lport); @@ -505,7 +564,7 @@ ipread(Chan *ch, void *a, long n, ulong offset) return rv; case Qstatus: buf = smalloc(Statelen); - x = fs.p[PROTO(ch->qid)]; + x = f->p[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; m = sprint(buf, "%s/%d %d ", c->p->name, c->x, c->inuse); (*x->state)(c, buf, Statelen-m-2); @@ -513,17 +572,17 @@ ipread(Chan *ch, void *a, long n, ulong offset) free(buf); return rv; case Qdata: - c = fs.p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; + c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; return qread(c->rq, a, n); case Qerr: - c = fs.p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; + c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; return qread(c->eq, a, n); case Qstats: - x = fs.p[PROTO(ch->qid)]; + x = f->p[PROTO(ch->qid)]; if(x->stats == nil) error("stats not implemented"); buf = smalloc(Statelen); - (*x->stats)(buf, Statelen); + (*x->stats)(x, buf, Statelen); rv = readstr(offset, p, n, buf); free(buf); return rv; @@ -542,7 +601,7 @@ ipbread(Chan* c, long n, ulong offset) static void setladdr(Conv* c) { - findlocalip(c->laddr, c->raddr); + findlocalip(c->p->f, c->laddr, c->raddr); } /* @@ -787,12 +846,15 @@ ipwrite(Chan* ch, char* a, long n, ulong) char *p; Cmdbuf *cb; uchar ia[IPaddrlen]; + Fs *f; + + f = ipfs[ch->dev]; switch(TYPE(ch->qid)){ default: error(Eperm); case Qdata: - x = fs.p[PROTO(ch->qid)]; + x = f->p[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; if(c->wq == nil) @@ -802,16 +864,16 @@ ipwrite(Chan* ch, char* a, long n, ulong) x->kick(c, n); break; case Qarp: - return arpwrite(a, n); + return arpwrite(f->arp, a, n); case Qiproute: - return routewrite(ch, a, n); + return routewrite(f, ch, a, n); case Qlog: - p = netlogctl(a, n); + p = netlogctl(f, a, n); if(p != nil) error(p); return n; case Qctl: - x = fs.p[PROTO(ch->qid)]; + x = f->p[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; cb = parsecmd(a, n); @@ -887,26 +949,29 @@ Dev ipdevtab = { }; int -Fsproto(Fs *fs, Proto *p) +Fsproto(Fs *f, Proto *p) { - if(fs->np >= Maxproto) + if(f->np >= Maxproto) return -1; + p->f = f; + if(p->ipproto > 0){ - if(fs->t2p[p->ipproto] != nil) + if(f->t2p[p->ipproto] != nil) return -1; - fs->t2p[p->ipproto] = p; + f->t2p[p->ipproto] = p; } - p->qid.path = CHDIR|QID(fs->np, 0, Qprotodir); + p->qid.path = CHDIR|QID(f->np, 0, Qprotodir); p->conv = malloc(sizeof(Conv*)*(p->nc+1)); if(p->conv == nil) panic("Fsproto"); - p->x = fs->np; + p->x = f->np; p->nextport = 0; p->nextrport = 600; - fs->p[fs->np++] = p; + f->p[f->np++] = p; + return 0; } @@ -915,9 +980,9 @@ Fsproto(Fs *fs, Proto *p) * built in */ int -Fsbuiltinproto(Fs* fs, uchar proto) +Fsbuiltinproto(Fs* f, uchar proto) { - return fs->t2p[proto] != nil; + return f->t2p[proto] != nil; } Conv* @@ -990,7 +1055,7 @@ Fsprotoclone(Proto *p, char *user) } int -Fsconnected(Fs*, Conv* c, char* msg) +Fsconnected(Conv* c, char* msg) { if(msg != nil && *msg != '\0') strncpy(c->cerr, msg, ERRLEN-1); @@ -1011,13 +1076,13 @@ Fsconnected(Fs*, Conv* c, char* msg) } Proto* -Fsrcvpcol(Fs* fs, uchar proto) +Fsrcvpcol(Fs* f, uchar proto) { - return fs->t2p[proto]; + return f->t2p[proto]; } Conv* -Fsnewcall(Fs*, Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport) +Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport) { Conv *nc; Conv **l; diff --git a/ip/ethermedium.c b/ip/ethermedium.c index 76571a6c94f054d45284c5d3269b1e125ffbfed7..c5e9424b64fbbd5621eef6ff339caf8c8a2a0fea 100644 --- a/ip/ethermedium.c +++ b/ip/ethermedium.c @@ -22,7 +22,7 @@ static void etherunbind(Ipifc *ifc); static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia); static void etherremmulti(Ipifc *ifc, uchar *a, uchar *ia); -static Block* multicastarp(Arpent *a, uchar *mac); +static Block* multicastarp(Fs *f, Arpent *a, uchar *mac); static void sendarp(Ipifc *ifc, Arpent *a); static int multicastea(uchar *ea, uchar *ip); static void recvarpproc(Ipifc *ifc); @@ -51,6 +51,7 @@ Medium ethermedium = typedef struct Etherrock Etherrock; struct Etherrock { + Fs *f; /* file system we belong to */ Proc *arpp; /* arp process */ Proc *readp; /* reading process */ Chan *mchan; /* Data channel */ @@ -128,8 +129,8 @@ etherbind(Ipifc *ifc, int argc, char **argv) fd = kdial(addr, nil, dir, &cfd); if(fd < 0) error("dial 0x800 failed"); - mchan = fdtochan(fd, ORDWR, 0, 1); - cchan = fdtochan(cfd, ORDWR, 0, 1); + mchan = commonfdtochan(fd, ORDWR, 0, 1); + cchan = commonfdtochan(cfd, ORDWR, 0, 1); kclose(fd); kclose(cfd); @@ -162,13 +163,14 @@ etherbind(Ipifc *ifc, int argc, char **argv) fd = kdial(addr, nil, nil, nil); if(fd < 0) error("dial 0x806 failed"); - achan = fdtochan(fd, ORDWR, 0, 1); + achan = commonfdtochan(fd, ORDWR, 0, 1); kclose(fd); er = smalloc(sizeof(*er)); er->mchan = mchan; er->cchan = cchan; er->achan = achan; + er->f = ifc->conv->p->f; ifc->arg = er; free(buf); @@ -217,10 +219,10 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) Etherrock *er = ifc->arg; /* get mac address of destination */ - a = arpget(bp, version, ðermedium, ip, mac); + a = arpget(er->f->arp, bp, version, ðermedium, ip, mac); if(a){ /* check for broadcast or multicast */ - bp = multicastarp(a, mac); + bp = multicastarp(er->f, a, mac); if(bp == nil){ sendarp(ifc, a); return; @@ -281,7 +283,7 @@ etherread(void *a) if(ifc->lifc == nil) freeb(bp); else - ipiput(ifc->lifc->local, bp); + ipiput(er->f, ifc->lifc->local, bp); runlock(ifc); locked = 0; USED(locked); } @@ -325,7 +327,7 @@ sendarp(Ipifc *ifc, Arpent *a) /* don't do anything if it's been less than a second since the last */ if(msec - a->time < 1000){ - arprelease(a); + arprelease(er->f->arp, a); return; } @@ -339,7 +341,7 @@ sendarp(Ipifc *ifc, Arpent *a) /* try to keep it around for a second more */ a->time = msec; - arprelease(a); + arprelease(er->f->arp, a); n = sizeof(Etherarp); if(n < a->type->minmtu) @@ -387,7 +389,7 @@ recvarp(Ipifc *ifc) break; case ARPREPLY: - arpenter(ifc, V4, e->spa, e->sha, ðermedium, 0); + arpenter(er->f->arp, ifc, V4, e->spa, e->sha, ðermedium, 0); break; case ARPREQUEST: @@ -408,12 +410,12 @@ recvarp(Ipifc *ifc) } /* refresh what we know about sender */ - arpenter(ifc, V4, e->spa, e->sha, ðermedium, 1); + arpenter(er->f->arp, ifc, V4, e->spa, e->sha, ðermedium, 1); /* answer only requests for our address or systems we're proxying for */ v4tov6(ip, e->tpa); if(!iplocalonifc(ifc, ip)) - if(ipproxyifc(ifc, ip) == 0) + if(ipproxyifc(er->f, ifc, ip) == 0) break; /* print("arp: rem %I %E (for %I)\n", e->spa, e->sha, e->tpa); /**/ @@ -490,15 +492,15 @@ multicastea(uchar *ea, uchar *ip) * addresses */ static Block* -multicastarp(Arpent *a, uchar *mac) +multicastarp(Fs *f, Arpent *a, uchar *mac) { /* is it broadcast? */ - switch(ipforme(a->ip)){ + switch(ipforme(f, a->ip)){ case Runi: return nil; case Rbcast: memset(mac, 0xff, 6); - return arpresolve(a, ðermedium, mac); + return arpresolve(f->arp, a, ðermedium, mac); default: break; } @@ -507,7 +509,7 @@ multicastarp(Arpent *a, uchar *mac) switch(multicastea(mac, a->ip)){ case V4: case V6: - return arpresolve(a, ðermedium, mac); + return arpresolve(f->arp, a, ðermedium, mac); } /* let arp take care of it */ diff --git a/ip/gre.c b/ip/gre.c index 065a492f224db7fb298e5faf5ab05bee8c91173e..5cfa9b2ea781344ae1b9e0b35b214ca3a4f2ae2c 100644 --- a/ip/gre.c +++ b/ip/gre.c @@ -39,9 +39,13 @@ typedef struct GREhdr uchar eproto[2]; /* encapsulation protocol */ } GREhdr; - Proto gre; -extern Fs fs; - int gredebug; +typedef struct GREpriv GREpriv; +struct GREpriv +{ + /* non-MIB stats */ + ulong csumerr; /* checksum errors */ + ulong lenerr; /* short packet */ +}; static char* greconnect(Conv *c, char **argv, int argc) @@ -75,7 +79,7 @@ greconnect(Conv *c, char **argv, int argc) if(err != nil) return err; - Fsconnected(&fs, c, nil); + Fsconnected(c, nil); return nil; } @@ -147,7 +151,7 @@ grekick(Conv *c, int l) v4tov6(laddr, ghp->src); if(ipcmp(laddr, v4prefix) == 0){ if(ipcmp(c->laddr, IPnoaddr) == 0) - findlocalip(c->laddr, raddr); /* pick interface closest to dest */ + findlocalip(c->p->f, c->laddr, raddr); /* pick interface closest to dest */ memmove(ghp->src, c->laddr + IPv4off, IPv4addrlen); } @@ -156,18 +160,20 @@ grekick(Conv *c, int l) ghp->frag[0] = 0; ghp->frag[1] = 0; - ipoput(bp, 0, c->ttl); + ipoput(c->p->f, bp, 0, c->ttl); } static void -greiput(uchar*, Block *bp) +greiput(Proto *gre, uchar*, Block *bp) { int len; GREhdr *ghp; Conv *c, **p; ushort eproto; uchar raddr[IPaddrlen]; + GREpriv *gpriv; + gpriv = gre->priv; ghp = (GREhdr*)(bp->rp); v4tov6(raddr, ghp->src); @@ -175,7 +181,7 @@ greiput(uchar*, Block *bp) /* Look for a conversation structure for this port and address */ c = nil; - for(p = gre.conv; *p; p++) { + for(p = gre->conv; *p; p++) { c = *p; if(c->inuse == 0) continue; @@ -198,7 +204,7 @@ greiput(uchar*, Block *bp) } bp = trimblock(bp, GRE_IPONLY, len); if(bp == nil){ - gre.lenerr++; + gpriv->lenerr++; return; } @@ -216,30 +222,36 @@ greiput(uchar*, Block *bp) } int -grestats(char *buf, int len) +grestats(Proto *gre, char *buf, int len) { - return snprint(buf, len, - "gre: csum %d hlen %d len %d order %d rexmit %d\n", - gre.csumerr, gre.hlenerr, gre.lenerr, gre.order, gre.rexmit); + GREpriv *gpriv; + + gpriv = gre->priv; + + return snprint(buf, len, "gre: len %d\n", gpriv->lenerr); } void greinit(Fs *fs) { - gre.name = "gre"; - gre.kick = grekick; - gre.connect = greconnect; - gre.announce = greannounce; - gre.state = grestate; - gre.create = grecreate; - gre.close = greclose; - gre.rcv = greiput; - gre.ctl = nil; - gre.advise = nil; - gre.stats = grestats; - gre.ipproto = IP_GREPROTO; - gre.nc = 64; - gre.ptclsize = 0; - - Fsproto(fs, &gre); + Proto *gre; + + gre = smalloc(sizeof(Proto)); + gre->priv = smalloc(sizeof(GREpriv)); + gre->name = "gre"; + gre->kick = grekick; + gre->connect = greconnect; + gre->announce = greannounce; + gre->state = grestate; + gre->create = grecreate; + gre->close = greclose; + gre->rcv = greiput; + gre->ctl = nil; + gre->advise = nil; + gre->stats = grestats; + gre->ipproto = IP_GREPROTO; + gre->nc = 64; + gre->ptclsize = 0; + + Fsproto(fs, gre); } diff --git a/ip/icmp.c b/ip/icmp.c index 623547145816805b2ef0cbe8a8e4514a097b5d9b..4fa21dd6edf420537349c2d344b21f5d8ba9e4b7 100644 --- a/ip/icmp.c +++ b/ip/icmp.c @@ -46,14 +46,16 @@ enum { ICMP_HDRSIZE = 8, }; - Proto icmp; -extern Fs fs; - -static struct Icmpstats +typedef struct Icmppriv Icmppriv; +struct Icmppriv { + /* non-MIB stats */ + ulong csumerr; /* checksum errors */ + ulong lenerr; /* short packet */ + ulong hlenerr; /* short header */ ulong in[Maxtype+1]; ulong out[Maxtype+1]; -} stats; +}; static char* icmpconnect(Conv *c, char **argv, int argc) @@ -61,7 +63,7 @@ icmpconnect(Conv *c, char **argv, int argc) char *e; e = Fsstdconnect(c, argv, argc); - Fsconnected(&fs, c, e); + Fsconnected(c, e); return e; } @@ -88,7 +90,7 @@ icmpannounce(Conv *c, char **argv, int argc) e = Fsstdannounce(c, argv, argc); if(e != nil); return e; - Fsconnected(&fs, c, nil); + Fsconnected(c, nil); return nil; } @@ -109,6 +111,7 @@ icmpkick(Conv *c, int l) { Icmp *p; Block *bp; + Icmppriv *ipriv; USED(l); bp = qget(c->wq); @@ -120,25 +123,27 @@ icmpkick(Conv *c, int l) return; } p = (Icmp *)(bp->rp); - if(p->type <= Maxtype) - stats.out[p->type]++; + if(p->type <= Maxtype){ + ipriv = c->p->priv; + ipriv->out[p->type]++; + } v6tov4(p->dst, c->raddr); v6tov4(p->src, c->laddr); p->proto = IP_ICMPPROTO; hnputs(p->icmpid, c->lport); memset(p->cksum, 0, sizeof(p->cksum)); hnputs(p->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE)); - ipoput(bp, 0, c->ttl); + ipoput(c->p->f, bp, 0, c->ttl); } extern void -icmpnoconv(Block *bp) +icmpnoconv(Fs *f, Block *bp) { Block *nbp; Icmp *p, *np; p = (Icmp *)bp->rp; - netlog(Logicmp, "sending icmpnoconv -> %V\n", p->src); + netlog(f, Logicmp, "sending icmpnoconv -> %V\n", p->src); nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8); nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8; np = (Icmp *)nbp->rp; @@ -152,12 +157,12 @@ icmpnoconv(Block *bp) hnputs(np->seq, 0); memset(np->cksum, 0, sizeof(np->cksum)); hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE)); - stats.out[Unreachable]++; - ipoput(nbp, 0, MAXTTL); +/* stats.out[Unreachable]++; */ + ipoput(f, nbp, 0, MAXTTL); } static void -goticmpkt(Block *bp) +goticmpkt(Proto *icmp, Block *bp) { Conv **c, *s; Icmp *p; @@ -168,7 +173,7 @@ goticmpkt(Block *bp) v4tov6(dst, p->src); recid = nhgets(p->icmpid); - for(c = icmp.conv; *c; c++) { + for(c = icmp->conv; *c; c++) { s = *c; if(s->lport == recid) if(ipcmp(s->raddr, dst) == 0){ @@ -207,7 +212,7 @@ static char *unreachcode[] = }; static void -icmpiput(uchar*, Block *bp) +icmpiput(Proto *icmp, uchar*, Block *bp) { int n, iplen; Icmp *p; @@ -215,33 +220,36 @@ icmpiput(uchar*, Block *bp) Proto *pr; char *msg; char m2[128]; + Icmppriv *ipriv; + + ipriv = icmp->priv; p = (Icmp *)bp->rp; - netlog(Logicmp, "icmpiput %d %d\n", p->type, p->code); + netlog(icmp->f, Logicmp, "icmpiput %d %d\n", p->type, p->code); n = blocklen(bp); if(n < ICMP_IPSIZE+ICMP_HDRSIZE){ - icmp.hlenerr++; - netlog(Logicmp, "icmp hlen %d\n", n); + ipriv->hlenerr++; + netlog(icmp->f, Logicmp, "icmp hlen %d\n", n); goto raise; } iplen = nhgets(p->length); if(iplen > n || (iplen % 1)){ - icmp.lenerr++; - netlog(Logicmp, "icmp length %d\n", iplen); + ipriv->lenerr++; + netlog(icmp->f, Logicmp, "icmp length %d\n", iplen); goto raise; } if(ptclcsum(bp, ICMP_IPSIZE, iplen - ICMP_IPSIZE)){ - icmp.csumerr++; - netlog(Logicmp, "icmp checksum error\n"); + ipriv->csumerr++; + netlog(icmp->f, Logicmp, "icmp checksum error\n"); goto raise; } if(p->type <= Maxtype) - stats.in[p->type]++; + ipriv->in[p->type]++; switch(p->type) { case EchoRequest: r = mkechoreply(bp); - stats.out[EchoReply]++; - ipoput(r, 0, MAXTTL); + ipriv->out[EchoReply]++; + ipoput(icmp->f, r, 0, MAXTTL); break; case Unreachable: if(p->code > 5 || p->code < 0) @@ -251,18 +259,18 @@ icmpiput(uchar*, Block *bp) bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE; if(blocklen(bp) < 8){ - icmp.lenerr++; + ipriv->lenerr++; goto raise; } p = (Icmp *)bp->rp; - pr = Fsrcvpcol(&fs, p->proto); + pr = Fsrcvpcol(icmp->f, p->proto); if(pr != nil && pr->advise != nil) { - (*pr->advise)(bp, msg); + (*pr->advise)(pr, bp, msg); return; } bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE; - goticmpkt(bp); + goticmpkt(icmp, bp); break; case TimeExceed: if(p->code == 0){ @@ -270,21 +278,21 @@ icmpiput(uchar*, Block *bp) bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE; if(blocklen(bp) < 8){ - icmp.lenerr++; + ipriv->lenerr++; goto raise; } p = (Icmp *)bp->rp; - pr = Fsrcvpcol(&fs, p->proto); + pr = Fsrcvpcol(icmp->f, p->proto); if(pr != nil && pr->advise != nil) { - (*pr->advise)(bp, m2); + (*pr->advise)(pr, bp, m2); return; } } - goticmpkt(bp); + goticmpkt(icmp, bp); break; default: - goticmpkt(bp); + goticmpkt(icmp, bp); break; } return; @@ -294,7 +302,7 @@ raise: } void -icmpadvise(Block *bp, char *msg) +icmpadvise(Proto *icmp, Block *bp, char *msg) { Conv **c, *s; Icmp *p; @@ -305,7 +313,7 @@ icmpadvise(Block *bp, char *msg) v4tov6(dst, p->dst); recid = nhgets(p->icmpid); - for(c = icmp.conv; *c; c++) { + for(c = icmp->conv; *c; c++) { s = *c; if(s->lport == recid) if(ipcmp(s->raddr, dst) == 0){ @@ -318,20 +326,22 @@ icmpadvise(Block *bp, char *msg) } int -icmpstats(char *buf, int len) +icmpstats(Proto *icmp, char *buf, int len) { int i, n; + Icmppriv *ipriv; + ipriv = icmp->priv; n = snprint(buf, len, - "icmp: csum %d hlen %d len %d order %d rexmit %d\n", - icmp.csumerr, icmp.hlenerr, icmp.lenerr, icmp.order, icmp.rexmit); + "icmp: csum %d hlen %d len %d\n", + ipriv->csumerr, ipriv->hlenerr, ipriv->lenerr); n += snprint(buf+n, len-n, "\trcvd "); for(i = 0; i < Maxtype && len > n; i++) - n += snprint(buf+n, len-n, " %d", stats.in[i]); + n += snprint(buf+n, len-n, " %d", ipriv->in[i]); n += snprint(buf+n, len-n, "\n\tsent "); for(i = 0; i < Maxtype && len > n; i++) - n += snprint(buf+n, len-n, " %d", stats.out[i]); + n += snprint(buf+n, len-n, " %d", ipriv->out[i]); if(n < len) n += snprint(buf+n, len-n, "\n"); return n; @@ -340,20 +350,24 @@ icmpstats(char *buf, int len) void icmpinit(Fs *fs) { - icmp.name = "icmp"; - icmp.kick = icmpkick; - icmp.connect = icmpconnect; - icmp.announce = icmpannounce; - icmp.state = icmpstate; - icmp.create = icmpcreate; - icmp.close = icmpclose; - icmp.rcv = icmpiput; - icmp.stats = icmpstats; - icmp.ctl = nil; - icmp.advise = icmpadvise; - icmp.ipproto = IP_ICMPPROTO; - icmp.nc = 16; - icmp.ptclsize = 0; - - Fsproto(fs, &icmp); + Proto *icmp; + + icmp = smalloc(sizeof(Proto)); + icmp->priv = smalloc(sizeof(Icmppriv)); + icmp->name = "icmp"; + icmp->kick = icmpkick; + icmp->connect = icmpconnect; + icmp->announce = icmpannounce; + icmp->state = icmpstate; + icmp->create = icmpcreate; + icmp->close = icmpclose; + icmp->rcv = icmpiput; + icmp->stats = icmpstats; + icmp->ctl = nil; + icmp->advise = icmpadvise; + icmp->ipproto = IP_ICMPPROTO; + icmp->nc = 16; + icmp->ptclsize = 0; + + Fsproto(fs, icmp); } diff --git a/ip/il.c b/ip/il.c index 4d8c58016fd785cffd8001f280711310ac5b0d20..11b7ae73f21c88914e0e0e64dab85c2a01615f35 100644 --- a/ip/il.c +++ b/ip/il.c @@ -121,11 +121,22 @@ struct Ilhdr uchar ilack[4]; /* Acked sequence */ }; -static struct Ilstats + +typedef struct Ilpriv Ilpriv; +struct Ilpriv { - ulong dup; - ulong dupb; -} ilstats; + + /* non-MIB stats */ + ulong csumerr; /* checksum errors */ + ulong hlenerr; /* header length error */ + ulong lenerr; /* short packet */ + ulong order; /* out of order */ + ulong rexmit; /* retransmissions */ + ulong dup; + ulong dupb; + + Rendez ilr; +}; /* Always Acktime < Fasttime < Slowtime << Ackkeepalive */ enum @@ -164,18 +175,14 @@ void ilrexmit(Ilcb*); void ilbackoff(Ilcb*); void iltimers(Ilcb*); char* ilstart(Conv*, int, int); -void ilackproc(); +void ilackproc(void*); void iloutoforder(Conv*, Ilhdr*, Block*); -void iliput(uchar*, Block*); -void iladvise(Block*, char*); +void iliput(Proto*, uchar*, Block*); +void iladvise(Proto*, Block*, char*); int ilnextqt(Ilcb*); -#define DBG(x) if((logmask & Logilmsg) && (iponly == 0 || x == iponly))netlog - - Proto il; int ilcksum = 1; static int initseq = 25001; -extern Fs fs; static char* ilconnect(Conv *c, char **argv, int argc) @@ -222,7 +229,7 @@ ilannounce(Conv *c, char **argv, int argc) e = ilstart(c, IL_LISTEN, 20); if(e != nil) return e; - Fsconnected(&fs, c, nil); + Fsconnected(c, nil); return nil; } @@ -266,9 +273,11 @@ ilkick(Conv *c, int l) int dlen; ulong id; Block *bp; + Fs *f; USED(l); + f = c->p->f; ic = (Ilcb*)c->ptcl; bp = qget(c->wq); @@ -327,7 +336,7 @@ ilkick(Conv *c, int l) } ic->acktime = Ackkeepalive; - ipoput(bp, 0, c->ttl); + ipoput(f, bp, 0, c->ttl); } static void @@ -338,40 +347,46 @@ ilcreate(Conv *c) } int -ilxstats(char *buf, int len) +ilxstats(Proto *il, char *buf, int len) { int n; + Ilpriv *ipriv; + + ipriv = il->priv; n = snprint(buf, len, "il: csum %d hlen %d len %d order %d rexmit %d", - il.csumerr, il.hlenerr, il.lenerr, il.order, il.rexmit); + ipriv->csumerr, ipriv->hlenerr, ipriv->lenerr, ipriv->order, ipriv->rexmit); n += snprint(buf+n, len-n, " dupp %d dupb %d\n", - ilstats.dup, ilstats.dupb); + ipriv->dup, ipriv->dupb); return n; } void -ilinit(Fs *fs) +ilinit(Fs *f) { - il.name = "il"; - il.kick = ilkick; - il.connect = ilconnect; - il.announce = ilannounce; - il.state = ilstate; - il.create = ilcreate; - il.close = ilclose; - il.rcv = iliput; - il.ctl = nil; - il.advise = iladvise; - il.stats = ilxstats; - il.inuse = ilinuse; - il.ipproto = IP_ILPROTO; - il.nc = Nchans; - il.ptclsize = sizeof(Ilcb); - - kproc("ilack", ilackproc, 0); - - Fsproto(fs, &il); + Proto *il; + + il = smalloc(sizeof(Proto)); + il->priv = smalloc(sizeof(Ilpriv)); + il->name = "il"; + il->kick = ilkick; + il->connect = ilconnect; + il->announce = ilannounce; + il->state = ilstate; + il->create = ilcreate; + il->close = ilclose; + il->rcv = iliput; + il->ctl = nil; + il->advise = iladvise; + il->stats = ilxstats; + il->inuse = ilinuse; + il->ipproto = IP_ILPROTO; + il->nc = Nchans; + il->ptclsize = sizeof(Ilcb); + Fsproto(f, il); + + kproc("ilack", ilackproc, il); } void @@ -467,7 +482,7 @@ ilackto(Ilcb *ic, ulong ackto) } void -iliput(uchar*, Block *bp) +iliput(Proto *il, uchar*, Block *bp) { char *st; Ilcb *ic; @@ -477,19 +492,22 @@ iliput(uchar*, Block *bp) ushort sp, dp, csum; int plen, illen; Conv *s, **p, *new, *spec, *gen; + Ilpriv *ipriv; + + ipriv = il->priv; ih = (Ilhdr *)bp->rp; plen = blocklen(bp); if(plen < IL_IPSIZE+IL_HDRSIZE){ - netlog(Logil, "il: hlenerr\n"); - il.hlenerr++; + netlog(il->f, Logil, "il: hlenerr\n"); + ipriv->hlenerr++; goto raise; } illen = nhgets(ih->illen); if(illen+IL_IPSIZE > plen){ - netlog(Logil, "il: lenerr\n"); - il.lenerr++; + netlog(il->f, Logil, "il: lenerr\n"); + ipriv->lenerr++; goto raise; } @@ -497,18 +515,18 @@ iliput(uchar*, Block *bp) dp = nhgets(ih->ilsrc); v4tov6(raddr, ih->src); - if(ilcksum && (csum = ptclcsum(bp, IL_IPSIZE, illen)) != 0) { + if((csum = ptclcsum(bp, IL_IPSIZE, illen)) != 0) { if(ih->iltype < 0 || ih->iltype > Ilclose) st = "?"; else st = iltype[ih->iltype]; - il.csumerr++; - netlog(Logil, "il: cksum %ux %ux, pkt(%s id %lud ack %lud %I/%d->%d)\n", + ipriv->csumerr++; + netlog(il->f, Logil, "il: cksum %ux %ux, pkt(%s id %lud ack %lud %I/%d->%d)\n", csum, st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp); goto raise; } - for(p = il.conv; *p; p++) { + for(p = il->conv; *p; p++) { s = *p; if(s->lport == sp) if(s->rport == dp) @@ -523,14 +541,14 @@ iliput(uchar*, Block *bp) st = "?"; else st = iltype[ih->iltype]; - netlog(Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n", + netlog(il->f, Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n", st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp); goto raise; } gen = nil; spec = nil; - for(p = il.conv; *p; p++) { + for(p = il->conv; *p; p++) { s = *p; ic = (Ilcb*)s->ptcl; if(ic->state != Illistening) @@ -555,9 +573,9 @@ iliput(uchar*, Block *bp) goto raise; v4tov6(laddr, ih->dst); - new = Fsnewcall(&fs, s, raddr, dp, laddr, sp); + new = Fsnewcall(s, raddr, dp, laddr, sp); if(new == nil){ - netlog(Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp); + netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp); ilsendctl(nil, ih, Ilclose, 0, nhgetl(ih->ilid), 0); goto raise; } @@ -602,7 +620,7 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) switch(ic->state) { default: - netlog(Logil, "il: unknown state %d\n", ic->state); + netlog(s->p->f, Logil, "il: unknown state %d\n", ic->state); case Ilclosed: freeblist(bp); break; @@ -618,7 +636,7 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) ic->rstart = id; ilsendctl(s, nil, Ilack, ic->next, ic->recvd, 0); ic->state = Ilestablished; - Fsconnected(&fs, s, nil); + Fsconnected(s, nil); ilpullup(s); iltimers(ic); } @@ -742,6 +760,7 @@ ilrexmit(Ilcb *ic) Conv *c; ulong id; int x; + Ilpriv *ipriv; nb = nil; qlock(&ic->ackq); @@ -759,16 +778,16 @@ ilrexmit(Ilcb *ic) h->ilspec = ilnextqt(ic); h->ilsum[0] = 0; h->ilsum[1] = 0; - if(ilcksum) - hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen))); + hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen))); c = ic->conv; + ipriv = c->p->priv; id = nhgetl(h->ilid); - netlog(Logil, "il: rexmit %ud %ud: %d %d: %i %d/%d\n", id, ic->recvd, + netlog(c->p->f, Logil, "il: rexmit %ud %ud: %d %d: %i %d/%d\n", id, ic->recvd, ic->fasttime, ic->timeout, c->raddr, c->lport, c->rport); - il.rexmit++; + ipriv->rexmit++; ic->rexmit++; /* @@ -782,7 +801,7 @@ ilrexmit(Ilcb *ic) if(x >= (1<rate = x; - ipoput(nb, 0, ic->conv->ttl); + ipoput(c->p->f, nb, 0, ic->conv->ttl); } /* DEBUG */ @@ -794,14 +813,14 @@ ilprocess(Conv *s, Ilhdr *h, Block *bp) ic = (Ilcb*)s->ptcl; USED(ic); - DBG(s->raddr)(Logilmsg, "%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ", + netlog(s->p->f, Logilmsg, "%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ", ilstates[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(s->raddr)(Logilmsg, "%11s rcv %d snt %d\n", ilstates[ic->state], ic->recvd, ic->next); + netlog(s->p->f, Logilmsg, "%11s rcv %d snt %d\n", ilstates[ic->state], ic->recvd, ic->next); } void @@ -810,7 +829,7 @@ ilhangup(Conv *s, char *msg) Ilcb *ic; int callout; - netlog(Logil, "il: hangup! %I %d/%d: %s\n", s->raddr, s->lport, s->rport, msg?msg:"no reason"); + netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr, s->lport, s->rport, msg?msg:"no reason"); ic = (Ilcb*)s->ptcl; callout = ic->state == Ilsyncer; @@ -820,7 +839,7 @@ ilhangup(Conv *s, char *msg) qhangup(s->wq, msg); if(callout) - Fsconnected(&fs, s, msg); + Fsconnected(s, msg); } void @@ -830,6 +849,7 @@ ilpullup(Conv *s) Ilhdr *oh; Block *bp; ulong oid, dlen; + Ilpriv *ipriv; ic = (Ilcb*)s->ptcl; if(ic->state != Ilestablished) @@ -846,7 +866,8 @@ ilpullup(Conv *s) continue; } if(oid != ic->recvd+1){ - il.order++; + ipriv = s->p->priv; + ipriv->order++; break; } @@ -875,14 +896,16 @@ iloutoforder(Conv *s, Ilhdr *h, Block *bp) uchar *lid; Block *f, **l; ulong id, newid; + Ilpriv *ipriv; + ipriv = s->p->priv; ic = (Ilcb*)s->ptcl; bp->list = nil; id = nhgetl(h->ilid); /* Window checks */ if(id <= ic->recvd || id > ic->recvd+ic->window) { - netlog(Logil, "il: message outside window %ud <%ud-%ud>: %i %d/%d\n", + netlog(s->p->f, Logil, "il: message outside window %ud <%ud-%ud>: %i %d/%d\n", id, ic->recvd, ic->recvd+ic->window, s->raddr, s->lport, s->rport); freeblist(bp); return; @@ -899,8 +922,8 @@ iloutoforder(Conv *s, Ilhdr *h, Block *bp) newid = nhgetl(lid); if(id <= newid) { if(id == newid) { - ilstats.dup++; - ilstats.dupb += blocklen(bp); + ipriv->dup++; + ipriv->dupb += blocklen(bp); qunlock(&ic->outo); freeblist(bp); return; @@ -964,24 +987,28 @@ ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec) hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE)); if(ipc){ - DBG(ipc->raddr)(Logilmsg, "ctl(%s id %d ack %d %d->%d)\n", + netlog(ipc->p->f, Logilmsg, "ctl(%s id %d ack %d %d->%d)\n", iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack), nhgets(ih->ilsrc), nhgets(ih->ildst)); } - ipoput(bp, 0, ttl); + ipoput(ipc->p->f, bp, 0, ttl); } void -ilackproc() +ilackproc(void *x) { Ilcb *ic; Conv **s, *p; - static Rendez ilr; + Proto *il; + Ilpriv *ipriv; + + il = x; + ipriv = il->priv; loop: - tsleep(&ilr, return0, 0, Iltickms); - for(s = il.conv; s && *s; s++) { + tsleep(&ipriv->ilr, return0, 0, Iltickms); + for(s = il->conv; s && *s; s++) { p = *s; ic = (Ilcb*)p->ptcl; @@ -1016,7 +1043,7 @@ loop: if(ic->querytime <= 0){ ic->deathtime -= Querytime; if(ic->deathtime < 0){ - netlog(Logil, "il: hangup due to deathtime (%d) < 0 \n", ic->deathtime); + netlog(il->f, Logil, "il: hangup due to deathtime (%d) < 0 \n", ic->deathtime); ilhangup(p, etime); break; } @@ -1032,7 +1059,7 @@ loop: ilbackoff(ic); } if(ic->timeout >= ic->slowtime) { - netlog(Logil, "il: hangup due to timeout (%d) >= slowtime (%d)\n", ic->timeout, ic->slowtime); + netlog(il->f, Logil, "il: hangup due to timeout (%d) >= slowtime (%d)\n", ic->timeout, ic->slowtime); ilhangup(p, etime); break; } @@ -1080,7 +1107,7 @@ ilstart(Conv *c, int type, int window) switch(type) { default: - netlog(Logil, "il: start: type %d\n", type); + netlog(c->p->f, Logil, "il: start: type %d\n", type); break; case IL_LISTEN: ic->state = Illistening; @@ -1132,7 +1159,7 @@ iltimers(Ilcb *ic) } void -iladvise(Block *bp, char *msg) +iladvise(Proto *il, Block *bp, char *msg) { Ilhdr *h; Ilcb *ic; @@ -1148,7 +1175,7 @@ iladvise(Block *bp, char *msg) /* Look for a connection, unfortunately the destination port is missing */ - for(p = il.conv; *p; p++) { + for(p = il->conv; *p; p++) { s = *p; if(s->lport == psource) if(ipcmp(s->laddr, source) == 0) diff --git a/ip/inferno.c b/ip/inferno.c new file mode 100644 index 0000000000000000000000000000000000000000..211b745038adc524e342308880265be337df7d0d --- /dev/null +++ b/ip/inferno.c @@ -0,0 +1,46 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "ip.h" + +/* + * some hacks for commonality twixt inferno and plan9 + */ + +char* +commonuser(void) +{ + return up->user; +} + +Chan* +commonfdtochan(int fd, int mode, int a, int b) +{ + return fdtochan(fd, mode, a, b); +} + +char* +commonerror(void) +{ + return up->error; +} + +char* +bootp(Ipifc*) +{ + return "unimplmented"; +} + +int +bootpread(char*, ulong, int) +{ + return 0; +} + +Medium tripmedium = +{ + "trip", +}; diff --git a/ip/ip.c b/ip/ip.c index d9105e75dada35645dbdcf1e180872bfe0554c2b..637780bf2cd26b2b5986c5f28818544b166a3d7c 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -26,13 +26,13 @@ struct Iphdr uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ - uchar id[2]; /* Identification */ + uchar id[2]; /* ip->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 */ + uchar src[4]; /* IP source */ + uchar dst[4]; /* IP destination */ }; struct Fragment @@ -51,14 +51,44 @@ struct Ipfrag ushort flen; }; -QLock fraglock; -Fragment* flisthead; -Fragment* fragfree; -ulong Id; -int iprouting; /* true if we route like a gateway */ -ulong ipcsumerr; -ulong ipin, ippin; /* uchars, packets in */ -ulong ipout, ippout; /* uchars, packets out */ +/* MIB II counters */ +typedef struct Ipstats Ipstats; +struct Ipstats +{ + ulong ipForwarding; + ulong ipDefaultTTL; + ulong ipInReceives; + ulong ipInHdrErrors; + ulong ipInAddrErrors; + ulong ipForwDatagrams; + ulong ipInUnknownProtos; + ulong ipInDiscards; + ulong ipInDelivers; + ulong ipOutRequests; + ulong ipOutDiscards; + ulong ipOutNoRoutes; + ulong ipReasmTimeout; + ulong ipReasmReqds; + ulong ipReasmOKs; + ulong ipReasmFails; + ulong ipFragOKs; + ulong ipFragFails; + ulong ipFragCreates; +}; + +/* an instance of IP */ +struct IP +{ + Ipstats istats; + + QLock fraglock; + Fragment* flisthead; + Fragment* fragfree; + + ulong id; + int iprouting; /* true if we route like a gateway */ + void (*ipextprotoiput)(Block*); +}; #define BLKIP(xp) ((Iphdr*)((xp)->rp)) /* @@ -67,19 +97,23 @@ ulong ipout, ippout; /* uchars, packets out */ */ #define BKFG(xp) ((Ipfrag*)((xp)->base)) -static struct Stats +ushort ipcsum(uchar*); +Block* ipreassemble(IP*, int, Block*, Iphdr*); +void ipfragfree(IP*, Fragment*); +Fragment* ipfragallo(IP*); + +void +ip_init(Fs *f) { - ulong noroute; - ulong droppedfrag; -} stats; + IP *ip; -ushort ipcsum(uchar*); -Block* ipreassemble(int, Block*, Iphdr*); -void ipfragfree(Fragment*); -Fragment* ipfragallo(void); + ip = smalloc(sizeof(IP)); + initfrag(ip, 100); + f->ip = ip; +} void -ipoput(Block *bp, int gating, int ttl) +ipoput(Fs *f, Block *bp, int gating, int ttl) { Ipifc *ifc; uchar *gate; @@ -87,45 +121,60 @@ ipoput(Block *bp, int gating, int ttl) Block *xp, *nb; Iphdr *eh, *feh; int lid, len, seglen, chunk, dlen, blklen, offset, medialen; - Route *r; + Route *r, *sr; + IP *ip; + + ip = f->ip; /* Fill out the ip header */ eh = (Iphdr *)(bp->rp); + ip->istats.ipOutRequests++; + /* Number of uchars in data and ip header to write */ len = blocklen(bp); - ipout += len; - ippout++; + if(gating){ chunk = nhgets(eh->length); if(chunk > len){ - netlog(Logip, "short gated packet\n"); + ip->istats.ipOutDiscards++; + netlog(f, Logip, "short gated packet\n"); goto free; } if(chunk < len) len = chunk; } if(len >= IP_MAX){ - netlog(Logip, "exceeded ip max size %V\n", eh->dst); + ip->istats.ipOutDiscards++; + netlog(f, Logip, "exceeded ip max size %V\n", eh->dst); goto free; } - r = v4lookup(eh->dst); + r = v4lookup(f, eh->dst); if(r == nil){ - stats.noroute++; - netlog(Logip, "no interface %V\n", eh->dst); + ip->istats.ipOutNoRoutes++; + netlog(f, Logip, "no interface %V\n", eh->dst); goto free; } - if(r->type & (Rifc|Runi|Rbcast|Rmulti)) + + ifc = r->ifc; + if(r->type & (Rifc|Runi)) gate = eh->dst; + else + if(r->type & (Rbcast|Rmulti)) { + gate = eh->dst; + sr = v4lookup(f, eh->src); + if(sr != nil && (sr->type & Runi)) + ifc = sr->ifc; + } else gate = r->v4.gate; + if(!gating){ eh->vihl = IP_VER|IP_HLEN; eh->tos = 0; eh->ttl = ttl; } - ifc = r->ifc; if(waserror()){ runlock(ifc); @@ -139,7 +188,7 @@ ipoput(Block *bp, int gating, int ttl) medialen = ifc->m->maxmtu - ifc->m->hsize; if(len <= medialen) { if(!gating) - hnputs(eh->id, Id++); + hnputs(eh->id, ip->id++); hnputs(eh->length, len); eh->frag[0] = 0; eh->frag[1] = 0; @@ -147,7 +196,7 @@ ipoput(Block *bp, int gating, int ttl) eh->cksum[1] = 0; hnputs(eh->cksum, ipcsum(&eh->vihl)); -/*print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate);*/ +/* print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate); /**/ ifc->m->bwrite(ifc, bp, V4, gate); runlock(ifc); poperror(); @@ -155,13 +204,15 @@ ipoput(Block *bp, int gating, int ttl) } if(eh->frag[0] & (IP_DF>>8)){ - netlog(Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst); + ip->istats.ipOutDiscards++; + netlog(f, Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst); goto raise; } seglen = (medialen - IPHDR) & ~7; if(seglen < 8){ - netlog(Logip, "%V seglen < 8\n", eh->dst); + ip->istats.ipOutDiscards++; + netlog(f, Logip, "%V seglen < 8\n", eh->dst); goto raise; } @@ -170,7 +221,7 @@ ipoput(Block *bp, int gating, int ttl) if(gating) lid = nhgets(eh->id); else - lid = Id++; + lid = ip->id++; offset = IPHDR; while(xp != nil && offset && offset >= BLEN(xp)) { @@ -200,8 +251,9 @@ ipoput(Block *bp, int gating, int ttl) chunk = seglen; while(chunk) { if(!xp) { + ip->istats.ipOutDiscards++; freeblist(nb); - netlog(Logip, "!xp: chunk %d\n", chunk); + netlog(f, Logip, "!xp: chunk %d\n", chunk); goto raise; } blklen = chunk; @@ -213,14 +265,14 @@ ipoput(Block *bp, int gating, int ttl) chunk -= blklen; if(xp->rp == xp->wp) xp = xp->next; - } + } feh->cksum[0] = 0; feh->cksum[1] = 0; hnputs(feh->cksum, ipcsum(&feh->vihl)); ifc->m->bwrite(ifc, nb, V4, gate); + ip->istats.ipFragCreates++; } - raise: runlock(ifc); poperror(); @@ -229,36 +281,40 @@ free: } void -initfrag(int size) +initfrag(IP *ip, int size) { Fragment *fq, *eq; - fragfree = (Fragment*)malloc(sizeof(Fragment) * size); - if(fragfree == nil) + ip->fragfree = (Fragment*)malloc(sizeof(Fragment) * size); + if(ip->fragfree == nil) panic("initfrag"); - eq = &fragfree[size]; - for(fq = fragfree; fq < eq; fq++) + eq = &ip->fragfree[size]; + for(fq = ip->fragfree; fq < eq; fq++) fq->next = fq+1; - fragfree[size-1].next = nil; + ip->fragfree[size-1].next = nil; } -void (*ipextprotoiput)(Block*); - -//#define DBG(x) if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog +#define DBG(x) if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog void -ipiput(uchar *ia, Block *bp) +ipiput(Fs *f, uchar *ia, Block *bp) { + int hl; Iphdr *h; Proto *p; ushort frag; int notforme; - uchar v6dst[IPaddrlen]; + uchar *dp, v6dst[IPaddrlen]; + IP *ip; + + ip = f->ip; + ip->istats.ipInReceives++; // h = (Iphdr *)(bp->rp); -// DBG(nhgetl(h->src))(Logipmsg, "ipiput %I %I len %d proto %d\n", h->src, h->dst, BLEN(bp), h->proto); +// DBG(nhgetl(h->src))(Logipmsg, "ipiput %V %V len %d proto %d\n", +// h->src, h->dst, BLEN(bp), h->proto); /* Ensure we have enough data to process */ if(BLEN(bp) < IPHDR) { @@ -270,70 +326,95 @@ ipiput(uchar *ia, Block *bp) /* dump anything that whose header doesn't checksum */ if(ipcsum(&h->vihl)) { - ipcsumerr++; - netlog(Logip, "ip: checksum error %I\n", h->src); + ip->istats.ipInHdrErrors++; + netlog(f, Logip, "ip: checksum error %I\n", h->src); freeblist(bp); return; } - /* route */ v4tov6(v6dst, h->dst); - notforme = ipforme(v6dst) == 0; + notforme = ipforme(f, v6dst) == 0; + + /* Check header length and version */ + if(h->vihl != (IP_VER|IP_HLEN)) { + hl = (h->vihl&0xF)<<2; + if((h->vihl&0xF0) != IP_VER || hl < (IP_HLEN<<2)) { + ip->istats.ipInHdrErrors++; + netlog(f, Logip, "ip: %V bad hivl %ux\n", h->src, h->vihl); + freeblist(bp); + return; + } + /* If this is not routed strip off the options */ + if(notforme == 0) { + dp = bp->rp + (hl - (IP_HLEN<<2)); + memmove(dp, h, IP_HLEN<<2); + bp->rp = dp; + h = (Iphdr *)(bp->rp); + h->vihl = (IP_VER|IP_HLEN); + } + } + + /* route */ if(notforme) { - if(iprouting) { + if(ip->iprouting) { /* gate */ if(h->ttl <= 1) freeblist(bp); - else - ipoput(bp, 1, h->ttl - 1); + else { + ip->istats.ipForwDatagrams++; + ipoput(f, bp, 1, h->ttl - 1); + } } else - useriprouter(ia, bp); + useriprouter(f, ia, bp); return; } - /* Check header length and version */ - if(h->vihl != (IP_VER|IP_HLEN)) { - netlog(Logip, "ip: %I bad hivl %ux\n", h->src, h->vihl); - freeblist(bp); - return; - } + + frag = nhgets(h->frag); if(frag) { h->tos = 0; if(frag & IP_MF) h->tos = 1; - bp = ipreassemble(frag, bp, h); + bp = ipreassemble(ip, frag, bp, h); if(bp == nil) return; h = (Iphdr *)(bp->rp); } - ipin += blocklen(bp); - ippin++; - - p = Fsrcvpcol(&fs, h->proto); - if(p != nil && p->rcv != nil) - (*p->rcv)(ia, bp); - else if(ipextprotoiput != nil) - ipextprotoiput(bp); - else - freeblist(bp); + p = Fsrcvpcol(f, h->proto); + if(p != nil && p->rcv != nil) { + ip->istats.ipInDelivers++; + (*p->rcv)(p, ia, bp); + return; + } + ip->istats.ipInDiscards++; + ip->istats.ipInUnknownProtos++; + freeblist(bp); } int -ipstats(char *buf, int len) +ipstats(Fs *f, char *buf, int len) { - int n; - - n = snprint(buf, len, "ip: csum %lud inb %lud outb %lud inp %lud outp %lud\n", - ipcsumerr, ipin, ipout, ippin, ippout); - n += snprint(buf+n, len - n, "\tnoroute %lud droppedfrag %lud\n", - stats.noroute, stats.droppedfrag); - return n; + IP *ip; + + ip = f->ip; + return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d %d %d", + ip->istats.ipForwarding, ip->istats.ipDefaultTTL, + ip->istats.ipInReceives, ip->istats.ipInHdrErrors, + ip->istats.ipInAddrErrors, ip->istats.ipForwDatagrams, + ip->istats.ipInUnknownProtos, ip->istats.ipInDiscards, + ip->istats.ipInDelivers, ip->istats.ipOutRequests, + ip->istats.ipOutDiscards, ip->istats.ipOutNoRoutes, + ip->istats.ipReasmTimeout, ip->istats.ipReasmReqds, + ip->istats.ipReasmOKs, ip->istats.ipReasmFails, + ip->istats.ipFragOKs, ip->istats.ipFragFails, + ip->istats.ipFragCreates); } Block* -ipreassemble(int offset, Block *bp, Iphdr *ip) +ipreassemble(IP *ip, int offset, Block *bp, Iphdr *ih) { int fend; ushort id; @@ -342,30 +423,30 @@ ipreassemble(int offset, Block *bp, Iphdr *ip) Block *bl, **l, *last, *prev; int ovlap, len, fragsize, pktposn; - src = nhgetl(ip->src); - dst = nhgetl(ip->dst); - id = nhgets(ip->id); + src = nhgetl(ih->src); + dst = nhgetl(ih->dst); + id = nhgets(ih->id); /* * block lists are too hard, pullupblock into a single block */ if(bp->next){ bp = pullupblock(bp, blocklen(bp)); - ip = (Iphdr *)(bp->rp); + ih = (Iphdr *)(bp->rp); } - qlock(&fraglock); + qlock(&ip->fraglock); /* * find a reassembly queue for this fragment */ - for(f = flisthead; f; f = fnext){ + for(f = ip->flisthead; f; f = fnext){ fnext = f->next; /* because ipfragfree changes the list */ if(f->src == src && f->dst == dst && f->id == id) break; if(f->age < msec){ - stats.droppedfrag++; - ipfragfree(f); + ip->istats.ipReasmTimeout++; + ipfragfree(ip, f); } } @@ -374,10 +455,12 @@ ipreassemble(int offset, Block *bp, Iphdr *ip) * and get rid of any fragments that might go * with it. */ - if(!ip->tos && (offset & ~(IP_MF|IP_DF)) == 0) { - if(f != nil) - ipfragfree(f); - qunlock(&fraglock); + if(!ih->tos && (offset & ~(IP_MF|IP_DF)) == 0) { + if(f != nil) { + ipfragfree(ip, f); + ip->istats.ipReasmFails++; + } + qunlock(&ip->fraglock); return bp; } @@ -387,18 +470,19 @@ ipreassemble(int offset, Block *bp, Iphdr *ip) } BKFG(bp)->foff = offset<<3; - BKFG(bp)->flen = nhgets(ip->length)-IPHDR; + BKFG(bp)->flen = nhgets(ih->length)-IPHDR; /* First fragment allocates a reassembly queue */ if(f == nil) { - f = ipfragallo(); + f = ipfragallo(ip); f->id = id; f->src = src; f->dst = dst; f->blist = bp; - qunlock(&fraglock); + qunlock(&ip->fraglock); + ip->istats.ipReasmReqds++; return nil; } @@ -420,7 +504,7 @@ ipreassemble(int offset, Block *bp, Iphdr *ip) if(ovlap > 0) { if(ovlap >= BKFG(bp)->flen) { freeblist(bp); - qunlock(&fraglock); + qunlock(&ip->fraglock); return nil; } BKFG(prev)->flen -= ovlap; @@ -443,7 +527,7 @@ ipreassemble(int offset, Block *bp, Iphdr *ip) if(ovlap < BKFG(*l)->flen) { BKFG(*l)->flen -= ovlap; BKFG(*l)->foff += ovlap; - /* move up ip hdrs */ + /* move up ih hdrs */ memmove((*l)->rp + ovlap, (*l)->rp, IPHDR); (*l)->rp += ovlap; break; @@ -480,15 +564,16 @@ ipreassemble(int offset, Block *bp, Iphdr *ip) bl = f->blist; f->blist = nil; - ipfragfree(f); - ip = BLKIP(bl); - hnputs(ip->length, len); - qunlock(&fraglock); + ipfragfree(ip, f); + ih = BLKIP(bl); + hnputs(ih->length, len); + qunlock(&ip->fraglock); + ip->istats.ipReasmOKs++; return bl; } pktposn += BKFG(bl)->flen; } - qunlock(&fraglock); + qunlock(&ip->fraglock); return nil; } @@ -496,7 +581,7 @@ ipreassemble(int offset, Block *bp, Iphdr *ip) * ipfragfree - Free a list of fragments - assume hold fraglock */ void -ipfragfree(Fragment *frag) +ipfragfree(IP *ip, Fragment *frag) { Fragment *fl, **l; @@ -507,7 +592,7 @@ ipfragfree(Fragment *frag) frag->id = 0; frag->blist = nil; - l = &flisthead; + l = &ip->flisthead; for(fl = *l; fl; fl = fl->next) { if(fl == frag) { *l = frag->next; @@ -516,8 +601,8 @@ ipfragfree(Fragment *frag) l = &fl->next; } - frag->next = fragfree; - fragfree = frag; + frag->next = ip->fragfree; + ip->fragfree = frag; } @@ -525,20 +610,20 @@ ipfragfree(Fragment *frag) * ipfragallo - allocate a reassembly queue - assume hold fraglock */ Fragment * -ipfragallo(void) +ipfragallo(IP *ip) { Fragment *f; - while(fragfree == nil) { + while(ip->fragfree == nil) { /* free last entry on fraglist */ - for(f = flisthead; f->next; f = f->next) + for(f = ip->flisthead; f->next; f = f->next) ; - ipfragfree(f); + ipfragfree(ip, f); } - f = fragfree; - fragfree = f->next; - f->next = flisthead; - flisthead = f; + f = ip->fragfree; + ip->fragfree = f->next; + f->next = ip->flisthead; + ip->flisthead = f; f->age = msec + 30000; return f; diff --git a/ip/ip.h b/ip/ip.h index fff75a24c12ab870f204ca236afb7609ea336999..1cf7c78122a38c5b00748df5dfd2010a9f814a6a 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -2,17 +2,22 @@ typedef struct Conv Conv; typedef struct Fs Fs; typedef union Hwaddr Hwaddr; typedef struct Ifcconv Ifcconv; +typedef struct IP IP; typedef struct Ipself Ipself; +typedef struct Ipselftab Ipselftab; typedef struct Iplink Iplink; typedef struct Iplifc Iplifc; typedef struct Ipmulti Ipmulti; typedef struct Iproute Iproute; +typedef struct IProuter IProuter; typedef struct Ipifc Ipifc; +typedef struct Log Log; typedef struct Medium Medium; typedef struct Proto Proto; typedef struct Pstate Pstate; typedef struct Tcpc Tcpc; typedef struct Arpent Arpent; +typedef struct Arp Arp; typedef struct Route Route; enum @@ -34,6 +39,9 @@ enum /* ip versions */ V4= 4, V6= 6, + + /* 2^Lroot trees in the root table */ + Lroot = 10, }; enum @@ -106,7 +114,7 @@ struct Medium void (*remmulti)(Ipifc *ifc, uchar *a, uchar *ia); /* process packets written to 'data' */ - void (*pktin)(Ipifc *ifc, Block *bp); + void (*pktin)(Fs *f, Ipifc *ifc, Block *bp); /* routes for router boards */ void (*addroute)(Ipifc *ifc, int, uchar*, uchar*, uchar*, int); @@ -114,7 +122,7 @@ struct Medium void (*flushroutes)(Ipifc *ifc); /* for routing multicast groups */ - void (*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia, uchar **iap); + void (*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia); void (*leavemulti)(Ipifc *ifc, uchar *a, uchar *ia); int unbindonclose; /* if non-zero, unbind on last close */ @@ -196,13 +204,14 @@ struct Proto int (*state)(Conv*, char*, int); void (*create)(Conv*); void (*close)(Conv*); - void (*rcv)(uchar*, Block*); + void (*rcv)(Proto*, uchar*, Block*); char* (*ctl)(Conv*, char**, int); - void (*advise)(Block*, char*); - int (*stats)(char*, int); + void (*advise)(Proto*, Block*, char*); + int (*stats)(Proto*, char*, int); int (*local)(Conv*, char*, int); int (*inuse)(Conv*); + Fs *f; /* file system this proto is part of */ Conv **conv; /* array of conversations */ int ptclsize; /* size of per protocol ctl block */ int nc; /* number of conversations */ @@ -211,13 +220,21 @@ struct Proto ushort nextport; ushort nextrport; - ulong csumerr; /* checksum errors */ - ulong hlenerr; /* header length error */ - ulong lenerr; /* short packet */ - ulong order; /* out of order */ - ulong rexmit; /* retransmissions */ + void *priv; +}; + +/* + * Stream for sending packets to user level + */ +struct IProuter { + QLock; + int opens; + Queue *q; }; +/* + * one per IP protocol stack + */ struct Fs { Lock; @@ -225,9 +242,22 @@ struct Fs int np; Proto* p[Maxproto+1]; /* list of supported protocols */ Proto* t2p[256]; /* vector of all ip protocol handlers */ + Proto* ipifc; /* kludge for ipifcremroute & ipifcaddroute */ + + IP *ip; + Ipselftab *self; + Arp *arp; + IProuter iprouter; + + Route *v4root[1< sizeof(cb->buf)-1) n = sizeof(cb->buf)-1; memmove(cb->buf, p, n); + if(n > 0 && cb->buf[n-1] == '\n') + n--; cb->buf[n] = '\0'; cb->nf = parsefields(cb->buf, cb->f, nelem(cb->f), " "); return cb; diff --git a/ip/ipifc.c b/ip/ipifc.c index e8d16b235ebc3f2ca1a3fcd5cd59a0d0aedab6d4..3dc142c08674ce38b16836a4093095c69a58040f 100644 --- a/ip/ipifc.c +++ b/ip/ipifc.c @@ -17,14 +17,12 @@ enum { QMAX = 64*1024-1, }; - Proto ipifc; -extern Fs fs; - Medium *media[] = { ðermedium, &pktmedium, &nullmedium, + &tripmedium, 0 }; @@ -43,7 +41,6 @@ struct Ipself Ipself *next; /* free list */ }; -typedef struct Ipselftab Ipselftab; struct Ipselftab { QLock; @@ -51,7 +48,6 @@ struct Ipselftab int acceptall; /* true if an interface has the null address */ Ipself *hash[NHASH]; /* hash chains */ }; -Ipselftab selftab; /* * Multicast addresses are chained onto a Chan so that @@ -70,8 +66,8 @@ struct Ipmcast static char tifc[] = "ifc "; -static void addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type); -static void remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a); +static void addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type); +static void remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a); static char* ipifcjoinmulti(Ipifc *ifc, char **argv, int argc); static char* ipifcleavemulti(Ipifc *ifc, char **argv, int argc); @@ -252,7 +248,7 @@ ipifckick(Conv *c, int) if(ifc->m == nil || ifc->m->pktin == nil) freeb(bp); else - (*ifc->m->pktin)(ifc, bp); + (*ifc->m->pktin)(c->p->f, ifc, bp); } /* @@ -299,6 +295,9 @@ ipifcadd(Ipifc *ifc, char **argv, int argc) uchar bcast[IPaddrlen], net[IPaddrlen]; Iplifc *lifc, **l; int i, type, mtu; + Fs *f; + + f = ifc->conv->p->f; memset(ip, 0, IPaddrlen); memset(mask, 0, IPaddrlen); @@ -359,24 +358,24 @@ ipifcadd(Ipifc *ifc, char **argv, int argc) if(ipcmp(mask, IPallbits) == 0) type |= Rptpt; if(isv4(ip)) - v4addroute(tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type); + v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type); else - v6addroute(tifc, ip, mask, rem, type); + v6addroute(f, tifc, ip, mask, rem, type); - addselfcache(ifc, lifc, ip, Runi); + addselfcache(f, ifc, lifc, ip, Runi); /* add subnet directed broadcast addresses to the self cache */ for(i = 0; i < IPaddrlen; i++) bcast[i] = (ip[i] & mask[i]) | ~mask[i]; - addselfcache(ifc, lifc, bcast, Rbcast); + addselfcache(f, ifc, lifc, bcast, Rbcast); /* add network directed broadcast addresses to the self cache */ memmove(mask, defmask(ip), IPaddrlen); for(i = 0; i < IPaddrlen; i++) bcast[i] = (ip[i] & mask[i]) | ~mask[i]; - addselfcache(ifc, lifc, bcast, Rbcast); + addselfcache(f, ifc, lifc, bcast, Rbcast); - addselfcache(ifc, lifc, IPv4bcast, Rbcast); + addselfcache(f, ifc, lifc, IPv4bcast, Rbcast); out: wunlock(ifc); @@ -394,10 +393,13 @@ ipifcrem(Ipifc *ifc, char **argv, int argc, int dolock) uchar ip[IPaddrlen]; uchar mask[IPaddrlen]; Iplifc *lifc, **l; + Fs *f; if(argc < 3) return Ebadarg; + f = ifc->conv->p->f; + parseip(ip, argv[1]); parseipmask(mask, argv[2]); @@ -424,13 +426,13 @@ ipifcrem(Ipifc *ifc, char **argv, int argc, int dolock) /* disassociate any addresses */ while(lifc->link) - remselfcache(ifc, lifc, lifc->link->self->a); + remselfcache(f, ifc, lifc, lifc->link->self->a); /* remove the route for this logical interface */ if(isv4(ip)) - v4delroute(lifc->remote+IPv4off, lifc->mask+IPv4off); + v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off); else - v6delroute(lifc->remote, lifc->mask); + v6delroute(f, lifc->remote, lifc->mask); free(lifc); @@ -447,13 +449,14 @@ out: * TRIP linecards */ void -ipifcaddroute(int vers, uchar *addr, uchar *mask, uchar *gate, int type) +ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type) { Medium *m; - Conv **cp; + Conv **cp, **e; Ipifc *ifc; - for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ + e = &f->ipifc->conv[f->ipifc->nc]; + for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp != nil) { ifc = (Ipifc*)(*cp)->ptcl; m = ifc->m; @@ -466,13 +469,14 @@ ipifcaddroute(int vers, uchar *addr, uchar *mask, uchar *gate, int type) } void -ipifcremroute(int vers, uchar *addr, uchar *mask) +ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask) { Medium *m; - Conv **cp; + Conv **cp, **e; Ipifc *ifc; - for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ + e = &f->ipifc->conv[f->ipifc->nc]; + for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp != nil) { ifc = (Ipifc*)(*cp)->ptcl; m = ifc->m; @@ -523,7 +527,7 @@ ipifcconnect(Conv* c, char **argv, int argc) if(err) return err; - Fsconnected(&fs, c, nil); + Fsconnected(c, nil); return nil; } @@ -540,6 +544,8 @@ ipifcctl(Conv* c, char**argv, int argc) ifc = (Ipifc*)c->ptcl; if(strcmp(argv[0], "add") == 0) return ipifcadd(ifc, argv, argc); + else if(strcmp(argv[0], "bootp") == 0) + return bootp(ifc); else if(strcmp(argv[0], "remove") == 0) return ipifcrem(ifc, argv, argc, 1); else if(strcmp(argv[0], "unbind") == 0) @@ -551,28 +557,39 @@ ipifcctl(Conv* c, char**argv, int argc) return "unsupported ctl"; } +ipifcstats(Proto *ipifc, char *buf, int len) +{ + return ipstats(ipifc->f, buf, len); +} + void -ipifcinit(Fs *fs) +ipifcinit(Fs *f) { - ipifc.name = "ipifc"; - ipifc.kick = ipifckick; - ipifc.connect = ipifcconnect; - ipifc.announce = nil; - ipifc.bind = ipifcbind; - ipifc.state = ipifcstate; - ipifc.create = ipifccreate; - ipifc.close = ipifcclose; - ipifc.rcv = nil; - ipifc.ctl = ipifcctl; - ipifc.advise = nil; - ipifc.stats = ipstats; - ipifc.inuse = ipifcinuse; - ipifc.local = ipifclocal; - ipifc.ipproto = -1; - ipifc.nc = Maxmedia; - ipifc.ptclsize = sizeof(Ipifc); - - Fsproto(fs, &ipifc); + Proto *ipifc; + + ipifc = smalloc(sizeof(Ipifc)); + ipifc->name = "ipifc"; + ipifc->kick = ipifckick; + ipifc->connect = ipifcconnect; + ipifc->announce = nil; + ipifc->bind = ipifcbind; + ipifc->state = ipifcstate; + ipifc->create = ipifccreate; + ipifc->close = ipifcclose; + ipifc->rcv = nil; + ipifc->ctl = ipifcctl; + ipifc->advise = nil; + ipifc->stats = ipifcstats; + ipifc->inuse = ipifcinuse; + ipifc->local = ipifclocal; + ipifc->ipproto = -1; + ipifc->nc = Maxmedia; + ipifc->ptclsize = sizeof(Ipifc); + + f->ipifc = ipifc; /* hack for ipifcremroute, findipifc, ... */ + f->self = smalloc(sizeof(Ipselftab)); /* hack for ipforme */ + + Fsproto(f, ipifc); } /* @@ -580,17 +597,17 @@ ipifcinit(Fs *fs) * called with c->car locked */ static void -addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type) +addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type) { Ipself *p; Iplink *lp; int h; - qlock(&selftab); + qlock(f->self); /* see if the address already exists */ h = hashipa(a); - for(p = selftab.hash[h]; p; p = p->next) + for(p = f->self->hash[h]; p; p = p->next) if(memcmp(a, p->a, IPaddrlen) == 0) break; @@ -599,12 +616,12 @@ addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type) p = smalloc(sizeof(*p)); ipmove(p->a, a); p->type = type; - p->next = selftab.hash[h]; - selftab.hash[h] = p; + p->next = f->self->hash[h]; + f->self->hash[h] = p; /* if the null address, accept all packets */ if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0) - selftab.acceptall = 1; + f->self->acceptall = 1; } /* look for a link for this lifc */ @@ -625,9 +642,9 @@ addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type) /* add to routing table */ if(isv4(a)) - v4addroute(tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type); + v4addroute(f, tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type); else - v6addroute(tifc, a, IPallbits, a, type); + v6addroute(f, tifc, a, IPallbits, a, type); if((type & Rmulti) && ifc->m->addmulti != nil) (*ifc->m->addmulti)(ifc, a, lifc->local); @@ -635,14 +652,14 @@ addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type) lp->ref++; } - qunlock(&selftab); + qunlock(f->self); } /* * These structures are unlinked from their chains while * other threads may be using them. To avoid excessive locking, * just put them aside for a while before freeing them. - * called with &selftab locked + * called with f->self locked */ static Iplink *freeiplink; static Ipself *freeipself; @@ -692,15 +709,15 @@ ipselffree(Ipself *p) * called with c->car locked */ static void -remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a) +remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a) { Ipself *p, **l; Iplink *link, **l_self, **l_lifc; - qlock(&selftab); + qlock(f->self); /* find the unique selftab entry */ - l = &selftab.hash[hashipa(a)]; + l = &f->self->hash[hashipa(a)]; for(p = *l; p; p = *l){ if(ipcmp(p->a, a) == 0) break; @@ -754,9 +771,9 @@ remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a) /* remove from routing table */ if(isv4(a)) - v4delroute(a+IPv4off, IPallbits+IPv4off); + v4delroute(f, a+IPv4off, IPallbits+IPv4off); else - v6delroute(a, IPallbits); + v6delroute(f, a, IPallbits); /* no more links, remove from hash and free */ *l = p->next; @@ -764,29 +781,10 @@ remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a) /* if IPnoaddr, forget */ if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0) - selftab.acceptall = 0; + f->self->acceptall = 0; out: - qunlock(&selftab); -} - -static void -dumpselftab(void) -{ - int i, count; - Ipself *p; - - qlock(&selftab); - for(i = 0; i < NHASH; i++){ - p = selftab.hash[i]; - if(p == nil) - continue; - count = 0; - for(; p != nil && count++ < 6; p = p->next) - print("(%I %d %lux)", p->a, p->type, p); - print("\n"); - } - qunlock(&selftab); + qunlock(f->self); } static char *stformat = "%-32.32I %2.2d %4.4s\n"; @@ -796,7 +794,7 @@ enum }; long -ipselftabread(char *cp, ulong offset, int n) +ipselftabread(Fs *f, char *cp, ulong offset, int n) { int i, m, nifc; Ipself *p; @@ -804,9 +802,9 @@ ipselftabread(char *cp, ulong offset, int n) char state[8]; m = 0; - qlock(&selftab); + qlock(f->self); for(i = 0; i < NHASH && m < n; i++){ - for(p = selftab.hash[i]; p != nil && m < n; p = p->next){ + for(p = f->self->hash[i]; p != nil && m < n; p = p->next){ if(offset == 0){ nifc = 0; for(link = p->link; link; link = link->selflink) @@ -817,7 +815,7 @@ ipselftabread(char *cp, ulong offset, int n) offset -= Nstformat; } } - qunlock(&selftab); + qunlock(f->self); return m; } @@ -830,24 +828,18 @@ ipselftabread(char *cp, ulong offset, int n) * Rmcast */ int -ipforme(uchar *addr) +ipforme(Fs *f, uchar *addr) { Ipself *p; - int count; - p = selftab.hash[hashipa(addr)]; - count = 0; + p = f->self->hash[hashipa(addr)]; for(; p; p = p->next){ - if(count++ > 1000){ /* check for loops */ - dumpselftab(); - break; - } if(ipcmp(addr, p->a) == 0) return p->type; } /* hack to say accept anything */ - if(selftab.acceptall) + if(f->self->acceptall) return Runi; return 0; @@ -858,29 +850,28 @@ ipforme(uchar *addr) * return nil. */ Ipifc* -findipifc(uchar *remote, int type) +findipifc(Fs *f, uchar *remote, int type) { Ipifc *ifc; Iplifc *lifc; - Conv **cp; + Conv **cp, **e; uchar gnet[IPaddrlen]; - for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ + e = &f->ipifc->conv[f->ipifc->nc]; + for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp == 0) continue; ifc = (Ipifc*)(*cp)->ptcl; for(lifc = ifc->lifc; lifc; lifc = lifc->next){ maskip(remote, lifc->mask, gnet); - if(ipcmp(gnet, lifc->net) == 0){ - qunlock(&ipifc); + if(ipcmp(gnet, lifc->net) == 0) return ifc; - } } } /* for now for broadcast and mutlicast, just use first interface */ if(type & (Rbcast|Rmulti)){ - for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ + for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp == 0) continue; ifc = (Ipifc*)(*cp)->ptcl; @@ -897,17 +888,17 @@ findipifc(uchar *remote, int type) * local and return the ifc for that address */ void -findlocalip(uchar *local, uchar *remote) +findlocalip(Fs *f, uchar *local, uchar *remote) { Ipifc *ifc; Iplifc *lifc; - Conv **cp; + Conv **cp, **e; Route *r; uchar gate[IPaddrlen]; uchar gnet[IPaddrlen]; - qlock(&ipifc); - r = v6lookup(remote); + qlock(f->ipifc); + r = v6lookup(f, remote); if(r != nil){ ifc = r->ifc; @@ -932,7 +923,8 @@ findlocalip(uchar *local, uchar *remote) } /* no match, choose first ifc local address */ - for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ + e = &f->ipifc->conv[f->ipifc->nc]; + for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp == 0) continue; ifc = (Ipifc*)(*cp)->ptcl; @@ -943,7 +935,7 @@ findlocalip(uchar *local, uchar *remote) } out: - qunlock(&ipifc); + qunlock(f->ipifc); } /* @@ -999,14 +991,14 @@ iplocalonifc(Ipifc *ifc, uchar *ip) * See if we're proxying for this address on this interface */ int -ipproxyifc(Ipifc *ifc, uchar *ip) +ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip) { Route *r; uchar net[IPaddrlen]; Iplifc *lifc; /* see if this is a direct connected pt to pt address */ - r = v6lookup(ip); + r = v6lookup(f, ip); if(r == nil) return 0; if((r->type & Rifc) == 0) @@ -1050,6 +1042,9 @@ ipifcaddmulti(Conv *c, uchar *ma, uchar *ia) Iplifc *lifc; Conv **p; Ipmulti *multi, **l; + Fs *f; + + f = c->p->f; for(l = &c->multi; *l; l = &(*l)->next) if(ipcmp(ma, (*l)->ma) == 0) @@ -1061,7 +1056,7 @@ ipifcaddmulti(Conv *c, uchar *ma, uchar *ia) ipmove(multi->ia, ia); multi->next = nil; - for(p = ipifc.conv; *p; p++){ + for(p = f->ipifc->conv; *p; p++){ if((*p)->inuse == 0) continue; ifc = (Ipifc*)(*p)->ptcl; @@ -1072,7 +1067,7 @@ ipifcaddmulti(Conv *c, uchar *ma, uchar *ia) wlock(ifc); for(lifc = ifc->lifc; lifc; lifc = lifc->next) if(ipcmp(ia, lifc->local) == 0) - addselfcache(ifc, lifc, ma, Rmulti); + addselfcache(f, ifc, lifc, ma, Rmulti); wunlock(ifc); poperror(); } @@ -1089,6 +1084,9 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia) Iplifc *lifc; Conv **p; Ipifc *ifc; + Fs *f; + + f = c->p->f; for(l = &c->multi; *l; l = &(*l)->next) if(ipcmp(ma, (*l)->ma) == 0) @@ -1101,7 +1099,7 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia) *l = multi->next; - for(p = ipifc.conv; *p; p++){ + for(p = f->ipifc->conv; *p; p++){ if((*p)->inuse == 0) continue; @@ -1113,7 +1111,7 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia) wlock(ifc); for(lifc = ifc->lifc; lifc; lifc = lifc->next) if(ipcmp(ia, lifc->local) == 0) - remselfcache(ifc, lifc, ma); + remselfcache(f, ifc, lifc, ma); wunlock(ifc); poperror(); } diff --git a/ip/iproute.c b/ip/iproute.c index c2dfe9fbe0d49f6f0956f07bfa35cf3fc77a6908..4bf022e34c22990dd9c89d5ab30d9edf1711f37c 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -7,17 +7,11 @@ #include "ip.h" -enum -{ - Lroot = 10, -}; - -Route *v4root[1<right; p->left = 0; p->right = 0; - addnode(root, p); + addnode(f, root, p); if(l) - walkadd(root, l); + walkadd(f, root, l); if(r) - walkadd(root, r); + walkadd(f, root, r); } /* @@ -238,7 +232,7 @@ balancetree(Route **cur) * add a new node to the tree */ static void -addnode(Route **cur, Route *new) +addnode(Fs *f, Route **cur, Route *new) { Route *p; @@ -251,10 +245,10 @@ addnode(Route **cur, Route *new) switch(rangecompare(new, p)){ case Rpreceeds: - addnode(&p->left, new); + addnode(f, &p->left, new); break; case Rfollows: - addnode(&p->right, new); + addnode(f, &p->right, new); break; case Rcontains: /* @@ -266,14 +260,14 @@ addnode(Route **cur, Route *new) */ *cur = new; new->depth = 1; - addqueue(&queue, p); + addqueue(&f->queue, p); break; case Requals: copygate(p, new); freeroute(new); break; case Rcontained: - addnode(&p->mid, new); + addnode(f, &p->mid, new); break; } @@ -283,7 +277,7 @@ addnode(Route **cur, Route *new) #define V4H(a) ((a&0x07ffffff)>>(32-Lroot-5)) void -v4addroute(char *tag, uchar *a, uchar *mask, uchar *gate, int type) +v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type) { Route *p; ulong sa; @@ -304,22 +298,22 @@ v4addroute(char *tag, uchar *a, uchar *mask, uchar *gate, int type) memmove(p->tag, tag, sizeof(p->tag)); wlock(&routelock); - addnode(&v4root[h], p); - while(p = queue) { - queue = p->mid; - walkadd(&v4root[h], p->left); + addnode(f, &f->v4root[h], p); + while(p = f->queue) { + f->queue = p->mid; + walkadd(f, &f->v4root[h], p->left); freeroute(p); } wunlock(&routelock); } - ipifcaddroute(Rv4, a, mask, gate, type); + ipifcaddroute(f, Rv4, a, mask, gate, type); } #define V6H(a) (((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5)) void -v6addroute(char *tag, uchar *a, uchar *mask, uchar *gate, int type) +v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type) { Route *p; ulong sa[IPllen], ea[IPllen]; @@ -342,16 +336,16 @@ v6addroute(char *tag, uchar *a, uchar *mask, uchar *gate, int type) memmove(p->tag, tag, sizeof(p->tag)); wlock(&routelock); - addnode(&v6root[h], p); - while(p = queue) { - queue = p->mid; - walkadd(&v6root[h], p->left); + addnode(f, &f->v6root[h], p); + while(p = f->queue) { + f->queue = p->mid; + walkadd(f, &f->v6root[h], p->left); freeroute(p); } wunlock(&routelock); } - ipifcaddroute(0, a, mask, gate, type); + ipifcaddroute(f, 0, a, mask, gate, type); } Route** @@ -383,7 +377,7 @@ looknode(Route **cur, Route *r) } void -v4delroute(uchar *a, uchar *mask) +v4delroute(Fs *f, uchar *a, uchar *mask) { Route **r, *p; Route rt; @@ -398,28 +392,28 @@ v4delroute(uchar *a, uchar *mask) eh = V4H(rt.v4.endaddress); for(h=V4H(rt.v4.address); h<=eh; h++) { wlock(&routelock); - r = looknode(&v4root[h], &rt); + r = looknode(&f->v4root[h], &rt); if(r) { p = *r; *r = 0; - addqueue(&queue, p->left); - addqueue(&queue, p->mid); - addqueue(&queue, p->right); + addqueue(&f->queue, p->left); + addqueue(&f->queue, p->mid); + addqueue(&f->queue, p->right); freeroute(p); - while(p = queue) { - queue = p->mid; - walkadd(&v4root[h], p->left); + while(p = f->queue) { + f->queue = p->mid; + walkadd(f, &f->v4root[h], p->left); freeroute(p); } } wunlock(&routelock); } - ipifcremroute(Rv4, a, mask); + ipifcremroute(f, Rv4, a, mask); } void -v6delroute(uchar *a, uchar *mask) +v6delroute(Fs *f, uchar *a, uchar *mask) { Route **r, *p; Route rt; @@ -437,28 +431,28 @@ v6delroute(uchar *a, uchar *mask) eh = V6H(rt.v6.endaddress); for(h=V6H(rt.v6.address); h<=eh; h++) { wlock(&routelock); - r = looknode(&v6root[h], &rt); + r = looknode(&f->v6root[h], &rt); if(r) { p = *r; *r = 0; - addqueue(&queue, p->left); - addqueue(&queue, p->mid); - addqueue(&queue, p->right); + addqueue(&f->queue, p->left); + addqueue(&f->queue, p->mid); + addqueue(&f->queue, p->right); freeroute(p); - while(p = queue) { - queue = p->mid; - walkadd(&v6root[h], p->left); + while(p = f->queue) { + f->queue = p->mid; + walkadd(f, &f->v6root[h], p->left); freeroute(p); } } wunlock(&routelock); } - ipifcremroute(0, a, mask); + ipifcremroute(f, 0, a, mask); } Route* -v4lookup(uchar *a) +v4lookup(Fs *f, uchar *a) { Route *p, *q; ulong la; @@ -466,7 +460,7 @@ v4lookup(uchar *a) la = nhgetl(a); q = nil; - for(p=v4root[V4H(la)]; p;) + for(p=f->v4root[V4H(la)]; p;) if(la >= p->v4.address) { if(la <= p->v4.endaddress) { q = p; @@ -478,7 +472,7 @@ v4lookup(uchar *a) if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){ v4tov6(gate, q->v4.gate); - q->ifc = findipifc(gate, q->type); + q->ifc = findipifc(f, gate, q->type); if(q->ifc == nil) return nil; q->ifcid = q->ifc->ifcid; @@ -488,7 +482,7 @@ v4lookup(uchar *a) } Route* -v6lookup(uchar *a) +v6lookup(Fs *f, uchar *a) { Route *p, *q; ulong la[IPllen]; @@ -496,7 +490,7 @@ v6lookup(uchar *a) ulong x, y; if(memcmp(a, v4prefix, 12) == 0){ - q = v4lookup(a+12); + q = v4lookup(f, a+12); if(q != nil) return q; } @@ -505,7 +499,7 @@ v6lookup(uchar *a) la[h] = nhgetl(a+4*h); q = 0; - for(p=v6root[V6H(la)]; p;){ + for(p=f->v6root[V6H(la)]; p;){ for(h = 0; h < IPllen; h++){ x = la[h]; y = p->v6.address[h]; @@ -534,7 +528,7 @@ next: ; } if(q && q->ifc == nil){ - q->ifc = findipifc(q->v6.gate, q->type); + q->ifc = findipifc(f, q->v6.gate, q->type); if(q->ifc == nil) return nil; if(q->ifcid != q->ifc->ifcid) @@ -654,24 +648,24 @@ rr(Route *r, Routewalk *rw) } void -ipwalkroutes(Routewalk *rw) +ipwalkroutes(Fs *f, Routewalk *rw) { rlock(&routelock); if(rw->n > rw->o) { - for(rw->h = 0; rw->h < nelem(v4root); rw->h++) - if(rr(v4root[rw->h], rw) == 0) + for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++) + if(rr(f->v4root[rw->h], rw) == 0) break; } if(rw->n > rw->o) { - for(rw->h = 0; rw->h < nelem(v6root); rw->h++) - if(rr(v6root[rw->h], rw) == 0) + for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++) + if(rr(f->v6root[rw->h], rw) == 0) break; } runlock(&routelock); } long -routeread(char *p, ulong offset, int n) +routeread(Fs *f, char *p, ulong offset, int n) { Routewalk rw; @@ -683,7 +677,7 @@ routeread(char *p, ulong offset, int n) rw.o = -(offset/Rlinelen); rw.walk = sprintroute; - ipwalkroutes(&rw); + ipwalkroutes(f, &rw); if(rw.o < 0) rw.o = 0; @@ -695,7 +689,7 @@ routeread(char *p, ulong offset, int n) * this code is not in routeflush to reduce stack size */ void -delroute(Route *r) +delroute(Fs *f, Route *r) { uchar addr[IPaddrlen]; uchar mask[IPaddrlen]; @@ -705,9 +699,9 @@ delroute(Route *r) convroute(r, addr, mask, gate, t, &nifc); if(r->type & Rv4) - v4delroute(addr+IPv4off, mask+IPv4off); + v4delroute(f, addr+IPv4off, mask+IPv4off); else - v6delroute(addr, mask); + v6delroute(f, addr, mask); } /* @@ -715,25 +709,25 @@ delroute(Route *r) * returns 0 if nothing is deleted, 1 otherwise */ int -routeflush(Route *r) +routeflush(Fs *f, Route *r) { if(r == nil) return 0; - if(routeflush(r->mid)) + if(routeflush(f, r->mid)) return 1; - if(routeflush(r->left)) + if(routeflush(f, r->left)) return 1; - if(routeflush(r->right)) + if(routeflush(f, r->right)) return 1; if((r->type & Rifc) == 0){ - delroute(r); + delroute(f, r); return 1; } return 0; } long -routewrite(Chan *c, char *p, int n) +routewrite(Fs *f, Chan *c, char *p, int n) { int h; char *tag; @@ -750,11 +744,11 @@ routewrite(Chan *c, char *p, int n) if(strcmp(cb->f[0], "flush") == 0){ wlock(&routelock); - for(h = 0; h < nelem(v4root); h++) - while(routeflush(v4root[h]) == 1) + for(h = 0; h < nelem(f->v4root); h++) + while(routeflush(f, f->v4root[h]) == 1) ; - for(h = 0; h < nelem(v6root); h++) - while(routeflush(v6root[h]) == 1) + for(h = 0; h < nelem(f->v6root); h++) + while(routeflush(f, f->v6root[h]) == 1) ; wunlock(&routelock); } else if(strcmp(cb->f[0], "remove") == 0){ @@ -763,9 +757,9 @@ routewrite(Chan *c, char *p, int n) parseip(addr, cb->f[1]); parseipmask(mask, cb->f[2]); if(memcmp(addr, v4prefix, IPv4off) == 0) - v4delroute(addr+IPv4off, mask+IPv4off); + v4delroute(f, addr+IPv4off, mask+IPv4off); else - v6delroute(addr, mask); + v6delroute(f, addr, mask); } else if(strcmp(cb->f[0], "add") == 0){ if(cb->nf < 4) error(Ebadarg); @@ -776,9 +770,9 @@ routewrite(Chan *c, char *p, int n) if(c != nil) tag = c->tag; if(memcmp(addr, v4prefix, IPv4off) == 0) - v4addroute(tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); + v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); else - v6addroute(tag, addr, mask, gate, 0); + v6addroute(f, tag, addr, mask, gate, 0); } else if(strcmp(cb->f[0], "tag") == 0) { if(cb->nf < 2) error(Ebadarg); diff --git a/ip/netlog.c b/ip/netlog.c index 50f36f917c725a705a6baf955f73bfc5ea722228..9e11753d7844e8bbd3b837fd9a49d302365ae3fd 100644 --- a/ip/netlog.c +++ b/ip/netlog.c @@ -6,10 +6,6 @@ #include "../port/error.h" #include "../ip/ip.h" -int logmask; /* mask of things to debug */ -uchar iponly[IPaddrlen]; /* ip address to print debugging for */ -int iponlyset; - enum { Nlog = 4*1024, }; @@ -17,7 +13,7 @@ enum { /* * action log */ -typedef struct Log { +struct Log { Lock; int opens; char* buf; @@ -25,15 +21,19 @@ typedef struct Log { char *rptr; int len; + int logmask; /* mask of things to debug */ + uchar iponly[IPaddrlen]; /* ip address to print debugging for */ + int iponlyset; + QLock; Rendez; -} Log; -static Log alog; +}; typedef struct Logflag { char* name; int mask; } Logflag; + static Logflag flags[] = { { "ppp", Logppp, }, @@ -55,73 +55,81 @@ static Logflag flags[] = static char Ebadnetctl[] = "unknown netlog ctl message"; void -netlogopen(void) +netloginit(Fs *f) +{ + f->alog = smalloc(sizeof(Log)); +} + +void +netlogopen(Fs *f) { - lock(&alog); + lock(f->alog); if(waserror()){ - unlock(&alog); + unlock(f->alog); nexterror(); } - if(alog.opens == 0){ - if(alog.buf == nil) - alog.buf = malloc(Nlog); - alog.rptr = alog.buf; - alog.end = alog.buf + Nlog; + if(f->alog->opens == 0){ + if(f->alog->buf == nil) + f->alog->buf = malloc(Nlog); + f->alog->rptr = f->alog->buf; + f->alog->end = f->alog->buf + Nlog; } - alog.opens++; - unlock(&alog); + f->alog->opens++; + unlock(f->alog); poperror(); } void -netlogclose(void) +netlogclose(Fs *f) { - lock(&alog); + lock(f->alog); if(waserror()){ - unlock(&alog); + unlock(f->alog); nexterror(); } - alog.opens--; - if(alog.opens == 0){ - free(alog.buf); - alog.buf = nil; + f->alog->opens--; + if(f->alog->opens == 0){ + free(f->alog->buf); + f->alog->buf = nil; } - unlock(&alog); + unlock(f->alog); poperror(); } static int -netlogready(void*) +netlogready(void *a) { - return alog.len; + Fs *f = a; + + return f->alog->len; } long -netlogread(void* a, ulong, long n) +netlogread(Fs *f, void *a, ulong, long n) { int i, d; char *p, *rptr; - qlock(&alog); + qlock(f->alog); if(waserror()){ - qunlock(&alog); + qunlock(f->alog); nexterror(); } for(;;){ - lock(&alog); - if(alog.len){ - if(n > alog.len) - n = alog.len; + lock(f->alog); + if(f->alog->len){ + if(n > f->alog->len) + n = f->alog->len; d = 0; - rptr = alog.rptr; - alog.rptr += n; - if(alog.rptr >= alog.end){ - d = alog.rptr - alog.end; - alog.rptr = alog.buf + d; + rptr = f->alog->rptr; + f->alog->rptr += n; + if(f->alog->rptr >= f->alog->end){ + d = f->alog->rptr - f->alog->end; + f->alog->rptr = f->alog->buf + d; } - alog.len -= n; - unlock(&alog); + f->alog->len -= n; + unlock(f->alog); i = n; p = a; @@ -129,28 +137,28 @@ netlogread(void* a, ulong, long n) memmove(p, rptr, d); i -= d; p += d; - rptr = alog.buf; + rptr = f->alog->buf; } memmove(p, rptr, i); break; } else - unlock(&alog); + unlock(f->alog); - sleep(&alog, netlogready, 0); + sleep(f->alog, netlogready, 0); } - qunlock(&alog); + qunlock(f->alog); poperror(); return n; } char* -netlogctl(char* s, int len) +netlogctl(Fs *f, char* s, int len) { int i, n, set; - Logflag *f; + Logflag *fp; char *fields[10], *p, buf[256]; if(len == 0) @@ -172,11 +180,11 @@ netlogctl(char* s, int len) else if(strcmp("clear", fields[0]) == 0) set = 0; else if(strcmp("only", fields[0]) == 0){ - parseip(iponly, fields[1]); - if(ipcmp(iponly, IPnoaddr) == 0) - iponlyset = 0; + parseip(f->alog->iponly, fields[1]); + if(ipcmp(f->alog->iponly, IPnoaddr) == 0) + f->alog->iponlyset = 0; else - iponlyset = 1; + f->alog->iponlyset = 1; return nil; } else return Ebadnetctl; @@ -186,56 +194,54 @@ netlogctl(char* s, int len) *p = 0; for(i = 1; i < n; i++){ - for(f = flags; f->name; f++) - if(strcmp(f->name, fields[i]) == 0) + for(fp = flags; fp->name; fp++) + if(strcmp(fp->name, fields[i]) == 0) break; - if(f->name == nil) + if(fp->name == nil) continue; if(set) - logmask |= f->mask; + f->alog->logmask |= fp->mask; else - logmask &= ~f->mask; + f->alog->logmask &= ~fp->mask; } return nil; } void -netlog(int mask, char *fmt, ...) +netlog(Fs *f, int mask, char *fmt, ...) { - char buf[128], *t, *f; + char buf[128], *t, *fp; int i, n; va_list arg; - if(!(logmask & mask)) + if(!(f->alog->logmask & mask)) return; va_start(arg, fmt); n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); -print("%s", buf); - - if(alog.opens == 0) + if(f->alog->opens == 0) return; - lock(&alog); - i = alog.len + n - Nlog; + lock(f->alog); + i = f->alog->len + n - Nlog; if(i > 0){ - alog.len -= i; - alog.rptr += i; - if(alog.rptr >= alog.end) - alog.rptr = alog.buf + (alog.rptr - alog.end); + f->alog->len -= i; + f->alog->rptr += i; + if(f->alog->rptr >= f->alog->end) + f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end); } - t = alog.rptr + alog.len; - f = buf; - alog.len += n; + t = f->alog->rptr + f->alog->len; + fp = buf; + f->alog->len += n; while(n-- > 0){ - if(t >= alog.end) - t = alog.buf + (t - alog.end); - *t++ = *f++; + if(t >= f->alog->end) + t = f->alog->buf + (t - f->alog->end); + *t++ = *fp++; } - unlock(&alog); + unlock(f->alog); - wakeup(&alog); + wakeup(f->alog); } diff --git a/ip/pktmedium.c b/ip/pktmedium.c index 8c1b6c50675d22889f57681a3feefa7408e8b19f..4da21e2e2d537b4241bba4f037da259a4845d1fc 100644 --- a/ip/pktmedium.c +++ b/ip/pktmedium.c @@ -12,7 +12,7 @@ static void pktbind(Ipifc *ifc, int argc, char **argv); static void pktunbind(Ipifc *ifc); static void pktbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); -static void pktin(Ipifc *ifc, Block *bp); +static void pktin(Fs*, Ipifc *ifc, Block *bp); Medium pktmedium = { @@ -64,13 +64,13 @@ pktbwrite(Ipifc *ifc, Block *bp, int, uchar*) } /* - * called when someone write's to 'data' with ifc rlocked + * called with ifc rlocked when someone write's to 'data' */ static void -pktin(Ipifc *ifc, Block *bp) +pktin(Fs *f, Ipifc *ifc, Block *bp) { if(ifc->lifc == nil) freeb(bp); else - ipiput(ifc->lifc->local, bp); + ipiput(f, ifc->lifc->local, bp); } diff --git a/ip/tcp.c b/ip/tcp.c index ed2b5c305e7fbadb66b5cfcdc5b410a4b45b764b..a26ba76216442b75c3158d1455b63d8edb373040 100644 --- a/ip/tcp.c +++ b/ip/tcp.c @@ -180,25 +180,52 @@ struct Tcpctl Tcphdr protohdr; /* prototype header */ }; -#define DBG(x) if((logmask & Logtcpmsg) && (iponlyset == 0 || memcmp(x, iponly+12, 4) == 0))netlog - -Proto tcp; int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */ -Timer *timers; /* List of active timers */ -QLock tl; /* Protect timer list */ -static struct Tcpstats +/* MIB II counters */ +typedef struct Tcpstats Tcpstats; +struct Tcpstats { - ulong dup; /* (partially) duplicated packets */ - ulong dupb; /* duplicated uchars */ -} tstats; + ulong tcpRtoAlgorithm; + ulong tcpRtoMin; + ulong tcpRtoMax; + ulong tcpMaxConn; + ulong tcpActiveOpens; + ulong tcpPassiveOpens; + ulong tcpAttemptFails; + ulong tcpEstabResets; + ulong tcpCurrEstab; + ulong tcpInSegs; + ulong tcpOutSegs; + ulong tcpRetransSegs; + ulong InErrs; + ulong OutRsts; +}; + +typedef struct Tcppriv Tcppriv; +struct Tcppriv +{ + Timer *timers; /* List of active timers */ + QLock tl; /* Protect timer list */ + Rendez tcpr; /* used by tcpackproc */ + + /* MIB stats */ + Tcpstats tstats; + + /* non-MIB stats */ + ulong csumerr; /* checksum errors */ + ulong hlenerr; /* header length error */ + ulong lenerr; /* short packet */ + ulong order; /* out of order */ + +}; void addreseq(Tcpctl*, Tcp*, Block*, ushort); void getreseq(Tcpctl*, Tcp*, Block**, ushort*); void localclose(Conv*, char*); void procsyn(Conv*, Tcp*); -void tcpiput(uchar*, Block*); +void tcpiput(Proto*, uchar*, Block*); void tcpoutput(Conv*); int tcptrim(Tcpctl*, Tcp*, Block**, ushort*); void tcpstart(Conv*, int, ushort); @@ -212,6 +239,9 @@ tcpsetstate(Conv *s, uchar newstate) { Tcpctl *tcb; uchar oldstate; + Tcppriv *tpriv; + + tpriv = s->p->priv; tcb = (Tcpctl*)s->ptcl; @@ -219,6 +249,11 @@ tcpsetstate(Conv *s, uchar newstate) if(oldstate == newstate) return; + if(oldstate == Established) + tpriv->tstats.tcpCurrEstab--; + if(newstate == Established) + tpriv->tstats.tcpCurrEstab++; + /* print("%d/%d %s->%s\n", s->lport, s->rport, tcpstates[oldstate], tcpstates[newstate]); @@ -241,7 +276,7 @@ tcpsetstate(Conv *s, uchar newstate) } if(oldstate == Syn_sent && newstate != Closed) - Fsconnected(&fs, s, nil); + Fsconnected(s, nil); } static char* @@ -288,7 +323,7 @@ tcpannounce(Conv *c, char **argv, int argc) if(e != nil) return e; tcpstart(c, TCP_LISTEN, QMAX); - Fsconnected(&fs, c, nil); + Fsconnected(c, nil); return nil; } @@ -311,7 +346,7 @@ tcpclose(Conv *c) /* * reset any incoming calls to this listener */ - Fsconnected(&fs, c, "Hangup"); + Fsconnected(c, "Hangup"); qlock(tcb); localclose(c, nil); @@ -376,10 +411,10 @@ tcpkick(Conv *s, int len) * get remote sender going if it was flow controlled due to a closed window */ static void -deltimer(Timer *t) +deltimer(Tcppriv *tpriv, Timer *t) { - if(timers == t) - timers = t->next; + if(tpriv->timers == t) + tpriv->timers = t->next; if(t->next) t->next->prev = t->prev; if(t->prev) @@ -423,29 +458,33 @@ tcpcreate(Conv *c) } void -tcpackproc(void*) +tcpackproc(void *a) { Timer *t, *tp, *timeo; - static Rendez tcpr; + Proto *tcp; + Tcppriv *tpriv; + + tcp = a; + tpriv = tcp->priv; for(;;) { - tsleep(&tcpr, return0, 0, MSPTICK); + tsleep(&tpriv->tcpr, return0, 0, MSPTICK); - qlock(&tl); + qlock(&tpriv->tl); timeo = nil; - for(t = timers; t != nil; t = tp) { + for(t = tpriv->timers; t != nil; t = tp) { tp = t->next; if(t->state == TimerON) { t->count--; if(t->count == 0) { - deltimer(t); + deltimer(tpriv, t); t->state = TimerDONE; t->next = timeo; timeo = t; } } } - qunlock(&tl); + qunlock(&tpriv->tl); for(;;) { t = timeo; @@ -460,35 +499,35 @@ tcpackproc(void*) } void -tcpgo(Timer *t) +tcpgo(Tcppriv *tpriv, Timer *t) { if(t == nil || t->start == 0) return; - qlock(&tl); + qlock(&tpriv->tl); t->count = t->start; if(t->state != TimerON) { t->state = TimerON; t->prev = nil; - t->next = timers; + t->next = tpriv->timers; if(t->next) t->next->prev = t; - timers = t; + tpriv->timers = t; } - qunlock(&tl); + qunlock(&tpriv->tl); } void -tcphalt(Timer *t) +tcphalt(Tcppriv *tpriv, Timer *t) { if(t == nil) return; - qlock(&tl); + qlock(&tpriv->tl); if(t->state == TimerON) - deltimer(t); + deltimer(tpriv, t); t->state = TimerOFF; - qunlock(&tl); + qunlock(&tpriv->tl); } int @@ -505,11 +544,13 @@ localclose(Conv *s, char *reason) /* called with tcb locked */ { Tcpctl *tcb; Reseq *rp,*rp1; + Tcppriv *tpriv; + tpriv = s->p->priv; tcb = (Tcpctl*)s->ptcl; - tcphalt(&tcb->timer); - tcphalt(&tcb->rtt_timer); + tcphalt(tpriv, &tcb->timer); + tcphalt(tpriv, &tcb->rtt_timer); /* Flush reassembly queue; nothing more can arrive */ for(rp = tcb->reseq; rp != nil; rp = rp1) { @@ -519,7 +560,7 @@ localclose(Conv *s, char *reason) /* called with tcb locked */ } if(tcb->state == Syn_sent) - Fsconnected(&fs, s, reason); + Fsconnected(s, reason); qhangup(s->rq, reason); qhangup(s->wq, reason); @@ -553,7 +594,7 @@ inittcpctl(Conv *s) /* create a prototype(pseudo) header */ if(ipcmp(s->laddr, IPnoaddr) == 0) - findlocalip(s->laddr, s->raddr); + findlocalip(s->p->f, s->laddr, s->raddr); h = &tcb->protohdr; memset(h, 0, sizeof(*h)); h->proto = IP_TCPPROTO; @@ -571,7 +612,7 @@ tcpmtu(Conv *s) int mtu; mtu = 0; - ifc = findipifc(s->raddr, 0); + ifc = findipifc(s->p->f, s->raddr, 0); if(ifc != nil) mtu = ifc->maxmtu - ifc->m->hsize - (TCP_PKT + TCP_HDRSIZE); if(mtu < 4) @@ -583,6 +624,9 @@ void tcpstart(Conv *s, int mode, ushort window) { Tcpctl *tcb; + Tcppriv *tpriv; + + tpriv = s->p->priv; tcb = (Tcpctl*)s->ptcl; @@ -592,11 +636,13 @@ tcpstart(Conv *s, int mode, ushort window) switch(mode) { case TCP_LISTEN: + tpriv->tstats.tcpPassiveOpens++; tcb->flags |= CLONE; tcpsetstate(s, Listen); break; case TCP_CONNECT: + tpriv->tstats.tcpActiveOpens++; /* Send SYN, go into SYN_SENT state */ qlock(tcb); tcb->flags |= ACTIVE; @@ -676,10 +722,10 @@ htontcp(Tcp *tcph, Block *data, Tcphdr *ph) csum = ptclcsum(data, TCP_IPLEN, hdrlen+dlen+TCP_PHDRSIZE); hnputs(h->tcpcksum, csum); - DBG(h->tcpdst)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", +/* netlog(f, Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", tcph->source, tcph->dest, tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), - tcph->wnd, dlen); + tcph->wnd, dlen); */ return data; } @@ -717,10 +763,10 @@ ntohtcp(Tcp *tcph, Block **bpp) if(*bpp == nil) return -1; - DBG(h->tcpsrc)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", +/* netlog(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", tcph->source, tcph->dest, tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), - tcph->wnd, nhgets(h->length)-hdrlen-TCP_PKT); + tcph->wnd, nhgets(h->length)-hdrlen-TCP_PKT); */ optr = h->tcpopt; for(i = TCP_HDRSIZE; i < hdrlen;) { @@ -761,11 +807,14 @@ tcpsndsyn(Tcpctl *tcb) * called with v4 (4 byte) addresses */ void -sndrst(uchar *source, uchar *dest, ushort length, Tcp *seg) +sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg) { Tcphdr ph; Block *hbp; uchar rflags; + Tcppriv *tpriv; + + tpriv = tcp->priv; if(seg->flags & RST) return; @@ -779,6 +828,7 @@ sndrst(uchar *source, uchar *dest, ushort length, Tcp *seg) hnputs(ph.tcpsport, seg->dest); hnputs(ph.tcpdport, seg->source); + tpriv->tstats.OutRsts++; rflags = RST; /* convince the other end that this reset is in band */ @@ -804,7 +854,7 @@ sndrst(uchar *source, uchar *dest, ushort length, Tcp *seg) if(hbp == nil) return; - ipoput(hbp, 0, MAXTTL); + ipoput(tcp->f, hbp, 0, MAXTTL); } /* @@ -821,7 +871,7 @@ tcphangup(Conv *s) tcb = (Tcpctl*)s->ptcl; if(waserror()){ qunlock(tcb); - return up->error; + return commonerror(); } qlock(tcb); if(s->raddr != 0) { @@ -834,7 +884,7 @@ tcphangup(Conv *s) tcb->last_ack = tcb->rcv.nxt; hnputs(ph.tcplen, TCP_HDRSIZE); hbp = htontcp(&seg, nil, &tcb->protohdr); - ipoput(hbp, 0, s->ttl); + ipoput(s->p->f, hbp, 0, s->ttl); } localclose(s, nil); poperror(); @@ -849,7 +899,7 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst) Tcpctl *tcb; Tcphdr *h; - new = Fsnewcall(&fs, s, src, segp->source, dst, segp->dest); + new = Fsnewcall(s, src, segp->source, dst, segp->dest); if(new == nil) return nil; @@ -919,15 +969,17 @@ tcpsynackrtt(Conv *s) { Tcpctl *tcb; int delta; + Tcppriv *tpriv; tcb = (Tcpctl*)s->ptcl; + tpriv = s->p->priv; delta = msec - tcb->sndsyntime; tcb->srtt = delta<mdev = delta<rtt_timer); + tcphalt(tpriv, &tcb->rtt_timer); } void @@ -936,7 +988,9 @@ update(Conv *s, Tcp *seg) int rtt, delta; Tcpctl *tcb; ushort acked, expand; + Tcppriv *tpriv; + tpriv = s->p->priv; tcb = (Tcpctl*)s->ptcl; tcb->kacounter = MAXBACKOFF; /* keep alive count down */ @@ -983,7 +1037,7 @@ update(Conv *s, Tcp *seg) /* Adjust the timers according to the round trip time */ if(tcb->rtt_timer.state == TimerON && seq_ge(seg->ack, tcb->rttseq)) { - tcphalt(&tcb->rtt_timer); + tcphalt(tpriv, &tcb->rtt_timer); if((tcb->flags&RETRAN) == 0) { tcb->backoff = 0; rtt = tcb->rtt_timer.start - tcb->rtt_timer.count; @@ -1020,9 +1074,9 @@ update(Conv *s, Tcp *seg) if(seq_gt(seg->ack, tcb->snd.urg)) tcb->snd.urg = seg->ack; - tcphalt(&tcb->timer); + tcphalt(tpriv, &tcb->timer); if(tcb->snd.una != tcb->snd.nxt) - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); if(seq_lt(tcb->snd.ptr, tcb->snd.una)) tcb->snd.ptr = tcb->snd.una; @@ -1032,7 +1086,7 @@ update(Conv *s, Tcp *seg) } void -tcpiput(uchar*, Block *bp) +tcpiput(Proto *tcp, uchar*, Block *bp) { Tcp seg; Tcphdr *h; @@ -1041,6 +1095,13 @@ tcpiput(uchar*, Block *bp) ushort length; uchar source[IPaddrlen], dest[IPaddrlen]; Conv *spec, *gen, *s, **p; + Fs *f; + Tcppriv *tpriv; + + f = tcp->f; + tpriv = tcp->priv; + + tpriv->tstats.tcpInSegs++; h = (Tcphdr*)(bp->rp); @@ -1051,16 +1112,16 @@ tcpiput(uchar*, Block *bp) h->Unused = 0; hnputs(h->tcplen, length-TCP_PKT); if(ptclcsum(bp, TCP_IPLEN, length-TCP_IPLEN)) { - tcp.csumerr++; - netlog(Logtcp, "bad tcp proto cksum\n"); + tpriv->csumerr++; + netlog(f, Logtcp, "bad tcp proto cksum\n"); freeblist(bp); return; } hdrlen = ntohtcp(&seg, &bp); if(hdrlen < 0){ - tcp.hlenerr++; - netlog(Logtcp, "bad tcp hdr len\n"); + tpriv->hlenerr++; + netlog(f, Logtcp, "bad tcp hdr len\n"); return; } @@ -1068,14 +1129,14 @@ tcpiput(uchar*, Block *bp) length -= hdrlen+TCP_PKT; bp = trimblock(bp, hdrlen+TCP_PKT, length); if(bp == nil){ - tcp.lenerr++; - netlog(Logtcp, "tcp len < 0 after trim\n"); + tpriv->lenerr++; + netlog(f, Logtcp, "tcp len < 0 after trim\n"); return; } /* Look for a connection. failing that look for a listener. */ - for(p = tcp.conv; *p; p++) { + for(p = tcp->conv; *p; p++) { s = *p; if(s->rport == seg.source) if(s->lport == seg.dest) @@ -1100,7 +1161,7 @@ tcpiput(uchar*, Block *bp) return; } if(seg.flags & ACK) { - sndrst(source, dest, length, &seg); + sndrst(tcp, source, dest, length, &seg); freeblist(bp); return; } @@ -1111,7 +1172,7 @@ tcpiput(uchar*, Block *bp) */ gen = nil; spec = nil; - for(p = tcp.conv; *p; p++) { + for(p = tcp->conv; *p; p++) { s = *p; tcb = (Tcpctl*)s->ptcl; if((tcb->flags & CLONE) == 0) @@ -1136,7 +1197,7 @@ tcpiput(uchar*, Block *bp) } if(s == nil) { freeblist(bp); - sndrst(source, dest, length, &seg); + sndrst(tcp, source, dest, length, &seg); return; } @@ -1149,7 +1210,7 @@ tcpiput(uchar*, Block *bp) switch(tcb->state) { case Closed: - sndrst(source, dest, length, &seg); + sndrst(tcp, source, dest, length, &seg); goto raise; case Listen: if(seg.flags & SYN) { @@ -1163,7 +1224,7 @@ tcpiput(uchar*, Block *bp) case Syn_sent: if(seg.flags & ACK) { if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) { - sndrst(source, dest, length, &seg); + sndrst(tcp, source, dest, length, &seg); goto raise; } } @@ -1203,12 +1264,12 @@ tcpiput(uchar*, Block *bp) /* Cut the data to fit the receive window */ if(tcptrim(tcb, &seg, &bp, &length) == -1) { - netlog(Logtcp, "tcp len < 0, %lux\n", seg.seq); + netlog(f, Logtcp, "tcp len < 0, %lux\n", seg.seq); update(s, &seg); if(tcb->sndcnt == 0 && tcb->state == Closing) { tcpsetstate(s, Time_wait); tcb->timer.start = MSL2*(1000 / MSPTICK); - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); } if(!(seg.flags & RST)) { tcb->flags |= FORCE; @@ -1220,7 +1281,7 @@ tcpiput(uchar*, Block *bp) /* Cannot accept so answer with a rst */ if(length && tcb->state == Closed) { - sndrst(source, dest, length, &seg); + sndrst(tcp, source, dest, length, &seg); goto raise; } @@ -1230,7 +1291,7 @@ tcpiput(uchar*, Block *bp) if(seg.seq != tcb->rcv.nxt) if(length != 0 || (seg.flags & (SYN|FIN))) { update(s, &seg); - tcp.order++; + tpriv->order++; addreseq(tcb, &seg, bp, length); tcb->flags |= FORCE; goto output; @@ -1242,6 +1303,8 @@ tcpiput(uchar*, Block *bp) */ for(;;) { if(seg.flags & RST) { + if(tcb->state == Established) + tpriv->tstats.tcpEstabResets++; localclose(s, Econrefused); goto raise; } @@ -1252,7 +1315,7 @@ tcpiput(uchar*, Block *bp) switch(tcb->state) { case Syn_received: if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){ - sndrst(source, dest, length, &seg); + sndrst(tcp, source, dest, length, &seg); goto raise; } update(s, &seg); @@ -1267,7 +1330,7 @@ tcpiput(uchar*, Block *bp) tcb->f2counter = MAXBACKOFF; tcpsetstate(s, Finwait2); tcb->timer.start = MSL2 * (1000 / MSPTICK); - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); } break; case Finwait2: @@ -1278,7 +1341,7 @@ tcpiput(uchar*, Block *bp) if(tcb->sndcnt == 0) { tcpsetstate(s, Time_wait); tcb->timer.start = MSL2*(1000 / MSPTICK); - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); } break; case Last_ack: @@ -1290,7 +1353,7 @@ tcpiput(uchar*, Block *bp) case Time_wait: tcb->flags |= FORCE; if(tcb->timer.state != TimerON) - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); } if((seg.flags&URG) && seg.urg) { @@ -1328,7 +1391,7 @@ tcpiput(uchar*, Block *bp) tcb->rcv.nxt += length; tcprcvwin(s); if(tcb->acktimer.state != TimerON) - tcpgo(&tcb->acktimer); + tcpgo(tpriv, &tcb->acktimer); /* force an ack if there's a lot of unacked data */ if(tcb->rcv.nxt-tcb->last_ack > (QMAX>>4)) @@ -1339,7 +1402,7 @@ tcpiput(uchar*, Block *bp) /* no process to read the data, send a reset */ if(bp != nil) freeblist(bp); - sndrst(source, dest, length, &seg); + sndrst(tcp, source, dest, length, &seg); qunlock(tcb); return; } @@ -1359,7 +1422,7 @@ tcpiput(uchar*, Block *bp) if(tcb->sndcnt == 0) { tcpsetstate(s, Time_wait); tcb->timer.start = MSL2*(1000/MSPTICK); - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); } else tcpsetstate(s, Closing); @@ -1368,14 +1431,14 @@ tcpiput(uchar*, Block *bp) tcb->rcv.nxt++; tcpsetstate(s, Time_wait); tcb->timer.start = MSL2 * (1000/MSPTICK); - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); break; case Close_wait: case Closing: case Last_ack: break; case Time_wait: - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); break; } } @@ -1420,6 +1483,11 @@ tcpoutput(Conv *s) Block *hbp, *bp; int sndcnt, n, first; ulong ssize, dsize, usable, sent; + Fs *f; + Tcppriv *tpriv; + + f = s->p->f; + tpriv = s->p->priv; tcb = (Tcpctl*)s->ptcl; @@ -1489,7 +1557,7 @@ tcpoutput(Conv *s) if((tcb->flags&FORCE) == 0) break; - tcphalt(&tcb->acktimer); + tcphalt(tpriv, &tcb->acktimer); tcb->flags &= ~FORCE; tcprcvwin(s); @@ -1525,7 +1593,7 @@ tcpoutput(Conv *s) seg.flags |= FIN; dsize--; } - netlog(Logtcp, "qcopy: dlen %d blen %d sndcnt %d qlen %d sent %d rp[0] %d\n", + netlog(f, Logtcp, "qcopy: dlen %d blen %d sndcnt %d qlen %d sent %d rp[0] %d\n", dsize, BLEN(bp), sndcnt, qlen(s->wq), sent, bp->rp[0]); } @@ -1566,16 +1634,17 @@ tcpoutput(Conv *s) tcb->timer.start = x; if(tcb->timer.state != TimerON) - tcpgo(&tcb->timer); + tcpgo(tpriv, &tcb->timer); /* If round trip timer isn't running, start it */ if(tcb->rtt_timer.state != TimerON) { - tcpgo(&tcb->rtt_timer); + tcpgo(tpriv, &tcb->rtt_timer); tcb->rttseq = tcb->snd.ptr; } } - ipoput(hbp, 0, s->ttl); + tpriv->tstats.tcpOutSegs++; + ipoput(f, hbp, 0, s->ttl); } } @@ -1616,17 +1685,18 @@ tcpkeepalive(Conv *s) return; } - ipoput(hbp, 0, s->ttl); + ipoput(s->p->f, hbp, 0, s->ttl); } void tcprxmit(Conv *s) { Tcpctl *tcb; + Tcppriv *tpriv; + tpriv = s->p->priv; tcb = (Tcpctl*)s->ptcl; - qlock(tcb); tcb->flags |= RETRAN|FORCE; tcb->snd.ptr = tcb->snd.una; @@ -1642,8 +1712,7 @@ tcprxmit(Conv *s) tcb->cwind = tcb->mss; tcpoutput(s); - tcp.rexmit++; - + tpriv->tstats.tcpRetransSegs++; qunlock(tcb); } @@ -1678,7 +1747,7 @@ tcptimeout(void *arg) qlock(tcb); tcpkeepalive(s); qunlock(tcb); - tcpgo(&tcb->timer); + tcpgo(s->p->priv, &tcb->timer); } break; case Time_wait: @@ -1807,8 +1876,6 @@ tcptrim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length) dupcnt = tcb->rcv.nxt - seg->seq; if(dupcnt > 0){ tcb->rerecv += dupcnt; - tstats.dup++; - tstats.dupb += dupcnt; if(seg->flags & SYN){ seg->flags &= ~SYN; seg->seq++; @@ -1845,7 +1912,7 @@ tcptrim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length) } void -tcpadvise(Block *bp, char *msg) +tcpadvise(Proto *tcp, Block *bp, char *msg) { Tcphdr *h; Tcpctl *tcb; @@ -1862,7 +1929,7 @@ tcpadvise(Block *bp, char *msg) pdest = nhgets(h->tcpdport); /* Look for a connection */ - for(p = tcp.conv; *p; p++) { + for(p = tcp->conv; *p; p++) { s = *p; if(s->rport == pdest) if(s->lport == psource) @@ -1892,39 +1959,54 @@ tcpctl(Conv* c, char** f, int n) } int -tcpstats(char *buf, int len) +tcpstats(Proto *tcp, char *buf, int len) { - int n; - - n = snprint(buf, len, - "tcp: csum %d hlen %d len %d order %d rexmit %d", - tcp.csumerr, tcp.hlenerr, tcp.lenerr, tcp.order, tcp.rexmit); - n += snprint(buf+n, len-n, " dupp %d dupb %d\n", - tstats.dup, tstats.dupb); - return n; + Tcpstats *tstats; + + tstats = tcp->priv; + return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d", + tstats->tcpRtoAlgorithm, + tstats->tcpRtoMin, + tstats->tcpRtoMax, + tstats->tcpMaxConn, + tstats->tcpActiveOpens, + tstats->tcpPassiveOpens, + tstats->tcpAttemptFails, + tstats->tcpEstabResets, + tstats->tcpCurrEstab, + tstats->tcpInSegs, + tstats->tcpOutSegs, + tstats->tcpRetransSegs, + tstats->InErrs, + tstats->OutRsts); } void tcpinit(Fs *fs) { - tcp.name = "tcp"; - tcp.kick = tcpkick; - tcp.connect = tcpconnect; - tcp.announce = tcpannounce; - tcp.ctl = tcpctl; - tcp.state = tcpstate; - tcp.create = tcpcreate; - tcp.close = tcpclose; - tcp.rcv = tcpiput; - tcp.advise = tcpadvise; - tcp.stats = tcpstats; - tcp.inuse = tcpinuse; - tcp.ipproto = IP_TCPPROTO; - tcp.nc = Nchans; - tcp.ptclsize = sizeof(Tcpctl); - - kproc("tcpack", tcpackproc, 0); - - Fsproto(fs, &tcp); + Proto *tcp; + Tcppriv *tpriv; + + tcp = smalloc(sizeof(Proto)); + tpriv = tcp->priv = smalloc(sizeof(Tcppriv)); + tcp->name = "tcp"; + tcp->kick = tcpkick; + tcp->connect = tcpconnect; + tcp->announce = tcpannounce; + tcp->ctl = tcpctl; + tcp->state = tcpstate; + tcp->create = tcpcreate; + tcp->close = tcpclose; + tcp->rcv = tcpiput; + tcp->advise = tcpadvise; + tcp->stats = tcpstats; + tcp->inuse = tcpinuse; + tcp->ipproto = IP_TCPPROTO; + tcp->nc = Nchans; + tcp->ptclsize = sizeof(Tcpctl); + tpriv->tstats.tcpMaxConn = Nchans; + + Fsproto(fs, tcp); + + kproc("tcpack", tcpackproc, tcp); } - diff --git a/ip/udp.c b/ip/udp.c index 5cf5098980605d1a52283b5211a670a6e117a271..ff8752e97613299e848e7d2aa739740e074ddac8 100644 --- a/ip/udp.c +++ b/ip/udp.c @@ -15,7 +15,8 @@ enum UDP_HDRSIZE = 20, UDP_IPHDR = 8, IP_UDPPROTO = 17, - UDP_USEAD = 12, + UDP_USEAD6 = 36, + UDP_USEAD4 = 12, Udprxms = 200, Udptickms = 100, @@ -44,6 +45,27 @@ struct Udphdr uchar udpcksum[2]; /* Checksum */ }; +/* MIB II counters */ +typedef struct Udpstats Udpstats; +struct Udpstats +{ + ulong udpInDatagrams; + ulong udpNoPorts; + ulong udpInErrors; + ulong udpOutDatagrams; +}; + +typedef struct Udppriv Udppriv; +struct Udppriv +{ + /* MIB counters */ + Udpstats ustats; + + /* non-MIB stats */ + ulong csumerr; /* checksum errors */ + ulong lenerr; /* short packet */ +}; + /* * protocol specific part of Conv */ @@ -54,23 +76,18 @@ struct Udpcb uchar headers; }; - Proto udp; - int udpsum; - uint generation; -extern Fs fs; - int udpdebug; - static char* udpconnect(Conv *c, char **argv, int argc) { char *e; e = Fsstdconnect(c, argv, argc); - Fsconnected(&fs, c, e); + Fsconnected(c, e); return e; } + static int udpstate(Conv *c, char *state, int n) { @@ -86,7 +103,7 @@ udpannounce(Conv *c, char** argv, int argc) e = Fsstdannounce(c, argv, argc); if(e != nil) return e; - Fsconnected(&fs, c, nil); + Fsconnected(c, nil); return nil; } @@ -126,30 +143,54 @@ udpkick(Conv *c, int) Block *bp; Udpcb *ucb; int dlen, ptcllen; + Udppriv *upriv; + Fs *f; - netlog(Logudp, "udp: kick\n"); + upriv = c->p->priv; + f = c->p->f; + + netlog(c->p->f, Logudp, "udp: kick\n"); bp = qget(c->wq); if(bp == nil) return; ucb = (Udpcb*)c->ptcl; - if(ucb->headers) { + switch(ucb->headers) { + case 6: /* get user specified addresses */ - bp = pullupblock(bp, UDP_USEAD); + bp = pullupblock(bp, UDP_USEAD6); if(bp == nil) return; ipmove(raddr, bp->rp); bp->rp += IPaddrlen; ipmove(laddr, bp->rp); bp->rp += IPaddrlen; - if(ipforme(laddr) != Runi) - findlocalip(laddr, raddr); /* pick interface closest to dest */ + if(ipforme(f, laddr) != Runi) + findlocalip(f, laddr, raddr); /* pick interface closest to dest */ + rport = nhgets(bp->rp); + bp->rp += 2; + /* ignore local port number */ + bp->rp += 2; + break; + case 4: + /* get user specified addresses */ + bp = pullupblock(bp, UDP_USEAD4); + if(bp == nil) + return; + v4tov6(raddr, bp->rp); + bp->rp += IPv4addrlen; + v4tov6(laddr, bp->rp); + bp->rp += IPv4addrlen; + if(ipforme(f, laddr) != Runi) + findlocalip(f, laddr, raddr); /* pick interface closest to dest */ rport = nhgets(bp->rp); bp->rp += 2; /* ignore local port number */ bp->rp += 2; - } else { + break; + default: rport = 0; + break; } dlen = blocklen(bp); @@ -167,16 +208,24 @@ udpkick(Conv *c, int) uh->frag[0] = 0; uh->frag[1] = 0; hnputs(uh->udpplen, ptcllen); - if(ucb->headers) { + switch(ucb->headers){ + case 6: v6tov4(uh->udpdst, raddr); hnputs(uh->udpdport, rport); v6tov4(uh->udpsrc, laddr); - } else { + break; + case 4: + memmove(uh->udpdst, raddr, IPv4addrlen); + hnputs(uh->udpdport, rport); + memmove(uh->udpsrc, laddr, IPv4addrlen); + break; + default: v6tov4(uh->udpdst, c->raddr); hnputs(uh->udpdport, c->rport); if(ipcmp(c->laddr, IPnoaddr) == 0) - findlocalip(c->laddr, c->raddr); /* pick interface closest to dest */ + findlocalip(f, c->laddr, c->raddr); /* pick interface closest to dest */ v6tov4(uh->udpsrc, c->laddr); + break; } hnputs(uh->udpsport, c->lport); hnputs(uh->udplen, ptcllen); @@ -185,11 +234,12 @@ udpkick(Conv *c, int) hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, dlen+UDP_HDRSIZE)); - ipoput(bp, 0, c->ttl); + upriv->ustats.udpOutDatagrams++; + ipoput(f, bp, 0, c->ttl); } void -udpiput(uchar *ia, Block *bp) +udpiput(Proto *udp, uchar *ia, Block *bp) { int len, olen, ottl; Udphdr *uh; @@ -197,6 +247,13 @@ udpiput(uchar *ia, Block *bp) Udpcb *ucb; uchar raddr[IPaddrlen], laddr[IPaddrlen]; ushort rport, lport; + Udppriv *upriv; + Fs *f; + + upriv = udp->priv; + f = udp->f; + + upriv->ustats.udpInDatagrams++; uh = (Udphdr*)(bp->rp); @@ -212,10 +269,10 @@ udpiput(uchar *ia, Block *bp) lport = nhgets(uh->udpdport); rport = nhgets(uh->udpsport); - if(udpsum && nhgets(uh->udpcksum)) { + if(nhgets(uh->udpcksum)) { if(ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE)) { - udp.csumerr++; - netlog(Logudp, "udp: checksum error %I\n", raddr); + upriv->ustats.udpInErrors++; + netlog(f, Logudp, "udp: checksum error %I\n", raddr); freeblist(bp); return; } @@ -223,7 +280,7 @@ udpiput(uchar *ia, Block *bp) /* Look for a conversation structure for this port */ c = nil; - for(p = udp.conv; *p; p++) { + for(p = udp->conv; *p; p++) { c = *p; if(c->inuse == 0) continue; @@ -232,13 +289,14 @@ udpiput(uchar *ia, Block *bp) } if(*p == nil) { - netlog(Logudp, "udp: no conv %I.%d -> %I.%d\n", raddr, rport, + upriv->ustats.udpNoPorts++; + netlog(f, Logudp, "udp: no conv %I.%d -> %I.%d\n", raddr, rport, laddr, lport); /* don't complain about broadcasts... */ - if(ipforme(raddr) == 0){ + if(ipforme(f, raddr) == 0){ uh->Unused = ottl; hnputs(uh->udpplen, olen); - icmpnoconv(bp); + icmpnoconv(f, bp); } freeblist(bp); return; @@ -250,28 +308,41 @@ udpiput(uchar *ia, Block *bp) len -= (UDP_HDRSIZE-UDP_PHDRSIZE); bp = trimblock(bp, UDP_IPHDR+UDP_HDRSIZE, len); if(bp == nil){ - netlog(Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport, + netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport, laddr, lport); - udp.lenerr++; + upriv->lenerr++; return; } - netlog(Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport, + netlog(f, Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport, laddr, lport, len); ucb = (Udpcb*)c->ptcl; - if(ucb->headers) { + switch(ucb->headers){ + case 6: /* pass the src address */ - bp = padblock(bp, UDP_USEAD); + bp = padblock(bp, UDP_USEAD6); ipmove(bp->rp, raddr); - if(ipforme(laddr) == Runi) + if(ipforme(f, laddr) == Runi) ipmove(bp->rp+IPaddrlen, laddr); else ipmove(bp->rp+IPaddrlen, ia); hnputs(bp->rp+2*IPaddrlen, rport); hnputs(bp->rp+2*IPaddrlen+2, lport); - } else { + break; + case 4: + /* pass the src address */ + bp = padblock(bp, UDP_USEAD4); + memmove(bp->rp, raddr, IPv4addrlen); + if(ipforme(f, laddr) == Runi) + memmove(bp->rp+IPv4addrlen, laddr, IPv4addrlen); + else + memmove(bp->rp+IPv4addrlen, ia, IPv4addrlen); + hnputs(bp->rp + 2*IPv4addrlen, rport); + hnputs(bp->rp + 2*IPv4addrlen + 2, lport); + break; + default: /* connection oriented udp */ if(c->raddr == 0){ /* save the src address in the conversation */ @@ -279,17 +350,18 @@ udpiput(uchar *ia, Block *bp) c->rport = rport; /* reply with the same ip address (if not broadcast) */ - if(ipforme(laddr) == Runi) + if(ipforme(f, laddr) == Runi) ipmove(c->laddr, laddr); else - ipmove(c->laddr, ia); + v4tov6(c->laddr, ia); } + break; } if(bp->next) bp = concatblock(bp); if(qfull(c->rq)){ - netlog(Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport, + netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport, laddr, lport); freeblist(bp); }else @@ -302,19 +374,20 @@ udpctl(Conv *c, char **f, int n) Udpcb *ucb; ucb = (Udpcb*)c->ptcl; - if(n == 1 && strcmp(f[0], "headers") == 0){ - ucb->headers = 1; - return nil; - } - if(n == 1 && strcmp(f[0], "debug") == 0){ - udpdebug = 1; - return nil; + if(n == 1){ + if(strcmp(f[0], "headers4") == 0){ + ucb->headers = 4; + return nil; + } else if(strcmp(f[0], "headers") == 0){ + ucb->headers = 6; + return nil; + } } return "unknown control request"; } void -udpadvise(Block *bp, char *msg) +udpadvise(Proto *udp, Block *bp, char *msg) { Udphdr *h; uchar source[IPaddrlen], dest[IPaddrlen]; @@ -329,7 +402,7 @@ udpadvise(Block *bp, char *msg) pdest = nhgets(h->udpdport); /* Look for a connection */ - for(p = udp.conv; *p; p++) { + for(p = udp->conv; *p; p++) { s = *p; if(s->rport == pdest) if(s->lport == psource) @@ -344,30 +417,39 @@ udpadvise(Block *bp, char *msg) } int -udpstats(char *buf, int len) +udpstats(Proto *udp, char *buf, int len) { - return snprint(buf, len, - "udp: csum %d hlen %d len %d order %d rexmit %d\n", - udp.csumerr, udp.hlenerr, udp.lenerr, udp.order, udp.rexmit); + Udppriv *upriv; + + upriv = udp->priv; + return snprint(buf, len, "%d %d %d %d", + upriv->ustats.udpInDatagrams, + upriv->ustats.udpNoPorts, + upriv->ustats.udpInErrors, + upriv->ustats.udpOutDatagrams); } void udpinit(Fs *fs) { - udp.name = "udp"; - udp.kick = udpkick; - udp.connect = udpconnect; - udp.announce = udpannounce; - udp.ctl = udpctl; - udp.state = udpstate; - udp.create = udpcreate; - udp.close = udpclose; - udp.rcv = udpiput; - udp.advise = udpadvise; - udp.stats = udpstats; - udp.ipproto = IP_UDPPROTO; - udp.nc = 16; - udp.ptclsize = sizeof(Udpcb); - - Fsproto(fs, &udp); + Proto *udp; + + udp = smalloc(sizeof(Proto)); + udp->priv = smalloc(sizeof(Udppriv)); + udp->name = "udp"; + udp->kick = udpkick; + udp->connect = udpconnect; + udp->announce = udpannounce; + udp->ctl = udpctl; + udp->state = udpstate; + udp->create = udpcreate; + udp->close = udpclose; + udp->rcv = udpiput; + udp->advise = udpadvise; + udp->stats = udpstats; + udp->ipproto = IP_UDPPROTO; + udp->nc = 16; + udp->ptclsize = sizeof(Udpcb); + + Fsproto(fs, udp); }