| plan 9 kernel history: overview | file list | diff list |
1997/0531/ip/gre.c (diff list | history)
| ip/gre.c on 1997/0327 | ||
| 1997/0327 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "ip.h" #define DPRINT if(0)print enum { | |
| 1997/0530 | GRE_IPONLY = 12, /* size of ip header */ GRE_IPPLUSGRE = 12, /* minimum size of GRE header */ | |
| 1997/0327 | IP_GREPROTO = 47, GRErxms = 200, GREtickms = 100, GREmaxxmit = 10, }; typedef struct GREhdr { /* ip header */ byte vihl; /* Version and header length */ byte tos; /* Type of service */ byte len[2]; /* packet length (including headers) */ byte id[2]; /* Identification */ byte frag[2]; /* Fragment information */ byte Unused; byte proto; /* Protocol */ byte cksum[2]; /* checksum */ byte src[4]; /* Ip source */ byte dst[4]; /* Ip destination */ /* gre header */ byte flags[2]; byte eproto[2]; /* encapsulation protocol */ } GREhdr; Proto gre; extern Fs fs; int gredebug; static char* greconnect(Conv *c, char **argv, int argc) { Proto *p; char *err; Conv *tc, **cp, **ecp; err = Fsstdconnect(c, argv, argc); if(err != nil) return err; /* make sure noone's already connected to this other sys */ p = c->p; lock(p); ecp = &p->conv[p->nc]; for(cp = p->conv; cp < ecp; cp++){ tc = *cp; if(tc == nil) break; if(tc == c) continue; if(tc->rport == c->rport && tc->raddr == c->raddr){ err = "already connected to that addr/proto"; c->rport = 0; c->raddr = 0; break; } } unlock(p); | |
| 1997/0403 | if(err != nil) return err; Fsconnected(&fs, c, nil); | |
| 1997/0327 | ||
| 1997/0403 | return nil; | |
| 1997/0327 | } static int grestate(char **msg, Conv *c) { USED(c); *msg = "Datagram"; return 1; } static void grecreate(Conv *c) { c->rq = qopen(64*1024, 0, 0, c); c->wq = qopen(64*1024, 0, 0, 0); } | |
| 1997/0403 | static char* greannounce(Conv*, char**, int) | |
| 1997/0327 | { | |
| 1997/0403 | return "pktifc does not support announce"; | |
| 1997/0327 | } static void greclose(Conv *c) { qclose(c->rq); qclose(c->wq); qclose(c->eq); c->laddr = 0; c->raddr = 0; c->lport = 0; c->rport = 0; unlock(c); } int drop; static void grekick(Conv *c, int l) { GREhdr *ghp; | |
| 1997/0524 | Block *bp; | |
| 1997/0530 | ulong raddr, laddr; | |
| 1997/0327 | USED(l); bp = qget(c->wq); if(bp == nil) return; /* Make space to fit ip header (gre header already there) */ | |
| 1997/0530 | bp = padblock(bp, GRE_IPONLY); | |
| 1997/0327 | if(bp == nil) return; /* make sure the message has a GRE header */ | |
| 1997/0530 | bp = pullupblock(bp, GRE_IPONLY+GRE_IPPLUSGRE); | |
| 1997/0327 | if(bp == nil) return; ghp = (GREhdr *)(bp->rp); | |
| 1997/0531 | raddr = nhgetl(ghp->dst); laddr = nhgetl(ghp->src); | |
| 1997/0530 | if(raddr == 0) raddr = c->raddr; | |
| 1997/0531 | if(laddr == 0 || Mediaforme(ghp->src) <= 0) | |
| 1997/0530 | laddr = c->laddr; | |
| 1997/0327 | ghp->proto = IP_GREPROTO; | |
| 1997/0530 | hnputl(ghp->dst, raddr); hnputl(ghp->src, laddr); | |
| 1997/0327 | hnputs(ghp->eproto, c->rport); | |
| 1997/0522 | ghp->frag[0] = 0; ghp->frag[1] = 0; | |
| 1997/0327 | ipoput(bp, 0, c->ttl); } static void | |
| 1997/0423 | greiput(Media *m, Block *bp) | |
| 1997/0327 | { int len; GREhdr *ghp; Ipaddr addr; Conv *c, **p; ushort eproto; | |
| 1997/0423 | USED(m); | |
| 1997/0327 | ghp = (GREhdr*)(bp->rp); eproto = nhgets(ghp->eproto); addr = nhgetl(ghp->src); /* Look for a conversation structure for this port and address */ c = nil; for(p = gre.conv; *p; p++) { c = *p; if(c->inuse == 0) continue; if(c->raddr == addr && c->rport == eproto) break; } if(*p == nil) { freeblist(bp); return; } /* * Trim the packet down to data size */ | |
| 1997/0530 | len = nhgets(ghp->len) - GRE_IPONLY; if(len < GRE_IPPLUSGRE){ | |
| 1997/0327 | freeblist(bp); return; } | |
| 1997/0530 | bp = trimblock(bp, GRE_IPONLY, len); | |
| 1997/0327 | if(bp == nil){ gre.lenerr++; return; } /* * Can't delimit packet so pull it all into one block. */ if(qlen(c->rq) > 64*1024) freeblist(bp); else{ bp = concatblock(bp); if(bp == 0) panic("greiput"); qpass(c->rq, bp); } } void greinit(Fs *fs) { gre.name = "gre"; gre.kick = grekick; gre.connect = greconnect; gre.announce = greannounce; gre.state = grestate; gre.create = grecreate; gre.close = greclose; gre.rcv = greiput; gre.ctl = nil; gre.advise = nil; gre.ipproto = IP_GREPROTO; gre.nc = 64; gre.ptclsize = 0; Fsproto(fs, &gre); } | |