📄 ppp.c
字号:
if(c->state == Cauthok) { setphase(ppp, Pnet); } else { /* restart chapp negotiation */ chapinit(ppp); } break; case Csuccess: netlog("ppp: chap succeeded\n"); break; case Cfailure: netlog("ppp: chap failed\n"); break; default: syslog(0, LOG, "chap code %d?\n", m->code); break; } qunlock(ppp); freeb(b);}static voidputpaprequest(PPP *ppp){ Block *b; Lcpmsg *m; Chap *c; int len, nlen, slen; getauth(ppp); c = ppp->chap; c->id++; netlog("PPP: pap: send authreq %d %s %s\n", c->id, ppp->chapname, "****"); nlen = strlen(ppp->chapname); slen = strlen(ppp->secret); len = 4 + 1 + nlen + 1 + slen; b = alloclcp(Pauthreq, c->id, len, &m); *b->wptr++ = nlen; memmove(b->wptr, ppp->chapname, nlen); b->wptr += nlen; *b->wptr++ = slen; memmove(b->wptr, ppp->secret, slen); b->wptr += slen; hnputs(m->len, len); putframe(ppp, Ppasswd, b); freeb(b);}static voidpapinit(PPP *ppp){ ppp->chap->id = 0; putpaprequest(ppp);}static voidgetpap(PPP *ppp, Block *b){ Lcpmsg *m; int len; m = (Lcpmsg*)b->rptr; len = 4; if(BLEN(b) < 4 || BLEN(b) < (len = nhgets(m->len))){ syslog(0, LOG, "short pap message (%ld < %d)", BLEN(b), len); freeb(b); return; } if(len < sizeof(Lcpmsg)) m->data[0] = 0; qlock(ppp); switch(m->code){ case Pauthreq: netlog("PPP: pap auth request, not supported\n"); break; case Pauthack: if(ppp->phase == Pauth && ppp->chap->proto == APpasswd && m->id <= ppp-> chap->id){ netlog("PPP: pap succeeded\n"); setphase(ppp, Pnet); } break; case Pauthnak: if(ppp->phase == Pauth && ppp->chap->proto == APpasswd && m->id <= ppp-> chap->id){ netlog("PPP: pap failed (%d:%.*s)\n", m->data[0], m->data[0], (char*)m->data+1); terminate(ppp, 0); } break; default: netlog("PPP: unknown pap messsage %d\n", m->code); } qunlock(ppp); freeb(b);}static voidprintopts(Pstate *p, Block *b, int send){ Lcpmsg *m; Lcpopt *o; int proto, x, period; uchar *cp; char *code, *dir; m = (Lcpmsg*)b->rptr; switch(m->code) { default: code = "<unknown>"; break; case Lconfreq: code = "confrequest"; break; case Lconfack: code = "confack"; break; case Lconfnak: code = "confnak"; break; case Lconfrej: code = "confreject"; break; } if(send) dir = "send"; else dir = "recv"; netlog("ppp: %s %s: id=%d\n", dir, code, m->id); for(cp = m->data; cp < b->wptr; cp += o->len){ o = (Lcpopt*)cp; if(cp + o->len > b->wptr){ netlog("\tbad option length %ux\n", o->type); return; } switch(p->proto){ case Plcp: switch(o->type){ default: netlog("\tunknown %d len=%d\n", o->type, o->len); break; case Omtu: netlog("\tmtu = %d\n", nhgets(o->data)); break; case Octlmap: netlog("\tctlmap = %ux\n", nhgetl(o->data)); break; case Oauth: netlog("\tauth = %ux", nhgetl(o->data)); proto = nhgets(o->data); switch(proto) { default: netlog("unknown auth proto %d\n", proto); break; case Ppasswd: netlog("password\n"); break; case Pchap: netlog("chap %ux\n", o->data[2]); break; } break; case Oquality: proto = nhgets(o->data); switch(proto) { default: netlog("\tunknown quality proto %d\n", proto); break; case Plqm: x = nhgetl(o->data+2)*10; period = (x+Period-1)/Period; netlog("\tlqm period = %d\n", period); break; } case Omagic: netlog("\tmagic = %ux\n", nhgetl(o->data)); break; case Opc: netlog("\tprotocol compress\n"); break; case Oac: netlog("\taddr compress\n"); break; } break; case Pccp: switch(o->type){ default: netlog("\tunknown %d len=%d\n", o->type, o->len); break; case Ocoui: netlog("\tOUI\n"); break; case Ocstac: netlog("\tstac LZS\n"); break; case Ocmppc: netlog("\tMicrosoft PPC len=%d %ux\n", o->len, nhgetl(o->data)); break; case Octhwack: netlog("\tThwack\n"); break; } break; case Pecp: switch(o->type){ default: netlog("\tunknown %d len=%d\n", o->type, o->len); break; case Oeoui: netlog("\tOUI\n"); break; case Oedese: netlog("\tDES\n"); break; } break; case Pipcp: switch(o->type){ default: netlog("\tunknown %d len=%d\n", o->type, o->len); break; case Oipaddrs: netlog("\tip addrs - deprecated\n"); break; case Oipcompress: netlog("\tip compress\n"); break; case Oipaddr: netlog("\tip addr %V\n", o->data); break; case Oipdns: netlog("\tdns addr %V\n", o->data); break; case Oipwins: netlog("\twins addr %V\n", o->data); break; case Oipdns2: netlog("\tdns2 addr %V\n", o->data); break; case Oipwins2: netlog("\twins2 addr %V\n", o->data); break; } break; } }}static voidsendtermreq(PPP *ppp, Pstate *p){ Block *b; Lcpmsg *m; p->termid = ++(p->id); b = alloclcp(Ltermreq, p->termid, 4, &m); hnputs(m->len, 4); putframe(ppp, p->proto, b); freeb(b); newstate(ppp, p, Sclosing);}static voidsendechoreq(PPP *ppp, Pstate *p){ Block *b; Lcpmsg *m; p->termid = ++(p->id); b = alloclcp(Lechoreq, p->id, 4, &m); hnputs(m->len, 4); putframe(ppp, p->proto, b); freeb(b);}enum{ CtrlD = 0x4, CtrlE = 0x5, CtrlO = 0xf, Cr = 13, View = 0x80,};int conndone;static voidxfer(int fd){ int i, n; uchar xbuf[128]; for(;;) { n = read(fd, xbuf, sizeof(xbuf)); if(n < 0) break; if(conndone) break; for(i = 0; i < n; i++) if(xbuf[i] == Cr) xbuf[i] = ' '; write(1, xbuf, n); } close(fd);}static intreadcr(int fd, char *buf, int nbuf){ char c; int n, tot; tot = 0; while((n=read(fd, &c, 1)) == 1){ if(c == '\n'){ buf[tot] = 0; return tot; } buf[tot++] = c; if(tot == nbuf) sysfatal("line too long in readcr"); } return n;}static voidconnect(int fd, int cfd){ int n, ctl; char xbuf[128]; if (chatfile) { int chatfd, lineno, nb; char *buf, *p, *s, response[128]; Dir *dir; if ((chatfd = open(chatfile, OREAD)) < 0) sysfatal("cannot open %s: %r", chatfile); if ((dir = dirfstat(chatfd)) == nil) sysfatal("cannot fstat %s: %r",chatfile); buf = (char *)malloc(dir->length + 1); assert(buf); if ((nb = read(chatfd, buf, dir->length)) < 0) sysfatal("cannot read chatfile %s: %r", chatfile); assert(nb == dir->length); buf[dir->length] = '\0'; free(dir); close(chatfd); p = buf; lineno = 0; for(;;) { char *_args[3]; if ((s = strchr(p, '\n')) == nil) break; *s++ = '\0'; lineno++; if (*p == '#') { p = s; continue; } if (tokenize(p, _args, 3) != 2) sysfatal("invalid line %d (line expected: 'send' 'expect')", lineno); if (debug) print("sending %s, expecting %s\n", _args[0], _args[1]); if(strlen(_args[0])){ nb = fprint(fd, "%s\r", _args[0]); assert(nb > 0); } if (strlen(_args[1]) > 0) { if ((nb = readcr(fd, response, sizeof response-1)) < 0) sysfatal("cannot read response from: %r"); if (debug) print("response %s\n", response); if (nb == 0) sysfatal("eof on input?\n"); if (cistrstr(response, _args[1]) == nil) sysfatal("expected %s, got %s\n", _args[1], response); } p = s; } free(buf); return; } print("Connect to file system now, type ctrl-d when done.\n"); print("...(Use the view or down arrow key to send a break)\n"); print("...(Use ctrl-e to set even parity or ctrl-o for odd)\n"); ctl = open("/dev/consctl", OWRITE); if(ctl < 0) sysfatal("opening consctl"); fprint(ctl, "rawon"); fd = dup(fd, -1); conndone = 0; switch(rfork(RFPROC|RFMEM|RFNOWAIT)){ case -1: sysfatal("forking xfer"); case 0: xfer(fd); _exits(nil); } for(;;){ read(0, xbuf, 1); switch(xbuf[0]&0xff) { case CtrlD: /* done */ conndone = 1; close(ctl); print("\n"); return; case CtrlE: /* set even parity */ fprint(cfd, "pe"); break; case CtrlO: /* set odd parity */ fprint(cfd, "po"); break; case View: /* send a break */ fprint(cfd, "k500"); break; default: n = write(fd, xbuf, 1); if(n < 0) { errstr(xbuf, sizeof(xbuf)); conndone = 1; close(ctl); print("[remote write error (%s)]\n", xbuf); return; } } }}int interactive;voidusage(void){ fprint(2, "usage: ppp [-cCdfPSu] [-b baud] [-k keyspec] [-m mtu] [-p dev] [-s username] [-x netmntpt] [-t modemcmd] [local-addr [remote-addr]]\n"); exits("usage");}voidmain(int argc, char **argv){ int mtu, baud, framing, user, mediain, mediaout, cfd; Ipaddr ipaddr, remip; char *dev, *modemcmd; char net[128]; PPP *ppp; char buf[128]; rfork(RFREND|RFNOTEG|RFNAMEG); fmtinstall('I', eipfmt); fmtinstall('V', eipfmt); fmtinstall('E', eipfmt); dev = nil; invalidate(ipaddr); invalidate(remip); mtu = Defmtu; baud = 0; framing = 0; setnetmtpt(net, sizeof(net), nil); user = 0; modemcmd = nil; ARGBEGIN{ case 'b': baud = atoi(EARGF(usage())); if(baud < 0) baud = 0; break; case 'c': nocompress = 1; break; case 'C': noipcompress = 1; break; case 'd': debug++; break; case 'f': framing = 1; break; case 'F': pppframing = 0; break; case 'k': keyspec = EARGF(usage()); break; case 'm': mtu = atoi(EARGF(usage())); if(mtu < Minmtu) mtu = Minmtu; if(mtu > Maxmtu) mtu = Maxmtu; break; case 'M': chatfile = EARGF(usage()); break; case 'p': dev = EARGF(usage()); break; case 'P': primary = 1; break; case 'S': server = 1; break; case 't': modemcmd = EARGF(usage()); break; case 'u': user = 1; break; case 'x': setnetmtpt(net, sizeof net, EARGF(usage())); break; default: fprint(2, "unknown option %c\n", ARGC()); usage(); }ARGEND; switch(argc){ case 2: parseip(remip, argv[1]); case 1: parseip(ipaddr, argv[0]); case 0: break; default: usage(); } nip = nipifcs(net); if(nip == 0 && !server) primary = 1; if(dev != nil){ mediain = open(dev, ORDWR); if(mediain < 0){ if(strchr(dev, '!')){ if((mediain = dial(dev, 0, 0, &cfd)) == -1){ fprint(2, "ppp: couldn't dial %s: %r\n", dev); exits(dev); } } else { fprint(2, "ppp: couldn't open %s\n", dev); exits(dev); } } else { snprint(buf, sizeof buf, "%sctl", dev); cfd = open(buf, ORDWR); } if(cfd > 0){ if(baud) fprint(cfd, "b%d", baud); fprint(cfd, "m1"); /* cts/rts flow control (and fifo's) on */ fprint(cfd, "q64000"); /* increase q size to 64k */ fprint(cfd, "n1"); /* nonblocking writes on */ fprint(cfd, "r1"); /* rts on */ fprint(cfd, "d1"); /* dtr on */ fprint(cfd, "c1"); /* dcdhup on */ if(user || chatfile) connect(mediain, cfd); close(cfd); } else { if(user || chatfile) connect(mediain, -1); } mediaout = mediain; } else { mediain = open("/fd/0", OREAD); if(mediain < 0){ fprint(2, "ppp: couldn't open /fd/0\n"); exits("/fd/0"); } mediaout = open("/fd/1", OWRITE); if(mediaout < 0){ fprint(2, "ppp: couldn't open /fd/0\n"); exits("/fd/1"); } } if(modemcmd != nil && mediaout >= 0) fprint(mediaout, "%s\r", modemcmd); ppp = mallocz(sizeof(*ppp), 1); pppopen(ppp, mediain, mediaout, net, ipaddr, remip, mtu, framing); /* wait until ip is configured */ rendezvous((void*)Rmagic, 0); if(primary){ /* create a /net/ndb entry */ putndb(ppp, net); } exits(0);}voidnetlog(char *fmt, ...){ va_list arg; char *m; static long start; long now; if(debug == 0) return; now = time(0); if(start == 0) start = now; va_start(arg, fmt); m = vsmprint(fmt, arg); fprint(2, "%ld %s", now-start, m); free(m); va_end(arg);}/* * return non-zero if this is a valid v4 address */static intvalidv4(Ipaddr addr){ return memcmp(addr, v4prefix, IPv4off) == 0 && memcmp(addr, v4prefix, IPaddrlen) != 0;}static voidinvalidate(Ipaddr addr){ ipmove(addr, IPnoaddr);}/* * return number of networks */static intnipifcs(char *net){ static Ipifc *ifc; Ipifc *nifc; Iplifc *lifc; int n; n = 0; ifc = readipifc(net, ifc, -1); for(nifc = ifc; nifc != nil; nifc = nifc->next) for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next) n++; return n;}/* * make an ndb entry and put it into /net/ndb for the servers to see */static voidputndb(PPP *ppp, char *net){ char buf[1024]; char file[64]; char *p, *e; int fd; e = buf + sizeof(buf); p = buf; p = seprint(p, e, "ip=%I ipmask=255.255.255.255 ipgw=%I\n", ppp->local, ppp->remote); if(validv4(ppp->dns[0])) p = seprint(p, e, "\tdns=%I\n", ppp->dns[0]); if(validv4(ppp->dns[1])) p = seprint(p, e, "\tdns=%I\n", ppp->dns[1]); if(validv4(ppp->wins[0])) p = seprint(p, e, "\twins=%I\n", ppp->wins[0]); if(validv4(ppp->wins[1])) p = seprint(p, e, "\twins=%I\n", ppp->wins[1]); seprint(file, file+sizeof file, "%s/ndb", net); fd = open(file, OWRITE); if(fd < 0) return; write(fd, buf, p-buf); close(fd); seprint(file, file+sizeof file, "%s/cs", net); fd = open(file, OWRITE); write(fd, "refresh", 7); close(fd); seprint(file, file+sizeof file, "%s/dns", net); fd = open(file, OWRITE); write(fd, "refresh", 7); close(fd);}static voidgetauth(PPP *ppp){ UserPasswd *up; if(*ppp->chapname) return; up = auth_getuserpasswd(auth_getkey,"proto=pass service=ppp %s", keyspec); if(up != nil){ strcpy(ppp->chapname, up->user); strcpy(ppp->secret, up->passwd); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -