#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include <libcrypt.h>#include <kernel.h>#include "ip.h"#include "ppp.h" int nocompress;Ipaddr pppdns[2]; /* * Calculate FCS - rfc 1331 */ushort fcstab[256] ={ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78}; static char *snames[] ={ "Sclosed", "Sclosing", "Sreqsent", "Sackrcvd", "Sacksent", "Sopened",}; static void init(PPP*);static void setphase(PPP*, int);static void pinit(PPP*, Pstate*);static void ppptimer(void*);static void ptimer(PPP*, Pstate*);static int getframe(PPP*, Block**);static Block* putframe(PPP*, int, Block*);static uchar* escapebyte(PPP*, ulong, uchar*, ushort*);static void config(PPP*, Pstate*, int);static int getopts(PPP*, Pstate*, Block*);static void rejopts(PPP*, Pstate*, Block*, int);static void newstate(PPP*, Pstate*, int);static void rcv(PPP*, Pstate*, Block*);static void getchap(PPP*, Block*);static void getpap(PPP*, Block*);static void sendpap(PPP*);static void getlqm(PPP*, Block*);static void putlqm(PPP*);static void hangup(PPP*);static void remove(PPP*); static int validv4(Ipaddr);static void invalidate(Ipaddr);static void ipconnect(PPP *);static void setdefroute(PPP *, Ipaddr);static void printopts(PPP *, Pstate*, Block*, int);static void sendtermreq(PPP*, Pstate*); static voiderrlog(PPP *ppp, char *err){ int n; char msg[64]; n = snprint(msg, sizeof(msg), "%s\n", err); qproduce(ppp->ifc->conv->eq, msg, n);} static voidinit(PPP* ppp){ if(ppp->inbuf == nil){ ppp->inbuf = allocb(4096); ppp->outbuf = allocb(4096); ppp->lcp = malloc(sizeof(Pstate)); ppp->ipcp = malloc(sizeof(Pstate)); if(ppp->lcp == nil || ppp->ipcp == nil) error("ppp init: malloc"); ppp->lcp->proto = Plcp; ppp->lcp->state = Sclosed; ppp->ipcp->proto = Pipcp; ppp->ipcp->state = Sclosed; kproc("ppptimer", ppptimer, ppp, KPDUPPG|KPDUPFDG); } pinit(ppp, ppp->lcp); setphase(ppp, Plink);} static voidsetphase(PPP *ppp, int phase){ int oldphase; oldphase = ppp->phase; ppp->phase = phase; switch(phase){ default: panic("ppp: unknown phase %d", phase); case Pdead: /* restart or exit? */ pinit(ppp, ppp->lcp); setphase(ppp, Plink); break; case Plink: /* link down */ switch(oldphase) { case Pnet: newstate(ppp, ppp->ipcp, Sclosed); } break; case Pauth: if(ppp->usepap) sendpap(ppp); else if(!ppp->usechap) setphase(ppp, Pnet); break; case Pnet: pinit(ppp, ppp->ipcp); break; case Pterm: /* what? */ break; }} static voidpinit(PPP *ppp, Pstate *p){ p->timeout = 0; switch(p->proto){ case Plcp: ppp->magic = TK2MS(MACHP(0)->ticks); ppp->xctlmap = 0xffffffff; ppp->period = 0; p->optmask = 0xffffffff; ppp->rctlmap = 0; ppp->ipcp->state = Sclosed; ppp->ipcp->optmask = 0xffffffff; /* quality goo */ ppp->timeout = 0; memset(&ppp->in, 0, sizeof(ppp->in)); memset(&ppp->out, 0, sizeof(ppp->out)); memset(&ppp->pin, 0, sizeof(ppp->pin)); memset(&ppp->pout, 0, sizeof(ppp->pout)); memset(&ppp->sin, 0, sizeof(ppp->sin)); break; case Pipcp: if(ppp->localfrozen == 0) invalidate(ppp->local); if(ppp->remotefrozen == 0) invalidate(ppp->remote); p->optmask = 0xffffffff; ppp->ctcp = compress_init(ppp->ctcp); ppp->usedns = 3; invalidate(ppp->dns1); invalidate(ppp->dns2); break; } p->confid = p->rcvdconfid = -1; config(ppp, p, 1); newstate(ppp, p, Sreqsent);} /* * change protocol to a new state. */static voidnewstate(PPP *ppp, Pstate *p, int state){ netlog(ppp->f, Logppp, "%ux %ux %s->%s ctlmap %lux/%lux flags %ux mtu %d mru %d\n", ppp, p->proto, snames[p->state], snames[state], ppp->rctlmap, ppp->xctlmap, p->flags, ppp->mtu, ppp->mru); if(p->proto == Plcp) { if(state == Sopened) setphase(ppp, Pauth); else if(state == Sclosed) setphase(ppp, Pdead); else if(p->state == Sopened) setphase(ppp, Plink); } if(p->proto == Pipcp && state == Sopened && validv4(ppp->local) && validv4(ppp->remote)){ netlog(ppp->f, Logppp, "pppnewstate: local %I remote %I\n", ppp->local, ppp->remote); ipmove(pppdns[0], ppp->dns1); ipmove(pppdns[1], ppp->dns2); ipconnect(ppp); /* if this is the only network, set up a default route */// if(ppp->ifc->link==nil) /* how??? */ setdefroute(ppp, ppp->remote); errlog(ppp, Enoerror); } p->state = state;} static voidremove(PPP *ppp){ free(ppp->ipcp); ppp->ipcp = 0; free(ppp->ctcp); ppp->ctcp = 0; free(ppp->lcp); ppp->lcp = 0; if (ppp->inbuf) { freeb(ppp->inbuf); ppp->inbuf = nil; } if (ppp->outbuf) { freeb(ppp->outbuf); ppp->outbuf = nil; } free(ppp);} voidpppclose(PPP *ppp){ hangup(ppp); remove(ppp);} static voiddumpblock(Block *b){ char x[256]; int i; for(i = 0; i < (sizeof(x)-1)/3 && b->rp+i < b->wp; i++) sprint(&x[3*i], "%2.2ux ", b->rp[i]); print("%s\n", x);} /* returns (protocol, information) */static intgetframe(PPP *ppp, Block **info){ uchar *p, *from, *to; int n, len, proto; ulong c; ushort fcs; Block *buf, *b; buf = ppp->inbuf; for(;;){ /* read till we hit a frame byte or run out of room */ for(p = buf->rp; buf->wp < buf->lim;){ for(; p < buf->wp; p++) if(*p == HDLC_frame) goto break2; len = buf->lim - buf->wp; n = 0; if(ppp->dchan != nil) n = kchanio(ppp->dchan, buf->wp, len, OREAD); netlog(ppp->f, Logppp, "ppp kchanio %d bytes\n", n); if(n <= 0){ buf->wp = buf->rp;// if(n < 0)// print("ppp kchanio(%s) returned %d: %r",// ppp->dchan->path->elem, n); *info = nil; return 0; } buf->wp += n; }break2: /* copy into block, undoing escapes, and caculating fcs */ fcs = PPP_initfcs; b = allocb(p - buf->rp); to = b->wp; for(from = buf->rp; from != p;){ c = *from++; if(c == HDLC_esc){ if(from == p) break; c = *from++ ^ 0x20; } else if((c < 0x20) && (ppp->rctlmap & (1 << c))) continue; *to++ = c; fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff]; } /* copy down what's left in buffer */ p++; memmove(buf->rp, p, buf->wp - p); n = p - buf->rp; buf->wp -= n; b->wp = to - 2; /* return to caller if checksum matches */ if(fcs == PPP_goodfcs){ if(b->rp[0] == PPP_addr && b->rp[1] == PPP_ctl) b->rp += 2; proto = *b->rp++; if((proto & 0x1) == 0) proto = (proto<<8) | *b->rp++; if(b->rp < b->wp){ ppp->in.bytes += n; ppp->in.packets++; *info = b; return proto; } } else if(BLEN(b) > 0){ ppp->ifc->inerr++; ppp->in.discards++; netlog(ppp->f, Logppp, "len %d/%d cksum %ux (%ux %ux %ux %ux)\n", BLEN(b), BLEN(buf), fcs, b->rp[0], b->rp[1], b->rp[2], b->rp[3]); } freeblist(b); } *info = nil; return 0;} /* send a PPP frame */static Block *putframe(PPP *ppp, int proto, Block *b){ Block *buf; uchar *to, *from; ushort fcs; ulong ctlmap; int c; Block *bp; if(ppp->dchan == nil){ netlog(ppp->f, Logppp, "putframe: dchan down\n"); errlog(ppp, Ehungup); return b; } netlog(ppp->f, Logppp, "putframe %ux %d %d (%d bytes)\n", proto, b->rp[0], b->rp[1], BLEN(b)); ppp->out.packets++; if(proto == Plcp) ctlmap = 0xffffffff; else ctlmap = ppp->xctlmap; /* make sure we have head room */ if(b->rp - b->base < 4){ b = padblock(b, 4); b->rp += 4; } /* add in the protocol and address, we'd better have left room */ from = b->rp; *--from = proto; if(!(ppp->lcp->flags&Fpc) || proto > 0x100 || proto == Plcp) *--from = proto>>8; if(!(ppp->lcp->flags&Fac) || proto == Plcp){ *--from = PPP_ctl; *--from = PPP_addr; } qlock(&ppp->outlock); buf = ppp->outbuf; /* escape and checksum the body */ fcs = PPP_initfcs; to = buf->rp; *to++ = HDLC_frame; for(bp = b; bp; bp = bp->next){ if(bp != b) from = bp->rp; for(; from < bp->wp; from++){ c = *from; if(c == HDLC_frame || c == HDLC_esc || (c < 0x20 && ((1<<c) & ctlmap))){ *to++ = HDLC_esc; *to++ = c ^ 0x20; } else *to++ = c; fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff]; } } /* add on and escape the checksum */ fcs = ~fcs; c = fcs; if(c == HDLC_frame || c == HDLC_esc || (c < 0x20 && ((1<<c) & ctlmap))){ *to++ = HDLC_esc; *to++ = c ^ 0x20; } else *to++ = c; c = fcs>>8; if(c == HDLC_frame || c == HDLC_esc || (c < 0x20 && ((1<<c) & ctlmap))){ *to++ = HDLC_esc; *to++ = c ^ 0x20; } else *to++ = c; /* add frame marker and send */ *to++ = HDLC_frame; buf->wp = to; if(ppp->dchan == nil){ netlog(ppp->f, Logppp, "putframe: dchan down\n"); errlog(ppp, Ehungup); }else{ kchanio(ppp->dchan, buf->rp, BLEN(buf), OWRITE); ppp->out.bytes += BLEN(buf); } qunlock(&ppp->outlock); return b;} #define IPB2LCP(b) ((Lcpmsg*)((b)->wp-4)) static Block*alloclcp(int code, int id, int len){ Block *b; Lcpmsg *m; /* * leave room for header */ b = allocb(len); m = (Lcpmsg*)b->wp; m->code = code; m->id = id; b->wp += 4; return b;} static voidputao(Block *b, int type, int aproto, int alg){ *b->wp++ = type; *b->wp++ = 5; hnputs(b->wp, aproto); b->wp += 2; *b->wp++ = alg;} static voidputlo(Block *b, int type, ulong val){ *b->wp++ = type; *b->wp++ = 6; hnputl(b->wp, val); b->wp += 4;} static voidputv4o(Block *b, int type, Ipaddr val){ *b->wp++ = type;Lines 1–500 of 1656. Load more
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include <libcrypt.h> #include <kernel.h> #include "ip.h" #include "ppp.h" int nocompress; Ipaddr pppdns[2]; /* * Calculate FCS - rfc 1331 */ ushort fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; static char *snames[] = { "Sclosed", "Sclosing", "Sreqsent", "Sackrcvd", "Sacksent", "Sopened", }; static void init(PPP*); static void setphase(PPP*, int); static void pinit(PPP*, Pstate*); static void ppptimer(void*); static void ptimer(PPP*, Pstate*); static int getframe(PPP*, Block**); static Block* putframe(PPP*, int, Block*); static uchar* escapebyte(PPP*, ulong, uchar*, ushort*); static void config(PPP*, Pstate*, int); static int getopts(PPP*, Pstate*, Block*); static void rejopts(PPP*, Pstate*, Block*, int); static void newstate(PPP*, Pstate*, int); static void rcv(PPP*, Pstate*, Block*); static void getchap(PPP*, Block*); static void getpap(PPP*, Block*); static void sendpap(PPP*); static void getlqm(PPP*, Block*); static void putlqm(PPP*); static void hangup(PPP*); static void remove(PPP*); static int validv4(Ipaddr); static void invalidate(Ipaddr); static void ipconnect(PPP *); static void setdefroute(PPP *, Ipaddr); static void printopts(PPP *, Pstate*, Block*, int); static void sendtermreq(PPP*, Pstate*); static void errlog(PPP *ppp, char *err) { int n; char msg[64]; n = snprint(msg, sizeof(msg), "%s\n", err); qproduce(ppp->ifc->conv->eq, msg, n); } static void init(PPP* ppp) { if(ppp->inbuf == nil){ ppp->inbuf = allocb(4096); ppp->outbuf = allocb(4096); ppp->lcp = malloc(sizeof(Pstate)); ppp->ipcp = malloc(sizeof(Pstate)); if(ppp->lcp == nil || ppp->ipcp == nil) error("ppp init: malloc"); ppp->lcp->proto = Plcp; ppp->lcp->state = Sclosed; ppp->ipcp->proto = Pipcp; ppp->ipcp->state = Sclosed; kproc("ppptimer", ppptimer, ppp, KPDUPPG|KPDUPFDG); } pinit(ppp, ppp->lcp); setphase(ppp, Plink); } static void setphase(PPP *ppp, int phase) { int oldphase; oldphase = ppp->phase; ppp->phase = phase; switch(phase){ default: panic("ppp: unknown phase %d", phase); case Pdead: /* restart or exit? */ pinit(ppp, ppp->lcp); setphase(ppp, Plink); break; case Plink: /* link down */ switch(oldphase) { case Pnet: newstate(ppp, ppp->ipcp, Sclosed); } break; case Pauth: if(ppp->usepap) sendpap(ppp); else if(!ppp->usechap) setphase(ppp, Pnet); break; case Pnet: pinit(ppp, ppp->ipcp); break; case Pterm: /* what? */ break; } } static void pinit(PPP *ppp, Pstate *p) { p->timeout = 0; switch(p->proto){ case Plcp: ppp->magic = TK2MS(MACHP(0)->ticks); ppp->xctlmap = 0xffffffff; ppp->period = 0; p->optmask = 0xffffffff; ppp->rctlmap = 0; ppp->ipcp->state = Sclosed; ppp->ipcp->optmask = 0xffffffff; /* quality goo */ ppp->timeout = 0; memset(&ppp->in, 0, sizeof(ppp->in)); memset(&ppp->out, 0, sizeof(ppp->out)); memset(&ppp->pin, 0, sizeof(ppp->pin)); memset(&ppp->pout, 0, sizeof(ppp->pout)); memset(&ppp->sin, 0, sizeof(ppp->sin)); break; case Pipcp: if(ppp->localfrozen == 0) invalidate(ppp->local); if(ppp->remotefrozen == 0) invalidate(ppp->remote); p->optmask = 0xffffffff; ppp->ctcp = compress_init(ppp->ctcp); ppp->usedns = 3; invalidate(ppp->dns1); invalidate(ppp->dns2); break; } p->confid = p->rcvdconfid = -1; config(ppp, p, 1); newstate(ppp, p, Sreqsent); } /* * change protocol to a new state. */ static void newstate(PPP *ppp, Pstate *p, int state) { netlog(ppp->f, Logppp, "%ux %ux %s->%s ctlmap %lux/%lux flags %ux mtu %d mru %d\n", ppp, p->proto, snames[p->state], snames[state], ppp->rctlmap, ppp->xctlmap, p->flags, ppp->mtu, ppp->mru); if(p->proto == Plcp) { if(state == Sopened) setphase(ppp, Pauth); else if(state == Sclosed) setphase(ppp, Pdead); else if(p->state == Sopened) setphase(ppp, Plink); } if(p->proto == Pipcp && state == Sopened && validv4(ppp->local) && validv4(ppp->remote)){ netlog(ppp->f, Logppp, "pppnewstate: local %I remote %I\n", ppp->local, ppp->remote); ipmove(pppdns[0], ppp->dns1); ipmove(pppdns[1], ppp->dns2); ipconnect(ppp); /* if this is the only network, set up a default route */ // if(ppp->ifc->link==nil) /* how??? */ setdefroute(ppp, ppp->remote); errlog(ppp, Enoerror); } p->state = state; } static void remove(PPP *ppp) { free(ppp->ipcp); ppp->ipcp = 0; free(ppp->ctcp); ppp->ctcp = 0; free(ppp->lcp); ppp->lcp = 0; if (ppp->inbuf) { freeb(ppp->inbuf); ppp->inbuf = nil; } if (ppp->outbuf) { freeb(ppp->outbuf); ppp->outbuf = nil; } free(ppp); } void pppclose(PPP *ppp) { hangup(ppp); remove(ppp); } static void dumpblock(Block *b) { char x[256]; int i; for(i = 0; i < (sizeof(x)-1)/3 && b->rp+i < b->wp; i++) sprint(&x[3*i], "%2.2ux ", b->rp[i]); print("%s\n", x); } /* returns (protocol, information) */ static int getframe(PPP *ppp, Block **info) { uchar *p, *from, *to; int n, len, proto; ulong c; ushort fcs; Block *buf, *b; buf = ppp->inbuf; for(;;){ /* read till we hit a frame byte or run out of room */ for(p = buf->rp; buf->wp < buf->lim;){ for(; p < buf->wp; p++) if(*p == HDLC_frame) goto break2; len = buf->lim - buf->wp; n = 0; if(ppp->dchan != nil) n = kchanio(ppp->dchan, buf->wp, len, OREAD); netlog(ppp->f, Logppp, "ppp kchanio %d bytes\n", n); if(n <= 0){ buf->wp = buf->rp; // if(n < 0) // print("ppp kchanio(%s) returned %d: %r", // ppp->dchan->path->elem, n); *info = nil; return 0; } buf->wp += n; } break2: /* copy into block, undoing escapes, and caculating fcs */ fcs = PPP_initfcs; b = allocb(p - buf->rp); to = b->wp; for(from = buf->rp; from != p;){ c = *from++; if(c == HDLC_esc){ if(from == p) break; c = *from++ ^ 0x20; } else if((c < 0x20) && (ppp->rctlmap & (1 << c))) continue; *to++ = c; fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff]; } /* copy down what's left in buffer */ p++; memmove(buf->rp, p, buf->wp - p); n = p - buf->rp; buf->wp -= n; b->wp = to - 2; /* return to caller if checksum matches */ if(fcs == PPP_goodfcs){ if(b->rp[0] == PPP_addr && b->rp[1] == PPP_ctl) b->rp += 2; proto = *b->rp++; if((proto & 0x1) == 0) proto = (proto<<8) | *b->rp++; if(b->rp < b->wp){ ppp->in.bytes += n; ppp->in.packets++; *info = b; return proto; } } else if(BLEN(b) > 0){ ppp->ifc->inerr++; ppp->in.discards++; netlog(ppp->f, Logppp, "len %d/%d cksum %ux (%ux %ux %ux %ux)\n", BLEN(b), BLEN(buf), fcs, b->rp[0], b->rp[1], b->rp[2], b->rp[3]); } freeblist(b); } *info = nil; return 0; } /* send a PPP frame */ static Block * putframe(PPP *ppp, int proto, Block *b) { Block *buf; uchar *to, *from; ushort fcs; ulong ctlmap; int c; Block *bp; if(ppp->dchan == nil){ netlog(ppp->f, Logppp, "putframe: dchan down\n"); errlog(ppp, Ehungup); return b; } netlog(ppp->f, Logppp, "putframe %ux %d %d (%d bytes)\n", proto, b->rp[0], b->rp[1], BLEN(b)); ppp->out.packets++; if(proto == Plcp) ctlmap = 0xffffffff; else ctlmap = ppp->xctlmap; /* make sure we have head room */ if(b->rp - b->base < 4){ b = padblock(b, 4); b->rp += 4; } /* add in the protocol and address, we'd better have left room */ from = b->rp; *--from = proto; if(!(ppp->lcp->flags&Fpc) || proto > 0x100 || proto == Plcp) *--from = proto>>8; if(!(ppp->lcp->flags&Fac) || proto == Plcp){ *--from = PPP_ctl; *--from = PPP_addr; } qlock(&ppp->outlock); buf = ppp->outbuf; /* escape and checksum the body */ fcs = PPP_initfcs; to = buf->rp; *to++ = HDLC_frame; for(bp = b; bp; bp = bp->next){ if(bp != b) from = bp->rp; for(; from < bp->wp; from++){ c = *from; if(c == HDLC_frame || c == HDLC_esc || (c < 0x20 && ((1<<c) & ctlmap))){ *to++ = HDLC_esc; *to++ = c ^ 0x20; } else *to++ = c; fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff]; } } /* add on and escape the checksum */ fcs = ~fcs; c = fcs; if(c == HDLC_frame || c == HDLC_esc || (c < 0x20 && ((1<<c) & ctlmap))){ *to++ = HDLC_esc; *to++ = c ^ 0x20; } else *to++ = c; c = fcs>>8; if(c == HDLC_frame || c == HDLC_esc || (c < 0x20 && ((1<<c) & ctlmap))){ *to++ = HDLC_esc; *to++ = c ^ 0x20; } else *to++ = c; /* add frame marker and send */ *to++ = HDLC_frame; buf->wp = to; if(ppp->dchan == nil){ netlog(ppp->f, Logppp, "putframe: dchan down\n"); errlog(ppp, Ehungup); }else{ kchanio(ppp->dchan, buf->rp, BLEN(buf), OWRITE); ppp->out.bytes += BLEN(buf); } qunlock(&ppp->outlock); return b; } #define IPB2LCP(b) ((Lcpmsg*)((b)->wp-4)) static Block* alloclcp(int code, int id, int len) { Block *b; Lcpmsg *m; /* * leave room for header */ b = allocb(len); m = (Lcpmsg*)b->wp; m->code = code; m->id = id; b->wp += 4; return b; } static void putao(Block *b, int type, int aproto, int alg) { *b->wp++ = type; *b->wp++ = 5; hnputs(b->wp, aproto); b->wp += 2; *b->wp++ = alg; } static void putlo(Block *b, int type, ulong val) { *b->wp++ = type; *b->wp++ = 6; hnputl(b->wp, val); b->wp += 4; } static void putv4o(Block *b, int type, Ipaddr val) { *b->wp++ = type;