| plan 9 kernel history: overview | file list | diff list |
2000/0404/port/devbridge.c (diff list | history)
| 2000/0331/sys/src/9/port/devbridge.c:135,140 – 2000/0404/sys/src/9/port/devbridge.c:135,143 (short | long | prev | next) | ||
| 1999/0826 | enum { IP_VER = 0x40, /* Using IP version 4 */ IP_HLEN = 0x05, /* Header length in characters */ | |
| 2000/0404 | IP_DF = 0x4000, /* Don't fragment */ IP_MF = 0x2000, /* More fragments */ IP_MAX = (32*1024), /* Maximum Internet packet size */ | |
| 1999/0826 | IP_TCPPROTO = 6, | |
| 1999/0827 | EOLOPT = 0, NOOPOPT = 1, | |
| 2000/0331/sys/src/9/port/devbridge.c:141,146 – 2000/0404/sys/src/9/port/devbridge.c:144,150 | ||
| 1999/0826 | MSSOPT = 2, MSS_LENGTH = 4, /* Mean segment size */ | |
| 1999/0827 | SYN = 0x02, /* Pkt. is synchronise */ | |
| 2000/0404 | IPHDR = 20, /* sizeof(Iphdr) */ | |
| 1999/0826 | }; struct Iphdr | |
| 2000/0331/sys/src/9/port/devbridge.c:187,192 – 2000/0404/sys/src/9/port/devbridge.c:191,197 | ||
| 2000/0331 | static void etherwrite(Port *port, Block *bp); | |
| 1999/0316 | extern ulong parseip(uchar*, char*); | |
| 2000/0404 | extern ushort ipcsum(uchar *addr); | |
| 1999/0316 | static void bridgeinit(void) | |
| 2000/0331/sys/src/9/port/devbridge.c:326,334 – 2000/0404/sys/src/9/port/devbridge.c:331,339 | ||
| 1999/0316 | } | |
| 1999/0731 | ingood = port->in-port->inmulti-port->inunknown; outgood = port->out-port->outmulti-port->outunknown; | |
| 2000/0404 | i += snprint(buf+i, sizeof(buf)-i, "in=%d(%d:%d:%d) out=%d(%d:%d:%d:%d)\n", | |
| 1999/0731 | port->in, ingood, port->inmulti, port->inunknown, | |
| 2000/0404 | port->out, outgood, port->outmulti, port->outunknown, port->outfrag); | |
| 1999/0316 | USED(i); } n = readstr(off, a, n, buf); | |
| 2000/0331/sys/src/9/port/devbridge.c:887,893 – 2000/0404/sys/src/9/port/devbridge.c:892,898 | ||
| 1999/0826 | return; | |
| 1999/0827 | iphdr = (Iphdr*)(epkt->data); | |
| 1999/0826 | n -= ETHERHDRSIZE; | |
| 2000/0404 | if(n < IPHDR) | |
| 1999/0826 | return; // check it is ok IP packet | |
| 2000/0331/sys/src/9/port/devbridge.c:1032,1042 – 2000/0404/sys/src/9/port/devbridge.c:1037,1156 | ||
| 1999/0316 | pexit("hangup", 1); | |
| 2000/0331 | } | |
| 2000/0404 | static int fragment(Etherpkt *epkt, int n) { Iphdr *iphdr; if(n <= TunnelMtu) return 0; // check it is an ip packet if(nhgets(epkt->type) != 0x800) return 0; iphdr = (Iphdr*)(epkt->data); n -= ETHERHDRSIZE; if(n < IPHDR) return 0; // check it is ok IP packet - I don't handle IP options for the momment if(iphdr->vihl != (IP_VER|IP_HLEN)) return 0; // check for don't fragment if(iphdr->frag[0] & (IP_DF>>8)) return 0; // check for short block if(nhgets(iphdr->length) > n) return 0; return 1; } | |
| 2000/0331 | static void etherwrite(Port *port, Block *bp) { | |
| 2000/0404 | Iphdr *eh, *feh; Etherpkt *epkt; int n, lid, len, seglen, chunk, dlen, blklen, offset, mf; Block *xp, *nb; ushort fragoff, frag; | |
| 2000/0331 | port->out++; | |
| 2000/0404 | epkt = (Etherpkt*)bp->rp; n = blocklen(bp); if(port->type != Ttun || !fragment(epkt, n)) { devtab[port->data[1]->type]->bwrite(port->data[1], bp, 0); return; } port->outfrag++; if(waserror()){ freeblist(bp); nexterror(); } seglen = (TunnelMtu - ETHERHDRSIZE - IPHDR) & ~7; eh = (Iphdr*)(epkt->data); len = nhgets(eh->length); frag = nhgets(eh->frag); mf = frag & IP_MF; frag <<= 3; dlen = len - IPHDR; xp = bp; lid = nhgets(eh->id); offset = ETHERHDRSIZE+IPHDR; while(xp != nil && offset && offset >= BLEN(xp)) { offset -= BLEN(xp); xp = xp->next; } xp->rp += offset; if(0) print("seglen=%d, dlen=%d, mf=%x, frag=%d\n", seglen, dlen, mf, frag); for(fragoff = 0; fragoff < dlen; fragoff += seglen) { nb = allocb(ETHERHDRSIZE+IPHDR+seglen); feh = (Iphdr*)(nb->wp+ETHERHDRSIZE); memmove(nb->wp, epkt, ETHERHDRSIZE+IPHDR); nb->wp += ETHERHDRSIZE+IPHDR; if((fragoff + seglen) >= dlen) { seglen = dlen - fragoff; hnputs(feh->frag, (frag+fragoff)>>3 | mf); } else hnputs(feh->frag, (frag+fragoff>>3) | IP_MF); hnputs(feh->length, seglen + IPHDR); hnputs(feh->id, lid); /* Copy up the data area */ chunk = seglen; while(chunk) { 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)); // don't generate small packets if(BLEN(nb) < ETHERMINTU) nb->wp = nb->rp + ETHERMINTU; devtab[port->data[1]->type]->bwrite(port->data[1], nb, 0); } poperror(); freeblist(bp); | |
| 1999/0316 | } // hold b lock | |