| plan 9 kernel history: overview | file list | diff list |
1999/0930/port/devbridge.c (diff list | history)
| 1999/0316/sys/src/9/port/devbridge.c:513,518 – 1999/0625/sys/src/9/port/devbridge.c:513,520 (short | long) | ||
| 1999/0316 | devtab[ctl->type]->write(ctl, buf, strlen(buf), 0); snprint(buf, sizeof(buf), "promiscuous"); devtab[ctl->type]->write(ctl, buf, strlen(buf), 0); | |
| 1999/0625 | snprint(buf, sizeof(buf), "bridge"); devtab[ctl->type]->write(ctl, buf, strlen(buf), 0); | |
| 1999/0316 | // open data port port->data[0] = namec(path, Aopen, ORDWR, 0); | |
| 1999/0625/sys/src/9/port/devbridge.c:179,186 – 1999/0630/sys/src/9/port/devbridge.c:179,184 (short | long) | ||
| 1999/0316 | static int bridgewalk(Chan *c, char *name) { | |
| 1999/0625/sys/src/9/port/devbridge.c:193,201 – 1999/0630/sys/src/9/port/devbridge.c:191,196 | ||
| 1999/0316 | default: panic("bridgewalk %lux", c->qid.path); } | |
| 1999/0630/sys/src/9/port/devbridge.c:266,272 – 1999/0731/sys/src/9/port/devbridge.c:266,272 (short | long) | ||
| 1999/0316 | char buf[256]; Bridge *b = bridgetab + c->dev; Port *port; | |
| 1999/0731 | int i, ingood, outgood; | |
| 1999/0316 | USED(off); switch(TYPE(c->qid)) { | |
| 1999/0630/sys/src/9/port/devbridge.c:294,302 – 1999/0731/sys/src/9/port/devbridge.c:294,304 | ||
| 1999/0316 | i += snprint(buf+i, sizeof(buf)-i, "tunnel %I: ", port->addr); break; } | |
| 1999/0731 | ingood = port->in-port->inmulti-port->inunknown; outgood = port->out-port->outmulti-port->outunknown; i += snprint(buf+i, sizeof(buf)-i, "in=%d(%d:%d:%d) out=%d(%d:%d:%d)\n", port->in, ingood, port->inmulti, port->inunknown, port->out, outgood, port->outmulti, port->outunknown); | |
| 1999/0316 | USED(i); } n = readstr(off, a, n, buf); | |
| 1999/0630/sys/src/9/port/devbridge.c:317,323 – 1999/0731/sys/src/9/port/devbridge.c:319,324 | ||
| 1999/0316 | char *p; USED(off); | |
| 1999/0630/sys/src/9/port/devbridge.c:482,488 – 1999/0731/sys/src/9/port/devbridge.c:483,488 | ||
| 1999/0316 | portfree(port); nexterror(); } | |
| 1999/0630/sys/src/9/port/devbridge.c:822,828 – 1999/0731/sys/src/9/port/devbridge.c:822,827 | ||
| 1999/0316 | if(waserror()) { if(bp) freeb(bp); | |
| 1999/0731/sys/src/9/port/devbridge.c:799,805 – 1999/0803/sys/src/9/port/devbridge.c:799,805 (short | long) | ||
| 1999/0316 | Block *bp, *bp2; Etherpkt *ep; Centry *ce; | |
| 1999/0803 | static uchar tribble[Eaddrlen] = {0x00, 0xd1, 0x80, 0xaa, 0xbb, 0x07}; | |
| 1999/0316 | qlock(b); port->readp = up; /* hide identity under a rock for unbind */ | |
| 1999/0731/sys/src/9/port/devbridge.c:841,848 – 1999/0803/sys/src/9/port/devbridge.c:841,850 | ||
| 1999/0316 | if(ce == nil) { b->miss++; port->inunknown++; | |
| 1999/0803 | if(port->type != Tether || memcmp(ep->s, tribble, Eaddrlen) == 0) { bp2 = bp; bp = nil; ethermultiwrite(b, bp2, port); } | |
| 1999/0316 | } else if (ce->port != port->id) { b->hit++; bp2 = bp; bp = nil; | |
| 1999/0803/sys/src/9/port/devbridge.c:59,65 – 1999/0807/sys/src/9/port/devbridge.c:59,65 (short | long) | ||
| 1999/0316 | enum { Tether, | |
| 1999/0807 | Ttun, | |
| 1999/0316 | }; static Logflag logflags[] = | |
| 1999/0803/sys/src/9/port/devbridge.c:290,296 – 1999/0807/sys/src/9/port/devbridge.c:290,296 | ||
| 1999/0316 | case Tether: i += snprint(buf+i, sizeof(buf)-i, "ether %E: ", port->addr); break; | |
| 1999/0807 | case Ttun: | |
| 1999/0316 | i += snprint(buf+i, sizeof(buf)-i, "tunnel %I: ", port->addr); break; } | |
| 1999/0803/sys/src/9/port/devbridge.c:455,461 – 1999/0807/sys/src/9/port/devbridge.c:455,461 | ||
| 1999/0316 | } else if(strcmp(argv[0], "tunnel") == 0) { if(argc != 5) error(usage); | |
| 1999/0807 | type = Ttun; | |
| 1999/0316 | parseip(addr, argv[1]); dev2 = argv[4]; } else | |
| 1999/0803/sys/src/9/port/devbridge.c:521,527 – 1999/0807/sys/src/9/port/devbridge.c:521,527 | ||
| 1999/0316 | cclose(ctl); break; | |
| 1999/0807 | case Ttun: | |
| 1999/0316 | port->data[0] = namec(dev, Aopen, OREAD, 0); port->data[1] = namec(dev2, Aopen, OWRITE, 0); break; | |
| 1999/0803/sys/src/9/port/devbridge.c:557,563 – 1999/0807/sys/src/9/port/devbridge.c:557,563 | ||
| 1999/0316 | type = Tether; parseaddr(addr, argv[1], Eaddrlen); } else if(strcmp(argv[0], "tunnel") == 0) { | |
| 1999/0807 | type = Ttun; | |
| 1999/0316 | parseip(addr, argv[1]); } else error(usage); | |
| 1999/0803/sys/src/9/port/devbridge.c:841,847 – 1999/0807/sys/src/9/port/devbridge.c:841,847 | ||
| 1999/0316 | if(ce == nil) { b->miss++; port->inunknown++; | |
| 1999/0803 |
| |
| 1999/0807 | if(1 || port->type != Tether || memcmp(ep->s, tribble, Eaddrlen) == 0) { | |
| 1999/0803 | bp2 = bp; bp = nil; ethermultiwrite(b, bp2, port); } | |
| 1999/0807/sys/src/9/port/devbridge.c:37,43 – 1999/0824/sys/src/9/port/devbridge.c:37,43 (short | long) | ||
| 1999/0316 | Addrlen= 16, // must be long enough of IP addr and ether addr }; | |
| 1999/0824 | static Dirtab bridgedirtab[]={ | |
| 1999/0316 | "ctl", {Qbctl}, 0, 0666, "stats", {Qstats}, 0, 0444, "cache", {Qcache}, 0, 0444, | |
| 1999/0807/sys/src/9/port/devbridge.c:44,50 – 1999/0824/sys/src/9/port/devbridge.c:44,50 | ||
| 1999/0316 | "log", {Qlog}, 0, 0666, }; | |
| 1999/0824 | static Dirtab portdirtab[]={ | |
| 1999/0316 | "ctl", {Qpctl}, 0, 0666, "local", {Qlocal}, 0, 0444, "status", {Qstatus}, 0, 0444, | |
| 1999/0824/sys/src/9/port/devbridge.c:9,14 – 1999/0826/sys/src/9/port/devbridge.c:9,16 (short | long) | ||
| 1999/0316 | typedef struct Bridge Bridge; typedef struct Port Port; typedef struct Centry Centry; | |
| 1999/0826 | typedef struct Iphdr Iphdr; typedef struct Tcphdr Tcphdr; | |
| 1999/0316 | enum { | |
| 1999/0824/sys/src/9/port/devbridge.c:34,39 – 1999/0826/sys/src/9/port/devbridge.c:36,43 | ||
| 1999/0316 | CacheSize= (CacheHash+CacheLook-1), CacheTimeout= 5*60, // timeout for cache entry in seconds | |
| 1999/0826 | TcpMssMax = 1400, // max desirable Tcp MSS value | |
| 1999/0316 | Addrlen= 16, // must be long enough of IP addr and ether addr }; | |
| 1999/0824/sys/src/9/port/devbridge.c:92,97 – 1999/0826/sys/src/9/port/devbridge.c:96,102 | ||
| 1999/0316 | Centry cache[CacheSize]; int hit; int miss; | |
| 1999/0826 | int tcpmss; // modify tcpmss value | |
| 1999/0316 | Log; }; | |
| 1999/0824/sys/src/9/port/devbridge.c:106,111 – 1999/0826/sys/src/9/port/devbridge.c:111,117 | ||
| 1999/0316 | Chan *data[2]; // channel to data int mcast; // send multi cast packets | |
| 1999/0826 | ||
| 1999/0316 | Proc *readp; // read proc // the following uniquely identifies the port | |
| 1999/0824/sys/src/9/port/devbridge.c:125,130 – 1999/0826/sys/src/9/port/devbridge.c:131,173 | ||
| 1999/0316 | int nentry; // number of cache entries for this port }; | |
| 1999/0826 | enum { IP_VER = 0x40, /* Using IP version 4 */ IP_HLEN = 0x05, /* Header length in characters */ IP_TCPPROTO = 6, MSSOPT = 2, MSS_LENGTH = 4, /* Mean segment size */ }; struct Iphdr { uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ 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 */ }; struct Tcphdr { uchar sport[2]; uchar dport[2]; uchar seq[4]; uchar ack[4]; uchar flag[2]; uchar win[2]; uchar cksum[2]; uchar urg[2]; /* Options segment */ uchar opt[2]; uchar mss[2]; }; | |
| 1999/0316 | static Bridge bridgetab[Maxbridge]; static int m2p[] = { | |
| 1999/0824/sys/src/9/port/devbridge.c:310,315 – 1999/0826/sys/src/9/port/devbridge.c:353,368 | ||
| 1999/0316 | } } | |
| 1999/0826 | static void bridgeoption(Bridge *b, char *option, int value) { if(strcmp(option, "tcpmss") == 0) b->tcpmss = value; else error("unknown bridge option"); } | |
| 1999/0316 | static long bridgewrite(Chan *c, void *a, long n, vlong off) { | |
| 1999/0824/sys/src/9/port/devbridge.c:333,345 – 1999/0826/sys/src/9/port/devbridge.c:386,406 | ||
| 1999/0316 | if(cb->nf == 0) error("short write"); arg0 = cb->f[0]; | |
| 1999/0826 | if(strcmp(arg0, "bind") == 0) { | |
| 1999/0316 | portbind(b, cb->nf-1, cb->f+1); | |
| 1999/0826 | } else if(strcmp(arg0, "unbind") == 0) { | |
| 1999/0316 | portunbind(b, cb->nf-1, cb->f+1); | |
| 1999/0826 | } else if(strcmp(arg0, "cacheflush") == 0) { | |
| 1999/0316 | log(b, Logcache, "cache flush\n"); memset(b->cache, 0, CacheSize*sizeof(Centry)); | |
| 1999/0826 | } else if(strcmp(arg0, "set") == 0) { if(cb->nf != 2) error("usage: set option"); bridgeoption(b, cb->f[1], 1); } else if(strcmp(arg0, "clear") == 0) { if(cb->nf != 2) error("usage: clear option"); bridgeoption(b, cb->f[1], 0); | |
| 1999/0316 | } else error("unknown control request"); poperror(); | |
| 1999/0824/sys/src/9/port/devbridge.c:788,793 – 1999/0826/sys/src/9/port/devbridge.c:849,904 | ||
| 1999/0316 | poperror(); } | |
| 1999/0826 | static void tcpmsshack(Block *bp) { int n = BLEN(bp); int hl; Etherpkt *epkt; Iphdr *iphdr; Tcphdr *tcphdr; epkt = (Etherpkt*)bp->rp; // check it is an ip packet if(nhgets(epkt->type) != 0x800) return; print("tcpmsshack is IP\n"); iphdr = (Iphdr*)(bp->rp + ETHERHDRSIZE); n -= ETHERHDRSIZE; if(n < sizeof(Iphdr)) return; // check it is ok IP packet if(iphdr->vihl != (IP_VER|IP_HLEN)) { hl = (iphdr->vihl&0xF)<<2; if((iphdr->vihl&0xF0) != IP_VER || hl < (IP_HLEN<<2)) return; } else { hl = IP_HLEN<<2; } print("tcpmsshack is ok IP\n"); // check TCP if(iphdr->proto != IP_TCPPROTO) return; print("tcpmsshack is TCP\n"); tcphdr = (Tcphdr*)((uchar*)(iphdr) + hl); n -= hl; if(n < sizeof(Tcphdr)) return; hl = (tcphdr->flag[0] & 0xf0)>>2; if(hl < sizeof(Tcphdr)) return; print("tcpmsshack is big enough\n"); // check for MSS option // for the momment, assume MSS is the first option // we could do better, but since options are not aligned, // this would make the checksum correction code tougher if(tcphdr->opt[0] != MSSOPT || tcphdr->opt[1] != MSS_LENGTH) return; print("got mss = %d\n", nhgets(tcphdr->mss)); } | |
| 1999/0316 | /* * process to read from the ethernet */ | |
| 1999/0824/sys/src/9/port/devbridge.c:799,805 – 1999/0826/sys/src/9/port/devbridge.c:910,915 | ||
| 1999/0316 | Block *bp, *bp2; Etherpkt *ep; Centry *ce; | |
| 1999/0803 |
| |
| 1999/0316 | qlock(b); port->readp = up; /* hide identity under a rock for unbind */ | |
| 1999/0824/sys/src/9/port/devbridge.c:811,819 – 1999/0826/sys/src/9/port/devbridge.c:921,929 | ||
| 1999/0316 | qlock(b); break; } | |
| 1999/0826 | if(0)print("devbridge: etherread: reading\n"); | |
| 1999/0316 | bp = devtab[port->data[0]->type]->bread(port->data[0], ETHERMAXTU, 0); | |
| 1999/0826 | if(0)print("devbridge: etherread: blocklen = %d\n", blocklen(bp)); | |
| 1999/0316 | poperror(); qlock(b); | |
| 1999/0824/sys/src/9/port/devbridge.c:841,852 – 1999/0826/sys/src/9/port/devbridge.c:951,964 | ||
| 1999/0316 | if(ce == nil) { b->miss++; port->inunknown++; | |
| 1999/0807 |
| |
| 1999/0803 |
| |
| 1999/0826 | if(b->tcpmss) tcpmsshack(bp); bp2 = bp; bp = nil; ethermultiwrite(b, bp2, port); | |
| 1999/0316 | } else if (ce->port != port->id) { b->hit++; | |
| 1999/0826 | if(b->tcpmss) tcpmsshack(bp); | |
| 1999/0316 | bp2 = bp; bp = nil; oport = b->port[ce->port]; oport->out++; | |
| 1999/0826/sys/src/9/port/devbridge.c:135,142 – 1999/0827/sys/src/9/port/devbridge.c:135,145 (short | long) | ||
| 1999/0826 | IP_VER = 0x40, /* Using IP version 4 */ IP_HLEN = 0x05, /* Header length in characters */ IP_TCPPROTO = 6, | |
| 1999/0827 | EOLOPT = 0, NOOPOPT = 1, | |
| 1999/0826 | MSSOPT = 2, MSS_LENGTH = 4, /* Mean segment size */ | |
| 1999/0827 | SYN = 0x02, /* Pkt. is synchronise */ | |
| 1999/0826 | }; struct Iphdr | |
| 1999/0826/sys/src/9/port/devbridge.c:163,171 – 1999/0827/sys/src/9/port/devbridge.c:166,171 | ||
| 1999/0826 | uchar win[2]; uchar cksum[2]; uchar urg[2]; | |
| 1999/0316 | static Bridge bridgetab[Maxbridge]; | |
| 1999/0826/sys/src/9/port/devbridge.c:850,869 – 1999/0827/sys/src/9/port/devbridge.c:850,869 | ||
| 1999/0316 | } | |
| 1999/0826 | static void | |
| 1999/0827 | tcpmsshack(Etherpkt *epkt, int n) | |
| 1999/0826 | { | |
| 1999/0827 | ulong mss; ulong cksum; int optlen; uchar *optr; | |
| 1999/0826 |
| |
| 1999/0827 | iphdr = (Iphdr*)(epkt->data); | |
| 1999/0826 | n -= ETHERHDRSIZE; if(n < sizeof(Iphdr)) return; | |
| 1999/0826/sys/src/9/port/devbridge.c:873,902 – 1999/0827/sys/src/9/port/devbridge.c:873,937 | ||
| 1999/0826 | hl = (iphdr->vihl&0xF)<<2; if((iphdr->vihl&0xF0) != IP_VER || hl < (IP_HLEN<<2)) return; | |
| 1999/0827 | } else | |
| 1999/0826 | hl = IP_HLEN<<2; | |
| 1999/0827 | tcphdr = (Tcphdr*)((uchar*)(iphdr) + hl); // MSS can only appear in SYN packet if(!(tcphdr->flag[1] & SYN)) return; | |
| 1999/0826 | hl = (tcphdr->flag[0] & 0xf0)>>2; | |
| 1999/0827 | if(n < hl) | |
| 1999/0826 | return; | |
| 1999/0827 | ||
| 1999/0826 | // check for MSS option | |
| 1999/0827 | optr = (uchar*)(tcphdr) + sizeof(Tcphdr); n = hl - sizeof(Tcphdr); for(;;) { if(n <= 0 || *optr == EOLOPT) | |
| 1999/0826 | return; | |
| 1999/0827 | if(*optr == NOOPOPT) { n--; optr++; continue; } optlen = optr[1]; if(optlen < 2 || optlen > n) return; if(*optr == MSSOPT && optlen == MSS_LENGTH) break; n -= optlen; optr += optlen; } mss = nhgets(optr+2); if(mss <= TcpMssMax) return; // fit checksum cksum = nhgets(tcphdr->cksum); if(optr-(uchar*)tcphdr & 1) { print("tcpmsshack: odd alignment!\n"); // odd alignments are a pain cksum += nhgets(optr+1); cksum -= (optr[1]<<8)|(TcpMssMax>>8); cksum += (cksum>>16); cksum &= 0xffff; cksum += nhgets(optr+3); cksum -= ((TcpMssMax&0xff)<<8)|optr[4]; cksum += (cksum>>16); } else { cksum += mss; cksum -= TcpMssMax; cksum += (cksum>>16); } hnputs(tcphdr->cksum, cksum); hnputs(optr+2, TcpMssMax); | |
| 1999/0826 | } | |
| 1999/0316 | /* | |
| 1999/0826/sys/src/9/port/devbridge.c:937,944 – 1999/0827/sys/src/9/port/devbridge.c:972,982 | ||
| 1999/0316 | if(blocklen(bp) < ETHERMINTU) error("short packet"); port->in++; | |
| 1999/0827 | ||
| 1999/0316 | ep = (Etherpkt*)bp->rp; cacheupdate(b, ep->s, port->id); | |
| 1999/0827 | if(b->tcpmss) tcpmsshack(ep, BLEN(bp)); | |
| 1999/0316 | if(ep->d[0] & 1) { log(b, Logmcast, "mulitcast: port=%d src=%E dst=%E type=%#.4ux\n", | |
| 1999/0826/sys/src/9/port/devbridge.c:951,964 – 1999/0827/sys/src/9/port/devbridge.c:989,998 | ||
| 1999/0316 | if(ce == nil) { b->miss++; port->inunknown++; | |
| 1999/0826 |
| |
| 1999/0316 | } else if (ce->port != port->id) { b->hit++; | |
| 1999/0826 |
| |
| 1999/0316 | bp2 = bp; bp = nil; oport = b->port[ce->port]; oport->out++; | |
| 1999/0827/sys/src/9/port/devbridge.c:94,101 – 1999/0901/sys/src/9/port/devbridge.c:94,102 (short | long) | ||
| 1999/0316 | int nport; Port *port[Maxport]; Centry cache[CacheSize]; | |
| 1999/0901 | ulong hit; ulong miss; ulong copy; | |
| 1999/0826 | int tcpmss; // modify tcpmss value | |
| 1999/0316 | Log; | |
| 1999/0827/sys/src/9/port/devbridge.c:350,355 – 1999/0901/sys/src/9/port/devbridge.c:351,361 | ||
| 1999/0316 | case Qcache: n = readstr(off, a, n, c->aux); return n; | |
| 1999/0901 | case Qstats: snprint(buf, sizeof(buf), "hit=%uld miss=%uld copy=%uld\n", b->hit, b->miss, b->copy); n = readstr(off, a, n, buf); return n; | |
| 1999/0316 | } } | |
| 1999/0827/sys/src/9/port/devbridge.c:832,838 – 1999/0901/sys/src/9/port/devbridge.c:838,844 | ||
| 1999/0316 | // delay one so that the last write does not copy if(c != nil) { | |
| 1999/0901 | b->copy++; | |
| 1999/0316 | bp2 = copyblock(bp, blocklen(bp)); devtab[c->type]->bwrite(c, bp2, 0); } | |
| 1999/0901/sys/src/9/port/devbridge.c:38,44 – 1999/0914/sys/src/9/port/devbridge.c:38,43 (short | long) | ||
| 1999/0316 | ||
| 1999/0826 | TcpMssMax = 1400, // max desirable Tcp MSS value | |
| 1999/0316 |
| |
| 1999/0824 | static Dirtab bridgedirtab[]={ | |
| 1999/0901/sys/src/9/port/devbridge.c:117,123 – 1999/0914/sys/src/9/port/devbridge.c:116,122 | ||
| 1999/0316 | // the following uniquely identifies the port int type; | |
| 1999/0914 | char name[NAMELEN]; | |
| 1999/0316 | // owner hash - avoids bind/unbind races ulong ownhash; | |
| 1999/0901/sys/src/9/port/devbridge.c:332,341 – 1999/0914/sys/src/9/port/devbridge.c:331,340 | ||
| 1999/0316 | switch(port->type) { default: panic("bridgeread: unknown port type: %d", port->type); case Tether: | |
| 1999/0914 | i += snprint(buf+i, sizeof(buf)-i, "ether %s: ", port->name); | |
| 1999/0316 | break; | |
| 1999/0807 | case Ttun: | |
| 1999/0316 |
| |
| 1999/0914 | i += snprint(buf+i, sizeof(buf)-i, "tunnel %s: ", port->name); | |
| 1999/0316 | break; } | |
| 1999/0731 | ingood = port->in-port->inmulti-port->inunknown; | |
| 1999/0901/sys/src/9/port/devbridge.c:507,517 – 1999/0914/sys/src/9/port/devbridge.c:506,516 | ||
| 1999/0316 | char *dev, *dev2=nil, *p; Chan *ctl; int type=0, i, n; | |
| 1999/0914 | char *usage = "usage: bind ether|tunnel name ownhash dev [dev2]"; char name[NAMELEN]; | |
| 1999/0316 | ulong ownhash; | |
| 1999/0914 | memset(name, 0, NAMELEN); | |
| 1999/0316 | if(argc < 4) error(usage); if(strcmp(argv[0], "ether") == 0) { | |
| 1999/0901/sys/src/9/port/devbridge.c:518,529 – 1999/0914/sys/src/9/port/devbridge.c:517,532 | ||
| 1999/0316 | if(argc != 4) error(usage); type = Tether; | |
| 1999/0914 | strncpy(name, argv[1], NAMELEN); name[NAMELEN-1] = 0; // parseaddr(addr, argv[1], Eaddrlen); | |
| 1999/0316 | } else if(strcmp(argv[0], "tunnel") == 0) { if(argc != 5) error(usage); | |
| 1999/0807 | type = Ttun; | |
| 1999/0316 |
| |
| 1999/0914 | strncpy(name, argv[1], NAMELEN); name[NAMELEN-1] = 0; // parseip(addr, argv[1]); | |
| 1999/0316 | dev2 = argv[4]; } else error(usage); | |
| 1999/0901/sys/src/9/port/devbridge.c:533,539 – 1999/0914/sys/src/9/port/devbridge.c:536,542 | ||
| 1999/0316 | port = b->port[i]; if(port != nil) if(port->type == type) | |
| 1999/0914 | if(memcmp(port->name, name, NAMELEN) == 0) | |
| 1999/0316 | error("port in use"); } for(i=0; i<Maxport; i++) | |
| 1999/0901/sys/src/9/port/devbridge.c:551,557 – 1999/0914/sys/src/9/port/devbridge.c:554,560 | ||
| 1999/0316 | nexterror(); } port->type = type; | |
| 1999/0914 | memmove(port->name, name, NAMELEN); | |
| 1999/0316 | switch(port->type) { default: panic("portbind: unknown port type: %d", type); case Tether: | |
| 1999/0901/sys/src/9/port/devbridge.c:614,631 – 1999/0914/sys/src/9/port/devbridge.c:617,638 | ||
| 1999/0316 | Port *port=nil; int type=0, i; char *usage = "usage: unbind ether|tunnel addr [ownhash]"; | |
| 1999/0914 | char name[NAMELEN]; | |
| 1999/0316 | ulong ownhash; | |
| 1999/0914 | memset(name, 0, NAMELEN); | |
| 1999/0316 | if(argc < 2 || argc > 3) error(usage); if(strcmp(argv[0], "ether") == 0) { type = Tether; | |
| 1999/0914 | strncpy(name, argv[1], NAMELEN); name[NAMELEN-1] = 0; // parseaddr(addr, argv[1], Eaddrlen); | |
| 1999/0316 | } else if(strcmp(argv[0], "tunnel") == 0) { | |
| 1999/0807 | type = Ttun; | |
| 1999/0316 |
| |
| 1999/0914 | strncpy(name, argv[1], NAMELEN); name[NAMELEN-1] = 0; // parseip(addr, argv[1]); | |
| 1999/0316 | } else error(usage); if(argc == 3) | |
| 1999/0901/sys/src/9/port/devbridge.c:636,642 – 1999/0914/sys/src/9/port/devbridge.c:643,649 | ||
| 1999/0316 | port = b->port[i]; if(port != nil) if(port->type == type) | |
| 1999/0914 | if(memcmp(port->name, name, NAMELEN) == 0) | |
| 1999/0316 | break; } if(i == b->nport) | |
| 1999/0914/sys/src/9/port/devbridge.c:606,613 – 1999/0915/sys/src/9/port/devbridge.c:606,613 (short | long) | ||
| 1999/0316 | b->nport = port->id+1; // assumes kproc always succeeds | |
| 1999/0915 | port->ref++; | |
| 1999/0316 | } // assumes b is locked | |
| 1999/0914/sys/src/9/port/devbridge.c:847,853 – 1999/0915/sys/src/9/port/devbridge.c:847,856 | ||
| 1999/0316 | if(c != nil) { | |
| 1999/0901 | b->copy++; | |
| 1999/0316 | bp2 = copyblock(bp, blocklen(bp)); | |
| 1999/0915 | if(!waserror()) { devtab[c->type]->bwrite(c, bp2, 0); poperror(); } | |
| 1999/0316 | } c = b->port[i]->data[1]; } | |
| 1999/0914/sys/src/9/port/devbridge.c:855,861 – 1999/0915/sys/src/9/port/devbridge.c:858,867 | ||
| 1999/0316 | // last write free block if(c) { bp2 = bp; bp = nil; USED(bp); | |
| 1999/0915 | if(!waserror()) { devtab[c->type]->bwrite(c, bp2, 0); poperror(); } | |
| 1999/0316 | } else freeb(bp); | |
| 1999/0914/sys/src/9/port/devbridge.c:966,971 – 1999/0915/sys/src/9/port/devbridge.c:972,978 | ||
| 1999/0316 | // release lock to read - error means it is time to quit qunlock(b); if(waserror()) { | |
| 1999/0915 | print("etherread read error\n"); | |
| 1999/0316 | qlock(b); break; } | |
| 1999/0914/sys/src/9/port/devbridge.c:978,983 – 1999/0915/sys/src/9/port/devbridge.c:985,991 | ||
| 1999/0316 | if(port->closed) break; if(waserror()) { | |
| 1999/0915 | print("etherread bridge error\n"); | |
| 1999/0316 | if(bp) freeb(bp); continue; | |
| 1999/0915/sys/src/9/port/devbridge.c:981,988 – 1999/0930/sys/src/9/port/devbridge.c:981,987 (short | long) | ||
| 1999/0826 | if(0)print("devbridge: etherread: blocklen = %d\n", blocklen(bp)); | |
| 1999/0316 | poperror(); qlock(b); | |
| 1999/0930 | if(bp == nil || port->closed) | |
| 1999/0316 | break; if(waserror()) { | |
| 1999/0915 | print("etherread bridge error\n"); | |
| 1999/0930/sys/src/9/port/devbridge.c:222,242 – 1999/1230/sys/src/9/port/devbridge.c:222,227 (short | long) | ||
| 1999/0316 | static int bridgewalk(Chan *c, char *name) { | |
| 1999/0930/sys/src/9/port/devbridge.c:430,435 – 1999/1230/sys/src/9/port/devbridge.c:415,437 | ||
| 1999/0316 | char buf[32]; Dirtab *dt; Qid qid; | |
| 1999/1230 | if(s == DEVDOTDOT){ switch(TYPE(c->qid)){ case Qtopdir: case Qbridgedir: snprint(buf, "#B%d", c->dev); devdir(c, (Qid){CHDIR|Qtopdir, 0}, buf, 0, eve, 0555, dp); break; case Qportdir: sprint(buf, "bridge%ld", c->dev); devdir(c, (Qid){CHDIR|Qbridgedir, 0}, buf, 0, eve, 0555, dp); break; default: panic("bridgewalk %lux", c->qid.path); } return 1; } | |
| 1999/0316 | switch(type) { default: | |
| 1999/1230/sys/src/9/port/devbridge.c:420,426 – 2000/0108/sys/src/9/port/devbridge.c:420,426 (short | long) | ||
| 1999/1230 | switch(TYPE(c->qid)){ case Qtopdir: case Qbridgedir: | |
| 2000/0108 | snprint(buf, sizeof(buf), "#B%ld", c->dev); | |
| 1999/1230 | devdir(c, (Qid){CHDIR|Qtopdir, 0}, buf, 0, eve, 0555, dp); break; case Qportdir: | |
| 2000/0108/sys/src/9/port/devbridge.c:36,42 – 2000/0205/sys/src/9/port/devbridge.c:36,42 (short | long) | ||
| 1999/0316 | CacheSize= (CacheHash+CacheLook-1), CacheTimeout= 5*60, // timeout for cache entry in seconds | |
| 1999/0826 |
| |
| 2000/0205 | TcpMssMax = 1360, // max desirable Tcp MSS value | |
| 1999/0826 | ||
| 1999/0316 | }; | |
| 2000/0205/sys/src/9/port/devbridge.c:986,992 – 2000/0211/sys/src/9/port/devbridge.c:986,992 (short | long) | ||
| 1999/0930 | if(bp == nil || port->closed) | |
| 1999/0316 | break; if(waserror()) { | |
| 1999/0915 |
| |
| 2000/0211 | //print("etherread bridge error\n"); | |
| 1999/0316 | if(bp) freeb(bp); continue; | |
| 2000/0205/sys/src/9/port/devbridge.c:1026,1032 – 2000/0211/sys/src/9/port/devbridge.c:1026,1032 | ||
| 1999/0316 | if(bp) freeb(bp); } | |
| 2000/0211 | //print("etherread: trying to exit\n"); | |
| 1999/0316 | port->readp = nil; portfree(port); qunlock(b); | |
| 2000/0211/sys/src/9/port/devbridge.c:30,36 – 2000/0227/sys/src/9/port/devbridge.c:30,36 (short | long) | ||
| 1999/0316 | MaxQ, Maxbridge= 4, | |
| 2000/0227 | Maxport= 32, // power of 2 | |
| 1999/0316 | CacheHash= 257, // prime CacheLook= 5, // how many cache entries to examine CacheSize= (CacheHash+CacheLook-1), | |
| 2000/0227/sys/src/9/port/devbridge.c:36,43 – 2000/0331/sys/src/9/port/devbridge.c:36,43 (short | long) | ||
| 1999/0316 | CacheSize= (CacheHash+CacheLook-1), CacheTimeout= 5*60, // timeout for cache entry in seconds | |
| 2000/0205 |
| |
| 1999/0826 | ||
| 2000/0331 | TcpMssMax = 1300, // max desirable Tcp MSS value TunnelMtu = 1400, | |
| 1999/0316 | }; | |
| 1999/0824 | static Dirtab bridgedirtab[]={ | |
| 2000/0227/sys/src/9/port/devbridge.c:128,133 – 2000/0331/sys/src/9/port/devbridge.c:128,134 | ||
| 1999/0316 | int out; // number of packets read int outmulti; // multicast or broadcast int outunknown; // unknown address | |
| 2000/0331 | int outfrag; // fragmented the packet | |
| 1999/0316 | int nentry; // number of cache entries for this port }; | |
| 2000/0227/sys/src/9/port/devbridge.c:183,188 – 2000/0331/sys/src/9/port/devbridge.c:184,190 | ||
| 1999/0316 | static char *cachedump(Bridge *b); static void portfree(Port *port); static void cacheflushport(Bridge *b, int port); | |
| 2000/0331 | static void etherwrite(Port *port, Block *bp); | |
| 1999/0316 | extern ulong parseip(uchar*, char*); | |
| 2000/0227/sys/src/9/port/devbridge.c:814,820 – 2000/0331/sys/src/9/port/devbridge.c:816,822 | ||
| 1999/0316 | static void ethermultiwrite(Bridge *b, Block *bp, Port *port) { | |
| 2000/0331 | Port *oport; | |
| 1999/0316 | Block *bp2; Etherpkt *ep; int i, mcast, bcast; | |
| 2000/0227/sys/src/9/port/devbridge.c:833,845 – 2000/0331/sys/src/9/port/devbridge.c:835,846 | ||
| 1999/0316 | else bcast = 0; | |
| 2000/0331 | oport = nil; | |
| 1999/0316 | for(i=0; i<b->nport; i++) { if(i == port->id || b->port[i] == nil) continue; if(mcast && !bcast && !b->port[i]->mcast) continue; | |
| 2000/0227/sys/src/9/port/devbridge.c:846,867 – 2000/0331/sys/src/9/port/devbridge.c:847,868 | ||
| 1999/0316 | b->port[i]->outunknown++; // delay one so that the last write does not copy | |
| 2000/0331 | if(oport != nil) { | |
| 1999/0901 | b->copy++; | |
| 1999/0316 | bp2 = copyblock(bp, blocklen(bp)); | |
| 1999/0915 | if(!waserror()) { | |
| 2000/0331 | etherwrite(oport, bp2); | |
| 1999/0915 | poperror(); } | |
| 1999/0316 | } | |
| 2000/0331 | oport = b->port[i]; | |
| 1999/0316 | } // last write free block | |
| 2000/0331 | if(oport) { | |
| 1999/0316 | bp2 = bp; bp = nil; USED(bp); | |
| 1999/0915 | if(!waserror()) { | |
| 2000/0331 | etherwrite(oport, bp2); | |
| 1999/0915 | poperror(); } | |
| 1999/0316 | } else | |
| 2000/0227/sys/src/9/port/devbridge.c:961,967 – 2000/0331/sys/src/9/port/devbridge.c:962,968 | ||
| 1999/0316 | static void etherread(void *a) { | |
| 2000/0331 | Port *port = a; | |
| 1999/0316 | Bridge *b = port->bridge; Block *bp, *bp2; Etherpkt *ep; | |
| 2000/0227/sys/src/9/port/devbridge.c:1016,1024 – 2000/0331/sys/src/9/port/devbridge.c:1017,1023 | ||
| 1999/0316 | } else if (ce->port != port->id) { b->hit++; bp2 = bp; bp = nil; | |
| 2000/0331 | etherwrite(b->port[ce->port], bp2); | |
| 1999/0316 | } } | |
| 2000/0227/sys/src/9/port/devbridge.c:1031,1036 – 2000/0331/sys/src/9/port/devbridge.c:1030,1042 | ||
| 1999/0316 | portfree(port); qunlock(b); pexit("hangup", 1); | |
| 2000/0331 | } static void etherwrite(Port *port, Block *bp) { port->out++; devtab[port->data[1]->type]->bwrite(port->data[1], bp, 0); | |
| 1999/0316 | } // hold b lock | |
| 2000/0331/sys/src/9/port/devbridge.c:135,140 – 2000/0404/sys/src/9/port/devbridge.c:135,143 (short | long) | ||
| 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 | |
| 2000/0404/sys/src/9/port/devbridge.c:30,36 – 2000/0526/sys/src/9/port/devbridge.c:30,36 (short | long) | ||
| 1999/0316 | MaxQ, Maxbridge= 4, | |
| 2000/0227 |
| |
| 2000/0526 | Maxport= 64, // power of 2 | |
| 1999/0316 | CacheHash= 257, // prime CacheLook= 5, // how many cache entries to examine CacheSize= (CacheHash+CacheLook-1), | |
| 2000/0526/sys/src/9/port/devbridge.c:95,101 – 2000/0527/sys/src/9/port/devbridge.c:95,103 (short | long) | ||
| 1999/0316 | Centry cache[CacheSize]; | |
| 1999/0901 | ulong hit; ulong miss; | |
| 2000/0527 | ulong copy; long delay0; // constant microsecond delay per packet long delayn; // microsecond delay per byte | |
| 1999/0826 | int tcpmss; // modify tcpmss value | |
| 1999/0316 | Log; | |
| 2000/0526/sys/src/9/port/devbridge.c:188,194 – 2000/0527/sys/src/9/port/devbridge.c:190,196 | ||
| 1999/0316 | static char *cachedump(Bridge *b); static void portfree(Port *port); static void cacheflushport(Bridge *b, int port); | |
| 2000/0331 |
| |
| 2000/0527 | static void etherwrite(Port *port, Block *bp); | |
| 1999/0316 | extern ulong parseip(uchar*, char*); | |
| 2000/0404 | extern ushort ipcsum(uchar *addr); | |
| 2000/0526/sys/src/9/port/devbridge.c:398,403 – 2000/0527/sys/src/9/port/devbridge.c:400,410 | ||
| 1999/0826 | if(cb->nf != 2) error("usage: clear option"); bridgeoption(b, cb->f[1], 0); | |
| 2000/0527 | } else if(strcmp(arg0, "delay") == 0) { if(cb->nf != 3) error("usage: delay delay0 delayn"); b->delay0 = strtol(cb->f[1], nil, 10); b->delayn = strtol(cb->f[2], nil, 10); | |
| 1999/0316 | } else error("unknown control request"); poperror(); | |
| 2000/0526/sys/src/9/port/devbridge.c:972,977 – 2000/0527/sys/src/9/port/devbridge.c:979,985 | ||
| 1999/0316 | Block *bp, *bp2; Etherpkt *ep; Centry *ce; | |
| 2000/0527 | long md; | |
| 1999/0316 | qlock(b); port->readp = up; /* hide identity under a rock for unbind */ | |
| 2000/0526/sys/src/9/port/devbridge.c:1005,1010 – 2000/0527/sys/src/9/port/devbridge.c:1013,1027 | ||
| 1999/0316 | cacheupdate(b, ep->s, port->id); | |
| 1999/0827 | if(b->tcpmss) tcpmsshack(ep, BLEN(bp)); | |
| 2000/0527 | /* * delay packets to simulate a slow link */ if(b->delay0 || b->delayn){ md = b->delay0 + b->delayn * BLEN(bp); if(md > 0) microdelay(md); } | |
| 1999/0316 | if(ep->d[0] & 1) { log(b, Logmcast, "mulitcast: port=%d src=%E dst=%E type=%#.4ux\n", | |
| 2000/0527/sys/src/9/port/devbridge.c:256,276 – 2000/0606/sys/src/9/port/devbridge.c:256,265 (short | long) | ||
| 1999/0316 | switch(TYPE(c->qid)) { default: break; | |
| 2000/0527/sys/src/9/port/devbridge.c:340,345 – 2000/0606/sys/src/9/port/devbridge.c:329,339 | ||
| 1999/0316 | } n = readstr(off, a, n, buf); qunlock(b); | |
| 2000/0606 | return n; case Qbctl: snprint(buf, sizeof(buf), "%s tcpmss\ndelay %ld %ld\n", b->tcpmss ? "set" : "clear", b->delay0, b->delayn); n = readstr(off, a, n, buf); | |
| 1999/0316 | return n; case Qcache: n = readstr(off, a, n, c->aux); | |
| 2000/0606/sys/src/9/port/devbridge.c:30,36 – 2001/0918/sys/src/9/port/devbridge.c:30,36 (short | long) | ||
| 1999/0316 | MaxQ, Maxbridge= 4, | |
| 2000/0526 |
| |
| 2001/0918 | Maxport= 128, // power of 2 | |
| 1999/0316 | CacheHash= 257, // prime CacheLook= 5, // how many cache entries to examine CacheSize= (CacheHash+CacheLook-1), | |
| 2000/0606/sys/src/9/port/devbridge.c:74,81 – 2001/0918/sys/src/9/port/devbridge.c:74,81 | ||
| 1999/0316 | static Dirtab *dirtab[MaxQ]; | |
| 2001/0918 | #define TYPE(x) (((ulong)(x).path) & 0xff) #define PORT(x) ((((ulong)(x).path) >> 8)&(Maxport-1)) | |
| 1999/0316 | #define QID(x, y) (((x)<<8) | (y)) struct Centry | |
| 2000/0606/sys/src/9/port/devbridge.c:118,124 – 2001/0918/sys/src/9/port/devbridge.c:118,124 | ||
| 1999/0316 | // the following uniquely identifies the port int type; | |
| 1999/0914 |
| |
| 2001/0918 | char name[KNAMELEN]; | |
| 1999/0316 | // owner hash - avoids bind/unbind races ulong ownhash; | |
| 2000/0606/sys/src/9/port/devbridge.c:183,189 – 2001/0918/sys/src/9/port/devbridge.c:183,189 | ||
| 1999/0316 | [ORDWR] 6 }; | |
| 2001/0918 | static int bridgegen(Chan *c, char*, Dirtab*, int, int s, Dir *dp); | |
| 1999/0316 | static void portbind(Bridge *b, int argc, char *argv[]); static void portunbind(Bridge *b, int argc, char *argv[]); static void etherread(void *a); | |
| 2000/0606/sys/src/9/port/devbridge.c:222,243 – 2001/0918/sys/src/9/port/devbridge.c:222,243 | ||
| 1999/0316 | error("bad specification"); c = devattach('B', spec); | |
| 2001/0918 | mkqid(&c->qid, QID(0, Qtopdir), 0, QTDIR); | |
| 1999/0316 | c->dev = dev; return c; } | |
| 2001/0918 | static Walkqid* bridgewalk(Chan *c, Chan *nc, char **name, int nname) | |
| 1999/0316 | { | |
| 2001/0918 | return devwalk(c, nc, name, nname, (Dirtab*)0, 0, bridgegen); | |
| 1999/0316 | } | |
| 2001/0918 | static int bridgestat(Chan* c, uchar* db, int n) | |
| 1999/0316 | { | |
| 2001/0918 | return devstat(c, db, n, (Dirtab *)0, 0L, bridgegen); | |
| 1999/0316 | } static Chan* | |
| 2000/0606/sys/src/9/port/devbridge.c:416,426 – 2001/0918/sys/src/9/port/devbridge.c:416,425 | ||
| 1999/0316 | } static int | |
| 2001/0918 | bridgegen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) | |
| 1999/0316 | { Bridge *b = bridgetab + c->dev; int type = TYPE(c->qid); | |
| 1999/1230 | ||
| 2000/0606/sys/src/9/port/devbridge.c:428,439 – 2001/0918/sys/src/9/port/devbridge.c:427,440 | ||
| 1999/1230 | switch(TYPE(c->qid)){ case Qtopdir: case Qbridgedir: | |
| 2000/0108 |
| |
| 1999/1230 |
| |
| 2001/0918 | snprint(up->genbuf, sizeof(up->genbuf), "#B%ld", c->dev); mkqid(&qid, Qtopdir, 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); | |
| 1999/1230 | break; case Qportdir: | |
| 2001/0918 | snprint(up->genbuf, sizeof(up->genbuf), "bridge%ld", c->dev); mkqid(&qid, Qbridgedir, 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); | |
| 1999/1230 | break; default: panic("bridgewalk %lux", c->qid.path); | |
| 2000/0606/sys/src/9/port/devbridge.c:444,450 – 2001/0918/sys/src/9/port/devbridge.c:445,451 | ||
| 1999/0316 | switch(type) { default: // non directory entries end up here | |
| 2001/0918 | if(c->qid.type & QTDIR) | |
| 1999/0316 | panic("bridgegen: unexpected directory"); if(s != 0) return -1; | |
| 2000/0606/sys/src/9/port/devbridge.c:456,463 – 2001/0918/sys/src/9/port/devbridge.c:457,465 | ||
| 1999/0316 | case Qtopdir: if(s != 0) return -1; | |
| 2001/0918 | snprint(up->genbuf, sizeof(up->genbuf), "bridge%ld", c->dev); mkqid(&qid, QID(0, Qbridgedir), 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); | |
| 1999/0316 | return 1; case Qbridgedir: if(s<nelem(bridgedirtab)) { | |
| 2000/0606/sys/src/9/port/devbridge.c:468,482 – 2001/0918/sys/src/9/port/devbridge.c:470,484 | ||
| 1999/0316 | s -= nelem(bridgedirtab); if(s >= b->nport) return -1; | |
| 2001/0918 | mkqid(&qid, QID(s, Qportdir), 0, QTDIR); snprint(up->genbuf, sizeof(up->genbuf), "%d", s); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); | |
| 1999/0316 | return 1; case Qportdir: if(s>=nelem(portdirtab)) return -1; dt = portdirtab+s; | |
| 2001/0918 | mkqid(&qid, QID(PORT(c->qid),TYPE(dt->qid)), 0, QTFILE); | |
| 1999/0316 | devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp); return 1; } | |
| 2000/0606/sys/src/9/port/devbridge.c:511,526 – 2001/0918/sys/src/9/port/devbridge.c:513,528 | ||
| 1999/0316 | portbind(Bridge *b, int argc, char *argv[]) { Port *port; | |
| 2001/0918 | char path[8*KNAMELEN]; | |
| 1999/0316 | char buf[100]; char *dev, *dev2=nil, *p; Chan *ctl; int type=0, i, n; | |
| 1999/0914 | char *usage = "usage: bind ether|tunnel name ownhash dev [dev2]"; | |
| 2001/0918 | char name[KNAMELEN]; | |
| 1999/0316 | ulong ownhash; | |
| 1999/0914 |
| |
| 2001/0918 | memset(name, 0, KNAMELEN); | |
| 1999/0316 | if(argc < 4) error(usage); if(strcmp(argv[0], "ether") == 0) { | |
| 2000/0606/sys/src/9/port/devbridge.c:527,541 – 2001/0918/sys/src/9/port/devbridge.c:529,543 | ||
| 1999/0316 | if(argc != 4) error(usage); type = Tether; | |
| 1999/0914 |
| |
| 2001/0918 | strncpy(name, argv[1], KNAMELEN); name[KNAMELEN-1] = 0; | |
| 1999/0914 | // parseaddr(addr, argv[1], Eaddrlen); | |
| 1999/0316 | } else if(strcmp(argv[0], "tunnel") == 0) { if(argc != 5) error(usage); | |
| 1999/0807 | type = Ttun; | |
| 1999/0914 |
| |
| 2001/0918 | strncpy(name, argv[1], KNAMELEN); name[KNAMELEN-1] = 0; | |
| 1999/0914 | // parseip(addr, argv[1]); | |
| 1999/0316 | dev2 = argv[4]; } else | |
| 2000/0606/sys/src/9/port/devbridge.c:546,552 – 2001/0918/sys/src/9/port/devbridge.c:548,554 | ||
| 1999/0316 | port = b->port[i]; if(port != nil) if(port->type == type) | |
| 1999/0914 |
| |
| 2001/0918 | if(memcmp(port->name, name, KNAMELEN) == 0) | |
| 1999/0316 | error("port in use"); } for(i=0; i<Maxport; i++) | |
| 2000/0606/sys/src/9/port/devbridge.c:564,570 – 2001/0918/sys/src/9/port/devbridge.c:566,572 | ||
| 1999/0316 | nexterror(); } port->type = type; | |
| 1999/0914 |
| |
| 2001/0918 | memmove(port->name, name, KNAMELEN); | |
| 1999/0316 | switch(port->type) { default: panic("portbind: unknown port type: %d", type); case Tether: | |
| 2000/0606/sys/src/9/port/devbridge.c:627,647 – 2001/0918/sys/src/9/port/devbridge.c:629,649 | ||
| 1999/0316 | Port *port=nil; int type=0, i; char *usage = "usage: unbind ether|tunnel addr [ownhash]"; | |
| 1999/0914 |
| |
| 2001/0918 | char name[KNAMELEN]; | |
| 1999/0316 | ulong ownhash; | |
| 1999/0914 |
| |
| 2001/0918 | memset(name, 0, KNAMELEN); | |
| 1999/0316 | if(argc < 2 || argc > 3) error(usage); if(strcmp(argv[0], "ether") == 0) { type = Tether; | |
| 1999/0914 |
| |
| 2001/0918 | strncpy(name, argv[1], KNAMELEN); name[KNAMELEN-1] = 0; | |
| 1999/0914 | // parseaddr(addr, argv[1], Eaddrlen); | |
| 1999/0316 | } else if(strcmp(argv[0], "tunnel") == 0) { | |
| 1999/0807 | type = Ttun; | |
| 1999/0914 |
| |
| 2001/0918 | strncpy(name, argv[1], KNAMELEN); name[KNAMELEN-1] = 0; | |
| 1999/0914 | // parseip(addr, argv[1]); | |
| 1999/0316 | } else error(usage); | |
| 2000/0606/sys/src/9/port/devbridge.c:653,659 – 2001/0918/sys/src/9/port/devbridge.c:655,661 | ||
| 1999/0316 | port = b->port[i]; if(port != nil) if(port->type == type) | |
| 1999/0914 |
| |
| 2001/0918 | if(memcmp(port->name, name, KNAMELEN) == 0) | |
| 1999/0316 | break; } if(i == b->nport) | |
| 2000/0606/sys/src/9/port/devbridge.c:1189,1195 – 2001/0918/sys/src/9/port/devbridge.c:1191,1196 | ||
| 1999/0316 | devreset, bridgeinit, bridgeattach, | |
| 2001/0918/sys/src/9/port/devbridge.c:1190,1195 – 2002/0109/sys/src/9/port/devbridge.c:1190,1196 (short | long) | ||
|
Add devshutdown.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1999/0316 | devreset, bridgeinit, | |
| 2002/0109 | devshutdown, | |
| 1999/0316 | bridgeattach, bridgewalk, bridgestat, | |
| 2002/0109/sys/src/9/port/devbridge.c:437,443 – 2002/0125/sys/src/9/port/devbridge.c:437,443 (short | long) | ||
|
Bug fix: print format (serious).
rsc Fri Mar 4 12:44:25 2005 | ||
| 2001/0918 | devdir(c, qid, up->genbuf, 0, eve, 0555, dp); | |
| 1999/1230 | break; default: | |
| 2002/0125 | panic("bridgewalk %llux", c->qid.path); | |
| 1999/1230 | } return 1; } | |
| 2002/0109/sys/src/9/port/devbridge.c:451,457 – 2002/0125/sys/src/9/port/devbridge.c:451,457 | ||
| 1999/0316 | return -1; dt = dirtab[TYPE(c->qid)]; if(dt == nil) | |
| 2002/0125 | panic("bridgegen: unknown type: %lud", TYPE(c->qid)); | |
| 1999/0316 | devdir(c, c->qid, dt->name, dt->length, eve, dt->perm, dp); return 1; case Qtopdir: | |
| Too many diffs (26 > 25). Stopping. | ||