2 * ppp - point-to-point protocol, rfc1331
16 static int nocompress;
17 static int pppframing = 1;
18 static int noipcompress;
21 static int nip; /* number of ip interfaces */
22 static int dying; /* flag to signal to all threads its time to go */
23 static int primary; /* this is the primary IP interface */
24 static char *chatfile;
36 * Calculate FCS - rfc 1331
40 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
41 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
42 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
43 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
44 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
45 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
46 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
47 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
48 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
49 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
50 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
51 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
52 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
53 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
54 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
55 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
56 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
57 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
58 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
59 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
60 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
61 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
62 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
63 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
64 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
65 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
66 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
67 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
68 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
69 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
70 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
71 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
74 static char *snames[] =
84 static void authtimer(PPP*);
85 static void chapinit(PPP*);
86 static void config(PPP*, Pstate*, int);
87 static uchar* escapeuchar(PPP*, ulong, uchar*, ushort*);
88 static void getchap(PPP*, Block*);
89 static Block* getframe(PPP*, int*);
90 static void getlqm(PPP*, Block*);
91 static int getopts(PPP*, Pstate*, Block*);
92 static void getpap(PPP*, Block*);
93 static void init(PPP*);
94 static void invalidate(Ipaddr);
95 static void ipinproc(PPP*);
96 static char* ipopen(PPP*);
97 static void mediainproc(PPP*);
98 static void newstate(PPP*, Pstate*, int);
99 static int nipifcs(char*);
100 static void papinit(PPP*);
101 static void pinit(PPP*, Pstate*);
102 static void ppptimer(PPP*);
103 static void printopts(Pstate*, Block*, int);
104 static void ptimer(PPP*, Pstate*);
105 static int putframe(PPP*, int, Block*);
106 static void putlqm(PPP*);
107 static void putndb(PPP*, char*);
108 static void putpaprequest(PPP*);
109 static void rcv(PPP*, Pstate*, Block*);
110 static void rejopts(PPP*, Pstate*, Block*, int);
111 static void sendechoreq(PPP*, Pstate*);
112 static void sendtermreq(PPP*, Pstate*);
113 static void setphase(PPP*, int);
114 static void terminate(PPP*, int);
115 static int validv4(Ipaddr);
116 static void dmppkt(char *s, uchar *a, int na);
117 static void getauth(PPP*);
120 pppopen(PPP *ppp, int mediain, int mediaout, char *net,
121 Ipaddr ipaddr, Ipaddr remip,
122 int mtu, int framing)
126 invalidate(ppp->remote);
127 invalidate(ppp->local);
128 invalidate(ppp->curremote);
129 invalidate(ppp->curlocal);
130 invalidate(ppp->dns[0]);
131 invalidate(ppp->dns[1]);
132 invalidate(ppp->wins[0]);
133 invalidate(ppp->wins[1]);
135 ppp->mediain = mediain;
136 ppp->mediaout = mediaout;
138 ipmove(ppp->remote, remip);
139 ppp->remotefrozen = 1;
142 ipmove(ppp->local, ipaddr);
143 ppp->localfrozen = 1;
147 ppp->framing = framing;
151 switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
153 sysfatal("forking mediainproc");
164 if(ppp->inbuf == nil){
165 ppp->inbuf = allocb(4096);
166 if(ppp->inbuf == nil)
169 ppp->outbuf = allocb(4096);
170 if(ppp->outbuf == nil)
173 ppp->lcp = mallocz(sizeof(*ppp->lcp), 1);
176 ppp->lcp->proto = Plcp;
177 ppp->lcp->state = Sclosed;
179 ppp->ccp = mallocz(sizeof(*ppp->ccp), 1);
182 ppp->ccp->proto = Pccp;
183 ppp->ccp->state = Sclosed;
185 ppp->ipcp = mallocz(sizeof(*ppp->ipcp), 1);
188 ppp->ipcp->proto = Pipcp;
189 ppp->ipcp->state = Sclosed;
191 ppp->chap = mallocz(sizeof(*ppp->chap), 1);
194 ppp->chap->proto = APmschap;
195 ppp->chap->state = Cunauth;
196 auth_freechal(ppp->chap->cs);
199 switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
201 sysfatal("forking ppptimer");
208 ppp->ctcp = compress_init(ppp->ctcp);
209 pinit(ppp, ppp->lcp);
210 setphase(ppp, Plink);
214 setphase(PPP *ppp, int phase)
218 oldphase = ppp->phase;
223 sysfatal("ppp: unknown phase %d", phase);
225 /* restart or exit? */
226 pinit(ppp, ppp->lcp);
227 setphase(ppp, Plink);
233 auth_freechal(ppp->chap->cs);
235 ppp->chap->state = Cunauth;
238 auth_freechal(ppp->chap->cs);
240 ppp->chap->state = Cunauth;
241 newstate(ppp, ppp->ccp, Sclosed);
242 newstate(ppp, ppp->ipcp, Sclosed);
248 else if(ppp->chap->proto == APpasswd)
254 pinit(ppp, ppp->ccp);
255 pinit(ppp, ppp->ipcp);
264 pinit(PPP *ppp, Pstate *p)
270 ppp->magic = truerand();
271 ppp->xctlmap = 0xffffffff;
273 p->optmask = 0xffffffff;
275 p->optmask &= ~(Fauth|Fmtu);
277 ppp->ipcp->state = Sclosed;
278 ppp->ipcp->optmask = 0xffffffff;
284 memset(&ppp->in, 0, sizeof(ppp->in));
285 memset(&ppp->out, 0, sizeof(ppp->out));
286 memset(&ppp->pin, 0, sizeof(ppp->pin));
287 memset(&ppp->pout, 0, sizeof(ppp->pout));
288 memset(&ppp->sin, 0, sizeof(ppp->sin));
296 if(ppp->ctype != nil)
297 (*ppp->ctype->fini)(ppp->cstate);
303 (*ppp->unctype->fini)(ppp->uncstate);
308 p->optmask = 0xffffffff;
309 ppp->ctcp = compress_init(ppp->ctcp);
312 p->confid = p->rcvdconfid = -1;
314 newstate(ppp, p, Sreqsent);
318 * change protocol to a new state.
321 newstate(PPP *ppp, Pstate *p, int state)
325 netlog("ppp: %ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld\n",
326 p->proto, snames[p->state], snames[state], ppp->rctlmap,
327 ppp->xctlmap, p->flags,
329 syslog(0, "ppp", "%ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld",
330 p->proto, snames[p->state], snames[state], ppp->rctlmap,
331 ppp->xctlmap, p->flags,
334 if(p->proto == Plcp) {
336 setphase(ppp, noauth? Pnet : Pauth);
337 else if(state == Sclosed)
338 setphase(ppp, Pdead);
339 else if(p->state == Sopened)
340 setphase(ppp, Plink);
343 if(p->proto == Pccp && state == Sopened) {
345 (*ppp->unctype->fini)(ppp->uncstate);
348 if(p->optmask & Fcmppc) {
349 ppp->unctype = &uncmppc;
350 ppp->uncstate = (*uncmppc.init)(ppp);
352 if(p->optmask & Fcthwack){
353 ppp->unctype = &uncthwack;
354 ppp->uncstate = (*uncthwack.init)(ppp);
358 if(p->proto == Pipcp && state == Sopened) {
359 if(server && !noauth && ppp->chap->state != Cauthok)
370 /* returns (protocol, information) */
372 getframe(PPP *ppp, int *protop)
374 uchar *p, *from, *to;
381 if(ppp->framing == 0) {
382 /* assume data is already framed */
384 len = b->lim - b->wptr;
385 n = read(ppp->mediain, b->wptr, len);
386 dmppkt("RX", b->wptr, n);
387 if(n <= 0 || n == len){
394 /* should probably copy to another block if small */
396 if(pppframing && b->rptr[0] == PPP_addr && b->rptr[1] == PPP_ctl)
399 if((proto & 0x1) == 0)
400 proto = (proto<<8) | *b->rptr++;
402 if(b->rptr >= b->wptr){
410 netlog("getframe 0x%x\n", proto);
416 /* read till we hit a frame uchar or run out of room */
417 for(p = buf->rptr; buf->wptr < buf->lim;){
418 for(; p < buf->wptr; p++)
424 len = buf->lim - buf->wptr;
425 n = read(ppp->mediain, buf->wptr, len);
427 syslog(0, LOG, "medium read returns %d: %r", n);
428 buf->wptr = buf->rptr;
431 dmppkt("RX", buf->wptr, n);
435 /* copy into block, undoing escapes, and caculating fcs */
437 b = allocb(p - buf->rptr);
439 for(from = buf->rptr; from != p;){
445 } else if((c < 0x20) && (ppp->rctlmap & (1 << c)))
448 fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
451 /* copy down what's left in buffer */
453 memmove(buf->rptr, p, buf->wptr - p);
458 /* return to caller if checksum matches */
459 if(fcs == PPP_goodfcs){
460 if(b->rptr[0] == PPP_addr && b->rptr[1] == PPP_ctl)
463 if((proto & 0x1) == 0)
464 proto = (proto<<8) | *b->rptr++;
465 if(b->rptr < b->wptr){
469 netlog("getframe 0x%x\n", proto);
472 } else if(BLEN(b) > 0){
474 compress_error(ppp->ctcp);
476 netlog("ppp: discard len %ld/%ld cksum %ux (%ux %ux %ux %ux)\n",
477 BLEN(b), BLEN(buf), fcs, b->rptr[0],
478 b->rptr[1], b->rptr[2], b->rptr[3]);
485 /* send a PPP frame */
487 putframe(PPP *ppp, int proto, Block *b)
501 ctlmap = ppp->xctlmap;
503 /* make sure we have head room */
504 if(b->rptr - b->base < 4){
509 netlog("ppp: putframe 0x%ux %ld\n", proto, b->wptr-b->rptr);
511 /* add in the protocol and address, we'd better have left room */
514 if(!(ppp->lcp->flags&Fpc) || proto > 0x100 || proto == Plcp)
516 if(pppframing && (!(ppp->lcp->flags&Fac) || proto == Plcp)){
521 qlock(&ppp->outlock);
524 if(ppp->framing == 0) {
526 for(bp = b; bp; bp = bp->next){
529 memmove(to, from, bp->wptr-from);
533 /* escape and checksum the body */
537 /* add frame marker */
540 for(bp = b; bp; bp = bp->next){
543 for(; from < bp->wptr; from++){
545 if(c == HDLC_frame || c == HDLC_esc
546 || (c < 0x20 && ((1<<c) & ctlmap))){
551 fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
555 /* add on and escape the checksum */
558 if(c == HDLC_frame || c == HDLC_esc
559 || (c < 0x20 && ((1<<c) & ctlmap))){
565 if(c == HDLC_frame || c == HDLC_esc
566 || (c < 0x20 && ((1<<c) & ctlmap))){
572 /* add frame marker */
578 dmppkt("TX", buf->rptr, BLEN(buf));
579 if(write(ppp->mediaout, buf->rptr, BLEN(buf)) < 0){
580 qunlock(&ppp->outlock);
583 ppp->out.uchars += BLEN(buf);
585 qunlock(&ppp->outlock);
590 alloclcp(int code, int id, int len, Lcpmsg **mp)
596 * leave room for header
600 m = (Lcpmsg*)b->wptr;
611 putlo(Block *b, int type, ulong val)
615 hnputl(b->wptr, val);
620 putv4o(Block *b, int type, Ipaddr val)
624 v6tov4(b->wptr, val);
629 putso(Block *b, int type, ulong val)
633 hnputs(b->wptr, val);
638 puto(Block *b, int type)
645 * send configuration request
648 config(PPP *ppp, Pstate *p, int newid)
657 p->timeout = Timeout;
660 b = alloclcp(Lconfreq, id, 256, &m);
665 if(p->optmask & Fctlmap)
666 putlo(b, Octlmap, 0); /* we don't want anything escaped */
667 if(p->optmask & Fmagic)
668 putlo(b, Omagic, ppp->magic);
669 if(p->optmask & Fmtu)
670 putso(b, Omtu, ppp->mru);
671 if(p->optmask & Fauth) {
674 hnputs(b->wptr, Pchap);
676 *b->wptr++ = ppp->chap->proto;
684 if(p->optmask & Fcthwack)
686 else if(p->optmask & Fcmppc) {
696 if(p->optmask & Fipaddr)
697 {syslog(0, "ppp", "requesting %I", ppp->local);
698 putv4o(b, Oipaddr, ppp->local);
700 if(primary && (p->optmask & Fipdns))
701 putv4o(b, Oipdns, ppp->dns[0]);
702 if(primary && (p->optmask & Fipdns2))
703 putv4o(b, Oipdns2, ppp->dns[1]);
704 if(primary && (p->optmask & Fipwins))
705 putv4o(b, Oipwins, ppp->wins[0]);
706 if(primary && (p->optmask & Fipwins2))
707 putv4o(b, Oipwins2, ppp->wins[1]);
709 * don't ask for header compression while data compression is still pending.
710 * perhaps we should restart ipcp negotiation if compression negotiation fails.
712 if(!noipcompress && !ppp->ccp->optmask && (p->optmask & Fipcompress)) {
713 *b->wptr++ = Oipcompress;
715 hnputs(b->wptr, Pvjctcp);
717 *b->wptr++ = MAX_STATES-1;
722 hnputs(m->len, BLEN(b));
724 putframe(ppp, p->proto, b);
736 if(!validv4(ppp->local))
741 sprint(ip, "%I", ppp->local);
742 t = csipinfo(ppp->net, "ip", ip, av, 2);
744 for(nt = t; nt != nil; nt = nt->entry){
745 if(strcmp(nt->attr, "dns") == 0){
747 parseip(ppp->dns[ndns++], nt->val);
748 } else if(strcmp(nt->attr, "wins") == 0){
750 parseip(ppp->wins[nwins++], nt->val);
758 * parse configuration request, sends an ack or reject packet
760 * returns: -1 if request was syntacticly incorrect
761 * 0 if packet was accepted
762 * 1 if packet was rejected
765 getopts(PPP *ppp, Pstate *p, Block *b)
770 ulong rejecting, nacking, flags, proto, chapproto;
771 ulong mtu, ctlmap, period;
789 m = (Lcpmsg*)b->rptr;
790 repb = alloclcp(Lconfack, m->id, BLEN(b), &repm);
792 /* copy options into ack packet */
793 memmove(repm->data, m->data, b->wptr - m->data);
794 repb->wptr += b->wptr - m->data;
796 /* look for options we don't recognize or like */
797 for(cp = m->data; cp < b->wptr; cp += o->len){
799 if(cp + o->len > b->wptr || o->len==0){
801 netlog("ppp: bad option length %ux\n", o->type);
815 mtu = nhgets(o->data);
818 if(ppp->magic == nhgetl(o->data))
819 netlog("ppp: possible loop\n");
822 ctlmap = nhgetl(o->data);
825 proto = nhgets(o->data);
828 x = nhgetl(o->data+2)*10;
829 period = (x+Period-1)/Period;
832 proto = nhgets(o->data);
833 if(proto == Ppasswd && !server){
834 chapproto = APpasswd;
839 if(o->data[2] != APmd5 && o->data[2] != APmschap)
841 chapproto = o->data[2];
858 repb->wptr = repm->data;
859 repm->code = Lconfnak;
861 puto(repb, Octhwack);
872 if((x&0x41) == 0 || ppp->ctries++ > 5) {
874 * turn off requests as well - I don't think this
875 * is needed in the standard
877 p->optmask &= ~Fcmppc;
884 ppp->sendencrypted = (o->data[3]&0x40) == 0x40;
889 repb->wptr = repm->data;
890 repm->code = Lconfnak;
892 *repb->wptr++ = Ocmppc;
897 *repb->wptr++ = 0x41;
904 v4tov6(ipaddr, o->data);
905 if(!validv4(ppp->remote))
907 if(!validv4(ipaddr) && !rejecting){
908 /* other side requesting an address */
911 repb->wptr = repm->data;
912 repm->code = Lconfnak;
914 putv4o(repb, Oipaddr, ppp->remote);
934 v4tov6(ipaddr, o->data);
935 if(!validv4(ipaddr) && !rejecting){
936 /* other side requesting an address */
939 repb->wptr = repm->data;
940 repm->code = Lconfnak;
942 putv4o(repb, o->type, ap);
947 * don't compress tcp header if we've negotiated data compression.
948 * tcp header compression has very poor performance if there is an error.
950 proto = nhgets(o->data);
951 if(noipcompress || proto != Pvjctcp || ppp->ctype != nil)
953 if(compress_negotiate(ppp->ctcp, o->data+2) < 0)
955 flags |= Fipcompress;
961 /* come here if option is not recognized */
964 repb->wptr = repm->data;
965 repm->code = Lconfrej;
967 netlog("ppp: bad %ux option %d\n", p->proto, o->type);
968 memmove(repb->wptr, o, o->len);
969 repb->wptr += o->len;
972 /* permanent changes only after we know that we liked the packet */
973 if(!rejecting && !nacking){
976 ppp->period = period;
977 ppp->xctlmap = ctlmap;
984 ppp->chap->proto = chapproto;
988 if(ppp->ctype != nil){
989 (*ppp->ctype->fini)(ppp->cstate);
994 ppp->cstate = (*ctype->init)(ppp);
997 if(validv4(ipaddr) && ppp->remotefrozen == 0)
998 ipmove(ppp->remote, ipaddr);
1004 hnputs(repm->len, BLEN(repb));
1005 printopts(p, repb, 1);
1006 putframe(ppp, p->proto, repb);
1009 return rejecting || nacking;
1012 dmppkt(char *s, uchar *a, int na)
1020 for(i = 0; i < na; i++)
1021 fprint(2, " %.2ux", a[i]);
1026 dropoption(Pstate *p, Lcpopt *o)
1028 unsigned n = o->type;
1034 p->optmask &= ~Fipdns;
1037 p->optmask &= ~Fipwins;
1040 p->optmask &= ~Fipdns2;
1043 p->optmask &= ~Fipwins2;
1046 if(o->type < 8*sizeof(p->optmask))
1047 p->optmask &= ~(1<<o->type);
1053 * parse configuration rejection, just stop sending anything that they
1054 * don't like (except for ipcp address nak).
1057 rejopts(PPP *ppp, Pstate *p, Block *b, int code)
1061 uchar newip[IPaddrlen];
1063 /* just give up trying what the other side doesn't like */
1064 m = (Lcpmsg*)b->rptr;
1065 for(b->rptr = m->data; b->rptr < b->wptr; b->rptr += o->len){
1066 o = (Lcpopt*)b->rptr;
1067 if(b->rptr + o->len > b->wptr){
1068 netlog("ppp: bad roption length %ux\n", o->type);
1072 if(code == Lconfrej){
1074 netlog("ppp: %ux rejecting %d\n",
1083 ppp->rctlmap = nhgetl(o->data);
1086 /* don't allow client to request no auth */
1087 /* could try different auth protocol here */
1088 fprint(2, "ppp: can not reject CHAP\n");
1092 if(o->type < 8*sizeof(p->optmask))
1093 p->optmask &= ~(1<<o->type);
1107 syslog(0, "ppp", "rejected addr %I with %V", ppp->local, o->data);
1108 /* if we're a server, don't let other end change our addr */
1109 if(ppp->localfrozen){
1114 /* accept whatever server tells us */
1115 if(!validv4(ppp->local)){
1116 v4tov6(ppp->local, o->data);
1121 /* if he didn't like our addr, ask for a generic one */
1122 v4tov6(newip, o->data);
1123 if(!validv4(newip)){
1124 invalidate(ppp->local);
1128 /* if he gives us something different, use it anyways */
1129 v4tov6(ppp->local, o->data);
1133 if (!validv4(ppp->dns[0])){
1134 v4tov6(ppp->dns[0], o->data);
1138 v4tov6(newip, o->data);
1139 if(!validv4(newip)){
1140 invalidate(ppp->dns[0]);
1143 v4tov6(ppp->dns[0], o->data);
1147 if (!validv4(ppp->wins[0])){
1148 v4tov6(ppp->wins[0], o->data);
1152 v4tov6(newip, o->data);
1153 if(!validv4(newip)){
1154 invalidate(ppp->wins[0]);
1157 v4tov6(ppp->wins[0], o->data);
1161 if (!validv4(ppp->dns[1])){
1162 v4tov6(ppp->dns[1], o->data);
1166 v4tov6(newip, o->data);
1167 if(!validv4(newip)){
1168 invalidate(ppp->dns[1]);
1171 v4tov6(ppp->dns[1], o->data);
1175 if (!validv4(ppp->wins[1])){
1176 v4tov6(ppp->wins[1], o->data);
1180 v4tov6(newip, o->data);
1181 if(!validv4(newip)){
1182 invalidate(ppp->wins[1]);
1185 v4tov6(ppp->wins[1], o->data);
1199 * put a messages through the lcp or ipcp state machine. They are
1203 rcv(PPP *ppp, Pstate *p, Block *b)
1211 netlog("ppp: short lcp message\n");
1215 m = (Lcpmsg*)b->rptr;
1216 len = nhgets(m->len);
1218 netlog("ppp: short lcp message\n");
1223 netlog("ppp: %ux rcv %d len %ld id %d/%d/%d\n",
1224 p->proto, m->code, len, m->id, p->confid, p->id);
1226 if(p->proto != Plcp && ppp->lcp->state != Sopened){
1227 netlog("ppp: non-lcp with lcp not open\n");
1236 err = getopts(ppp, p, b);
1240 if(m->id == p->rcvdconfid)
1241 break; /* don't change state for duplicates */
1247 newstate(ppp, p, Sopened);
1253 newstate(ppp, p, Sacksent);
1255 newstate(ppp, p, Sreqsent);
1260 newstate(ppp, p, Sacksent);
1262 newstate(ppp, p, Sreqsent);
1267 if(p->confid != m->id){
1268 /* ignore if it isn't the message we're sending */
1269 netlog("ppp: dropping confack\n");
1272 p->confid = -1; /* ignore duplicates */
1273 p->id++; /* avoid sending duplicates */
1275 netlog("ppp: recv confack\n");
1280 newstate(ppp, p, Sreqsent);
1283 newstate(ppp, p, Sackrcvd);
1286 newstate(ppp, p, Sopened);
1292 if(p->confid != m->id) {
1293 /* ignore if it isn't the message we're sending */
1294 netlog("ppp: dropping confrej or confnak\n");
1297 p->confid = -1; /* ignore duplicates */
1298 p->id++; /* avoid sending duplicates */
1304 newstate(ppp, p, Sreqsent);
1309 rejopts(ppp, p, b, m->code);
1316 putframe(ppp, p->proto, b);
1321 newstate(ppp, p, Sreqsent);
1324 newstate(ppp, p, Sclosing);
1329 if(p->termid != m->id) /* ignore if it isn't the message we're sending */
1332 if(p->proto == Plcp)
1333 ppp->ipcp->state = Sclosed;
1336 newstate(ppp, p, Sclosed);
1339 newstate(ppp, p, Sreqsent);
1343 newstate(ppp, p, Sreqsent);
1348 //newstate(ppp, p, Sclosed);
1349 syslog(0, LOG, "code reject %d", m->data[0]);
1352 proto = nhgets(m->data);
1353 netlog("ppp: proto reject %ux", proto);
1355 newstate(ppp, ppp->ccp, Sclosed);
1359 netlog("ppp: short lcp echo request\n");
1364 hnputl(m->data, ppp->magic);
1365 putframe(ppp, p->proto, b);
1374 if(p->proto != Pccp)
1376 ppp->stat.compreset++;
1377 if(ppp->ctype != nil)
1378 b = (*ppp->ctype->resetreq)(ppp->cstate, b);
1380 m = (Lcpmsg*)b->rptr;
1381 m->code = Lresetack;
1382 putframe(ppp, p->proto, b);
1386 if(p->proto != Pccp)
1388 if(ppp->unctype != nil)
1389 (*ppp->unctype->resetack)(ppp->uncstate, b);
1398 * timer for protocol state machine
1401 ptimer(PPP *ppp, Pstate *p)
1403 if(p->state == Sopened || p->state == Sclosed)
1409 sendtermreq(ppp, p);
1414 newstate(ppp, p, Sclosed);
1421 newstate(ppp, p, Sclosed);
1424 newstate(ppp, p, Sreqsent);
1430 /* paptimer -- pap timer event handler
1432 * If PAP authorization hasn't come through, resend an authreqst. If
1433 * the maximum number of requests have been sent (~ 30 seconds), give
1440 if(ppp->chap->proto != APpasswd)
1443 if(ppp->chap->id < 21)
1447 netlog("ppp: pap timed out--not authorized\n");
1462 netlog("ppp: ppptimer\n");
1463 ptimer(ppp, ppp->lcp);
1464 if(ppp->lcp->state == Sopened) {
1467 ptimer(ppp, ppp->ccp);
1468 ptimer(ppp, ppp->ipcp);
1476 /* link quality measurement */
1477 if(ppp->period && --(ppp->timeout) <= 0){
1478 ppp->timeout = ppp->period;
1487 setdefroute(char *net, Ipaddr gate)
1492 snprint(path, sizeof path, "%s/iproute", net);
1493 fd = open(path, ORDWR);
1496 fprint(fd, "add 0 0 %I", gate);
1516 static int ipinprocpid;
1521 if(ipinprocpid <= 0){
1522 snprint(path, sizeof path, "%s/ipifc/clone", ppp->net);
1523 cfd = open(path, ORDWR);
1525 return "can't open ip interface";
1527 n = read(cfd, buf, sizeof(buf) - 1);
1530 return "can't open ip interface";
1534 netlog("ppp: setting up IP interface local %I remote %I (valid %d)\n",
1535 ppp->local, ppp->remote, validv4(ppp->remote));
1536 if(!validv4(ppp->remote))
1537 ipmove(ppp->remote, ppp->local);
1539 snprint(path, sizeof path, "%s/ipifc/%s/data", ppp->net, buf);
1540 fd = open(path, ORDWR);
1543 return "can't open ip interface";
1546 if(fprint(cfd, "bind pkt") < 0)
1547 return "binding pkt to ip interface";
1548 if(fprint(cfd, "add %I 255.255.255.255 %I %lud proxy", ppp->local,
1549 ppp->remote, ppp->mtu-10) < 0){
1551 return "can't set addresses";
1554 setdefroute(ppp->net, ppp->remote);
1558 /* signal main() that ip is configured */
1559 rendezvous((void*)Rmagic, 0);
1561 switch(ipinprocpid = rfork(RFPROC|RFMEM|RFNOWAIT)){
1563 sysfatal("forking ipinproc");
1570 /* we may have changed addresses */
1571 if(ipcmp(ppp->local, ppp->curlocal) != 0 ||
1572 ipcmp(ppp->remote, ppp->curremote) != 0){
1573 snprint(buf, sizeof buf, "remove %I 255.255.255.255 %I",
1574 ppp->curlocal, ppp->curremote);
1575 if(fprint(ppp->ipcfd, "%s", buf) < 0)
1576 syslog(0, "ppp", "can't %s: %r", buf);
1577 snprint(buf, sizeof buf, "add %I 255.255.255.255 %I %lud proxy",
1578 ppp->local, ppp->remote, ppp->mtu-10);
1579 if(fprint(ppp->ipcfd, "%s", buf) < 0)
1580 syslog(0, "ppp", "can't %s: %r", buf);
1582 syslog(0, "ppp", "%I/%I -> %I/%I", ppp->curlocal, ppp->curremote,
1583 ppp->local, ppp->remote);
1585 ipmove(ppp->curlocal, ppp->local);
1586 ipmove(ppp->curremote, ppp->remote);
1591 /* return next input IP packet */
1600 b = getframe(ppp, &proto);
1607 rcv(ppp, ppp->lcp, b);
1610 rcv(ppp, ppp->ccp, b);
1613 rcv(ppp, ppp->ipcp, b);
1616 if(ppp->ipcp->state == Sopened)
1618 netlog("ppp: IP recved: link not up\n");
1632 if(ppp->ipcp->state != Sopened){
1633 netlog("ppp: VJ tcp recved: link not up\n");
1638 b = tcpuncompress(ppp->ctcp, b, proto);
1645 if(ppp->ccp->state != Sopened){
1646 netlog("ppp: compressed data recved: link not up\n");
1650 if(ppp->unctype == nil) {
1651 netlog("ppp: compressed data recved: no compression\n");
1656 b = (*ppp->unctype->uncompress)(ppp, b, &proto, &reply);
1659 ppp->stat.uncompreset++;
1660 putframe(ppp, Pccp, reply);
1665 ppp->stat.uncompin += len;
1666 ppp->stat.uncompout += BLEN(b);
1667 /* netlog("ppp: uncompressed frame %ux %d %d (%d uchars)\n", proto, b->rptr[0], b->rptr[1], BLEN(b)); /* */
1670 syslog(0, LOG, "unknown proto %ux", proto);
1671 if(ppp->lcp->state == Sopened){
1672 /* reject the protocol */
1674 m = (Lcpmsg*)b->rptr;
1675 m->code = Lprotorej;
1676 m->id = ++ppp->lcp->id;
1677 hnputs(m->data, proto);
1678 hnputs(m->len, BLEN(b));
1679 putframe(ppp, Plcp, b);
1688 /* transmit an IP packet */
1690 pppwrite(PPP *ppp, Block *b)
1696 /* can't send ip packets till we're established */
1697 if(ppp->ipcp->state != Sopened) {
1699 syslog(0, LOG, "IP write: link not up");
1708 if(ppp->ipcp->flags & Fipcompress){
1709 b = compress(ppp->ctcp, b, &proto);
1718 if(ppp->ctype != nil) {
1720 b = (*ppp->ctype->compress)(ppp, proto, b, &proto);
1721 if(proto == Pcdata) {
1723 ppp->stat.compin += len;
1724 ppp->stat.compout += blen(b);
1728 if(putframe(ppp, proto, b) < 0) {
1741 terminate(PPP *ppp, int kill)
1747 close(ppp->mediain);
1748 close(ppp->mediaout);
1754 postnote(PNGROUP, getpid(), "die");
1757 typedef struct Iphdr Iphdr;
1760 uchar vihl; /* Version and header length */
1761 uchar tos; /* Type of service */
1762 uchar length[2]; /* packet length */
1763 uchar id[2]; /* Identification */
1764 uchar frag[2]; /* Fragment information */
1765 uchar ttl; /* Time to live */
1766 uchar proto; /* Protocol */
1767 uchar cksum[2]; /* Header checksum */
1768 uchar src[4]; /* Ip source (uchar ordering unimportant) */
1769 uchar dst[4]; /* Ip destination (uchar ordering unimportant) */
1782 n = read(ppp->ipfd, b->wptr, b->lim-b->wptr);
1786 /* trim packet if there's padding (e.g. from ether) */
1787 ip = (Iphdr*)b->rptr;
1788 m = nhgets(ip->length);
1793 if(pppwrite(ppp, b) < 0)
1799 catchdie(void*, char *msg)
1801 if(strstr(msg, "die") != nil)
1808 hexdump(uchar *a, int na)
1813 fprint(2, "dump %p %d\n", a, na);
1815 for(i=0; i<na; i++){
1816 sprint(buf+strlen(buf), " %.2ux", a[i]);
1818 sprint(buf+strlen(buf), " --");
1820 sprint(buf+strlen(buf), "\n");
1821 write(2, buf, strlen(buf));
1826 sprint(buf+strlen(buf), "\n");
1827 write(2, buf, strlen(buf));
1832 mediainproc(PPP *ppp)
1841 syslog(0, LOG, "pppread return nil");
1845 if(ppp->ipcp->state != Sopened) {
1846 ppp->stat.iprecvnotup++;
1852 v4tov6(remote, b->rptr+12);
1853 if(ipcmp(remote, ppp->remote) != 0) {
1854 ppp->stat.iprecvbadsrc++;
1860 netlog("ip write pkt %p %d\n", b->rptr, blen(b));
1861 hexdump(b->rptr, blen(b));
1863 if(write(ppp->ipfd, b->rptr, blen(b)) < 0) {
1864 syslog(0, LOG, "error writing to pktifc");
1872 netlog(": remote=%I: ppp shutting down\n", ppp->remote);
1873 syslog(0, LOG, ": remote=%I: ppp shutting down", ppp->remote);
1874 syslog(0, LOG, "\t\tppp send = %lud/%lud recv= %lud/%lud",
1875 ppp->out.packets, ppp->out.uchars,
1876 ppp->in.packets, ppp->in.uchars);
1877 syslog(0, LOG, "\t\tip send=%lud", ppp->stat.ipsend);
1878 syslog(0, LOG, "\t\tip recv=%lud notup=%lud badsrc=%lud",
1879 ppp->stat.iprecv, ppp->stat.iprecvnotup, ppp->stat.iprecvbadsrc);
1880 syslog(0, LOG, "\t\tcompress=%lud in=%lud out=%lud reset=%lud",
1881 ppp->stat.comp, ppp->stat.compin, ppp->stat.compout, ppp->stat.compreset);
1882 syslog(0, LOG, "\t\tuncompress=%lud in=%lud out=%lud reset=%lud",
1883 ppp->stat.uncomp, ppp->stat.uncompin, ppp->stat.uncompout,
1884 ppp->stat.uncompreset);
1885 syslog(0, LOG, "\t\tvjin=%lud vjout=%lud vjfail=%lud",
1886 ppp->stat.vjin, ppp->stat.vjout, ppp->stat.vjfail);
1890 * link quality management
1893 getlqm(PPP *ppp, Block *b)
1897 p = (Qualpkt*)b->rptr;
1898 if(BLEN(b) == sizeof(Qualpkt)){
1900 ppp->pout.reports = nhgetl(p->peeroutreports);
1901 ppp->pout.packets = nhgetl(p->peeroutpackets);
1902 ppp->pout.uchars = nhgetl(p->peeroutuchars);
1903 ppp->pin.reports = nhgetl(p->peerinreports);
1904 ppp->pin.packets = nhgetl(p->peerinpackets);
1905 ppp->pin.discards = nhgetl(p->peerindiscards);
1906 ppp->pin.errors = nhgetl(p->peerinerrors);
1907 ppp->pin.uchars = nhgetl(p->peerinuchars);
1909 /* save our numbers at time of reception */
1910 memmove(&ppp->sin, &ppp->in, sizeof(Qualstats));
1914 if(ppp->period == 0)
1925 b = allocb(sizeof(Qualpkt));
1926 b->wptr += sizeof(Qualpkt);
1927 p = (Qualpkt*)b->rptr;
1928 hnputl(p->magic, 0);
1930 /* heresay (what he last told us) */
1931 hnputl(p->lastoutreports, ppp->pout.reports);
1932 hnputl(p->lastoutpackets, ppp->pout.packets);
1933 hnputl(p->lastoutuchars, ppp->pout.uchars);
1935 /* our numbers at time of last reception */
1936 hnputl(p->peerinreports, ppp->sin.reports);
1937 hnputl(p->peerinpackets, ppp->sin.packets);
1938 hnputl(p->peerindiscards, ppp->sin.discards);
1939 hnputl(p->peerinerrors, ppp->sin.errors);
1940 hnputl(p->peerinuchars, ppp->sin.uchars);
1942 /* our numbers now */
1943 hnputl(p->peeroutreports, ppp->out.reports+1);
1944 hnputl(p->peeroutpackets, ppp->out.packets+1);
1945 hnputl(p->peeroutuchars, ppp->out.uchars+53/*hack*/);
1947 putframe(ppp, Plqm, b);
1953 * init challenge response dialog
1979 if((c->cs = auth_challenge("proto=%q role=server", aproto)) == nil)
1980 sysfatal("auth_challenge: %r");
1981 syslog(0, LOG, ": remote=%I: sending %d byte challenge", ppp->remote, c->cs->nchal);
1982 len = 4 + 1 + c->cs->nchal + strlen(ppp->chapname);
1983 b = alloclcp(Cchallenge, c->id, len, &m);
1985 *b->wptr++ = c->cs->nchal;
1986 memmove(b->wptr, c->cs->chal, c->cs->nchal);
1987 b->wptr += c->cs->nchal;
1988 memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));
1989 b->wptr += strlen(ppp->chapname);
1990 hnputs(m->len, len);
1991 putframe(ppp, Pchap, b);
1994 c->state = Cchalsent;
1998 * BUG factotum should do this
2007 desencrypt(uchar data[8], uchar key[7])
2011 key_setup(key, ekey);
2012 block_cipher(ekey, data, 0);
2016 nthash(uchar hash[MShashlen], char *passwd)
2021 for(i=0; *passwd && i<sizeof(buf); passwd++) {
2025 memset(hash, 0, 16);
2026 md4(buf, i, hash, 0);
2030 mschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen])
2035 memset(buf, 0, sizeof(buf));
2036 memcpy(buf, hash, MShashlen);
2038 for(i=0; i<3; i++) {
2039 memmove(resp+i*MSchallen, chal, MSchallen);
2040 desencrypt(resp+i*MSchallen, buf+i*7);
2045 * challenge response dialog
2047 extern int _asrdresp(int, uchar*, int);
2050 getchap(PPP *ppp, Block *b)
2054 int len, vlen, i, id, n, nresp;
2055 char md5buf[512], code;
2060 uchar digest[16], *p, *resp, sdigest[SHA1dlen];
2061 uchar mshash[MShashlen], mshash2[MShashlen];
2063 uchar msresp[2*MSresplen+1];
2065 m = (Lcpmsg*)b->rptr;
2066 len = nhgets(m->len);
2068 syslog(0, LOG, "short chap message");
2080 if(vlen > len - 5) {
2081 netlog("PPP: chap: bad challenge len\n");
2086 switch(ppp->chap->proto){
2091 strcpy(md5buf+1, ppp->secret);
2092 n = strlen(ppp->secret) + 1;
2093 memmove(md5buf+n, m->data+1, vlen);
2095 md5((uchar*)md5buf, n, digest, nil);
2100 nthash(mshash, ppp->secret);
2101 memset(msresp, 0, sizeof msresp);
2102 mschalresp(msresp+MSresplen, mshash, m->data+1);
2104 nresp = sizeof msresp;
2105 nthash(mshash, ppp->secret);
2106 md4(mshash, 16, mshash2, 0);
2107 s = sha1(mshash2, 16, 0, 0);
2108 sha1(mshash2, 16, 0, s);
2109 sha1(m->data+1, 8, sdigest, s);
2110 memmove(ppp->key, sdigest, 16);
2113 len = 4 + 1 + nresp + strlen(ppp->chapname);
2115 b = alloclcp(Cresponse, id, len, &m);
2117 memmove(b->wptr, resp, nresp);
2119 memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));
2120 b->wptr += strlen(ppp->chapname);
2121 hnputs(m->len, len);
2122 netlog("PPP: sending response len %d\n", len);
2123 putframe(ppp, Pchap, b);
2128 if(m->id != c->id) {
2129 netlog("PPP: chap: bad response id\n");
2134 sysfatal("unknown chap protocol: %d", c->proto);
2136 if(vlen > len - 5 || vlen != 16) {
2137 netlog("PPP: chap: bad response len\n");
2142 memmove(cr.resp, m->data+1, 16);
2143 memset(uid, 0, sizeof(uid));
2147 memmove(uid, m->data+1+vlen, n);
2150 c->cs->nresp = sizeof cr;
2153 if(vlen > len - 5 || vlen != 49) {
2154 netlog("PPP: chap: bad response len\n");
2157 memset(&mscr, 0, sizeof(mscr));
2158 memmove(mscr.LMresp, m->data+1, 24);
2159 memmove(mscr.NTresp, m->data+24+1, 24);
2162 /* remove domain name */
2163 for(i=0; i<n; i++) {
2172 memset(uid, 0, sizeof(uid));
2175 c->cs->resp = 𝓂
2176 c->cs->nresp = sizeof mscr;
2180 syslog(0, LOG, ": remote=%I vlen %d proto %d response user %s nresp %d", ppp->remote, vlen, c->proto, c->cs->user, c->cs->nresp);
2181 if((ai = auth_response(c->cs)) == nil || auth_chuid(ai, nil) < 0){
2184 syslog(0, LOG, ": remote=%I: auth failed: %r, uid=%s", ppp->remote, uid);
2188 syslog(0, LOG, ": remote=%I: auth ok: uid=%s nsecret=%d", ppp->remote, uid, ai->nsecret);
2189 if(c->proto == APmschap){
2190 if(ai->nsecret != sizeof(ppp->key))
2191 sysfatal("could not get the encryption key");
2192 memmove(ppp->key, ai->secret, sizeof(ppp->key));
2196 auth_freechal(c->cs);
2202 b = alloclcp(code, c->id, len, &m);
2203 hnputs(m->len, len);
2204 putframe(ppp, Pchap, b);
2206 if(c->state == Cauthok) {
2207 setphase(ppp, Pnet);
2209 /* restart chapp negotiation */
2215 netlog("ppp: chap succeeded\n");
2218 netlog("ppp: chap failed\n");
2221 syslog(0, LOG, "chap code %d?", m->code);
2229 putpaprequest(PPP *ppp)
2234 int len, nlen, slen;
2240 netlog("PPP: pap: send authreq %d %s %s\n", c->id, ppp->chapname, "****");
2242 nlen = strlen(ppp->chapname);
2243 slen = strlen(ppp->secret);
2244 len = 4 + 1 + nlen + 1 + slen;
2245 b = alloclcp(Pauthreq, c->id, len, &m);
2248 memmove(b->wptr, ppp->chapname, nlen);
2251 memmove(b->wptr, ppp->secret, slen);
2253 hnputs(m->len, len);
2255 putframe(ppp, Ppasswd, b);
2267 getpap(PPP *ppp, Block *b)
2272 m = (Lcpmsg*)b->rptr;
2274 if(BLEN(b) < 4 || BLEN(b) < (len = nhgets(m->len))){
2275 syslog(0, LOG, "short pap message (%ld < %d)", BLEN(b), len);
2279 if(len < sizeof(Lcpmsg))
2285 netlog("PPP: pap auth request, not supported\n");
2288 if(ppp->phase == Pauth
2289 && ppp->chap->proto == APpasswd
2290 && m->id <= ppp-> chap->id){
2291 netlog("PPP: pap succeeded\n");
2292 setphase(ppp, Pnet);
2296 if(ppp->phase == Pauth
2297 && ppp->chap->proto == APpasswd
2298 && m->id <= ppp-> chap->id){
2299 netlog("PPP: pap failed (%d:%.*s)\n",
2300 m->data[0], m->data[0], (char*)m->data+1);
2305 netlog("PPP: unknown pap messsage %d\n", m->code);
2312 printopts(Pstate *p, Block *b, int send)
2316 int proto, x, period;
2320 m = (Lcpmsg*)b->rptr;
2322 default: code = "<unknown>"; break;
2323 case Lconfreq: code = "confrequest"; break;
2324 case Lconfack: code = "confack"; break;
2325 case Lconfnak: code = "confnak"; break;
2326 case Lconfrej: code = "confreject"; break;
2334 netlog("ppp: %s %s: id=%d\n", dir, code, m->id);
2336 for(cp = m->data; cp < b->wptr; cp += o->len){
2338 if(cp + o->len > b->wptr){
2339 netlog("\tbad option length %ux\n", o->type);
2347 netlog("\tunknown %d len=%d\n", o->type, o->len);
2350 netlog("\tmtu = %d\n", nhgets(o->data));
2353 netlog("\tctlmap = %ux\n", nhgetl(o->data));
2356 netlog("\tauth = %ux", nhgetl(o->data));
2357 proto = nhgets(o->data);
2360 netlog("unknown auth proto %d\n", proto);
2363 netlog("password\n");
2366 netlog("chap %ux\n", o->data[2]);
2371 proto = nhgets(o->data);
2374 netlog("\tunknown quality proto %d\n", proto);
2377 x = nhgetl(o->data+2)*10;
2378 period = (x+Period-1)/Period;
2379 netlog("\tlqm period = %d\n", period);
2383 netlog("\tmagic = %ux\n", nhgetl(o->data));
2386 netlog("\tprotocol compress\n");
2389 netlog("\taddr compress\n");
2396 netlog("\tunknown %d len=%d\n", o->type, o->len);
2402 netlog("\tstac LZS\n");
2405 netlog("\tMicrosoft PPC len=%d %ux\n", o->len, nhgetl(o->data));
2408 netlog("\tThwack\n");
2415 netlog("\tunknown %d len=%d\n", o->type, o->len);
2428 netlog("\tunknown %d len=%d\n", o->type, o->len);
2431 netlog("\tip addrs - deprecated\n");
2434 netlog("\tip compress\n");
2437 netlog("\tip addr %V\n", o->data);
2440 netlog("\tdns addr %V\n", o->data);
2443 netlog("\twins addr %V\n", o->data);
2446 netlog("\tdns2 addr %V\n", o->data);
2449 netlog("\twins2 addr %V\n", o->data);
2458 sendtermreq(PPP *ppp, Pstate *p)
2463 p->termid = ++(p->id);
2464 b = alloclcp(Ltermreq, p->termid, 4, &m);
2466 putframe(ppp, p->proto, b);
2468 newstate(ppp, p, Sclosing);
2472 sendechoreq(PPP *ppp, Pstate *p)
2477 p->termid = ++(p->id);
2478 b = alloclcp(Lechoreq, p->id, 4, &m);
2480 putframe(ppp, p->proto, b);
2502 n = read(fd, xbuf, sizeof(xbuf));
2507 for(i = 0; i < n; i++)
2516 readcr(int fd, char *buf, int nbuf)
2522 while((n=read(fd, &c, 1)) == 1){
2529 sysfatal("line too long in readcr");
2535 connect(int fd, int cfd)
2541 int chatfd, lineno, nb;
2542 char *buf, *p, *s, response[128];
2545 if ((chatfd = open(chatfile, OREAD)) < 0)
2546 sysfatal("cannot open %s: %r", chatfile);
2548 if ((dir = dirfstat(chatfd)) == nil)
2549 sysfatal("cannot fstat %s: %r",chatfile);
2551 buf = (char *)malloc(dir->length + 1);
2554 if ((nb = read(chatfd, buf, dir->length)) < 0)
2555 sysfatal("cannot read chatfile %s: %r", chatfile);
2556 assert(nb == dir->length);
2557 buf[dir->length] = '\0';
2566 if ((s = strchr(p, '\n')) == nil)
2577 if (tokenize(p, _args, 3) != 2)
2578 sysfatal("invalid line %d (line expected: 'send' 'expect')",
2582 print("sending %s, expecting %s\n", _args[0], _args[1]);
2584 if(strlen(_args[0])){
2585 nb = fprint(fd, "%s\r", _args[0]);
2589 if (strlen(_args[1]) > 0) {
2590 if ((nb = readcr(fd, response, sizeof response-1)) < 0)
2591 sysfatal("cannot read response from: %r");
2594 print("response %s\n", response);
2597 sysfatal("eof on input?");
2599 if (cistrstr(response, _args[1]) == nil)
2600 sysfatal("expected %s, got %s", _args[1], response);
2608 print("Connect to file system now, type ctrl-d when done.\n");
2609 print("...(Use the view or down arrow key to send a break)\n");
2610 print("...(Use ctrl-e to set even parity or ctrl-o for odd)\n");
2612 ctl = open("/dev/consctl", OWRITE);
2614 sysfatal("opening consctl");
2615 fprint(ctl, "rawon");
2619 switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
2621 sysfatal("forking xfer");
2629 switch(xbuf[0]&0xff) {
2630 case CtrlD: /* done */
2635 case CtrlE: /* set even parity */
2638 case CtrlO: /* set odd parity */
2641 case View: /* send a break */
2642 fprint(cfd, "k500");
2645 n = write(fd, xbuf, 1);
2647 errstr(xbuf, sizeof(xbuf));
2650 print("[remote write error (%s)]\n", xbuf);
2662 fprint(2, "usage: ppp [-CPSacdfu] [-b baud] [-k keyspec] [-m mtu] "
2663 "[-M chatfile] [-p dev] [-x netmntpt] [-t modemcmd] "
2664 "[local-addr [remote-addr]]\n");
2669 main(int argc, char **argv)
2671 int mtu, baud, framing, user, mediain, mediaout, cfd;
2672 Ipaddr ipaddr, remip;
2673 char *dev, *modemcmd;
2678 rfork(RFREND|RFNOTEG|RFNAMEG);
2680 fmtinstall('I', eipfmt);
2681 fmtinstall('V', eipfmt);
2682 fmtinstall('E', eipfmt);
2692 setnetmtpt(net, sizeof(net), nil);
2701 baud = atoi(EARGF(usage()));
2721 keyspec = EARGF(usage());
2724 mtu = atoi(EARGF(usage()));
2731 chatfile = EARGF(usage());
2734 dev = EARGF(usage());
2743 modemcmd = EARGF(usage());
2749 setnetmtpt(net, sizeof net, EARGF(usage()));
2752 fprint(2, "unknown option %c\n", ARGC());
2758 if (parseip(remip, argv[1]) == -1)
2759 sysfatal("bad remote ip %s", argv[1]);
2761 if (parseip(ipaddr, argv[0]) == -1)
2762 sysfatal("bad ip %s", argv[0]);
2770 if(nip == 0 && !server)
2774 mediain = open(dev, ORDWR);
2776 if(strchr(dev, '!')){
2777 if((mediain = dial(dev, 0, 0, &cfd)) == -1){
2778 fprint(2, "ppp: couldn't dial %s: %r\n", dev);
2782 fprint(2, "ppp: couldn't open %s\n", dev);
2786 snprint(buf, sizeof buf, "%sctl", dev);
2787 cfd = open(buf, ORDWR);
2791 fprint(cfd, "b%d", baud);
2792 fprint(cfd, "m1"); /* cts/rts flow control (and fifo's) on */
2793 fprint(cfd, "q64000"); /* increase q size to 64k */
2794 fprint(cfd, "n1"); /* nonblocking writes on */
2795 fprint(cfd, "r1"); /* rts on */
2796 fprint(cfd, "d1"); /* dtr on */
2797 fprint(cfd, "c1"); /* dcdhup on */
2798 if(user || chatfile)
2799 connect(mediain, cfd);
2802 if(user || chatfile)
2803 connect(mediain, -1);
2807 mediain = open("/fd/0", OREAD);
2809 fprint(2, "ppp: couldn't open /fd/0\n");
2812 mediaout = open("/fd/1", OWRITE);
2814 fprint(2, "ppp: couldn't open /fd/0\n");
2819 if(modemcmd != nil && mediaout >= 0)
2820 fprint(mediaout, "%s\r", modemcmd);
2822 ppp = mallocz(sizeof(*ppp), 1);
2823 pppopen(ppp, mediain, mediaout, net, ipaddr, remip, mtu, framing);
2825 /* wait until ip is configured */
2826 rendezvous((void*)Rmagic, 0);
2829 /* create a /net/ndb entry */
2837 netlog(char *fmt, ...)
2852 m = vsmprint(fmt, arg);
2853 fprint(2, "%ld %s", now-start, m);
2859 * return non-zero if this is a valid v4 address
2862 validv4(Ipaddr addr)
2864 return memcmp(addr, v4prefix, IPv4off) == 0 && memcmp(addr, v4prefix, IPaddrlen) != 0;
2868 invalidate(Ipaddr addr)
2870 ipmove(addr, IPnoaddr);
2874 * return number of networks
2885 ifc = readipifc(net, ifc, -1);
2886 for(nifc = ifc; nifc != nil; nifc = nifc->next)
2887 for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next)
2893 * make an ndb entry and put it into /net/ndb for the servers to see
2896 putndb(PPP *ppp, char *net)
2903 e = buf + sizeof(buf);
2905 p = seprint(p, e, "ip=%I ipmask=255.255.255.255 ipgw=%I\n", ppp->local,
2907 if(validv4(ppp->dns[0]))
2908 p = seprint(p, e, "\tdns=%I\n", ppp->dns[0]);
2909 if(validv4(ppp->dns[1]))
2910 p = seprint(p, e, "\tdns=%I\n", ppp->dns[1]);
2911 if(validv4(ppp->wins[0]))
2912 p = seprint(p, e, "\twins=%I\n", ppp->wins[0]);
2913 if(validv4(ppp->wins[1]))
2914 p = seprint(p, e, "\twins=%I\n", ppp->wins[1]);
2915 seprint(file, file+sizeof file, "%s/ndb", net);
2916 fd = open(file, OWRITE);
2919 write(fd, buf, p-buf);
2921 seprint(file, file+sizeof file, "%s/cs", net);
2922 fd = open(file, OWRITE);
2923 write(fd, "refresh", 7);
2925 seprint(file, file+sizeof file, "%s/dns", net);
2926 fd = open(file, OWRITE);
2927 write(fd, "refresh", 7);
2939 up = auth_getuserpasswd(auth_getkey,"proto=pass service=ppp %s", keyspec);
2941 strcpy(ppp->chapname, up->user);
2942 strcpy(ppp->secret, up->passwd);