## diffname ip/ip.c 1997/0327 ## diff -e /dev/null /n/emeliedump/1997/0327/sys/src/brazil/ip/ip.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "ip.h" typedef struct Iphdr Iphdr; typedef struct Fragment Fragment; typedef struct Ipfrag Ipfrag; enum { IPHDR = 20, /* sizeof(Iphdr) */ IP_VER = 0x40, /* Using IP version 4 */ IP_HLEN = 0x05, /* Header length in characters */ IP_DF = 0x4000, /* Don't fragment */ IP_MF = 0x2000, /* More fragments */ IP_MAX = (32*1024), /* Maximum Internet packet size */ }; struct Iphdr { byte vihl; /* Version and header length */ byte tos; /* Type of service */ byte length[2]; /* packet length */ byte id[2]; /* Identification */ byte frag[2]; /* Fragment information */ byte ttl; /* Time to live */ byte proto; /* Protocol */ byte cksum[2]; /* Header checksum */ byte src[4]; /* Ip source */ byte dst[4]; /* Ip destination */ }; struct Fragment { QLock; Block* blist; Fragment* next; Ipaddr src; Ipaddr dst; ushort id; ulong age; }; struct Ipfrag { ushort foff; ushort flen; }; Fragment* flisthead; Fragment* fragfree; QLock fraglock; ulong Id; int iprouting; /* true if we route like a gateway */ ulong ipcsumerr; ulong ipin, ippin; /* bytes, packets in */ ulong ipout, ippout; /* bytes, packets out */ #define BLKIP(xp) ((Iphdr*)((xp)->rp)) /* * This sleazy macro relies on the media header size being * larger than sizeof(Ipfrag). ipreassemble checks this is true */ #define BKFG(xp) ((Ipfrag*)((xp)->base)) ushort ipcsum(byte*); Block* ipreassemble(int, Block*, Iphdr*); void ipfragfree(Fragment*, int); Fragment* ipfragallo(void); void ipoput(Block *bp, int gating, int ttl) { Media *m; byte gate[4]; ushort fragoff; Block *xp, *nb; Iphdr *eh, *feh; int lid, len, seglen, chunk, dlen, blklen, offset, medialen; /* Fill out the ip header */ eh = (Iphdr *)(bp->rp); /* Number of bytes 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"); goto raise; } if(chunk < len) len = chunk; } if(len >= IP_MAX) { netlog(Logip, "exceeded ip max size %I\n", eh->dst); goto raise; } m = Mediaroute(eh->dst, gate); if(m == nil){ netlog(Logip, "no interface %I\n", eh->dst); goto raise; } if(!gating){ eh->vihl = IP_VER|IP_HLEN; eh->tos = 0; eh->ttl = ttl; } /* If we dont need to fragment just send it */ medialen = m->maxmtu-m->hsize; if(len <= medialen) { if(!gating) hnputs(eh->id, Id++); hnputs(eh->length, len); eh->frag[0] = 0; eh->frag[1] = 0; eh->cksum[0] = 0; eh->cksum[1] = 0; hnputs(eh->cksum, ipcsum(&eh->vihl)); Mediawrite(m, bp, gate); return; } if(eh->frag[0] & (IP_DF>>8)){ netlog(Logip, "%I: eh->frag[0] & (IP_DF>>8)", eh->dst); goto raise; } seglen = (medialen - IPHDR) & ~7; if(seglen < 8){ netlog(Logip, "%I seglen < 8\n", eh->dst); goto raise; } dlen = len - IPHDR; xp = bp; if(gating) lid = nhgets(eh->id); else lid = Id++; offset = IPHDR; while(xp != nil && offset && offset >= BLEN(xp)) { offset -= BLEN(xp); xp = xp->next; } xp->rp += offset; for(fragoff = 0; fragoff < dlen; fragoff += seglen) { nb = allocb(IPHDR+seglen); feh = (Iphdr*)(nb->rp); memmove(nb->wp, eh, IPHDR); nb->wp += IPHDR; if((fragoff + seglen) >= dlen) { seglen = dlen - fragoff; hnputs(feh->frag, fragoff>>3); } else hnputs(feh->frag, (fragoff>>3)|IP_MF); hnputs(feh->length, seglen + IPHDR); hnputs(feh->id, lid); /* Copy up the data area */ chunk = seglen; while(chunk) { if(!xp) { freeblist(nb); netlog(Logip, "!xp: chunk %d\n", chunk); goto raise; } blklen = chunk; if(BLEN(xp) < chunk) blklen = BLEN(xp); memmove(nb->wp, xp->rp, blklen); nb->wp += blklen; xp->rp += blklen; chunk -= blklen; if(xp->rp == xp->wp) xp = xp->next; } feh->cksum[0] = 0; feh->cksum[1] = 0; hnputs(feh->cksum, ipcsum(&feh->vihl)); Mediawrite(m, nb, gate); } raise: freeblist(bp); } void initfrag(int size) { Fragment *fq, *eq; fragfree = (Fragment*)malloc(sizeof(Fragment) * size); if(fragfree == nil) panic("initfrag"); eq = &fragfree[size]; for(fq = fragfree; fq < eq; fq++) fq->next = fq+1; fragfree[size-1].next = nil; } void (*ipextprotoiput)(Block*); void ipiput(Block *bp) { Iphdr *h; Proto *p; ushort frag; int notforme; /* h = (Iphdr *)(bp->rp); netlog(Logip, "ipiput %I %I len %d proto %d\n", h->src, h->dst, BLEN(bp), h->proto);*/ /* Ensure we have enough data to process */ if(BLEN(bp) < IPHDR) { bp = pullupblock(bp, IPHDR); if(bp == nil) return; } h = (Iphdr *)(bp->rp); /* Look to see if its for me before we waste time checksumming it */ notforme = Mediaforme(h->dst) == 0; if(notforme && !iprouting) { netlog(Logip, "ip: pkt not for me\n"); freeblist(bp); return; } if(ipcsum(&h->vihl)) { ipcsumerr++; netlog(Logip, "ip: checksum error %I\n", h->src); freeblist(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); if(bp == nil) return; h = (Iphdr *)(bp->rp); } ipin += blocklen(bp); ippin++; if(iprouting) { /* gate */ if(notforme){ if(h->ttl == 0) freeblist(bp); else ipoput(bp, 1, h->ttl - 1); return; } } p = Fsrcvpcol(&fs, h->proto); if(p != nil && p->rcv != nil) (*p->rcv)(bp); else if(ipextprotoiput != nil) ipextprotoiput(bp); else freeblist(bp); } int ipstats(char *buf, int len) { int n; n = snprint(buf, len, "ip: csum %d inb %d outb %d inp %d outp %d\n", ipcsumerr, ipin, ipout, ippin, ippout); return n; } QLock iplock; Block* ipreassemble(int offset, Block *bp, Iphdr *ip) { int fend; ushort id; Fragment *f, *fnext; Ipaddr src, dst; Block *bl, **l, *last, *prev; int ovlap, len, fragsize, pktposn; src = nhgetl(ip->src); dst = nhgetl(ip->dst); id = nhgets(ip->id); /* * block lists are too hard, pullupblock into a single block */ if(bp->next){ bp = pullupblock(bp, blocklen(bp)); ip = (Iphdr *)(bp->rp); } qlock(&iplock); /* * find a reassembly queue for this fragment */ qlock(&fraglock); for(f = 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 && canqlock(f)) ipfragfree(f, 0); } qunlock(&fraglock); /* * if this isn't a fragmented packet, accept it * and get rid of any fragments that might go * with it. */ if(!ip->tos && (offset & ~(IP_MF|IP_DF)) == 0) { if(f != nil) { qlock(f); ipfragfree(f, 1); } qunlock(&iplock); return bp; } if(bp->base+sizeof(Ipfrag) >= bp->rp) panic("ipreassemble"); BKFG(bp)->foff = offset<<3; BKFG(bp)->flen = nhgets(ip->length)-IPHDR; /* First fragment allocates a reassembly queue */ if(f == nil) { f = ipfragallo(); qlock(f); f->id = id; f->src = src; f->dst = dst; f->blist = bp; qunlock(f); qunlock(&iplock); return nil; } qlock(f); /* * find the new fragment's position in the queue */ prev = nil; l = &f->blist; bl = f->blist; while(bl != nil && BKFG(bp)->foff > BKFG(bl)->foff) { prev = bl; l = &bl->next; bl = bl->next; } /* Check overlap of a previous fragment - trim away as necessary */ if(prev) { ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff; if(ovlap > 0) { if(ovlap >= BKFG(bp)->flen) { freeblist(bp); qunlock(f); qunlock(&iplock); return nil; } BKFG(prev)->flen -= ovlap; } } /* Link onto assembly queue */ bp->next = *l; *l = bp; /* Check to see if succeeding segments overlap */ if(bp->next) { l = &bp->next; fend = BKFG(bp)->foff + BKFG(bp)->flen; /* Take completely covered segments out */ while(*l) { ovlap = fend - BKFG(*l)->foff; if(ovlap <= 0) break; if(ovlap < BKFG(*l)->flen) { BKFG(*l)->flen -= ovlap; BKFG(*l)->foff += ovlap; /* move up ip hdrs */ memmove((*l)->rp + ovlap, (*l)->rp, IPHDR); (*l)->rp += ovlap; break; } last = (*l)->next; (*l)->next = nil; freeblist(*l); *l = last; } } /* * look for a complete packet. if we get to a fragment * without IP_MF set, we're done. */ pktposn = 0; for(bl = f->blist; bl; bl = bl->next) { if(BKFG(bl)->foff != pktposn) break; if((BLKIP(bl)->frag[0]&(IP_MF>>8)) == 0) { bl = f->blist; len = nhgets(BLKIP(bl)->length); bl->wp = bl->rp + len; /* Pullup all the fragment headers and * return a complete packet */ for(bl = bl->next; bl; bl = bl->next) { fragsize = BKFG(bl)->flen; len += fragsize; bl->rp += IPHDR; bl->wp = bl->rp + fragsize; } bl = f->blist; f->blist = nil; ipfragfree(f, 1); ip = BLKIP(bl); hnputs(ip->length, len); qunlock(&iplock); return bl; } pktposn += BKFG(bl)->flen; } qunlock(f); qunlock(&iplock); return nil; } /* * ipfragfree - Free a list of fragments, fragment list must be locked */ void ipfragfree(Fragment *frag, int lockq) { Fragment *fl, **l; if(frag->blist) freeblist(frag->blist); frag->src = 0; frag->id = 0; frag->blist = nil; qunlock(frag); if(lockq) qlock(&fraglock); l = &flisthead; for(fl = *l; fl; fl = fl->next) { if(fl == frag) { *l = frag->next; break; } l = &fl->next; } frag->next = fragfree; fragfree = frag; if(lockq) qunlock(&fraglock); } /* * ipfragallo - allocate a reassembly queue */ Fragment * ipfragallo(void) { Fragment *f; qlock(&fraglock); while(fragfree == nil) { for(f = flisthead; f; f = f->next) if(canqlock(f)) { ipfragfree(f, 0); break; } } f = fragfree; fragfree = f->next; f->next = flisthead; flisthead = f; f->age = msec + 30000; qunlock(&fraglock); return f; } ushort ipcsum(byte *addr) { int len; ulong sum; sum = 0; len = (addr[0]&0xf)<<2; while(len > 0) { sum += addr[0]<<8 | addr[1] ; len -= 2; addr += 2; } sum = (sum & 0xffff) + (sum >> 16); sum = (sum & 0xffff) + (sum >> 16); return (sum^0xffff); } . ## diffname ip/ip.c 1997/0423 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0423/sys/src/brazil/ip/ip.c 291c (*p->rcv)(m, bp); . 225c ipiput(Media *m, Block *bp) . 107c if(isbmcast(eh->dst)){ m = Mediaroute(eh->src, nil); memmove(gate, eh->dst, Ipaddrlen); } else m = Mediaroute(eh->dst, gate); . ## diffname ip/ip.c 1997/0504 ## diff -e /n/emeliedump/1997/0423/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0504/sys/src/brazil/ip/ip.c 365,366c if(bp->base+sizeof(Ipfrag) >= bp->rp){ bp = padblock(bp, sizeof(Ipfrag)); bp->rp += sizeof(Ipfrag); } . ## diffname ip/ip.c 1997/0522 ## diff -e /n/emeliedump/1997/0504/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0522/sys/src/brazil/ip/ip.c 140c netlog(Logip, "%I: eh->frag[0] & (IP_DF>>8)\n", eh->dst); . ## diffname ip/ip.c 1997/0529 ## diff -e /n/emeliedump/1997/0522/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0529/sys/src/brazil/ip/ip.c 538d 526,530c /* free last entry on fraglist */ for(f = flisthead; f->next; f = f->next) ; ipfragfree(f); . 524d 517c * ipfragallo - allocate a reassembly queue - assume hold fraglock . 512,513d 497,499d 495d 485c ipfragfree(Fragment *frag) . 482c * ipfragfree - Free a list of fragments - assume hold fraglock . 476,477c qunlock(&fraglock); . 471c qunlock(&fraglock); . 468c ipfragfree(f); . 407,408c qunlock(&fraglock); . 387d 383,384c qunlock(&fraglock); . 376d 357,361c if(f != nil) ipfragfree(f); qunlock(&fraglock); . 349d 346,347c if(f->age < msec) ipfragfree(f); . 341d 336c qlock(&fraglock); . 312,313d 73c void ipfragfree(Fragment*); . 57d 54a QLock fraglock; . 40d ## diffname ip/ip.c 1997/0806 ## diff -e /n/emeliedump/1997/0529/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0806/sys/src/brazil/ip/ip.c 235,236c // 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); . 226a //#define DBG(x) if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog . ## diffname ip/ip.c 1997/0808 ## diff -e /n/emeliedump/1997/0806/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0808/sys/src/brazil/ip/ip.c 308c n = snprint(buf, len, "ip: csum %lud inb %lud outb %lud inp %lud outp %lud\n", . ## diffname ip/ip.c 1997/0815 ## diff -e /n/emeliedump/1997/0808/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0815/sys/src/brazil/ip/ip.c 108c memmove(gate, eh->dst, IPaddrlen); . ## diffname ip/ip.c 1997/0916 ## diff -e /n/emeliedump/1997/0815/sys/src/brazil/ip/ip.c /n/emeliedump/1997/0916/sys/src/brazil/ip/ip.c 345a } . 344c if(f->age < msec){ stats.droppedfrag++; . 309a n += snprint(buf+n, len - n, "\tnoroute %lud droppedfrag %lud\n", stats.noroute, stats.droppedfrag); . 111a stats.noroute++; . 69a static struct Stats { ulong noroute; ulong droppedfrag; } stats; . ## diffname ip/ip.c 1997/1104 ## diff -e /n/emeliedump/1997/0916/sys/src/brazil/ip/ip.c /n/emeliedump/1997/1104/sys/src/brazil/ip/ip.c 221c fragfree = malloc(sizeof(Fragment) * size); . ## diffname ip/ip.c 1998/0217 ## diff -e /n/emeliedump/1997/1104/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0217/sys/src/brazil/ip/ip.c 21c IP_MAX = (64*1024), /* Maximum Internet packet size */ . ## diffname ip/ip.c 1998/0306 ## diff -e /n/emeliedump/1998/0217/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0306/sys/src/brazil/ip/ip.c 535c ipcsum(uchar *addr) . 328c ulong src, dst; . 303c (*p->rcv)(ia, bp); . 290,300d 269a /* route */ v4tov6(v6dst, h->dst); notforme = ipforme(v6dst) == 0; if(notforme) { if(iprouting) { /* gate */ if(h->ttl <= 1) freeblist(bp); else ipoput(bp, 1, h->ttl - 1); } else useriprouter(ia, bp); return; } . 255,262c /* dump anything that whose header doesn't checksum */ . 242a uchar v6dst[IPaddrlen]; . 237c ipiput(uchar *ia, Block *bp) . 221c fragfree = (Fragment*)malloc(sizeof(Fragment) * size); . 209c ifc->m->bwrite(ifc, nb, V4, gate); . 152c netlog(Logip, "%V seglen < 8\n", eh->dst); . 146c netlog(Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst); . 141c /*print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate);*/ ifc->m->bwrite(ifc, bp, V4, gate); . 130c medialen = ifc->m->maxmtu - ifc->m->hsize; . 127a ifc = r->ifc; . 122c if(r->type & (Rifc|Runi|Rbcast|Rmulti)) gate = eh->dst; else gate = r->v4.gate; . 119c netlog(Logip, "no interface %V\n", eh->dst); . 112,117c r = v4lookup(eh->dst); if(r == nil){ . 107,108c if(len >= IP_MAX){ netlog(Logip, "exceeded ip max size %V\n", eh->dst); . 94c /* Number of uchars in data and ip header to write */ . 89a Route *r; . 84,85c Ipifc *ifc; uchar *gate; . 76c ushort ipcsum(uchar*); . 60,61c ulong ipin, ippin; /* uchars, packets in */ ulong ipout, ippout; /* uchars, packets out */ . 42,43c ulong src; ulong dst; . 26,35c uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* Identification */ uchar frag[2]; /* Fragment information */ uchar ttl; /* Time to live */ uchar proto; /* Protocol */ uchar cksum[2]; /* Header checksum */ uchar src[4]; /* Ip source */ uchar dst[4]; /* Ip destination */ . 21c IP_MAX = (32*1024), /* Maximum Internet packet size */ . ## diffname ip/ip.c 1998/0307 ## diff -e /n/emeliedump/1998/0306/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0307/sys/src/brazil/ip/ip.c 214a runlock(ifc); poperror(); . 206c } . 143a runlock(ifc); poperror(); . 129a if(waserror()){ runlock(ifc); nexterror(); } rlock(ifc); if(ifc->m == nil) goto raise; . ## diffname ip/ip.c 1998/0308 ## diff -e /n/emeliedump/1998/0307/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0308/sys/src/brazil/ip/ip.c 226a free: . 117c goto free; . 110c goto free; . 103c goto free; . ## diffname ip/ip.c 1998/0313 ## diff -e /n/emeliedump/1998/0308/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0313/sys/src/brazil/ip/ip.c 538,541c f = ip->fragfree; ip->fragfree = f->next; f->next = ip->flisthead; ip->flisthead = f; . 536c ipfragfree(ip, f); . 534c for(f = ip->flisthead; f->next; f = f->next) . 532c while(ip->fragfree == nil) { . 528c ipfragallo(IP *ip) . 519,520c frag->next = ip->fragfree; ip->fragfree = frag; . 510c l = &ip->flisthead; . 499c ipfragfree(IP *ip, Fragment *frag) . 491c qunlock(&ip->fraglock); . 483,486c ipfragfree(ip, f); ih = BLKIP(bl); hnputs(ih->length, len); qunlock(&ip->fraglock); ip->istats.ipReasmOKs++; . 446c /* move up ih hdrs */ . 423c qunlock(&ip->fraglock); . 401c qunlock(&ip->fraglock); ip->istats.ipReasmReqds++; . 394c f = ipfragallo(ip); . 390c BKFG(bp)->flen = nhgets(ih->length)-IPHDR; . 377,380c if(!ih->tos && (offset & ~(IP_MF|IP_DF)) == 0) { if(f != nil) { ipfragfree(ip, f); ip->istats.ipReasmFails++; } qunlock(&ip->fraglock); . 367,368c ip->istats.ipReasmTimeout++; ipfragfree(ip, f); . 362c for(f = ip->flisthead; f; f = fnext){ . 357c qlock(&ip->fraglock); . 354c ih = (Iphdr *)(bp->rp); . 345,347c src = nhgetl(ih->src); dst = nhgetl(ih->dst); id = nhgets(ih->id); . 336c ipreassemble(IP *ip, int offset, Block *bp, Iphdr *ih) . 328,332c 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); . 326c IP *ip; . 324c ipstats(Fs *f, char *buf, int len) . 311,320c 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); . 305c bp = ipreassemble(ip, frag, bp, h); . 294,299c . 290c useriprouter(f, ia, bp); . 287,288c else { ip->istats.ipForwDatagrams++; ipoput(f, bp, 1, h->ttl - 1); } . 283c if(ip->iprouting) { . 281c 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 */ . 279d 273,274c ip->istats.ipInHdrErrors++; netlog(f, Logip, "ip: checksum error %I\n", h->src); . 261c // DBG(nhgetl(h->src))(Logipmsg, "ipiput %V %V len %d proto %d\n", // h->src, h->dst, BLEN(bp), h->proto); . 259a ip = f->ip; ip->istats.ipInReceives++; . 258c uchar *dp, v6dst[IPaddrlen]; IP *ip; . 253a int hl; . 252c ipiput(Fs *f, uchar *ia, Block *bp) . 249,250d 247c #define DBG(x) if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog . 244c ip->fragfree[size-1].next = nil; . 240,241c eq = &ip->fragfree[size]; for(fq = ip->fragfree; fq < eq; fq++) . 236,237c ip->fragfree = (Fragment*)malloc(sizeof(Fragment) * size); if(ip->fragfree == nil) . 232c initfrag(IP *ip, int size) . 223d 221a ip->istats.ipFragCreates++; . 216c } . 204c netlog(f, Logip, "!xp: chunk %d\n", chunk); . 202a ip->istats.ipOutDiscards++; . 173c lid = ip->id++; . 164c ip->istats.ipOutDiscards++; netlog(f, Logip, "%V seglen < 8\n", eh->dst); . 158c ip->istats.ipOutDiscards++; netlog(f, Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst); . 150c /* print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate); /**/ . 142c hnputs(eh->id, ip->id++); . 128d 122a . 121a if(r->type & (Rbcast|Rmulti)) { gate = eh->dst; sr = v4lookup(f, eh->src); if(sr != nil && (sr->type & Runi)) ifc = sr->ifc; } else . 119c ifc = r->ifc; if(r->type & (Rifc|Runi)) . 115,116c ip->istats.ipOutNoRoutes++; netlog(f, Logip, "no interface %V\n", eh->dst); . 113c r = v4lookup(f, eh->dst); . 109c ip->istats.ipOutDiscards++; netlog(f, Logip, "exceeded ip max size %V\n", eh->dst); . 102c ip->istats.ipOutDiscards++; netlog(f, Logip, "short gated packet\n"); . 97,98c . 94a ip->istats.ipOutRequests++; . 91a ip = f->ip; . 90c Route *r, *sr; IP *ip; . 82c ipoput(Fs *f, Block *bp, int gating, int ttl) . 76,79c ip = smalloc(sizeof(IP)); initfrag(ip, 100); f->ip = ip; } . 72,74c IP *ip; . 70c ushort ipcsum(uchar*); Block* ipreassemble(IP*, int, Block*, Iphdr*); void ipfragfree(IP*, Fragment*); Fragment* ipfragallo(IP*); void ip_init(Fs *f) . 62a /* 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*); }; . 54,61c /* 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; }; . 34,35c uchar src[4]; /* IP source */ uchar dst[4]; /* IP destination */ . 29c uchar id[2]; /* ip->identification */ . ## diffname ip/ip.c 1998/0314 ## diff -e /n/emeliedump/1998/0313/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0314/sys/src/brazil/ip/ip.c 115a iprouting(Fs *f, int on) { f->ip->iprouting = on; } void . ## diffname ip/ip.c 1998/0326 ## diff -e /n/emeliedump/1998/0314/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0326/sys/src/brazil/ip/ip.c 325,327c /* * Ensure we have allt he header info in the first * block. Make life easier for other protocols by * collecting up to the first 64 bytes in the first block. */ if(BLEN(bp) < 64) { hl = blocklen(bp); if(hl < IPHDR) hl = IPHDR; if(hl > 64) hl = 64; bp = pullupblock(bp, hl); . ## diffname ip/ip.c 1998/0331 ## diff -e /n/emeliedump/1998/0326/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0331/sys/src/brazil/ip/ip.c 326c * Ensure we have all the header info in the first . ## diffname ip/ip.c 1998/0604 ## diff -e /n/emeliedump/1998/0331/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0604/sys/src/brazil/ip/ip.c 189d 184a rlock(ifc); . ## diffname ip/ip.c 1998/0630 ## diff -e /n/emeliedump/1998/0604/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0630/sys/src/brazil/ip/ip.c 189a rlock(ifc); . 185d 136c eh = (Iphdr*)(bp->rp); . ## diffname ip/ip.c 1998/0813 ## diff -e /n/emeliedump/1998/0630/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0813/sys/src/brazil/ip/ip.c 416a ip->istats.ipDefaultTTL = MAXTTL; . 378c } else { . 376c if(h->ttl <= 1){ ip->istats.ipInHdrErrors++; icmpttlexceeded(f, ia, bp); . 118a if(f->ip->iprouting==0) f->ip->istats.ipForwarding = 2; else f->ip->istats.ipForwarding = 1; . ## diffname ip/ip.c 1998/0825 ## diff -e /n/emeliedump/1998/0813/sys/src/brazil/ip/ip.c /n/emeliedump/1998/0825/sys/src/brazil/ip/ip.c 424,425c return snprint(buf, len, "%lud %lud %lud %lud %lud %lud %lud %lud %lud %lud " "%lud %lud %lud %lud %lud %lud %lud %lud %lud", . ## diffname ip/ip.c 1998/1208 ## diff -e /n/emeliedump/1998/0825/sys/src/brazil/ip/ip.c /n/emeliedump/1998/1208/sys/src/brazil/ip/ip.c 349c netlog(f, Logip, "ip: checksum error %V\n", h->src); . ## diffname ip/ip.c 1998/1209 ## diff -e /n/emeliedump/1998/1208/sys/src/brazil/ip/ip.c /n/emeliedump/1998/1209/sys/src/brazil/ip/ip.c 389a return; } /* don't forward to source's network */ sr = v4lookup(f, h->src); r = v4lookup(f, h->dst); if(r == nil || sr == r){ ip->istats.ipOutDiscards++; freeblist(bp); return; } /* don't forward if packet has timed out */ if(h->ttl <= 1){ ip->istats.ipInHdrErrors++; icmpttlexceeded(f, ia, bp); freeblist(bp); return; } ip->istats.ipForwDatagrams++; ipoput(f, bp, 1, h->ttl - 1); . 378,388c if(!ip->iprouting){ . 320a Route *r, *sr; . ## diffname ip/ip.c 1999/0302 ## diff -e /n/emeliedump/1998/1209/sys/src/brazil/ip/ip.c /n/emeliedump/1999/0302/sys/src/brazil/ip/ip.c 234c lid = incref(&ip->id); . 201c hnputs(eh->id, incref(&ip->id)); . 193d 188a if(!canrlock(ifc)) goto free; . 88c Ref id; . ## diffname ip/ip.c 1999/0309 ## diff -e /n/emeliedump/1999/0302/sys/src/brazil/ip/ip.c /n/emeliedump/1999/0309/sys/src/brazil/ip/ip.c 187a eh->ttl = ttl; . 186d ## diffname ip/ip.c 1999/0817 ## diff -e /n/emeliedump/1999/0309/sys/src/brazil/ip/ip.c /n/emeliedump/1999/0817/sys/src/brazil/ip/ip.c 403c ipoput(f, bp, 1, h->ttl - 1, h->tos); . 187a eh->tos = tos; . 126c ipoput(Fs *f, Block *bp, int gating, int ttl, int tos) . ## diffname ip/ip.c 1999/0917 ## diff -e /n/emeliedump/1999/0817/sys/src/brazil/ip/ip.c /n/emeliedump/1999/0917/sys/src/brazil/ip/ip.c 187,188d 185c eh->ttl = ttl; eh->tos = tos; . ## diffname ip/ip.c 1999/1003 ## diff -e /n/emeliedump/1999/0917/sys/src/brazil/ip/ip.c /n/emeliedump/1999/1003/sys/src/brazil/ip/ip.c 183c if(gating){ switch(eh->ttl){ case 0: case 1: goto free; default: eh->ttl--; break; } } else { . ## diffname ip/ip.c 1999/10041 ## diff -e /n/emeliedump/1999/1003/sys/src/brazil/ip/ip.c /n/emeliedump/1999/10041/sys/src/brazil/ip/ip.c 194,196c eh->ttl = ttl; eh->tos = tos; . 183,192c if(!gating) . ## diffname ip/ip.c 2000/0220 ## diff -e /n/emeliedump/1999/10041/sys/src/brazil/ip/ip.c /n/emeliedump/2000/0220/sys/src/9/ip/ip.c 380c freeb(bp); . 285a ip->istats.ipFragOKs++; . 264a ip->istats.ipFragFails++; . 223a ip->istats.ipFragFails++; . 216a ip->istats.ipFragFails++; . ## diffname ip/ip.c 2000/0329 ## diff -e /n/emeliedump/2000/0220/sys/src/9/ip/ip.c /n/emeliedump/2000/0329/sys/src/9/ip/ip.c 90d ## diffname ip/ip.c 2000/0706 ## diff -e /n/emeliedump/2000/0329/sys/src/9/ip/ip.c /n/emeliedump/2000/0706/sys/src/9/ip/ip.c 610c ip->stats[ReasmOKs]++; . 524c ip->stats[ReasmReqds]++; . 500c ip->stats[ReasmFails]++; . 487c ip->stats[ReasmTimeout]++; . 440,452c ip->stats[DefaultTTL] = MAXTTL; p = buf; e = p+len; for(i = 0; i < Nstats; i++) p = seprint(p, e, "%s: %lud\n", statnames[i], ip->stats[i]); return p - buf; . 437a char *p, *e; int i; . 429,430c ip->stats[InDiscards]++; ip->stats[InUnknownProtos]++; . 425c ip->stats[InDelivers]++; . 404c ip->stats[ForwDatagrams]++; . 398c ip->stats[InHdrErrors]++; . 391c ip->stats[OutDiscards]++; . 365c ip->stats[InHdrErrors]++; . 352c ip->stats[InHdrErrors]++; . 327c ip->stats[InReceives]++; . 288c ip->stats[FragOKs]++; . 286c ip->stats[FragCreates]++; . 265,266c ip->stats[OutDiscards]++; ip->stats[FragFails]++; . 224,225c ip->stats[FragFails]++; ip->stats[OutDiscards]++; . 216,217c ip->stats[FragFails]++; ip->stats[OutDiscards]++; . 164c ip->stats[OutNoRoutes]++; . 157c ip->stats[OutDiscards]++; . 149c ip->stats[OutDiscards]++; . 141c ip->stats[OutRequests]++; . 121c f->ip->stats[Forwarding] = 1; . 119c f->ip->stats[Forwarding] = 2; . 82c ulong stats[Nstats]; . 78a static char *statnames[] = { [Forwarding] "Forwarding", [DefaultTTL] "DefaultTTL", [InReceives] "InReceives", [InHdrErrors] "InHdrErrors", [InAddrErrors] "InAddrErrors", [ForwDatagrams] "ForwDatagrams", [InUnknownProtos] "InUnknownProtos", [InDiscards] "InDiscards", [InDelivers] "InDelivers", [OutRequests] "OutRequests", [OutDiscards] "OutDiscards", [OutNoRoutes] "OutNoRoutes", [ReasmTimeout] "ReasmTimeout", [ReasmReqds] "ReasmReqds", [ReasmOKs] "ReasmOKs", [ReasmFails] "ReasmFails", [FragOKs] "FragOKs", [FragFails] "FragFails", [FragCreates] "FragCreates", }; . 58,76c Forwarding, DefaultTTL, InReceives, InHdrErrors, InAddrErrors, ForwDatagrams, InUnknownProtos, InDiscards, InDelivers, OutRequests, OutDiscards, OutNoRoutes, ReasmTimeout, ReasmReqds, ReasmOKs, ReasmFails, FragOKs, FragFails, FragCreates, Nstats, . 55,56c enum . ## diffname ip/ip.c 2000/0905 ## diff -e /n/emeliedump/2000/0706/sys/src/9/ip/ip.c /n/emeliedump/2000/0905/sys/src/9/ip/ip.c 18c IP_HLEN = 0x05, /* Header length in words */ . ## diffname ip/ip.c 2000/0913 ## diff -e /n/emeliedump/2000/0905/sys/src/9/ip/ip.c /n/emeliedump/2000/0913/sys/src/9/ip/ip.c 221c medialen = ifc->maxmtu - ifc->m->hsize; . ## diffname ip/ip.c 2000/1111 ## diff -e /n/emeliedump/2000/0913/sys/src/9/ip/ip.c /n/emeliedump/2000/1111/sys/src/9/ip/ip.c 8c #include "../ip/ip.h" . ## diffname ip/ip.c 2001/0430 ## diff -e /n/emeliedump/2000/1111/sys/src/9/ip/ip.c /n/emeliedump/2001/0430/sys/src/9/ip/ip.c 268c if(gating) fragoff = nhgets(eh->frag); else fragoff = 0; dlen += fragoff; for(; fragoff < dlen; fragoff += seglen) { . 226,227c if(!gating){ eh->frag[0] = 0; eh->frag[1] = 0; } . 209c if(!gating) eh->tos = tos; . ## diffname ip/ip.c 2001/0623 ## diff -e /n/emeliedump/2001/0430/sys/src/9/ip/ip.c /n/emeliedump/2001/0623/sys/src/9/ip/ip.c 458c (*p->rcv)(p, ifc, bp); . 431c icmpttlexceeded(f, ifc, bp); . 347c ipiput(Fs *f, Ipifc *ifc, Block *bp) . ## diffname ip/ip.c 2001/1007 ## diff -e /n/emeliedump/2001/0623/sys/src/9/ip/ip.c /n/emeliedump/2001/1007/sys/src/9/ip/ip.c 272c fragoff = nhgets(eh->frag)<<3; . 153c ulong fragoff; . ## diffname ip/ip.c 2001/1117 ## diff -e /n/emeliedump/2001/1007/sys/src/9/ip/ip.c /n/emeliedump/2001/1117/sys/src/9/ip/ip.c 717a } enum { Nmtucache= 128, }; typedef struct MTUcache MTUcache; struct MTUcache { uchar ip[IPaddrlen]; ulong mtu; ulong ms; }; static struct { Lock; MTUcache c[Nmtucache]; } mc; void update_mtucache(uchar *ip, ulong mtu) { MTUcache *oldest, *p; if(mtu < 512) return; lock(&mc); oldest = mc.c; for(p = mc.c; p < &mc.c[Nmtucache]; p++){ if(ipcmp(ip, p->ip) == 0){ p->mtu = mtu; p->ms = msec; break; } if(p->ms < oldest->ms) oldest = p; } if(p == &mc.c[Nmtucache]){ ipmove(oldest->ip, ip); oldest->mtu = mtu; oldest->ms = msec; } unlock(&mc); } ulong restrict_mtu(uchar *ip, ulong mtu) { MTUcache *p; lock(&mc); for(p = mc.c; p < &mc.c[Nmtucache]; p++){ if(p->ms + 1000*10*60 < msec){ memset(p->ip, 0, sizeof(p->ip)); p->ms = 0; } if(ipcmp(ip, p->ip) == 0){ if(p->mtu < mtu) mtu = p->mtu; break; } } unlock(&mc); return mtu; . 442,443c /* reassemble */ . 434a /* reassemble if the interface expects it */ if(r->ifc->reassemble){ frag = nhgets(h->frag); if(frag) { h->tos = 0; if(frag & IP_MF) h->tos = 1; bp = ipreassemble(ip, frag, bp, h); if(bp == nil) return; h = (Iphdr *)(bp->rp); } } . ## diffname ip/ip.c 2002/0424 ## diff -e /n/emeliedump/2001/1117/sys/src/9/ip/ip.c /n/emeliedump/2002/0424/sys/src/9/ip/ip.c 408a hnputs(h->length, olen-hl+(IP_HLEN<<2)); . 403a olen = nhgets(h->length); . 356a int olen; . ## diffname ip/ip.c 2002/0507 ## diff -e /n/emeliedump/2002/0424/sys/src/9/ip/ip.c /n/emeliedump/2002/0507/sys/src/9/ip/ip.c 741,802d 736,739d 706,709c f = ip->fragfree4; ip->fragfree4 = f->next; f->next = ip->flisthead4; ip->flisthead4 = f; . 704c ipfragfree4(ip, f); . 702c for(f = ip->flisthead4; f->next; f = f->next) . 700c while(ip->fragfree4 == nil) { . 698c Fragment4 *f; . 695,696c Fragment4 * ipfragallo4(IP *ip) . 693c * ipfragallo4 - allocate a reassembly queue - assume hold fraglock4 . 687,688c frag->next = ip->fragfree4; ip->fragfree4 = frag; . 678c l = &ip->flisthead4; . 669c Fragment4 *fl, **l; . 667c ipfragfree4(IP *ip, Fragment4 *frag) . 664c * ipfragfree4 - Free a list of fragments - assume hold fraglock4 . 659c qunlock(&ip->fraglock4); . 653c qunlock(&ip->fraglock4); . 650c ipfragfree4(ip, f); . 644c bl->rp += IP4HDR; . 614c memmove((*l)->rp + ovlap, (*l)->rp, IP4HDR); . 590c qunlock(&ip->fraglock4); . 567c qunlock(&ip->fraglock4); . 560c f = ipfragallo4(ip); . 556c BKFG(bp)->flen = nhgets(ih->length)-IP4HDR; . 546c qunlock(&ip->fraglock4); . 543c ipfragfree4(ip, f); . 532c ipfragfree4(ip, f); . 526,527c for(f = ip->flisthead4; f; f = fnext){ fnext = f->next; /* because ipfragfree4 changes the list */ . 521c qlock(&ip->fraglock4); . 518c ih = (Ip4hdr*)(bp->rp); . 504c Fragment4 *f, *fnext; . 500c ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih) . 471c proto = h->proto; p = Fsrcvpcol(f, proto); . 468c h = (Ip4hdr*)(bp->rp); . 465c bp = ip4reassemble(ip, frag, bp, h); . 459d 454,455c tos = h->tos; hop = h->ttl; ipoput4(f, bp, 1, hop - 1, tos); . 449c h = (Ip4hdr*)(bp->rp); . 446c bp = ip4reassemble(ip, frag, bp, h); . 438c . 434c icmpttlexceeded(f, ifc->lifc->local, bp); . 432c hop = h->ttl; if(hop < 1) { . 424a . 421d 409,411c h = (Ip4hdr*)(bp->rp); h->vihl = (IP_VER4|IP_HLEN4); hnputs(h->length, olen-hl+(IP_HLEN4<<2)); . 406,407c dp = bp->rp + (hl - (IP_HLEN4<<2)); memmove(dp, h, IP_HLEN4<<2); . 403c /* If this is not routed strip off the options */ . 397c if(hl < (IP_HLEN4<<2)) { . 395c if((h->vihl&0x0F) != IP_HLEN4) { . 390d 382a h = (Ip4hdr*)(bp->rp); . 381d 373,374c if(hl < IP4HDR) hl = IP4HDR; . 362,365d 358a if(BLKIPVER(bp) != IP_VER4) { ipiput6(f, ifc, bp); return; } . 357d 350c int hop, tos, proto, olen; Ip4hdr *h; . 331,348d 329c ipiput4(Fs *f, Ipifc *ifc, Block *bp) . 290c hnputs(feh->length, seglen + IP4HDR); . 280,281c memmove(nb->wp, eh, IP4HDR); nb->wp += IP4HDR; . 277,278c nb = allocb(IP4HDR+seglen); feh = (Ip4hdr*)(nb->rp); . 264c offset = IP4HDR; . 262c lid = incref(&ip->id4); . 257c dlen = len - IP4HDR; . 249c seglen = (medialen - IP4HDR) & ~7; . 234,235d 225c hnputs(eh->id, incref(&ip->id4)); . 207c eh->vihl = IP_VER4|IP_HLEN4; . 163c eh = (Ip4hdr*)(bp->rp); . 155c Ip4hdr *eh, *feh; . 149c ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos) . 135a ip_init_6(f); . 128a ip_init_6(Fs *f) { v6params *v6p; v6p = smalloc(sizeof(v6params)); v6p->rp.mflag = 0; // default not managed v6p->rp.oflag = 0; v6p->rp.maxraint = 600000; // millisecs v6p->rp.minraint = 200000; v6p->rp.linkmtu = 0; // no mtu sent v6p->rp.reachtime = 0; v6p->rp.rxmitra = 0; v6p->rp.ttl = MAXTTL; v6p->rp.routerlt = 3*(v6p->rp.maxraint); v6p->hp.rxmithost = 1000; // v6 RETRANS_TIMER v6p->cdrouter = -1; f->v6p = v6p; } void initfrag(IP *ip, int size) { Fragment4 *fq4, *eq4; Fragment6 *fq6, *eq6; ip->fragfree4 = (Fragment4*)malloc(sizeof(Fragment4) * size); if(ip->fragfree4 == nil) panic("initfrag"); eq4 = &ip->fragfree4[size]; for(fq4 = ip->fragfree4; fq4 < eq4; fq4++) fq4->next = fq4+1; ip->fragfree4[size-1].next = nil; ip->fragfree6 = (Fragment6*)malloc(sizeof(Fragment6) * size); if(ip->fragfree6 == nil) panic("initfrag"); eq6 = &ip->fragfree6[size]; for(fq6 = ip->fragfree6; fq6 < eq6; fq6++) fq6->next = fq6+1; ip->fragfree6[size-1].next = nil; } void . 127a . 124,126c Block* ip4reassemble(IP*, int, Block*, Ip4hdr*); void ipfragfree4(IP*, Fragment4*); Fragment4* ipfragallo4(IP*); . 103,116c #define BLKIP(xp) ((Ip4hdr*)((xp)->rp)) . 79a struct Fragment4 { Block* blist; Fragment4* next; ulong src; ulong dst; ushort id; ulong age; }; struct Fragment6 { Block* blist; Fragment6* next; uchar src[IPaddrlen]; uchar dst[IPaddrlen]; uint id; ulong age; }; struct Ipfrag { ushort foff; ushort flen; }; /* an instance of IP */ struct IP { ulong stats[Nstats]; QLock fraglock4; Fragment4* flisthead4; Fragment4* fragfree4; Ref id4; QLock fraglock6; Fragment6* flisthead6; Fragment6* fragfree6; Ref id6; int iprouting; /* true if we route like a gateway */ }; . 38,53d 31c uchar ttl; /* Time to live */ . 24c #define BLKIPVER(xp) (((Ip4hdr*)((xp)->rp))->vihl&0xF0) struct Ip4hdr . 20a IP6FHDR = 8, /* sizeof(Fraghdr6) */ . 16,18c IP4HDR = 20, /* sizeof(Ip4hdr) */ IP6HDR = 40, /* sizeof(Ip6hdr) */ IP_HLEN4 = 0x05, /* Header length in words */ . 10,12c typedef struct Ip4hdr Ip4hdr; typedef struct IP IP; typedef struct Fragment4 Fragment4; typedef struct Fragment6 Fragment6; typedef struct Ipfrag Ipfrag; . 8c #include "ip.h" . ## diffname ip/ip.c 2002/0615 ## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/ip.c /n/emeliedump/2002/0615/sys/src/9/ip/ip.c 24c IP_MAX = 64*1024, /* Maximum Internet packet size */ . ## diffname ip/ip.c 2002/0710 ## diff -e /n/emeliedump/2002/0615/sys/src/9/ip/ip.c /n/emeliedump/2002/0710/sys/src/9/ip/ip.c 768c f->age = NOW + 30000; . 588c if(f->age < NOW){ . ## diffname ip/ip.c 2002/1204 ## diff -e /n/emeliedump/2002/0710/sys/src/9/ip/ip.c /n/emeliedump/2002/1204/sys/src/9/ip/ip.c 317a icmpcantfrag(f, bp); . 314a if((eh->frag[0] & (IP_DF>>8)) && !gating) print("%V: DF set\n", eh->dst); . ## diffname ip/ip.c 2002/1207 ## diff -e /n/emeliedump/2002/1204/sys/src/9/ip/ip.c /n/emeliedump/2002/1207/sys/src/9/ip/ip.c 529a /* don't let any frag info go up the stack */ h->frag[0] = 0; h->frag[1] = 0; . 320c icmpcantfrag(f, bp, medialen); . ## diffname ip/ip.c 2003/0209 ## diff -e /n/emeliedump/2002/1207/sys/src/9/ip/ip.c /n/emeliedump/2003/0209/sys/src/9/ip/ip.c 297c medialen = ifc->maxtu - ifc->m->hsize; . ## diffname ip/ip.c 2003/0213 ## diff -e /n/emeliedump/2003/0209/sys/src/9/ip/ip.c /n/emeliedump/2003/0213/sys/src/9/ip/ip.c 444c if((bp->flag & Bipck) == 0 && ipcsum(&h->vihl)) { . ## diffname ip/ip.c 2003/0214 ## diff -e /n/emeliedump/2003/0213/sys/src/9/ip/ip.c /n/emeliedump/2003/0214/sys/src/9/ip/ip.c 264a if(!gating){ freeblist(bp); error("no route"); } . 233a Proto *pr; . ## diffname ip/ip.c 2003/0216 ## diff -e /n/emeliedump/2003/0214/sys/src/9/ip/ip.c /n/emeliedump/2003/0216/sys/src/9/ip/ip.c 267c freeblist(bp); print("ipoput4: no route\n"); . ## diffname ip/ip.c 2003/0220 ## diff -e /n/emeliedump/2003/0216/sys/src/9/ip/ip.c /n/emeliedump/2003/0220/sys/src/9/ip/ip.c 407c freeblist(bp); return rv; . 318c return 0; . 266,270c rv = -1; . 234c int rv = 0; . 223c int . ## diffname ip/ip.c 2003/0308 ## diff -e /n/emeliedump/2003/0220/sys/src/9/ip/ip.c /n/emeliedump/2003/0308/sys/src/9/ip/ip.c 519c ipoput4(f, bp, 1, hop - 1, tos, &conv); . 487c /* don't forward to source's network */ conv.r = nil; r = v4lookup(f, h->dst, &conv); if(r != nil && r->ifc == ifc){ . 483,485d 478a Conv conv; . 418c Route *r; . 276c sr = v4lookup(f, eh->src, nil); . 262c r = v4lookup(f, eh->dst, c); . 224c ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) . ## diffname ip/ip.c 2003/0318 ## diff -e /n/emeliedump/2003/0308/sys/src/9/ip/ip.c /n/emeliedump/2003/0318/sys/src/9/ip/ip.c 504a if(r->ifc == nil) panic("nil route rfc"); . 489c if(r == nil || r->ifc == ifc){ .