## 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){
.
|