1225077b0SDavid du Colombier /*
2225077b0SDavid du Colombier * ppp - point-to-point protocol, rfc1331
3225077b0SDavid du Colombier */
47dd7cddfSDavid du Colombier #include <u.h>
57dd7cddfSDavid du Colombier #include <libc.h>
67dd7cddfSDavid du Colombier #include <auth.h>
77dd7cddfSDavid du Colombier #include <bio.h>
87dd7cddfSDavid du Colombier #include <ip.h>
97dd7cddfSDavid du Colombier #include <libsec.h>
107dd7cddfSDavid du Colombier #include <ndb.h>
117dd7cddfSDavid du Colombier #include "ppp.h"
127dd7cddfSDavid du Colombier
139a747e4fSDavid du Colombier #define PATH 128
149a747e4fSDavid du Colombier
157dd7cddfSDavid du Colombier static int baud;
167dd7cddfSDavid du Colombier static int nocompress;
179a747e4fSDavid du Colombier static int pppframing = 1;
187dd7cddfSDavid du Colombier static int noipcompress;
197dd7cddfSDavid du Colombier static int server;
20*4f81ea25SDavid du Colombier static int noauth;
217dd7cddfSDavid du Colombier static int nip; /* number of ip interfaces */
227dd7cddfSDavid du Colombier static int dying; /* flag to signal to all threads its time to go */
2359cc4ca5SDavid du Colombier static int primary; /* this is the primary IP interface */
243ff48bf5SDavid du Colombier static char *chatfile;
257dd7cddfSDavid du Colombier
269a747e4fSDavid du Colombier int debug;
277dd7cddfSDavid du Colombier char* LOG = "ppp";
28bedadc12SDavid du Colombier char* keyspec = "";
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier enum
317dd7cddfSDavid du Colombier {
327dd7cddfSDavid du Colombier Rmagic= 0x12345
337dd7cddfSDavid du Colombier };
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier /*
367dd7cddfSDavid du Colombier * Calculate FCS - rfc 1331
377dd7cddfSDavid du Colombier */
387dd7cddfSDavid du Colombier ushort fcstab[256] =
397dd7cddfSDavid du Colombier {
407dd7cddfSDavid du Colombier 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
417dd7cddfSDavid du Colombier 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
427dd7cddfSDavid du Colombier 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
437dd7cddfSDavid du Colombier 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
447dd7cddfSDavid du Colombier 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
457dd7cddfSDavid du Colombier 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
467dd7cddfSDavid du Colombier 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
477dd7cddfSDavid du Colombier 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
487dd7cddfSDavid du Colombier 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
497dd7cddfSDavid du Colombier 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
507dd7cddfSDavid du Colombier 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
517dd7cddfSDavid du Colombier 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
527dd7cddfSDavid du Colombier 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
537dd7cddfSDavid du Colombier 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
547dd7cddfSDavid du Colombier 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
557dd7cddfSDavid du Colombier 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
567dd7cddfSDavid du Colombier 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
577dd7cddfSDavid du Colombier 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
587dd7cddfSDavid du Colombier 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
597dd7cddfSDavid du Colombier 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
607dd7cddfSDavid du Colombier 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
617dd7cddfSDavid du Colombier 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
627dd7cddfSDavid du Colombier 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
637dd7cddfSDavid du Colombier 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
647dd7cddfSDavid du Colombier 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
657dd7cddfSDavid du Colombier 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
667dd7cddfSDavid du Colombier 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
677dd7cddfSDavid du Colombier 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
687dd7cddfSDavid du Colombier 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
697dd7cddfSDavid du Colombier 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
707dd7cddfSDavid du Colombier 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
717dd7cddfSDavid du Colombier 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
727dd7cddfSDavid du Colombier };
737dd7cddfSDavid du Colombier
747dd7cddfSDavid du Colombier static char *snames[] =
757dd7cddfSDavid du Colombier {
767dd7cddfSDavid du Colombier "Sclosed",
777dd7cddfSDavid du Colombier "Sclosing",
787dd7cddfSDavid du Colombier "Sreqsent",
797dd7cddfSDavid du Colombier "Sackrcvd",
807dd7cddfSDavid du Colombier "Sacksent",
817dd7cddfSDavid du Colombier "Sopened",
827dd7cddfSDavid du Colombier };
837dd7cddfSDavid du Colombier
8480ee5cbfSDavid du Colombier static void authtimer(PPP*);
8580ee5cbfSDavid du Colombier static void chapinit(PPP*);
8680ee5cbfSDavid du Colombier static void config(PPP*, Pstate*, int);
8780ee5cbfSDavid du Colombier static uchar* escapeuchar(PPP*, ulong, uchar*, ushort*);
8880ee5cbfSDavid du Colombier static void getchap(PPP*, Block*);
8980ee5cbfSDavid du Colombier static Block* getframe(PPP*, int*);
9080ee5cbfSDavid du Colombier static void getlqm(PPP*, Block*);
9180ee5cbfSDavid du Colombier static int getopts(PPP*, Pstate*, Block*);
9280ee5cbfSDavid du Colombier static void getpap(PPP*, Block*);
937dd7cddfSDavid du Colombier static void init(PPP*);
9480ee5cbfSDavid du Colombier static void invalidate(Ipaddr);
957dd7cddfSDavid du Colombier static void ipinproc(PPP*);
9680ee5cbfSDavid du Colombier static char* ipopen(PPP*);
977dd7cddfSDavid du Colombier static void mediainproc(PPP*);
9880ee5cbfSDavid du Colombier static void newstate(PPP*, Pstate*, int);
9980ee5cbfSDavid du Colombier static int nipifcs(char*);
10080ee5cbfSDavid du Colombier static void papinit(PPP*);
1017dd7cddfSDavid du Colombier static void pinit(PPP*, Pstate*);
1027dd7cddfSDavid du Colombier static void ppptimer(PPP*);
1037dd7cddfSDavid du Colombier static void printopts(Pstate*, Block*, int);
10480ee5cbfSDavid du Colombier static void ptimer(PPP*, Pstate*);
10580ee5cbfSDavid du Colombier static int putframe(PPP*, int, Block*);
10680ee5cbfSDavid du Colombier static void putlqm(PPP*);
1077dd7cddfSDavid du Colombier static void putndb(PPP*, char*);
10880ee5cbfSDavid du Colombier static void putpaprequest(PPP*);
10980ee5cbfSDavid du Colombier static void rcv(PPP*, Pstate*, Block*);
11080ee5cbfSDavid du Colombier static void rejopts(PPP*, Pstate*, Block*, int);
11180ee5cbfSDavid du Colombier static void sendechoreq(PPP*, Pstate*);
11280ee5cbfSDavid du Colombier static void sendtermreq(PPP*, Pstate*);
11380ee5cbfSDavid du Colombier static void setphase(PPP*, int);
11480ee5cbfSDavid du Colombier static void terminate(PPP*, int);
11580ee5cbfSDavid du Colombier static int validv4(Ipaddr);
116bedadc12SDavid du Colombier static void dmppkt(char *s, uchar *a, int na);
117dc5a79c1SDavid du Colombier static void getauth(PPP*);
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier void
pppopen(PPP * ppp,int mediain,int mediaout,char * net,Ipaddr ipaddr,Ipaddr remip,int mtu,int framing)120d9306527SDavid du Colombier pppopen(PPP *ppp, int mediain, int mediaout, char *net,
1217dd7cddfSDavid du Colombier Ipaddr ipaddr, Ipaddr remip,
122bedadc12SDavid du Colombier int mtu, int framing)
1237dd7cddfSDavid du Colombier {
1247dd7cddfSDavid du Colombier ppp->ipfd = -1;
1257dd7cddfSDavid du Colombier ppp->ipcfd = -1;
1267dd7cddfSDavid du Colombier invalidate(ppp->remote);
1277dd7cddfSDavid du Colombier invalidate(ppp->local);
1286b6b9ac8SDavid du Colombier invalidate(ppp->curremote);
1296b6b9ac8SDavid du Colombier invalidate(ppp->curlocal);
1307dd7cddfSDavid du Colombier invalidate(ppp->dns[0]);
1317dd7cddfSDavid du Colombier invalidate(ppp->dns[1]);
1327dd7cddfSDavid du Colombier invalidate(ppp->wins[0]);
1337dd7cddfSDavid du Colombier invalidate(ppp->wins[1]);
1347dd7cddfSDavid du Colombier
135d9306527SDavid du Colombier ppp->mediain = mediain;
136d9306527SDavid du Colombier ppp->mediaout = mediaout;
1377dd7cddfSDavid du Colombier if(validv4(remip)){
1387dd7cddfSDavid du Colombier ipmove(ppp->remote, remip);
1397dd7cddfSDavid du Colombier ppp->remotefrozen = 1;
1407dd7cddfSDavid du Colombier }
1417dd7cddfSDavid du Colombier if(validv4(ipaddr)){
1427dd7cddfSDavid du Colombier ipmove(ppp->local, ipaddr);
1437dd7cddfSDavid du Colombier ppp->localfrozen = 1;
1447dd7cddfSDavid du Colombier }
1457dd7cddfSDavid du Colombier ppp->mtu = Defmtu;
1467dd7cddfSDavid du Colombier ppp->mru = mtu;
1477dd7cddfSDavid du Colombier ppp->framing = framing;
1487dd7cddfSDavid du Colombier ppp->net = net;
149bedadc12SDavid du Colombier
1507dd7cddfSDavid du Colombier init(ppp);
1517dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
1527dd7cddfSDavid du Colombier case -1:
1537dd7cddfSDavid du Colombier sysfatal("forking mediainproc");
1547dd7cddfSDavid du Colombier case 0:
1557dd7cddfSDavid du Colombier mediainproc(ppp);
1567dd7cddfSDavid du Colombier terminate(ppp, 1);
1577dd7cddfSDavid du Colombier _exits(0);
1587dd7cddfSDavid du Colombier }
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier static void
init(PPP * ppp)1627dd7cddfSDavid du Colombier init(PPP* ppp)
1637dd7cddfSDavid du Colombier {
1647dd7cddfSDavid du Colombier if(ppp->inbuf == nil){
1657dd7cddfSDavid du Colombier ppp->inbuf = allocb(4096);
1667dd7cddfSDavid du Colombier if(ppp->inbuf == nil)
1677dd7cddfSDavid du Colombier abort();
1687dd7cddfSDavid du Colombier
1697dd7cddfSDavid du Colombier ppp->outbuf = allocb(4096);
1707dd7cddfSDavid du Colombier if(ppp->outbuf == nil)
1717dd7cddfSDavid du Colombier abort();
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier ppp->lcp = mallocz(sizeof(*ppp->lcp), 1);
1747dd7cddfSDavid du Colombier if(ppp->lcp == nil)
1757dd7cddfSDavid du Colombier abort();
1767dd7cddfSDavid du Colombier ppp->lcp->proto = Plcp;
1777dd7cddfSDavid du Colombier ppp->lcp->state = Sclosed;
1787dd7cddfSDavid du Colombier
1797dd7cddfSDavid du Colombier ppp->ccp = mallocz(sizeof(*ppp->ccp), 1);
1807dd7cddfSDavid du Colombier if(ppp->ccp == nil)
1817dd7cddfSDavid du Colombier abort();
1827dd7cddfSDavid du Colombier ppp->ccp->proto = Pccp;
1837dd7cddfSDavid du Colombier ppp->ccp->state = Sclosed;
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier ppp->ipcp = mallocz(sizeof(*ppp->ipcp), 1);
1867dd7cddfSDavid du Colombier if(ppp->ipcp == nil)
1877dd7cddfSDavid du Colombier abort();
1887dd7cddfSDavid du Colombier ppp->ipcp->proto = Pipcp;
1897dd7cddfSDavid du Colombier ppp->ipcp->state = Sclosed;
1907dd7cddfSDavid du Colombier
1917dd7cddfSDavid du Colombier ppp->chap = mallocz(sizeof(*ppp->chap), 1);
1927dd7cddfSDavid du Colombier if(ppp->chap == nil)
1937dd7cddfSDavid du Colombier abort();
1947dd7cddfSDavid du Colombier ppp->chap->proto = APmschap;
1957dd7cddfSDavid du Colombier ppp->chap->state = Cunauth;
1969a747e4fSDavid du Colombier auth_freechal(ppp->chap->cs);
1979a747e4fSDavid du Colombier ppp->chap->cs = nil;
1987dd7cddfSDavid du Colombier
1997dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
2007dd7cddfSDavid du Colombier case -1:
2017dd7cddfSDavid du Colombier sysfatal("forking ppptimer");
2027dd7cddfSDavid du Colombier case 0:
2037dd7cddfSDavid du Colombier ppptimer(ppp);
2047dd7cddfSDavid du Colombier _exits(0);
2057dd7cddfSDavid du Colombier }
2067dd7cddfSDavid du Colombier }
2077dd7cddfSDavid du Colombier
2087dd7cddfSDavid du Colombier ppp->ctcp = compress_init(ppp->ctcp);
2097dd7cddfSDavid du Colombier pinit(ppp, ppp->lcp);
2107dd7cddfSDavid du Colombier setphase(ppp, Plink);
2117dd7cddfSDavid du Colombier }
2127dd7cddfSDavid du Colombier
2137dd7cddfSDavid du Colombier static void
setphase(PPP * ppp,int phase)2147dd7cddfSDavid du Colombier setphase(PPP *ppp, int phase)
2157dd7cddfSDavid du Colombier {
2167dd7cddfSDavid du Colombier int oldphase;
2177dd7cddfSDavid du Colombier
2187dd7cddfSDavid du Colombier oldphase = ppp->phase;
2197dd7cddfSDavid du Colombier
2207dd7cddfSDavid du Colombier ppp->phase = phase;
2217dd7cddfSDavid du Colombier switch(phase){
2227dd7cddfSDavid du Colombier default:
2237dd7cddfSDavid du Colombier sysfatal("ppp: unknown phase %d", phase);
2247dd7cddfSDavid du Colombier case Pdead:
2257dd7cddfSDavid du Colombier /* restart or exit? */
2267dd7cddfSDavid du Colombier pinit(ppp, ppp->lcp);
2277dd7cddfSDavid du Colombier setphase(ppp, Plink);
2287dd7cddfSDavid du Colombier break;
2297dd7cddfSDavid du Colombier case Plink:
2307dd7cddfSDavid du Colombier /* link down */
2317dd7cddfSDavid du Colombier switch(oldphase) {
2327dd7cddfSDavid du Colombier case Pauth:
2339a747e4fSDavid du Colombier auth_freechal(ppp->chap->cs);
2349a747e4fSDavid du Colombier ppp->chap->cs = nil;
2357dd7cddfSDavid du Colombier ppp->chap->state = Cunauth;
2367dd7cddfSDavid du Colombier break;
2377dd7cddfSDavid du Colombier case Pnet:
2389a747e4fSDavid du Colombier auth_freechal(ppp->chap->cs);
2399a747e4fSDavid du Colombier ppp->chap->cs = nil;
2407dd7cddfSDavid du Colombier ppp->chap->state = Cunauth;
2417dd7cddfSDavid du Colombier newstate(ppp, ppp->ccp, Sclosed);
2427dd7cddfSDavid du Colombier newstate(ppp, ppp->ipcp, Sclosed);
2437dd7cddfSDavid du Colombier }
2447dd7cddfSDavid du Colombier break;
2457dd7cddfSDavid du Colombier case Pauth:
2467dd7cddfSDavid du Colombier if(server)
2477dd7cddfSDavid du Colombier chapinit(ppp);
24880ee5cbfSDavid du Colombier else if(ppp->chap->proto == APpasswd)
24980ee5cbfSDavid du Colombier papinit(ppp);
2507dd7cddfSDavid du Colombier else
2517dd7cddfSDavid du Colombier setphase(ppp, Pnet);
2527dd7cddfSDavid du Colombier break;
2537dd7cddfSDavid du Colombier case Pnet:
2547dd7cddfSDavid du Colombier pinit(ppp, ppp->ccp);
2557dd7cddfSDavid du Colombier pinit(ppp, ppp->ipcp);
2567dd7cddfSDavid du Colombier break;
2577dd7cddfSDavid du Colombier case Pterm:
2587dd7cddfSDavid du Colombier /* what? */
2597dd7cddfSDavid du Colombier break;
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier
2637dd7cddfSDavid du Colombier static void
pinit(PPP * ppp,Pstate * p)2647dd7cddfSDavid du Colombier pinit(PPP *ppp, Pstate *p)
2657dd7cddfSDavid du Colombier {
2667dd7cddfSDavid du Colombier p->timeout = 0;
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier switch(p->proto){
2697dd7cddfSDavid du Colombier case Plcp:
2706b6b9ac8SDavid du Colombier ppp->magic = truerand();
2717dd7cddfSDavid du Colombier ppp->xctlmap = 0xffffffff;
2727dd7cddfSDavid du Colombier ppp->period = 0;
2737dd7cddfSDavid du Colombier p->optmask = 0xffffffff;
2747dd7cddfSDavid du Colombier if(!server)
2756b6b9ac8SDavid du Colombier p->optmask &= ~(Fauth|Fmtu);
2767dd7cddfSDavid du Colombier ppp->rctlmap = 0;
2777dd7cddfSDavid du Colombier ppp->ipcp->state = Sclosed;
2787dd7cddfSDavid du Colombier ppp->ipcp->optmask = 0xffffffff;
2797dd7cddfSDavid du Colombier
2807dd7cddfSDavid du Colombier p->echotimeout = 0;
2817dd7cddfSDavid du Colombier
2827dd7cddfSDavid du Colombier /* quality goo */
2837dd7cddfSDavid du Colombier ppp->timeout = 0;
2847dd7cddfSDavid du Colombier memset(&ppp->in, 0, sizeof(ppp->in));
2857dd7cddfSDavid du Colombier memset(&ppp->out, 0, sizeof(ppp->out));
2867dd7cddfSDavid du Colombier memset(&ppp->pin, 0, sizeof(ppp->pin));
2877dd7cddfSDavid du Colombier memset(&ppp->pout, 0, sizeof(ppp->pout));
2887dd7cddfSDavid du Colombier memset(&ppp->sin, 0, sizeof(ppp->sin));
2897dd7cddfSDavid du Colombier break;
2907dd7cddfSDavid du Colombier case Pccp:
2917dd7cddfSDavid du Colombier if(nocompress)
2927dd7cddfSDavid du Colombier p->optmask = 0;
2937dd7cddfSDavid du Colombier else
2947dd7cddfSDavid du Colombier p->optmask = Fcmppc;
2957dd7cddfSDavid du Colombier
29659cc4ca5SDavid du Colombier if(ppp->ctype != nil)
2977dd7cddfSDavid du Colombier (*ppp->ctype->fini)(ppp->cstate);
2987dd7cddfSDavid du Colombier ppp->ctype = nil;
2997dd7cddfSDavid du Colombier ppp->ctries = 0;
3007dd7cddfSDavid du Colombier ppp->cstate = nil;
3017dd7cddfSDavid du Colombier
3027dd7cddfSDavid du Colombier if(ppp->unctype)
3037dd7cddfSDavid du Colombier (*ppp->unctype->fini)(ppp->uncstate);
3047dd7cddfSDavid du Colombier ppp->unctype = nil;
3057dd7cddfSDavid du Colombier ppp->uncstate = nil;
3067dd7cddfSDavid du Colombier break;
3077dd7cddfSDavid du Colombier case Pipcp:
3087dd7cddfSDavid du Colombier p->optmask = 0xffffffff;
3097dd7cddfSDavid du Colombier ppp->ctcp = compress_init(ppp->ctcp);
3107dd7cddfSDavid du Colombier break;
3117dd7cddfSDavid du Colombier }
3127dd7cddfSDavid du Colombier p->confid = p->rcvdconfid = -1;
3137dd7cddfSDavid du Colombier config(ppp, p, 1);
3147dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
3157dd7cddfSDavid du Colombier }
3167dd7cddfSDavid du Colombier
3177dd7cddfSDavid du Colombier /*
3187dd7cddfSDavid du Colombier * change protocol to a new state.
3197dd7cddfSDavid du Colombier */
3207dd7cddfSDavid du Colombier static void
newstate(PPP * ppp,Pstate * p,int state)3217dd7cddfSDavid du Colombier newstate(PPP *ppp, Pstate *p, int state)
3227dd7cddfSDavid du Colombier {
3237dd7cddfSDavid du Colombier char *err;
3247dd7cddfSDavid du Colombier
32559cc4ca5SDavid du Colombier netlog("ppp: %ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld\n",
3267dd7cddfSDavid du Colombier p->proto, snames[p->state], snames[state], ppp->rctlmap,
3277dd7cddfSDavid du Colombier ppp->xctlmap, p->flags,
3287dd7cddfSDavid du Colombier ppp->mtu, ppp->mru);
3296b6b9ac8SDavid du Colombier syslog(0, "ppp", "%ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld",
3306b6b9ac8SDavid du Colombier p->proto, snames[p->state], snames[state], ppp->rctlmap,
3316b6b9ac8SDavid du Colombier ppp->xctlmap, p->flags,
3326b6b9ac8SDavid du Colombier ppp->mtu, ppp->mru);
3337dd7cddfSDavid du Colombier
3347dd7cddfSDavid du Colombier if(p->proto == Plcp) {
3357dd7cddfSDavid du Colombier if(state == Sopened)
336*4f81ea25SDavid du Colombier setphase(ppp, noauth? Pnet : Pauth);
3377dd7cddfSDavid du Colombier else if(state == Sclosed)
3387dd7cddfSDavid du Colombier setphase(ppp, Pdead);
3397dd7cddfSDavid du Colombier else if(p->state == Sopened)
3407dd7cddfSDavid du Colombier setphase(ppp, Plink);
3417dd7cddfSDavid du Colombier }
3427dd7cddfSDavid du Colombier
3437dd7cddfSDavid du Colombier if(p->proto == Pccp && state == Sopened) {
3447dd7cddfSDavid du Colombier if(ppp->unctype)
3457dd7cddfSDavid du Colombier (*ppp->unctype->fini)(ppp->uncstate);
3467dd7cddfSDavid du Colombier ppp->unctype = nil;
3477dd7cddfSDavid du Colombier ppp->uncstate = nil;
3487dd7cddfSDavid du Colombier if(p->optmask & Fcmppc) {
3497dd7cddfSDavid du Colombier ppp->unctype = &uncmppc;
3507dd7cddfSDavid du Colombier ppp->uncstate = (*uncmppc.init)(ppp);
3517dd7cddfSDavid du Colombier }
3527dd7cddfSDavid du Colombier if(p->optmask & Fcthwack){
3537dd7cddfSDavid du Colombier ppp->unctype = &uncthwack;
3547dd7cddfSDavid du Colombier ppp->uncstate = (*uncthwack.init)(ppp);
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier if(p->proto == Pipcp && state == Sopened) {
359*4f81ea25SDavid du Colombier if(server && !noauth && ppp->chap->state != Cauthok)
3607dd7cddfSDavid du Colombier abort();
3617dd7cddfSDavid du Colombier
3627dd7cddfSDavid du Colombier err = ipopen(ppp);
3637dd7cddfSDavid du Colombier if(err != nil)
3647dd7cddfSDavid du Colombier sysfatal("%s", err);
3657dd7cddfSDavid du Colombier }
3667dd7cddfSDavid du Colombier
3677dd7cddfSDavid du Colombier p->state = state;
3687dd7cddfSDavid du Colombier }
3697dd7cddfSDavid du Colombier
3707dd7cddfSDavid du Colombier /* returns (protocol, information) */
3717dd7cddfSDavid du Colombier static Block*
getframe(PPP * ppp,int * protop)3727dd7cddfSDavid du Colombier getframe(PPP *ppp, int *protop)
3737dd7cddfSDavid du Colombier {
3747dd7cddfSDavid du Colombier uchar *p, *from, *to;
3757dd7cddfSDavid du Colombier int n, len, proto;
3767dd7cddfSDavid du Colombier ulong c;
3777dd7cddfSDavid du Colombier ushort fcs;
3787dd7cddfSDavid du Colombier Block *buf, *b;
3797dd7cddfSDavid du Colombier
3807dd7cddfSDavid du Colombier *protop = 0;
3817dd7cddfSDavid du Colombier if(ppp->framing == 0) {
3827dd7cddfSDavid du Colombier /* assume data is already framed */
3837dd7cddfSDavid du Colombier b = allocb(2000);
3847dd7cddfSDavid du Colombier len = b->lim - b->wptr;
385d9306527SDavid du Colombier n = read(ppp->mediain, b->wptr, len);
386bedadc12SDavid du Colombier dmppkt("RX", b->wptr, n);
3877dd7cddfSDavid du Colombier if(n <= 0 || n == len){
3887dd7cddfSDavid du Colombier freeb(b);
3897dd7cddfSDavid du Colombier
3907dd7cddfSDavid du Colombier return nil;
3917dd7cddfSDavid du Colombier }
3927dd7cddfSDavid du Colombier b->wptr += n;
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier /* should probably copy to another block if small */
3957dd7cddfSDavid du Colombier
3969a747e4fSDavid du Colombier if(pppframing && b->rptr[0] == PPP_addr && b->rptr[1] == PPP_ctl)
3977dd7cddfSDavid du Colombier b->rptr += 2;
3987dd7cddfSDavid du Colombier proto = *b->rptr++;
3997dd7cddfSDavid du Colombier if((proto & 0x1) == 0)
4007dd7cddfSDavid du Colombier proto = (proto<<8) | *b->rptr++;
4017dd7cddfSDavid du Colombier
4027dd7cddfSDavid du Colombier if(b->rptr >= b->wptr){
4037dd7cddfSDavid du Colombier freeb(b);
4047dd7cddfSDavid du Colombier return nil;
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier
4077dd7cddfSDavid du Colombier ppp->in.uchars += n;
4087dd7cddfSDavid du Colombier ppp->in.packets++;
4097dd7cddfSDavid du Colombier *protop = proto;
4109a747e4fSDavid du Colombier netlog("getframe 0x%x\n", proto);
4117dd7cddfSDavid du Colombier return b;
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier
4147dd7cddfSDavid du Colombier buf = ppp->inbuf;
4157dd7cddfSDavid du Colombier for(;;){
4167dd7cddfSDavid du Colombier /* read till we hit a frame uchar or run out of room */
4177dd7cddfSDavid du Colombier for(p = buf->rptr; buf->wptr < buf->lim;){
4187dd7cddfSDavid du Colombier for(; p < buf->wptr; p++)
4197dd7cddfSDavid du Colombier if(*p == HDLC_frame)
4207dd7cddfSDavid du Colombier break;
4217dd7cddfSDavid du Colombier if(p != buf->wptr)
4227dd7cddfSDavid du Colombier break;
4237dd7cddfSDavid du Colombier
4247dd7cddfSDavid du Colombier len = buf->lim - buf->wptr;
425d9306527SDavid du Colombier n = read(ppp->mediain, buf->wptr, len);
4267dd7cddfSDavid du Colombier if(n <= 0){
4279a747e4fSDavid du Colombier syslog(0, LOG, "medium read returns %d: %r", n);
4287dd7cddfSDavid du Colombier buf->wptr = buf->rptr;
4297dd7cddfSDavid du Colombier return nil;
4307dd7cddfSDavid du Colombier }
431bedadc12SDavid du Colombier dmppkt("RX", buf->wptr, n);
4327dd7cddfSDavid du Colombier buf->wptr += n;
4337dd7cddfSDavid du Colombier }
4347dd7cddfSDavid du Colombier
4357dd7cddfSDavid du Colombier /* copy into block, undoing escapes, and caculating fcs */
4367dd7cddfSDavid du Colombier fcs = PPP_initfcs;
4377dd7cddfSDavid du Colombier b = allocb(p - buf->rptr);
4387dd7cddfSDavid du Colombier to = b->wptr;
4397dd7cddfSDavid du Colombier for(from = buf->rptr; from != p;){
4407dd7cddfSDavid du Colombier c = *from++;
4417dd7cddfSDavid du Colombier if(c == HDLC_esc){
4427dd7cddfSDavid du Colombier if(from == p)
4437dd7cddfSDavid du Colombier break;
4447dd7cddfSDavid du Colombier c = *from++ ^ 0x20;
4457dd7cddfSDavid du Colombier } else if((c < 0x20) && (ppp->rctlmap & (1 << c)))
4467dd7cddfSDavid du Colombier continue;
4477dd7cddfSDavid du Colombier *to++ = c;
4487dd7cddfSDavid du Colombier fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
4497dd7cddfSDavid du Colombier }
4507dd7cddfSDavid du Colombier
4517dd7cddfSDavid du Colombier /* copy down what's left in buffer */
4527dd7cddfSDavid du Colombier p++;
4537dd7cddfSDavid du Colombier memmove(buf->rptr, p, buf->wptr - p);
4547dd7cddfSDavid du Colombier n = p - buf->rptr;
4557dd7cddfSDavid du Colombier buf->wptr -= n;
4567dd7cddfSDavid du Colombier b->wptr = to - 2;
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier /* return to caller if checksum matches */
4597dd7cddfSDavid du Colombier if(fcs == PPP_goodfcs){
4607dd7cddfSDavid du Colombier if(b->rptr[0] == PPP_addr && b->rptr[1] == PPP_ctl)
4617dd7cddfSDavid du Colombier b->rptr += 2;
4627dd7cddfSDavid du Colombier proto = *b->rptr++;
4637dd7cddfSDavid du Colombier if((proto & 0x1) == 0)
4647dd7cddfSDavid du Colombier proto = (proto<<8) | *b->rptr++;
4657dd7cddfSDavid du Colombier if(b->rptr < b->wptr){
4667dd7cddfSDavid du Colombier ppp->in.uchars += n;
4677dd7cddfSDavid du Colombier ppp->in.packets++;
4687dd7cddfSDavid du Colombier *protop = proto;
4699a747e4fSDavid du Colombier netlog("getframe 0x%x\n", proto);
4707dd7cddfSDavid du Colombier return b;
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier } else if(BLEN(b) > 0){
473fe853e23SDavid du Colombier if(ppp->ctcp)
474fe853e23SDavid du Colombier compress_error(ppp->ctcp);
4757dd7cddfSDavid du Colombier ppp->in.discards++;
47639734e7eSDavid du Colombier netlog("ppp: discard len %ld/%ld cksum %ux (%ux %ux %ux %ux)\n",
4777dd7cddfSDavid du Colombier BLEN(b), BLEN(buf), fcs, b->rptr[0],
4787dd7cddfSDavid du Colombier b->rptr[1], b->rptr[2], b->rptr[3]);
4797dd7cddfSDavid du Colombier }
4807dd7cddfSDavid du Colombier
4817dd7cddfSDavid du Colombier freeb(b);
4827dd7cddfSDavid du Colombier }
4837dd7cddfSDavid du Colombier }
4847dd7cddfSDavid du Colombier
4857dd7cddfSDavid du Colombier /* send a PPP frame */
4867dd7cddfSDavid du Colombier static int
putframe(PPP * ppp,int proto,Block * b)4877dd7cddfSDavid du Colombier putframe(PPP *ppp, int proto, Block *b)
4887dd7cddfSDavid du Colombier {
4897dd7cddfSDavid du Colombier Block *buf;
4907dd7cddfSDavid du Colombier uchar *to, *from;
4917dd7cddfSDavid du Colombier ushort fcs;
4927dd7cddfSDavid du Colombier ulong ctlmap;
4937dd7cddfSDavid du Colombier uchar c;
4947dd7cddfSDavid du Colombier Block *bp;
4957dd7cddfSDavid du Colombier
4967dd7cddfSDavid du Colombier ppp->out.packets++;
4977dd7cddfSDavid du Colombier
4987dd7cddfSDavid du Colombier if(proto == Plcp)
4997dd7cddfSDavid du Colombier ctlmap = 0xffffffff;
5007dd7cddfSDavid du Colombier else
5017dd7cddfSDavid du Colombier ctlmap = ppp->xctlmap;
5027dd7cddfSDavid du Colombier
5037dd7cddfSDavid du Colombier /* make sure we have head room */
5047dd7cddfSDavid du Colombier if(b->rptr - b->base < 4){
5057dd7cddfSDavid du Colombier b = padb(b, 4);
5067dd7cddfSDavid du Colombier b->rptr += 4;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier
5096b6b9ac8SDavid du Colombier netlog("ppp: putframe 0x%ux %ld\n", proto, b->wptr-b->rptr);
5106b6b9ac8SDavid du Colombier
51159cc4ca5SDavid du Colombier /* add in the protocol and address, we'd better have left room */
5127dd7cddfSDavid du Colombier from = b->rptr;
5137dd7cddfSDavid du Colombier *--from = proto;
5147dd7cddfSDavid du Colombier if(!(ppp->lcp->flags&Fpc) || proto > 0x100 || proto == Plcp)
5157dd7cddfSDavid du Colombier *--from = proto>>8;
5169a747e4fSDavid du Colombier if(pppframing && (!(ppp->lcp->flags&Fac) || proto == Plcp)){
5177dd7cddfSDavid du Colombier *--from = PPP_ctl;
5187dd7cddfSDavid du Colombier *--from = PPP_addr;
5197dd7cddfSDavid du Colombier }
5207dd7cddfSDavid du Colombier
5217dd7cddfSDavid du Colombier qlock(&ppp->outlock);
5227dd7cddfSDavid du Colombier buf = ppp->outbuf;
5237dd7cddfSDavid du Colombier
5247dd7cddfSDavid du Colombier if(ppp->framing == 0) {
5257dd7cddfSDavid du Colombier to = buf->rptr;
5267dd7cddfSDavid du Colombier for(bp = b; bp; bp = bp->next){
5277dd7cddfSDavid du Colombier if(bp != b)
5287dd7cddfSDavid du Colombier from = bp->rptr;
5297dd7cddfSDavid du Colombier memmove(to, from, bp->wptr-from);
5307dd7cddfSDavid du Colombier to += bp->wptr-from;
5317dd7cddfSDavid du Colombier }
5327dd7cddfSDavid du Colombier } else {
5337dd7cddfSDavid du Colombier /* escape and checksum the body */
5347dd7cddfSDavid du Colombier fcs = PPP_initfcs;
5357dd7cddfSDavid du Colombier to = buf->rptr;
5366b6b9ac8SDavid du Colombier
5376b6b9ac8SDavid du Colombier /* add frame marker */
5386b6b9ac8SDavid du Colombier *to++ = HDLC_frame;
5396b6b9ac8SDavid du Colombier
5407dd7cddfSDavid du Colombier for(bp = b; bp; bp = bp->next){
5417dd7cddfSDavid du Colombier if(bp != b)
5427dd7cddfSDavid du Colombier from = bp->rptr;
5437dd7cddfSDavid du Colombier for(; from < bp->wptr; from++){
5447dd7cddfSDavid du Colombier c = *from;
5457dd7cddfSDavid du Colombier if(c == HDLC_frame || c == HDLC_esc
5467dd7cddfSDavid du Colombier || (c < 0x20 && ((1<<c) & ctlmap))){
5477dd7cddfSDavid du Colombier *to++ = HDLC_esc;
5487dd7cddfSDavid du Colombier *to++ = c ^ 0x20;
5497dd7cddfSDavid du Colombier } else
5507dd7cddfSDavid du Colombier *to++ = c;
5517dd7cddfSDavid du Colombier fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
5527dd7cddfSDavid du Colombier }
5537dd7cddfSDavid du Colombier }
5547dd7cddfSDavid du Colombier
5557dd7cddfSDavid du Colombier /* add on and escape the checksum */
5567dd7cddfSDavid du Colombier fcs = ~fcs;
5577dd7cddfSDavid du Colombier c = fcs;
5587dd7cddfSDavid du Colombier if(c == HDLC_frame || c == HDLC_esc
5597dd7cddfSDavid du Colombier || (c < 0x20 && ((1<<c) & ctlmap))){
5607dd7cddfSDavid du Colombier *to++ = HDLC_esc;
5617dd7cddfSDavid du Colombier *to++ = c ^ 0x20;
5627dd7cddfSDavid du Colombier } else
5637dd7cddfSDavid du Colombier *to++ = c;
5647dd7cddfSDavid du Colombier c = fcs>>8;
5657dd7cddfSDavid du Colombier if(c == HDLC_frame || c == HDLC_esc
5667dd7cddfSDavid du Colombier || (c < 0x20 && ((1<<c) & ctlmap))){
5677dd7cddfSDavid du Colombier *to++ = HDLC_esc;
5687dd7cddfSDavid du Colombier *to++ = c ^ 0x20;
5697dd7cddfSDavid du Colombier } else
5707dd7cddfSDavid du Colombier *to++ = c;
5717dd7cddfSDavid du Colombier
5727dd7cddfSDavid du Colombier /* add frame marker */
5737dd7cddfSDavid du Colombier *to++ = HDLC_frame;
5747dd7cddfSDavid du Colombier }
5757dd7cddfSDavid du Colombier
5767dd7cddfSDavid du Colombier /* send */
5777dd7cddfSDavid du Colombier buf->wptr = to;
578bedadc12SDavid du Colombier dmppkt("TX", buf->rptr, BLEN(buf));
579d9306527SDavid du Colombier if(write(ppp->mediaout, buf->rptr, BLEN(buf)) < 0){
5807dd7cddfSDavid du Colombier qunlock(&ppp->outlock);
5817dd7cddfSDavid du Colombier return -1;
5827dd7cddfSDavid du Colombier }
5837dd7cddfSDavid du Colombier ppp->out.uchars += BLEN(buf);
5847dd7cddfSDavid du Colombier
5857dd7cddfSDavid du Colombier qunlock(&ppp->outlock);
5867dd7cddfSDavid du Colombier return 0;
5877dd7cddfSDavid du Colombier }
5887dd7cddfSDavid du Colombier
5897dd7cddfSDavid du Colombier Block*
alloclcp(int code,int id,int len,Lcpmsg ** mp)5907dd7cddfSDavid du Colombier alloclcp(int code, int id, int len, Lcpmsg **mp)
5917dd7cddfSDavid du Colombier {
5927dd7cddfSDavid du Colombier Block *b;
5937dd7cddfSDavid du Colombier Lcpmsg *m;
5947dd7cddfSDavid du Colombier
5957dd7cddfSDavid du Colombier /*
5967dd7cddfSDavid du Colombier * leave room for header
5977dd7cddfSDavid du Colombier */
5987dd7cddfSDavid du Colombier b = allocb(len);
5997dd7cddfSDavid du Colombier
6007dd7cddfSDavid du Colombier m = (Lcpmsg*)b->wptr;
6017dd7cddfSDavid du Colombier m->code = code;
6027dd7cddfSDavid du Colombier m->id = id;
6037dd7cddfSDavid du Colombier b->wptr += 4;
6047dd7cddfSDavid du Colombier
6057dd7cddfSDavid du Colombier *mp = m;
6067dd7cddfSDavid du Colombier return b;
6077dd7cddfSDavid du Colombier }
6087dd7cddfSDavid du Colombier
6097dd7cddfSDavid du Colombier
6107dd7cddfSDavid du Colombier static void
putlo(Block * b,int type,ulong val)6117dd7cddfSDavid du Colombier putlo(Block *b, int type, ulong val)
6127dd7cddfSDavid du Colombier {
6137dd7cddfSDavid du Colombier *b->wptr++ = type;
6147dd7cddfSDavid du Colombier *b->wptr++ = 6;
6157dd7cddfSDavid du Colombier hnputl(b->wptr, val);
6167dd7cddfSDavid du Colombier b->wptr += 4;
6177dd7cddfSDavid du Colombier }
6187dd7cddfSDavid du Colombier
6197dd7cddfSDavid du Colombier static void
putv4o(Block * b,int type,Ipaddr val)6207dd7cddfSDavid du Colombier putv4o(Block *b, int type, Ipaddr val)
6217dd7cddfSDavid du Colombier {
6227dd7cddfSDavid du Colombier *b->wptr++ = type;
6237dd7cddfSDavid du Colombier *b->wptr++ = 6;
6247dd7cddfSDavid du Colombier v6tov4(b->wptr, val);
6257dd7cddfSDavid du Colombier b->wptr += 4;
6267dd7cddfSDavid du Colombier }
6277dd7cddfSDavid du Colombier
6287dd7cddfSDavid du Colombier static void
putso(Block * b,int type,ulong val)6297dd7cddfSDavid du Colombier putso(Block *b, int type, ulong val)
6307dd7cddfSDavid du Colombier {
6317dd7cddfSDavid du Colombier *b->wptr++ = type;
6327dd7cddfSDavid du Colombier *b->wptr++ = 4;
6337dd7cddfSDavid du Colombier hnputs(b->wptr, val);
6347dd7cddfSDavid du Colombier b->wptr += 2;
6357dd7cddfSDavid du Colombier }
6367dd7cddfSDavid du Colombier
6377dd7cddfSDavid du Colombier static void
puto(Block * b,int type)6387dd7cddfSDavid du Colombier puto(Block *b, int type)
6397dd7cddfSDavid du Colombier {
6407dd7cddfSDavid du Colombier *b->wptr++ = type;
6417dd7cddfSDavid du Colombier *b->wptr++ = 2;
6427dd7cddfSDavid du Colombier }
6437dd7cddfSDavid du Colombier
6447dd7cddfSDavid du Colombier /*
6457dd7cddfSDavid du Colombier * send configuration request
6467dd7cddfSDavid du Colombier */
6477dd7cddfSDavid du Colombier static void
config(PPP * ppp,Pstate * p,int newid)6487dd7cddfSDavid du Colombier config(PPP *ppp, Pstate *p, int newid)
6497dd7cddfSDavid du Colombier {
6507dd7cddfSDavid du Colombier Block *b;
6517dd7cddfSDavid du Colombier Lcpmsg *m;
6527dd7cddfSDavid du Colombier int id;
6537dd7cddfSDavid du Colombier
6547dd7cddfSDavid du Colombier if(newid){
6556b6b9ac8SDavid du Colombier id = p->id++;
6567dd7cddfSDavid du Colombier p->confid = id;
6577dd7cddfSDavid du Colombier p->timeout = Timeout;
6587dd7cddfSDavid du Colombier } else
6597dd7cddfSDavid du Colombier id = p->confid;
6607dd7cddfSDavid du Colombier b = alloclcp(Lconfreq, id, 256, &m);
6617dd7cddfSDavid du Colombier USED(m);
6627dd7cddfSDavid du Colombier
6637dd7cddfSDavid du Colombier switch(p->proto){
6647dd7cddfSDavid du Colombier case Plcp:
6656b6b9ac8SDavid du Colombier if(p->optmask & Fctlmap)
6666b6b9ac8SDavid du Colombier putlo(b, Octlmap, 0); /* we don't want anything escaped */
6677dd7cddfSDavid du Colombier if(p->optmask & Fmagic)
6687dd7cddfSDavid du Colombier putlo(b, Omagic, ppp->magic);
6697dd7cddfSDavid du Colombier if(p->optmask & Fmtu)
6707dd7cddfSDavid du Colombier putso(b, Omtu, ppp->mru);
6717dd7cddfSDavid du Colombier if(p->optmask & Fauth) {
6727dd7cddfSDavid du Colombier *b->wptr++ = Oauth;
6737dd7cddfSDavid du Colombier *b->wptr++ = 5;
6747dd7cddfSDavid du Colombier hnputs(b->wptr, Pchap);
6757dd7cddfSDavid du Colombier b->wptr += 2;
6767dd7cddfSDavid du Colombier *b->wptr++ = ppp->chap->proto;
6777dd7cddfSDavid du Colombier }
6787dd7cddfSDavid du Colombier if(p->optmask & Fpc)
6797dd7cddfSDavid du Colombier puto(b, Opc);
6806b6b9ac8SDavid du Colombier if(p->optmask & Fac)
6816b6b9ac8SDavid du Colombier puto(b, Oac);
6827dd7cddfSDavid du Colombier break;
6837dd7cddfSDavid du Colombier case Pccp:
68459cc4ca5SDavid du Colombier if(p->optmask & Fcthwack)
68559cc4ca5SDavid du Colombier puto(b, Octhwack);
68659cc4ca5SDavid du Colombier else if(p->optmask & Fcmppc) {
6877dd7cddfSDavid du Colombier *b->wptr++ = Ocmppc;
6887dd7cddfSDavid du Colombier *b->wptr++ = 6;
6897dd7cddfSDavid du Colombier *b->wptr++ = 0;
6907dd7cddfSDavid du Colombier *b->wptr++ = 0;
6917dd7cddfSDavid du Colombier *b->wptr++ = 0;
6927dd7cddfSDavid du Colombier *b->wptr++ = 0x41;
6937dd7cddfSDavid du Colombier }
6947dd7cddfSDavid du Colombier break;
6957dd7cddfSDavid du Colombier case Pipcp:
6967dd7cddfSDavid du Colombier if(p->optmask & Fipaddr)
6976b6b9ac8SDavid du Colombier {syslog(0, "ppp", "requesting %I", ppp->local);
6987dd7cddfSDavid du Colombier putv4o(b, Oipaddr, ppp->local);
6996b6b9ac8SDavid du Colombier }
700bedadc12SDavid du Colombier if(primary && (p->optmask & Fipdns))
701bedadc12SDavid du Colombier putv4o(b, Oipdns, ppp->dns[0]);
702bedadc12SDavid du Colombier if(primary && (p->optmask & Fipdns2))
703bedadc12SDavid du Colombier putv4o(b, Oipdns2, ppp->dns[1]);
704bedadc12SDavid du Colombier if(primary && (p->optmask & Fipwins))
705bedadc12SDavid du Colombier putv4o(b, Oipwins, ppp->wins[0]);
706bedadc12SDavid du Colombier if(primary && (p->optmask & Fipwins2))
707bedadc12SDavid du Colombier putv4o(b, Oipwins2, ppp->wins[1]);
70859cc4ca5SDavid du Colombier /*
70959cc4ca5SDavid du Colombier * don't ask for header compression while data compression is still pending.
71059cc4ca5SDavid du Colombier * perhaps we should restart ipcp negotiation if compression negotiation fails.
71159cc4ca5SDavid du Colombier */
71259cc4ca5SDavid du Colombier if(!noipcompress && !ppp->ccp->optmask && (p->optmask & Fipcompress)) {
7137dd7cddfSDavid du Colombier *b->wptr++ = Oipcompress;
7147dd7cddfSDavid du Colombier *b->wptr++ = 6;
7157dd7cddfSDavid du Colombier hnputs(b->wptr, Pvjctcp);
7167dd7cddfSDavid du Colombier b->wptr += 2;
7177dd7cddfSDavid du Colombier *b->wptr++ = MAX_STATES-1;
7187dd7cddfSDavid du Colombier *b->wptr++ = 1;
7197dd7cddfSDavid du Colombier }
7207dd7cddfSDavid du Colombier break;
7217dd7cddfSDavid du Colombier }
7227dd7cddfSDavid du Colombier hnputs(m->len, BLEN(b));
7237dd7cddfSDavid du Colombier printopts(p, b, 1);
7247dd7cddfSDavid du Colombier putframe(ppp, p->proto, b);
7257dd7cddfSDavid du Colombier freeb(b);
7267dd7cddfSDavid du Colombier }
7277dd7cddfSDavid du Colombier
7287dd7cddfSDavid du Colombier static void
getipinfo(PPP * ppp)7297dd7cddfSDavid du Colombier getipinfo(PPP *ppp)
7307dd7cddfSDavid du Colombier {
7317dd7cddfSDavid du Colombier char *av[3];
7327dd7cddfSDavid du Colombier int ndns, nwins;
7337dd7cddfSDavid du Colombier char ip[64];
7347dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
7357dd7cddfSDavid du Colombier
7367dd7cddfSDavid du Colombier if(!validv4(ppp->local))
7377dd7cddfSDavid du Colombier return;
7387dd7cddfSDavid du Colombier
7397dd7cddfSDavid du Colombier av[0] = "dns";
7407dd7cddfSDavid du Colombier av[1] = "wins";
7417dd7cddfSDavid du Colombier sprint(ip, "%I", ppp->local);
7427dd7cddfSDavid du Colombier t = csipinfo(ppp->net, "ip", ip, av, 2);
7437dd7cddfSDavid du Colombier ndns = nwins = 0;
7447dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){
7457dd7cddfSDavid du Colombier if(strcmp(nt->attr, "dns") == 0){
7467dd7cddfSDavid du Colombier if(ndns < 2)
7477dd7cddfSDavid du Colombier parseip(ppp->dns[ndns++], nt->val);
7487dd7cddfSDavid du Colombier } else if(strcmp(nt->attr, "wins") == 0){
7497dd7cddfSDavid du Colombier if(nwins < 2)
7507dd7cddfSDavid du Colombier parseip(ppp->wins[nwins++], nt->val);
7517dd7cddfSDavid du Colombier }
7527dd7cddfSDavid du Colombier }
7537dd7cddfSDavid du Colombier if(t != nil)
7547dd7cddfSDavid du Colombier ndbfree(t);
7557dd7cddfSDavid du Colombier }
7567dd7cddfSDavid du Colombier
7577dd7cddfSDavid du Colombier /*
7587dd7cddfSDavid du Colombier * parse configuration request, sends an ack or reject packet
7597dd7cddfSDavid du Colombier *
7607dd7cddfSDavid du Colombier * returns: -1 if request was syntacticly incorrect
7617dd7cddfSDavid du Colombier * 0 if packet was accepted
7627dd7cddfSDavid du Colombier * 1 if packet was rejected
7637dd7cddfSDavid du Colombier */
7647dd7cddfSDavid du Colombier static int
getopts(PPP * ppp,Pstate * p,Block * b)7657dd7cddfSDavid du Colombier getopts(PPP *ppp, Pstate *p, Block *b)
7667dd7cddfSDavid du Colombier {
7677dd7cddfSDavid du Colombier Lcpmsg *m, *repm;
7687dd7cddfSDavid du Colombier Lcpopt *o;
7697dd7cddfSDavid du Colombier uchar *cp, *ap;
7709a747e4fSDavid du Colombier ulong rejecting, nacking, flags, proto, chapproto;
7717dd7cddfSDavid du Colombier ulong mtu, ctlmap, period;
7727dd7cddfSDavid du Colombier ulong x;
7737dd7cddfSDavid du Colombier Block *repb;
7747dd7cddfSDavid du Colombier Comptype *ctype;
7757dd7cddfSDavid du Colombier Ipaddr ipaddr;
7767dd7cddfSDavid du Colombier
7777dd7cddfSDavid du Colombier rejecting = 0;
7787dd7cddfSDavid du Colombier nacking = 0;
7797dd7cddfSDavid du Colombier flags = 0;
7807dd7cddfSDavid du Colombier
7817dd7cddfSDavid du Colombier /* defaults */
7827dd7cddfSDavid du Colombier invalidate(ipaddr);
7837dd7cddfSDavid du Colombier mtu = ppp->mtu;
7847dd7cddfSDavid du Colombier ctlmap = 0xffffffff;
7857dd7cddfSDavid du Colombier period = 0;
7867dd7cddfSDavid du Colombier ctype = nil;
7879a747e4fSDavid du Colombier chapproto = 0;
7887dd7cddfSDavid du Colombier
7897dd7cddfSDavid du Colombier m = (Lcpmsg*)b->rptr;
7907dd7cddfSDavid du Colombier repb = alloclcp(Lconfack, m->id, BLEN(b), &repm);
7917dd7cddfSDavid du Colombier
7927dd7cddfSDavid du Colombier /* copy options into ack packet */
7937dd7cddfSDavid du Colombier memmove(repm->data, m->data, b->wptr - m->data);
7947dd7cddfSDavid du Colombier repb->wptr += b->wptr - m->data;
7957dd7cddfSDavid du Colombier
7967dd7cddfSDavid du Colombier /* look for options we don't recognize or like */
7977dd7cddfSDavid du Colombier for(cp = m->data; cp < b->wptr; cp += o->len){
7987dd7cddfSDavid du Colombier o = (Lcpopt*)cp;
7997dd7cddfSDavid du Colombier if(cp + o->len > b->wptr || o->len==0){
8007dd7cddfSDavid du Colombier freeb(repb);
8017dd7cddfSDavid du Colombier netlog("ppp: bad option length %ux\n", o->type);
8027dd7cddfSDavid du Colombier return -1;
8037dd7cddfSDavid du Colombier }
8047dd7cddfSDavid du Colombier
8057dd7cddfSDavid du Colombier switch(p->proto){
8067dd7cddfSDavid du Colombier case Plcp:
8077dd7cddfSDavid du Colombier switch(o->type){
8087dd7cddfSDavid du Colombier case Oac:
8097dd7cddfSDavid du Colombier flags |= Fac;
8107dd7cddfSDavid du Colombier continue;
8117dd7cddfSDavid du Colombier case Opc:
8127dd7cddfSDavid du Colombier flags |= Fpc;
8137dd7cddfSDavid du Colombier continue;
8147dd7cddfSDavid du Colombier case Omtu:
8157dd7cddfSDavid du Colombier mtu = nhgets(o->data);
8167dd7cddfSDavid du Colombier continue;
8177dd7cddfSDavid du Colombier case Omagic:
8187dd7cddfSDavid du Colombier if(ppp->magic == nhgetl(o->data))
8197dd7cddfSDavid du Colombier netlog("ppp: possible loop\n");
8207dd7cddfSDavid du Colombier continue;
8217dd7cddfSDavid du Colombier case Octlmap:
8227dd7cddfSDavid du Colombier ctlmap = nhgetl(o->data);
8237dd7cddfSDavid du Colombier continue;
8247dd7cddfSDavid du Colombier case Oquality:
8257dd7cddfSDavid du Colombier proto = nhgets(o->data);
8267dd7cddfSDavid du Colombier if(proto != Plqm)
8277dd7cddfSDavid du Colombier break;
8287dd7cddfSDavid du Colombier x = nhgetl(o->data+2)*10;
8297dd7cddfSDavid du Colombier period = (x+Period-1)/Period;
8307dd7cddfSDavid du Colombier continue;
8317dd7cddfSDavid du Colombier case Oauth:
8327dd7cddfSDavid du Colombier proto = nhgets(o->data);
83380ee5cbfSDavid du Colombier if(proto == Ppasswd && !server){
8349a747e4fSDavid du Colombier chapproto = APpasswd;
83580ee5cbfSDavid du Colombier continue;
83680ee5cbfSDavid du Colombier }
8377dd7cddfSDavid du Colombier if(proto != Pchap)
8387dd7cddfSDavid du Colombier break;
8399a747e4fSDavid du Colombier if(o->data[2] != APmd5 && o->data[2] != APmschap)
8407dd7cddfSDavid du Colombier break;
8419a747e4fSDavid du Colombier chapproto = o->data[2];
8427dd7cddfSDavid du Colombier continue;
8437dd7cddfSDavid du Colombier }
8447dd7cddfSDavid du Colombier break;
8457dd7cddfSDavid du Colombier case Pccp:
8467dd7cddfSDavid du Colombier if(nocompress)
8477dd7cddfSDavid du Colombier break;
8487dd7cddfSDavid du Colombier switch(o->type){
8497dd7cddfSDavid du Colombier case Octhwack:
8507dd7cddfSDavid du Colombier break;
851b85a8364SDavid du Colombier /*
8527dd7cddfSDavid du Colombier if(o->len == 2){
8537dd7cddfSDavid du Colombier ctype = &cthwack;
8547dd7cddfSDavid du Colombier continue;
8557dd7cddfSDavid du Colombier }
8567dd7cddfSDavid du Colombier if(!nacking){
8577dd7cddfSDavid du Colombier nacking = 1;
8587dd7cddfSDavid du Colombier repb->wptr = repm->data;
8597dd7cddfSDavid du Colombier repm->code = Lconfnak;
8607dd7cddfSDavid du Colombier }
86159cc4ca5SDavid du Colombier puto(repb, Octhwack);
8627dd7cddfSDavid du Colombier continue;
863b85a8364SDavid du Colombier */
8647dd7cddfSDavid du Colombier case Ocmppc:
8657dd7cddfSDavid du Colombier x = nhgetl(o->data);
8667dd7cddfSDavid du Colombier
8677dd7cddfSDavid du Colombier // hack for Mac
8687dd7cddfSDavid du Colombier // if(x == 0)
8697dd7cddfSDavid du Colombier // continue;
8707dd7cddfSDavid du Colombier
8717dd7cddfSDavid du Colombier /* stop ppp loops */
8727dd7cddfSDavid du Colombier if((x&0x41) == 0 || ppp->ctries++ > 5) {
8737dd7cddfSDavid du Colombier /*
8747dd7cddfSDavid du Colombier * turn off requests as well - I don't think this
8757dd7cddfSDavid du Colombier * is needed in the standard
8767dd7cddfSDavid du Colombier */
8777dd7cddfSDavid du Colombier p->optmask &= ~Fcmppc;
8787dd7cddfSDavid du Colombier break;
8797dd7cddfSDavid du Colombier }
8807dd7cddfSDavid du Colombier if(rejecting)
8817dd7cddfSDavid du Colombier continue;
882bedadc12SDavid du Colombier if(x & 1) {
8837dd7cddfSDavid du Colombier ctype = &cmppc;
8847dd7cddfSDavid du Colombier ppp->sendencrypted = (o->data[3]&0x40) == 0x40;
8857dd7cddfSDavid du Colombier continue;
8867dd7cddfSDavid du Colombier }
8877dd7cddfSDavid du Colombier if(!nacking){
8887dd7cddfSDavid du Colombier nacking = 1;
8897dd7cddfSDavid du Colombier repb->wptr = repm->data;
8907dd7cddfSDavid du Colombier repm->code = Lconfnak;
8917dd7cddfSDavid du Colombier }
8927dd7cddfSDavid du Colombier *repb->wptr++ = Ocmppc;
8937dd7cddfSDavid du Colombier *repb->wptr++ = 6;
8947dd7cddfSDavid du Colombier *repb->wptr++ = 0;
8957dd7cddfSDavid du Colombier *repb->wptr++ = 0;
8967dd7cddfSDavid du Colombier *repb->wptr++ = 0;
8977dd7cddfSDavid du Colombier *repb->wptr++ = 0x41;
8987dd7cddfSDavid du Colombier continue;
8997dd7cddfSDavid du Colombier }
9007dd7cddfSDavid du Colombier break;
9017dd7cddfSDavid du Colombier case Pipcp:
9027dd7cddfSDavid du Colombier switch(o->type){
9037dd7cddfSDavid du Colombier case Oipaddr:
9047dd7cddfSDavid du Colombier v4tov6(ipaddr, o->data);
9057dd7cddfSDavid du Colombier if(!validv4(ppp->remote))
9067dd7cddfSDavid du Colombier continue;
9077dd7cddfSDavid du Colombier if(!validv4(ipaddr) && !rejecting){
9087dd7cddfSDavid du Colombier /* other side requesting an address */
9097dd7cddfSDavid du Colombier if(!nacking){
9107dd7cddfSDavid du Colombier nacking = 1;
9117dd7cddfSDavid du Colombier repb->wptr = repm->data;
9127dd7cddfSDavid du Colombier repm->code = Lconfnak;
9137dd7cddfSDavid du Colombier }
9147dd7cddfSDavid du Colombier putv4o(repb, Oipaddr, ppp->remote);
9157dd7cddfSDavid du Colombier }
9167dd7cddfSDavid du Colombier continue;
9177dd7cddfSDavid du Colombier case Oipdns:
9187dd7cddfSDavid du Colombier ap = ppp->dns[0];
9197dd7cddfSDavid du Colombier goto ipinfo;
9207dd7cddfSDavid du Colombier case Oipdns2:
9217dd7cddfSDavid du Colombier ap = ppp->dns[1];
9227dd7cddfSDavid du Colombier goto ipinfo;
9237dd7cddfSDavid du Colombier case Oipwins:
9247dd7cddfSDavid du Colombier ap = ppp->wins[0];
9257dd7cddfSDavid du Colombier goto ipinfo;
9267dd7cddfSDavid du Colombier case Oipwins2:
9277dd7cddfSDavid du Colombier ap = ppp->wins[1];
9287dd7cddfSDavid du Colombier goto ipinfo;
9297dd7cddfSDavid du Colombier ipinfo:
9307dd7cddfSDavid du Colombier if(!validv4(ap))
9317dd7cddfSDavid du Colombier getipinfo(ppp);
9327dd7cddfSDavid du Colombier if(!validv4(ap))
9337dd7cddfSDavid du Colombier break;
9347dd7cddfSDavid du Colombier v4tov6(ipaddr, o->data);
9357dd7cddfSDavid du Colombier if(!validv4(ipaddr) && !rejecting){
9367dd7cddfSDavid du Colombier /* other side requesting an address */
9377dd7cddfSDavid du Colombier if(!nacking){
9387dd7cddfSDavid du Colombier nacking = 1;
9397dd7cddfSDavid du Colombier repb->wptr = repm->data;
9407dd7cddfSDavid du Colombier repm->code = Lconfnak;
9417dd7cddfSDavid du Colombier }
9427dd7cddfSDavid du Colombier putv4o(repb, o->type, ap);
9437dd7cddfSDavid du Colombier }
9447dd7cddfSDavid du Colombier continue;
9457dd7cddfSDavid du Colombier case Oipcompress:
94659cc4ca5SDavid du Colombier /*
94759cc4ca5SDavid du Colombier * don't compress tcp header if we've negotiated data compression.
94859cc4ca5SDavid du Colombier * tcp header compression has very poor performance if there is an error.
94959cc4ca5SDavid du Colombier */
9507dd7cddfSDavid du Colombier proto = nhgets(o->data);
95159cc4ca5SDavid du Colombier if(noipcompress || proto != Pvjctcp || ppp->ctype != nil)
9527dd7cddfSDavid du Colombier break;
9537dd7cddfSDavid du Colombier if(compress_negotiate(ppp->ctcp, o->data+2) < 0)
9547dd7cddfSDavid du Colombier break;
9557dd7cddfSDavid du Colombier flags |= Fipcompress;
9567dd7cddfSDavid du Colombier continue;
9577dd7cddfSDavid du Colombier }
9587dd7cddfSDavid du Colombier break;
9597dd7cddfSDavid du Colombier }
9607dd7cddfSDavid du Colombier
9617dd7cddfSDavid du Colombier /* come here if option is not recognized */
9627dd7cddfSDavid du Colombier if(!rejecting){
9637dd7cddfSDavid du Colombier rejecting = 1;
9647dd7cddfSDavid du Colombier repb->wptr = repm->data;
9657dd7cddfSDavid du Colombier repm->code = Lconfrej;
9667dd7cddfSDavid du Colombier }
9677dd7cddfSDavid du Colombier netlog("ppp: bad %ux option %d\n", p->proto, o->type);
9687dd7cddfSDavid du Colombier memmove(repb->wptr, o, o->len);
9697dd7cddfSDavid du Colombier repb->wptr += o->len;
9707dd7cddfSDavid du Colombier }
9717dd7cddfSDavid du Colombier
9727dd7cddfSDavid du Colombier /* permanent changes only after we know that we liked the packet */
9737dd7cddfSDavid du Colombier if(!rejecting && !nacking){
9747dd7cddfSDavid du Colombier switch(p->proto){
9757dd7cddfSDavid du Colombier case Plcp:
9767dd7cddfSDavid du Colombier ppp->period = period;
9777dd7cddfSDavid du Colombier ppp->xctlmap = ctlmap;
9787dd7cddfSDavid du Colombier if(mtu > Maxmtu)
9797dd7cddfSDavid du Colombier mtu = Maxmtu;
9807dd7cddfSDavid du Colombier if(mtu < Minmtu)
9817dd7cddfSDavid du Colombier mtu = Minmtu;
9827dd7cddfSDavid du Colombier ppp->mtu = mtu;
9839a747e4fSDavid du Colombier if(chapproto)
9849a747e4fSDavid du Colombier ppp->chap->proto = chapproto;
9857dd7cddfSDavid du Colombier
9867dd7cddfSDavid du Colombier break;
9877dd7cddfSDavid du Colombier case Pccp:
98859cc4ca5SDavid du Colombier if(ppp->ctype != nil){
98959cc4ca5SDavid du Colombier (*ppp->ctype->fini)(ppp->cstate);
99059cc4ca5SDavid du Colombier ppp->cstate = nil;
99159cc4ca5SDavid du Colombier }
9927dd7cddfSDavid du Colombier ppp->ctype = ctype;
9937dd7cddfSDavid du Colombier if(ctype)
9947dd7cddfSDavid du Colombier ppp->cstate = (*ctype->init)(ppp);
9957dd7cddfSDavid du Colombier break;
9967dd7cddfSDavid du Colombier case Pipcp:
9977dd7cddfSDavid du Colombier if(validv4(ipaddr) && ppp->remotefrozen == 0)
9987dd7cddfSDavid du Colombier ipmove(ppp->remote, ipaddr);
9997dd7cddfSDavid du Colombier break;
10007dd7cddfSDavid du Colombier }
100159cc4ca5SDavid du Colombier p->flags = flags;
10027dd7cddfSDavid du Colombier }
10037dd7cddfSDavid du Colombier
10047dd7cddfSDavid du Colombier hnputs(repm->len, BLEN(repb));
10057dd7cddfSDavid du Colombier printopts(p, repb, 1);
10067dd7cddfSDavid du Colombier putframe(ppp, p->proto, repb);
10077dd7cddfSDavid du Colombier freeb(repb);
10087dd7cddfSDavid du Colombier
10097dd7cddfSDavid du Colombier return rejecting || nacking;
10107dd7cddfSDavid du Colombier }
1011bedadc12SDavid du Colombier static void
dmppkt(char * s,uchar * a,int na)1012bedadc12SDavid du Colombier dmppkt(char *s, uchar *a, int na)
1013bedadc12SDavid du Colombier {
1014bedadc12SDavid du Colombier int i;
1015bedadc12SDavid du Colombier
1016bedadc12SDavid du Colombier if (debug < 3)
1017bedadc12SDavid du Colombier return;
1018bedadc12SDavid du Colombier
1019bedadc12SDavid du Colombier fprint(2, "%s", s);
1020bedadc12SDavid du Colombier for(i = 0; i < na; i++)
1021bedadc12SDavid du Colombier fprint(2, " %.2ux", a[i]);
1022bedadc12SDavid du Colombier fprint(2, "\n");
1023bedadc12SDavid du Colombier }
10247dd7cddfSDavid du Colombier
10256b6b9ac8SDavid du Colombier static void
dropoption(Pstate * p,Lcpopt * o)10266b6b9ac8SDavid du Colombier dropoption(Pstate *p, Lcpopt *o)
10276b6b9ac8SDavid du Colombier {
1028bedadc12SDavid du Colombier unsigned n = o->type;
1029bedadc12SDavid du Colombier
1030bedadc12SDavid du Colombier switch(n){
103187dfdc75SDavid du Colombier case Oipaddr:
103287dfdc75SDavid du Colombier break;
1033bedadc12SDavid du Colombier case Oipdns:
1034bedadc12SDavid du Colombier p->optmask &= ~Fipdns;
1035bedadc12SDavid du Colombier break;
1036bedadc12SDavid du Colombier case Oipwins:
1037bedadc12SDavid du Colombier p->optmask &= ~Fipwins;
1038bedadc12SDavid du Colombier break;
1039bedadc12SDavid du Colombier case Oipdns2:
1040bedadc12SDavid du Colombier p->optmask &= ~Fipdns2;
1041bedadc12SDavid du Colombier break;
1042bedadc12SDavid du Colombier case Oipwins2:
1043bedadc12SDavid du Colombier p->optmask &= ~Fipwins2;
1044bedadc12SDavid du Colombier break;
1045bedadc12SDavid du Colombier default:
10466b6b9ac8SDavid du Colombier if(o->type < 8*sizeof(p->optmask))
10476b6b9ac8SDavid du Colombier p->optmask &= ~(1<<o->type);
1048bedadc12SDavid du Colombier break;
1049bedadc12SDavid du Colombier }
10506b6b9ac8SDavid du Colombier }
10516b6b9ac8SDavid du Colombier
10527dd7cddfSDavid du Colombier /*
10537dd7cddfSDavid du Colombier * parse configuration rejection, just stop sending anything that they
10547dd7cddfSDavid du Colombier * don't like (except for ipcp address nak).
10557dd7cddfSDavid du Colombier */
10567dd7cddfSDavid du Colombier static void
rejopts(PPP * ppp,Pstate * p,Block * b,int code)10577dd7cddfSDavid du Colombier rejopts(PPP *ppp, Pstate *p, Block *b, int code)
10587dd7cddfSDavid du Colombier {
10597dd7cddfSDavid du Colombier Lcpmsg *m;
10607dd7cddfSDavid du Colombier Lcpopt *o;
10616b6b9ac8SDavid du Colombier uchar newip[IPaddrlen];
10627dd7cddfSDavid du Colombier
10637dd7cddfSDavid du Colombier /* just give up trying what the other side doesn't like */
10647dd7cddfSDavid du Colombier m = (Lcpmsg*)b->rptr;
10657dd7cddfSDavid du Colombier for(b->rptr = m->data; b->rptr < b->wptr; b->rptr += o->len){
10667dd7cddfSDavid du Colombier o = (Lcpopt*)b->rptr;
10677dd7cddfSDavid du Colombier if(b->rptr + o->len > b->wptr){
10687dd7cddfSDavid du Colombier netlog("ppp: bad roption length %ux\n", o->type);
10697dd7cddfSDavid du Colombier return;
10707dd7cddfSDavid du Colombier }
10717dd7cddfSDavid du Colombier
10727dd7cddfSDavid du Colombier if(code == Lconfrej){
10736b6b9ac8SDavid du Colombier dropoption(p, o);
10747dd7cddfSDavid du Colombier netlog("ppp: %ux rejecting %d\n",
10757dd7cddfSDavid du Colombier p->proto, o->type);
10767dd7cddfSDavid du Colombier continue;
10777dd7cddfSDavid du Colombier }
10787dd7cddfSDavid du Colombier
10797dd7cddfSDavid du Colombier switch(p->proto){
10807dd7cddfSDavid du Colombier case Plcp:
10817dd7cddfSDavid du Colombier switch(o->type){
10827dd7cddfSDavid du Colombier case Octlmap:
10837dd7cddfSDavid du Colombier ppp->rctlmap = nhgetl(o->data);
10847dd7cddfSDavid du Colombier break;
10857dd7cddfSDavid du Colombier case Oauth:
10867dd7cddfSDavid du Colombier /* don't allow client to request no auth */
10877dd7cddfSDavid du Colombier /* could try different auth protocol here */
10887dd7cddfSDavid du Colombier fprint(2, "ppp: can not reject CHAP\n");
10897dd7cddfSDavid du Colombier exits("ppp: CHAP");
10907dd7cddfSDavid du Colombier break;
10917dd7cddfSDavid du Colombier default:
10927dd7cddfSDavid du Colombier if(o->type < 8*sizeof(p->optmask))
10937dd7cddfSDavid du Colombier p->optmask &= ~(1<<o->type);
10947dd7cddfSDavid du Colombier break;
10957dd7cddfSDavid du Colombier };
10967dd7cddfSDavid du Colombier break;
10977dd7cddfSDavid du Colombier case Pccp:
10987dd7cddfSDavid du Colombier switch(o->type){
10997dd7cddfSDavid du Colombier default:
11006b6b9ac8SDavid du Colombier dropoption(p, o);
11017dd7cddfSDavid du Colombier break;
11027dd7cddfSDavid du Colombier }
11037dd7cddfSDavid du Colombier break;
11047dd7cddfSDavid du Colombier case Pipcp:
11057dd7cddfSDavid du Colombier switch(o->type){
11067dd7cddfSDavid du Colombier case Oipaddr:
11076b6b9ac8SDavid du Colombier syslog(0, "ppp", "rejected addr %I with %V", ppp->local, o->data);
11086b6b9ac8SDavid du Colombier /* if we're a server, don't let other end change our addr */
11096b6b9ac8SDavid du Colombier if(ppp->localfrozen){
11106b6b9ac8SDavid du Colombier dropoption(p, o);
11116b6b9ac8SDavid du Colombier break;
11126b6b9ac8SDavid du Colombier }
11136b6b9ac8SDavid du Colombier
11146b6b9ac8SDavid du Colombier /* accept whatever server tells us */
11156b6b9ac8SDavid du Colombier if(!validv4(ppp->local)){
11166b6b9ac8SDavid du Colombier v4tov6(ppp->local, o->data);
11176b6b9ac8SDavid du Colombier dropoption(p, o);
11186b6b9ac8SDavid du Colombier break;
11196b6b9ac8SDavid du Colombier }
11206b6b9ac8SDavid du Colombier
11216b6b9ac8SDavid du Colombier /* if he didn't like our addr, ask for a generic one */
11226b6b9ac8SDavid du Colombier v4tov6(newip, o->data);
11236b6b9ac8SDavid du Colombier if(!validv4(newip)){
11246b6b9ac8SDavid du Colombier invalidate(ppp->local);
11256b6b9ac8SDavid du Colombier break;
11266b6b9ac8SDavid du Colombier }
11276b6b9ac8SDavid du Colombier
11286b6b9ac8SDavid du Colombier /* if he gives us something different, use it anyways */
11296b6b9ac8SDavid du Colombier v4tov6(ppp->local, o->data);
11306b6b9ac8SDavid du Colombier dropoption(p, o);
11317dd7cddfSDavid du Colombier break;
1132bedadc12SDavid du Colombier case Oipdns:
1133bedadc12SDavid du Colombier if (!validv4(ppp->dns[0])){
1134bedadc12SDavid du Colombier v4tov6(ppp->dns[0], o->data);
1135bedadc12SDavid du Colombier dropoption(p, o);
1136bedadc12SDavid du Colombier break;
1137bedadc12SDavid du Colombier }
1138bedadc12SDavid du Colombier v4tov6(newip, o->data);
1139bedadc12SDavid du Colombier if(!validv4(newip)){
1140bedadc12SDavid du Colombier invalidate(ppp->dns[0]);
1141bedadc12SDavid du Colombier break;
1142bedadc12SDavid du Colombier }
1143bedadc12SDavid du Colombier v4tov6(ppp->dns[0], o->data);
1144bedadc12SDavid du Colombier dropoption(p, o);
1145bedadc12SDavid du Colombier break;
1146bedadc12SDavid du Colombier case Oipwins:
1147bedadc12SDavid du Colombier if (!validv4(ppp->wins[0])){
1148bedadc12SDavid du Colombier v4tov6(ppp->wins[0], o->data);
1149bedadc12SDavid du Colombier dropoption(p, o);
1150bedadc12SDavid du Colombier break;
1151bedadc12SDavid du Colombier }
1152bedadc12SDavid du Colombier v4tov6(newip, o->data);
1153bedadc12SDavid du Colombier if(!validv4(newip)){
1154bedadc12SDavid du Colombier invalidate(ppp->wins[0]);
1155bedadc12SDavid du Colombier break;
1156bedadc12SDavid du Colombier }
1157bedadc12SDavid du Colombier v4tov6(ppp->wins[0], o->data);
1158bedadc12SDavid du Colombier dropoption(p, o);
1159bedadc12SDavid du Colombier break;
1160bedadc12SDavid du Colombier case Oipdns2:
1161bedadc12SDavid du Colombier if (!validv4(ppp->dns[1])){
1162bedadc12SDavid du Colombier v4tov6(ppp->dns[1], o->data);
1163bedadc12SDavid du Colombier dropoption(p, o);
1164bedadc12SDavid du Colombier break;
1165bedadc12SDavid du Colombier }
1166bedadc12SDavid du Colombier v4tov6(newip, o->data);
1167bedadc12SDavid du Colombier if(!validv4(newip)){
1168bedadc12SDavid du Colombier invalidate(ppp->dns[1]);
1169bedadc12SDavid du Colombier break;
1170bedadc12SDavid du Colombier }
1171bedadc12SDavid du Colombier v4tov6(ppp->dns[1], o->data);
1172bedadc12SDavid du Colombier dropoption(p, o);
1173bedadc12SDavid du Colombier break;
1174bedadc12SDavid du Colombier case Oipwins2:
1175bedadc12SDavid du Colombier if (!validv4(ppp->wins[1])){
1176bedadc12SDavid du Colombier v4tov6(ppp->wins[1], o->data);
1177bedadc12SDavid du Colombier dropoption(p, o);
1178bedadc12SDavid du Colombier break;
1179bedadc12SDavid du Colombier }
1180bedadc12SDavid du Colombier v4tov6(newip, o->data);
1181bedadc12SDavid du Colombier if(!validv4(newip)){
1182bedadc12SDavid du Colombier invalidate(ppp->wins[1]);
1183bedadc12SDavid du Colombier break;
1184bedadc12SDavid du Colombier }
1185bedadc12SDavid du Colombier v4tov6(ppp->wins[1], o->data);
1186bedadc12SDavid du Colombier dropoption(p, o);
1187bedadc12SDavid du Colombier break;
11887dd7cddfSDavid du Colombier default:
11896b6b9ac8SDavid du Colombier dropoption(p, o);
11907dd7cddfSDavid du Colombier break;
11917dd7cddfSDavid du Colombier }
11927dd7cddfSDavid du Colombier break;
11937dd7cddfSDavid du Colombier }
11947dd7cddfSDavid du Colombier }
11957dd7cddfSDavid du Colombier }
11967dd7cddfSDavid du Colombier
11977dd7cddfSDavid du Colombier
11987dd7cddfSDavid du Colombier /*
11997dd7cddfSDavid du Colombier * put a messages through the lcp or ipcp state machine. They are
12007dd7cddfSDavid du Colombier * very similar.
12017dd7cddfSDavid du Colombier */
12027dd7cddfSDavid du Colombier static void
rcv(PPP * ppp,Pstate * p,Block * b)12037dd7cddfSDavid du Colombier rcv(PPP *ppp, Pstate *p, Block *b)
12047dd7cddfSDavid du Colombier {
12057dd7cddfSDavid du Colombier ulong len;
12067dd7cddfSDavid du Colombier int err;
12077dd7cddfSDavid du Colombier Lcpmsg *m;
12087dd7cddfSDavid du Colombier int proto;
12097dd7cddfSDavid du Colombier
12107dd7cddfSDavid du Colombier if(BLEN(b) < 4){
12117dd7cddfSDavid du Colombier netlog("ppp: short lcp message\n");
12127dd7cddfSDavid du Colombier freeb(b);
12137dd7cddfSDavid du Colombier return;
12147dd7cddfSDavid du Colombier }
12157dd7cddfSDavid du Colombier m = (Lcpmsg*)b->rptr;
12167dd7cddfSDavid du Colombier len = nhgets(m->len);
12177dd7cddfSDavid du Colombier if(BLEN(b) < len){
12187dd7cddfSDavid du Colombier netlog("ppp: short lcp message\n");
12197dd7cddfSDavid du Colombier freeb(b);
12207dd7cddfSDavid du Colombier return;
12217dd7cddfSDavid du Colombier }
12227dd7cddfSDavid du Colombier
122359cc4ca5SDavid du Colombier netlog("ppp: %ux rcv %d len %ld id %d/%d/%d\n",
12247dd7cddfSDavid du Colombier p->proto, m->code, len, m->id, p->confid, p->id);
12257dd7cddfSDavid du Colombier
12267dd7cddfSDavid du Colombier if(p->proto != Plcp && ppp->lcp->state != Sopened){
12277dd7cddfSDavid du Colombier netlog("ppp: non-lcp with lcp not open\n");
12287dd7cddfSDavid du Colombier freeb(b);
12297dd7cddfSDavid du Colombier return;
12307dd7cddfSDavid du Colombier }
12317dd7cddfSDavid du Colombier
12327dd7cddfSDavid du Colombier qlock(ppp);
12337dd7cddfSDavid du Colombier switch(m->code){
12347dd7cddfSDavid du Colombier case Lconfreq:
12357dd7cddfSDavid du Colombier printopts(p, b, 0);
12367dd7cddfSDavid du Colombier err = getopts(ppp, p, b);
12377dd7cddfSDavid du Colombier if(err < 0)
12387dd7cddfSDavid du Colombier break;
12397dd7cddfSDavid du Colombier
12407dd7cddfSDavid du Colombier if(m->id == p->rcvdconfid)
12417dd7cddfSDavid du Colombier break; /* don't change state for duplicates */
12427dd7cddfSDavid du Colombier
12437dd7cddfSDavid du Colombier switch(p->state){
12447dd7cddfSDavid du Colombier case Sackrcvd:
12457dd7cddfSDavid du Colombier if(err)
12467dd7cddfSDavid du Colombier break;
12477dd7cddfSDavid du Colombier newstate(ppp, p, Sopened);
12487dd7cddfSDavid du Colombier break;
12497dd7cddfSDavid du Colombier case Sclosed:
12507dd7cddfSDavid du Colombier case Sopened:
12517dd7cddfSDavid du Colombier config(ppp, p, 1);
12527dd7cddfSDavid du Colombier if(err == 0)
12537dd7cddfSDavid du Colombier newstate(ppp, p, Sacksent);
12547dd7cddfSDavid du Colombier else
12557dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
12567dd7cddfSDavid du Colombier break;
12577dd7cddfSDavid du Colombier case Sreqsent:
12587dd7cddfSDavid du Colombier case Sacksent:
12597dd7cddfSDavid du Colombier if(err == 0)
12607dd7cddfSDavid du Colombier newstate(ppp, p, Sacksent);
12617dd7cddfSDavid du Colombier else
12627dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
12637dd7cddfSDavid du Colombier break;
12647dd7cddfSDavid du Colombier }
12657dd7cddfSDavid du Colombier break;
12667dd7cddfSDavid du Colombier case Lconfack:
12677dd7cddfSDavid du Colombier if(p->confid != m->id){
12687dd7cddfSDavid du Colombier /* ignore if it isn't the message we're sending */
12697dd7cddfSDavid du Colombier netlog("ppp: dropping confack\n");
12707dd7cddfSDavid du Colombier break;
12717dd7cddfSDavid du Colombier }
12727dd7cddfSDavid du Colombier p->confid = -1; /* ignore duplicates */
12737dd7cddfSDavid du Colombier p->id++; /* avoid sending duplicates */
12747dd7cddfSDavid du Colombier
12757dd7cddfSDavid du Colombier netlog("ppp: recv confack\n");
12767dd7cddfSDavid du Colombier switch(p->state){
12777dd7cddfSDavid du Colombier case Sopened:
12787dd7cddfSDavid du Colombier case Sackrcvd:
12797dd7cddfSDavid du Colombier config(ppp, p, 1);
12807dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
12817dd7cddfSDavid du Colombier break;
12827dd7cddfSDavid du Colombier case Sreqsent:
12837dd7cddfSDavid du Colombier newstate(ppp, p, Sackrcvd);
12847dd7cddfSDavid du Colombier break;
12857dd7cddfSDavid du Colombier case Sacksent:
12867dd7cddfSDavid du Colombier newstate(ppp, p, Sopened);
12877dd7cddfSDavid du Colombier break;
12887dd7cddfSDavid du Colombier }
12897dd7cddfSDavid du Colombier break;
12907dd7cddfSDavid du Colombier case Lconfrej:
12917dd7cddfSDavid du Colombier case Lconfnak:
12927dd7cddfSDavid du Colombier if(p->confid != m->id) {
12937dd7cddfSDavid du Colombier /* ignore if it isn't the message we're sending */
12947dd7cddfSDavid du Colombier netlog("ppp: dropping confrej or confnak\n");
12957dd7cddfSDavid du Colombier break;
12967dd7cddfSDavid du Colombier }
12977dd7cddfSDavid du Colombier p->confid = -1; /* ignore duplicates */
12987dd7cddfSDavid du Colombier p->id++; /* avoid sending duplicates */
12997dd7cddfSDavid du Colombier
13007dd7cddfSDavid du Colombier switch(p->state){
13017dd7cddfSDavid du Colombier case Sopened:
13027dd7cddfSDavid du Colombier case Sackrcvd:
13037dd7cddfSDavid du Colombier config(ppp, p, 1);
13047dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
13057dd7cddfSDavid du Colombier break;
13067dd7cddfSDavid du Colombier case Sreqsent:
13077dd7cddfSDavid du Colombier case Sacksent:
13087dd7cddfSDavid du Colombier printopts(p, b, 0);
13097dd7cddfSDavid du Colombier rejopts(ppp, p, b, m->code);
13107dd7cddfSDavid du Colombier config(ppp, p, 1);
13117dd7cddfSDavid du Colombier break;
13127dd7cddfSDavid du Colombier }
13137dd7cddfSDavid du Colombier break;
13147dd7cddfSDavid du Colombier case Ltermreq:
13157dd7cddfSDavid du Colombier m->code = Ltermack;
13167dd7cddfSDavid du Colombier putframe(ppp, p->proto, b);
13177dd7cddfSDavid du Colombier
13187dd7cddfSDavid du Colombier switch(p->state){
13197dd7cddfSDavid du Colombier case Sackrcvd:
13207dd7cddfSDavid du Colombier case Sacksent:
13217dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
13227dd7cddfSDavid du Colombier break;
13237dd7cddfSDavid du Colombier case Sopened:
13247dd7cddfSDavid du Colombier newstate(ppp, p, Sclosing);
13257dd7cddfSDavid du Colombier break;
13267dd7cddfSDavid du Colombier }
13277dd7cddfSDavid du Colombier break;
13287dd7cddfSDavid du Colombier case Ltermack:
13297dd7cddfSDavid du Colombier if(p->termid != m->id) /* ignore if it isn't the message we're sending */
13307dd7cddfSDavid du Colombier break;
13317dd7cddfSDavid du Colombier
13327dd7cddfSDavid du Colombier if(p->proto == Plcp)
13337dd7cddfSDavid du Colombier ppp->ipcp->state = Sclosed;
13347dd7cddfSDavid du Colombier switch(p->state){
13357dd7cddfSDavid du Colombier case Sclosing:
13367dd7cddfSDavid du Colombier newstate(ppp, p, Sclosed);
13377dd7cddfSDavid du Colombier break;
13387dd7cddfSDavid du Colombier case Sackrcvd:
13397dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
13407dd7cddfSDavid du Colombier break;
13417dd7cddfSDavid du Colombier case Sopened:
13427dd7cddfSDavid du Colombier config(ppp, p, 0);
13437dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
13447dd7cddfSDavid du Colombier break;
13457dd7cddfSDavid du Colombier }
13467dd7cddfSDavid du Colombier break;
13477dd7cddfSDavid du Colombier case Lcoderej:
13487dd7cddfSDavid du Colombier //newstate(ppp, p, Sclosed);
13497dd7cddfSDavid du Colombier syslog(0, LOG, "code reject %d\n", m->data[0]);
13507dd7cddfSDavid du Colombier break;
13517dd7cddfSDavid du Colombier case Lprotorej:
13527dd7cddfSDavid du Colombier proto = nhgets(m->data);
135359cc4ca5SDavid du Colombier netlog("ppp: proto reject %ux\n", proto);
13547dd7cddfSDavid du Colombier if(proto == Pccp)
13557dd7cddfSDavid du Colombier newstate(ppp, ppp->ccp, Sclosed);
13567dd7cddfSDavid du Colombier break;
13577dd7cddfSDavid du Colombier case Lechoreq:
13589a747e4fSDavid du Colombier if(BLEN(b) < 8){
13599a747e4fSDavid du Colombier netlog("ppp: short lcp echo request\n");
13609a747e4fSDavid du Colombier freeb(b);
13619a747e4fSDavid du Colombier return;
13629a747e4fSDavid du Colombier }
13637dd7cddfSDavid du Colombier m->code = Lechoack;
13649a747e4fSDavid du Colombier hnputl(m->data, ppp->magic);
13657dd7cddfSDavid du Colombier putframe(ppp, p->proto, b);
13667dd7cddfSDavid du Colombier break;
13677dd7cddfSDavid du Colombier case Lechoack:
13687dd7cddfSDavid du Colombier p->echoack = 1;
13697dd7cddfSDavid du Colombier break;
13707dd7cddfSDavid du Colombier case Ldiscard:
13717dd7cddfSDavid du Colombier /* nothing to do */
13727dd7cddfSDavid du Colombier break;
13737dd7cddfSDavid du Colombier case Lresetreq:
13747dd7cddfSDavid du Colombier if(p->proto != Pccp)
13757dd7cddfSDavid du Colombier break;
13767dd7cddfSDavid du Colombier ppp->stat.compreset++;
13777dd7cddfSDavid du Colombier if(ppp->ctype != nil)
13787dd7cddfSDavid du Colombier b = (*ppp->ctype->resetreq)(ppp->cstate, b);
13797dd7cddfSDavid du Colombier if(b != nil) {
13807dd7cddfSDavid du Colombier m = (Lcpmsg*)b->rptr;
13817dd7cddfSDavid du Colombier m->code = Lresetack;
13827dd7cddfSDavid du Colombier putframe(ppp, p->proto, b);
13837dd7cddfSDavid du Colombier }
13847dd7cddfSDavid du Colombier break;
13857dd7cddfSDavid du Colombier case Lresetack:
13867dd7cddfSDavid du Colombier if(p->proto != Pccp)
13877dd7cddfSDavid du Colombier break;
13887dd7cddfSDavid du Colombier if(ppp->unctype != nil)
13897dd7cddfSDavid du Colombier (*ppp->unctype->resetack)(ppp->uncstate, b);
13907dd7cddfSDavid du Colombier break;
13917dd7cddfSDavid du Colombier }
13927dd7cddfSDavid du Colombier
13937dd7cddfSDavid du Colombier qunlock(ppp);
13947dd7cddfSDavid du Colombier freeb(b);
13957dd7cddfSDavid du Colombier }
13967dd7cddfSDavid du Colombier
13977dd7cddfSDavid du Colombier /*
13987dd7cddfSDavid du Colombier * timer for protocol state machine
13997dd7cddfSDavid du Colombier */
14007dd7cddfSDavid du Colombier static void
ptimer(PPP * ppp,Pstate * p)14017dd7cddfSDavid du Colombier ptimer(PPP *ppp, Pstate *p)
14027dd7cddfSDavid du Colombier {
14037dd7cddfSDavid du Colombier if(p->state == Sopened || p->state == Sclosed)
14047dd7cddfSDavid du Colombier return;
14057dd7cddfSDavid du Colombier
14067dd7cddfSDavid du Colombier p->timeout--;
14077dd7cddfSDavid du Colombier switch(p->state){
14087dd7cddfSDavid du Colombier case Sclosing:
14097dd7cddfSDavid du Colombier sendtermreq(ppp, p);
14107dd7cddfSDavid du Colombier break;
14117dd7cddfSDavid du Colombier case Sreqsent:
14127dd7cddfSDavid du Colombier case Sacksent:
14137dd7cddfSDavid du Colombier if(p->timeout <= 0)
14147dd7cddfSDavid du Colombier newstate(ppp, p, Sclosed);
14157dd7cddfSDavid du Colombier else {
14167dd7cddfSDavid du Colombier config(ppp, p, 0);
14177dd7cddfSDavid du Colombier }
14187dd7cddfSDavid du Colombier break;
14197dd7cddfSDavid du Colombier case Sackrcvd:
14207dd7cddfSDavid du Colombier if(p->timeout <= 0)
14217dd7cddfSDavid du Colombier newstate(ppp, p, Sclosed);
14227dd7cddfSDavid du Colombier else {
14237dd7cddfSDavid du Colombier config(ppp, p, 0);
14247dd7cddfSDavid du Colombier newstate(ppp, p, Sreqsent);
14257dd7cddfSDavid du Colombier }
14267dd7cddfSDavid du Colombier break;
14277dd7cddfSDavid du Colombier }
14287dd7cddfSDavid du Colombier }
14297dd7cddfSDavid du Colombier
1430bedadc12SDavid du Colombier /* paptimer -- pap timer event handler
1431bedadc12SDavid du Colombier *
1432bedadc12SDavid du Colombier * If PAP authorization hasn't come through, resend an authreqst. If
1433bedadc12SDavid du Colombier * the maximum number of requests have been sent (~ 30 seconds), give
1434bedadc12SDavid du Colombier * up.
1435bedadc12SDavid du Colombier *
1436bedadc12SDavid du Colombier */
143780ee5cbfSDavid du Colombier static void
authtimer(PPP * ppp)143880ee5cbfSDavid du Colombier authtimer(PPP* ppp)
143980ee5cbfSDavid du Colombier {
144080ee5cbfSDavid du Colombier if(ppp->chap->proto != APpasswd)
144180ee5cbfSDavid du Colombier return;
144280ee5cbfSDavid du Colombier
144380ee5cbfSDavid du Colombier if(ppp->chap->id < 21)
144480ee5cbfSDavid du Colombier putpaprequest(ppp);
144580ee5cbfSDavid du Colombier else {
144680ee5cbfSDavid du Colombier terminate(ppp, 0);
144780ee5cbfSDavid du Colombier netlog("ppp: pap timed out--not authorized\n");
144880ee5cbfSDavid du Colombier }
144980ee5cbfSDavid du Colombier }
145080ee5cbfSDavid du Colombier
145180ee5cbfSDavid du Colombier
14527dd7cddfSDavid du Colombier /*
14537dd7cddfSDavid du Colombier * timer for ppp
14547dd7cddfSDavid du Colombier */
14557dd7cddfSDavid du Colombier static void
ppptimer(PPP * ppp)14567dd7cddfSDavid du Colombier ppptimer(PPP *ppp)
14577dd7cddfSDavid du Colombier {
14587dd7cddfSDavid du Colombier while(!dying){
14597dd7cddfSDavid du Colombier sleep(Period);
14607dd7cddfSDavid du Colombier qlock(ppp);
14617dd7cddfSDavid du Colombier
14623ff48bf5SDavid du Colombier netlog("ppp: ppptimer\n");
14637dd7cddfSDavid du Colombier ptimer(ppp, ppp->lcp);
14647dd7cddfSDavid du Colombier if(ppp->lcp->state == Sopened) {
146580ee5cbfSDavid du Colombier switch(ppp->phase){
146680ee5cbfSDavid du Colombier case Pnet:
14677dd7cddfSDavid du Colombier ptimer(ppp, ppp->ccp);
14687dd7cddfSDavid du Colombier ptimer(ppp, ppp->ipcp);
146980ee5cbfSDavid du Colombier break;
147080ee5cbfSDavid du Colombier case Pauth:
147180ee5cbfSDavid du Colombier authtimer(ppp);
147280ee5cbfSDavid du Colombier break;
147380ee5cbfSDavid du Colombier }
14747dd7cddfSDavid du Colombier }
14757dd7cddfSDavid du Colombier
14767dd7cddfSDavid du Colombier /* link quality measurement */
14777dd7cddfSDavid du Colombier if(ppp->period && --(ppp->timeout) <= 0){
14787dd7cddfSDavid du Colombier ppp->timeout = ppp->period;
14797dd7cddfSDavid du Colombier putlqm(ppp);
14807dd7cddfSDavid du Colombier }
14817dd7cddfSDavid du Colombier
14827dd7cddfSDavid du Colombier qunlock(ppp);
14837dd7cddfSDavid du Colombier }
14847dd7cddfSDavid du Colombier }
14857dd7cddfSDavid du Colombier
14867dd7cddfSDavid du Colombier static void
setdefroute(char * net,Ipaddr gate)14877dd7cddfSDavid du Colombier setdefroute(char *net, Ipaddr gate)
14887dd7cddfSDavid du Colombier {
14897dd7cddfSDavid du Colombier int fd;
14907dd7cddfSDavid du Colombier char path[128];
14917dd7cddfSDavid du Colombier
14927dd7cddfSDavid du Colombier snprint(path, sizeof path, "%s/iproute", net);
14937dd7cddfSDavid du Colombier fd = open(path, ORDWR);
14947dd7cddfSDavid du Colombier if(fd < 0)
14957dd7cddfSDavid du Colombier return;
14967dd7cddfSDavid du Colombier fprint(fd, "add 0 0 %I", gate);
14977dd7cddfSDavid du Colombier close(fd);
14987dd7cddfSDavid du Colombier }
14997dd7cddfSDavid du Colombier
15006b6b9ac8SDavid du Colombier enum
15016b6b9ac8SDavid du Colombier {
15026b6b9ac8SDavid du Colombier Mofd= 32,
15036b6b9ac8SDavid du Colombier };
15046b6b9ac8SDavid du Colombier struct
15056b6b9ac8SDavid du Colombier {
15066b6b9ac8SDavid du Colombier Lock;
15076b6b9ac8SDavid du Colombier
15086b6b9ac8SDavid du Colombier int fd[Mofd];
15096b6b9ac8SDavid du Colombier int cfd[Mofd];
15106b6b9ac8SDavid du Colombier int n;
15116b6b9ac8SDavid du Colombier } old;
15126b6b9ac8SDavid du Colombier
15137dd7cddfSDavid du Colombier static char*
ipopen(PPP * ppp)15147dd7cddfSDavid du Colombier ipopen(PPP *ppp)
15157dd7cddfSDavid du Colombier {
15166b6b9ac8SDavid du Colombier static int ipinprocpid;
15176b6b9ac8SDavid du Colombier int n, cfd, fd;
15187dd7cddfSDavid du Colombier char path[128];
15196b6b9ac8SDavid du Colombier char buf[128];
15207dd7cddfSDavid du Colombier
15216b6b9ac8SDavid du Colombier if(ipinprocpid <= 0){
15227dd7cddfSDavid du Colombier snprint(path, sizeof path, "%s/ipifc/clone", ppp->net);
15237dd7cddfSDavid du Colombier cfd = open(path, ORDWR);
15247dd7cddfSDavid du Colombier if(cfd < 0)
15257dd7cddfSDavid du Colombier return "can't open ip interface";
15267dd7cddfSDavid du Colombier
15277dd7cddfSDavid du Colombier n = read(cfd, buf, sizeof(buf) - 1);
15287dd7cddfSDavid du Colombier if(n <= 0){
15297dd7cddfSDavid du Colombier close(cfd);
15307dd7cddfSDavid du Colombier return "can't open ip interface";
15317dd7cddfSDavid du Colombier }
15327dd7cddfSDavid du Colombier buf[n] = 0;
15337dd7cddfSDavid du Colombier
1534a7b22450SDavid du Colombier netlog("ppp: setting up IP interface local %I remote %I (valid %d)\n",
1535a7b22450SDavid du Colombier ppp->local, ppp->remote, validv4(ppp->remote));
1536a7b22450SDavid du Colombier if(!validv4(ppp->remote))
1537a7b22450SDavid du Colombier ipmove(ppp->remote, ppp->local);
1538a7b22450SDavid du Colombier
15397dd7cddfSDavid du Colombier snprint(path, sizeof path, "%s/ipifc/%s/data", ppp->net, buf);
15407dd7cddfSDavid du Colombier fd = open(path, ORDWR);
15417dd7cddfSDavid du Colombier if(fd < 0){
15427dd7cddfSDavid du Colombier close(cfd);
15437dd7cddfSDavid du Colombier return "can't open ip interface";
15447dd7cddfSDavid du Colombier }
15457dd7cddfSDavid du Colombier
15467dd7cddfSDavid du Colombier if(fprint(cfd, "bind pkt") < 0)
15477dd7cddfSDavid du Colombier return "binding pkt to ip interface";
15486b6b9ac8SDavid du Colombier if(fprint(cfd, "add %I 255.255.255.255 %I %lud proxy", ppp->local,
15496b6b9ac8SDavid du Colombier ppp->remote, ppp->mtu-10) < 0){
15507dd7cddfSDavid du Colombier close(cfd);
15517dd7cddfSDavid du Colombier return "can't set addresses";
15527dd7cddfSDavid du Colombier }
155359cc4ca5SDavid du Colombier if(primary)
15547dd7cddfSDavid du Colombier setdefroute(ppp->net, ppp->remote);
15557dd7cddfSDavid du Colombier ppp->ipfd = fd;
15567dd7cddfSDavid du Colombier ppp->ipcfd = cfd;
15577dd7cddfSDavid du Colombier
15587dd7cddfSDavid du Colombier /* signal main() that ip is configured */
155974f16c81SDavid du Colombier rendezvous((void*)Rmagic, 0);
15607dd7cddfSDavid du Colombier
15616b6b9ac8SDavid du Colombier switch(ipinprocpid = rfork(RFPROC|RFMEM|RFNOWAIT)){
15627dd7cddfSDavid du Colombier case -1:
15637dd7cddfSDavid du Colombier sysfatal("forking ipinproc");
15647dd7cddfSDavid du Colombier case 0:
15657dd7cddfSDavid du Colombier ipinproc(ppp);
156659cc4ca5SDavid du Colombier terminate(ppp, 1);
15677dd7cddfSDavid du Colombier _exits(0);
15687dd7cddfSDavid du Colombier }
15696b6b9ac8SDavid du Colombier } else {
15706b6b9ac8SDavid du Colombier /* we may have changed addresses */
15716b6b9ac8SDavid du Colombier if(ipcmp(ppp->local, ppp->curlocal) != 0 ||
15726b6b9ac8SDavid du Colombier ipcmp(ppp->remote, ppp->curremote) != 0){
157339734e7eSDavid du Colombier snprint(buf, sizeof buf, "remove %I 255.255.255.255 %I",
157439734e7eSDavid du Colombier ppp->curlocal, ppp->curremote);
15756b6b9ac8SDavid du Colombier if(fprint(ppp->ipcfd, "%s", buf) < 0)
15766b6b9ac8SDavid du Colombier syslog(0, "ppp", "can't %s: %r", buf);
15776b6b9ac8SDavid du Colombier snprint(buf, sizeof buf, "add %I 255.255.255.255 %I %lud proxy",
15786b6b9ac8SDavid du Colombier ppp->local, ppp->remote, ppp->mtu-10);
15796b6b9ac8SDavid du Colombier if(fprint(ppp->ipcfd, "%s", buf) < 0)
15806b6b9ac8SDavid du Colombier syslog(0, "ppp", "can't %s: %r", buf);
15817dd7cddfSDavid du Colombier }
15826b6b9ac8SDavid du Colombier syslog(0, "ppp", "%I/%I -> %I/%I", ppp->curlocal, ppp->curremote,
15836b6b9ac8SDavid du Colombier ppp->local, ppp->remote);
15846b6b9ac8SDavid du Colombier }
15856b6b9ac8SDavid du Colombier ipmove(ppp->curlocal, ppp->local);
15866b6b9ac8SDavid du Colombier ipmove(ppp->curremote, ppp->remote);
15877dd7cddfSDavid du Colombier
15887dd7cddfSDavid du Colombier return nil;
15897dd7cddfSDavid du Colombier }
15907dd7cddfSDavid du Colombier
15917dd7cddfSDavid du Colombier /* return next input IP packet */
15927dd7cddfSDavid du Colombier Block*
pppread(PPP * ppp)15937dd7cddfSDavid du Colombier pppread(PPP *ppp)
15947dd7cddfSDavid du Colombier {
15957dd7cddfSDavid du Colombier Block *b, *reply;
15967dd7cddfSDavid du Colombier int proto, len;
15977dd7cddfSDavid du Colombier Lcpmsg *m;
15987dd7cddfSDavid du Colombier
15997dd7cddfSDavid du Colombier while(!dying){
16007dd7cddfSDavid du Colombier b = getframe(ppp, &proto);
16017dd7cddfSDavid du Colombier if(b == nil)
16027dd7cddfSDavid du Colombier return nil;
16037dd7cddfSDavid du Colombier
16047dd7cddfSDavid du Colombier Again:
16057dd7cddfSDavid du Colombier switch(proto){
16067dd7cddfSDavid du Colombier case Plcp:
16077dd7cddfSDavid du Colombier rcv(ppp, ppp->lcp, b);
16087dd7cddfSDavid du Colombier break;
16097dd7cddfSDavid du Colombier case Pccp:
16107dd7cddfSDavid du Colombier rcv(ppp, ppp->ccp, b);
16117dd7cddfSDavid du Colombier break;
16127dd7cddfSDavid du Colombier case Pipcp:
16137dd7cddfSDavid du Colombier rcv(ppp, ppp->ipcp, b);
16147dd7cddfSDavid du Colombier break;
16157dd7cddfSDavid du Colombier case Pip:
16167dd7cddfSDavid du Colombier if(ppp->ipcp->state == Sopened)
16177dd7cddfSDavid du Colombier return b;
16187dd7cddfSDavid du Colombier netlog("ppp: IP recved: link not up\n");
16197dd7cddfSDavid du Colombier freeb(b);
16207dd7cddfSDavid du Colombier break;
16217dd7cddfSDavid du Colombier case Plqm:
16227dd7cddfSDavid du Colombier getlqm(ppp, b);
16237dd7cddfSDavid du Colombier break;
16247dd7cddfSDavid du Colombier case Pchap:
16257dd7cddfSDavid du Colombier getchap(ppp, b);
16267dd7cddfSDavid du Colombier break;
162780ee5cbfSDavid du Colombier case Ppasswd:
162880ee5cbfSDavid du Colombier getpap(ppp, b);
162980ee5cbfSDavid du Colombier break;
16307dd7cddfSDavid du Colombier case Pvjctcp:
16317dd7cddfSDavid du Colombier case Pvjutcp:
16327dd7cddfSDavid du Colombier if(ppp->ipcp->state != Sopened){
16337dd7cddfSDavid du Colombier netlog("ppp: VJ tcp recved: link not up\n");
16347dd7cddfSDavid du Colombier freeb(b);
16357dd7cddfSDavid du Colombier break;
16367dd7cddfSDavid du Colombier }
16377dd7cddfSDavid du Colombier ppp->stat.vjin++;
16387dd7cddfSDavid du Colombier b = tcpuncompress(ppp->ctcp, b, proto);
16397dd7cddfSDavid du Colombier if(b != nil)
16407dd7cddfSDavid du Colombier return b;
16417dd7cddfSDavid du Colombier ppp->stat.vjfail++;
16427dd7cddfSDavid du Colombier break;
16437dd7cddfSDavid du Colombier case Pcdata:
16447dd7cddfSDavid du Colombier ppp->stat.uncomp++;
16457dd7cddfSDavid du Colombier if(ppp->ccp->state != Sopened){
16467dd7cddfSDavid du Colombier netlog("ppp: compressed data recved: link not up\n");
16477dd7cddfSDavid du Colombier freeb(b);
16487dd7cddfSDavid du Colombier break;
16497dd7cddfSDavid du Colombier }
16507dd7cddfSDavid du Colombier if(ppp->unctype == nil) {
16517dd7cddfSDavid du Colombier netlog("ppp: compressed data recved: no compression\n");
16527dd7cddfSDavid du Colombier freeb(b);
16537dd7cddfSDavid du Colombier break;
16547dd7cddfSDavid du Colombier }
16557dd7cddfSDavid du Colombier len = BLEN(b);
16567dd7cddfSDavid du Colombier b = (*ppp->unctype->uncompress)(ppp, b, &proto, &reply);
16577dd7cddfSDavid du Colombier if(reply != nil){
16587dd7cddfSDavid du Colombier /* send resetreq */
16597dd7cddfSDavid du Colombier ppp->stat.uncompreset++;
16607dd7cddfSDavid du Colombier putframe(ppp, Pccp, reply);
16617dd7cddfSDavid du Colombier freeb(reply);
16627dd7cddfSDavid du Colombier }
16637dd7cddfSDavid du Colombier if(b == nil)
16647dd7cddfSDavid du Colombier break;
16657dd7cddfSDavid du Colombier ppp->stat.uncompin += len;
16667dd7cddfSDavid du Colombier ppp->stat.uncompout += BLEN(b);
16677dd7cddfSDavid du Colombier /* netlog("ppp: uncompressed frame %ux %d %d (%d uchars)\n", proto, b->rptr[0], b->rptr[1], BLEN(b)); /* */
16687dd7cddfSDavid du Colombier goto Again;
16697dd7cddfSDavid du Colombier default:
16707dd7cddfSDavid du Colombier syslog(0, LOG, "unknown proto %ux", proto);
16717dd7cddfSDavid du Colombier if(ppp->lcp->state == Sopened){
16727dd7cddfSDavid du Colombier /* reject the protocol */
16737dd7cddfSDavid du Colombier b->rptr -= 6;
16747dd7cddfSDavid du Colombier m = (Lcpmsg*)b->rptr;
16757dd7cddfSDavid du Colombier m->code = Lprotorej;
16767dd7cddfSDavid du Colombier m->id = ++ppp->lcp->id;
16777dd7cddfSDavid du Colombier hnputs(m->data, proto);
16787dd7cddfSDavid du Colombier hnputs(m->len, BLEN(b));
16797dd7cddfSDavid du Colombier putframe(ppp, Plcp, b);
16807dd7cddfSDavid du Colombier }
16817dd7cddfSDavid du Colombier freeb(b);
16827dd7cddfSDavid du Colombier break;
16837dd7cddfSDavid du Colombier }
16847dd7cddfSDavid du Colombier }
16857dd7cddfSDavid du Colombier return nil;
16867dd7cddfSDavid du Colombier }
16877dd7cddfSDavid du Colombier
16887dd7cddfSDavid du Colombier /* transmit an IP packet */
16897dd7cddfSDavid du Colombier int
pppwrite(PPP * ppp,Block * b)16907dd7cddfSDavid du Colombier pppwrite(PPP *ppp, Block *b)
16917dd7cddfSDavid du Colombier {
16927dd7cddfSDavid du Colombier int proto;
16937dd7cddfSDavid du Colombier int len;
16947dd7cddfSDavid du Colombier
16957dd7cddfSDavid du Colombier qlock(ppp);
16967dd7cddfSDavid du Colombier /* can't send ip packets till we're established */
16977dd7cddfSDavid du Colombier if(ppp->ipcp->state != Sopened) {
16987dd7cddfSDavid du Colombier qunlock(ppp);
16997dd7cddfSDavid du Colombier syslog(0, LOG, "IP write: link not up");
17007dd7cddfSDavid du Colombier len = blen(b);
17017dd7cddfSDavid du Colombier freeb(b);
17027dd7cddfSDavid du Colombier return len;
17037dd7cddfSDavid du Colombier }
17047dd7cddfSDavid du Colombier
17057dd7cddfSDavid du Colombier proto = Pip;
17067dd7cddfSDavid du Colombier ppp->stat.ipsend++;
17077dd7cddfSDavid du Colombier
17087dd7cddfSDavid du Colombier if(ppp->ipcp->flags & Fipcompress){
17097dd7cddfSDavid du Colombier b = compress(ppp->ctcp, b, &proto);
17107dd7cddfSDavid du Colombier if(b == nil){
17117dd7cddfSDavid du Colombier qunlock(ppp);
17127dd7cddfSDavid du Colombier return 0;
17137dd7cddfSDavid du Colombier }
17147dd7cddfSDavid du Colombier if(proto != Pip)
17157dd7cddfSDavid du Colombier ppp->stat.vjout++;
17167dd7cddfSDavid du Colombier }
17177dd7cddfSDavid du Colombier
171859cc4ca5SDavid du Colombier if(ppp->ctype != nil) {
17197dd7cddfSDavid du Colombier len = blen(b);
17207dd7cddfSDavid du Colombier b = (*ppp->ctype->compress)(ppp, proto, b, &proto);
17217dd7cddfSDavid du Colombier if(proto == Pcdata) {
17227dd7cddfSDavid du Colombier ppp->stat.comp++;
17237dd7cddfSDavid du Colombier ppp->stat.compin += len;
17247dd7cddfSDavid du Colombier ppp->stat.compout += blen(b);
17257dd7cddfSDavid du Colombier }
17267dd7cddfSDavid du Colombier }
17277dd7cddfSDavid du Colombier
17287dd7cddfSDavid du Colombier if(putframe(ppp, proto, b) < 0) {
17297dd7cddfSDavid du Colombier qunlock(ppp);
17307dd7cddfSDavid du Colombier freeb(b);
17317dd7cddfSDavid du Colombier return -1;
17327dd7cddfSDavid du Colombier }
17337dd7cddfSDavid du Colombier qunlock(ppp);
17347dd7cddfSDavid du Colombier
17357dd7cddfSDavid du Colombier len = blen(b);
17367dd7cddfSDavid du Colombier freeb(b);
17377dd7cddfSDavid du Colombier return len;
17387dd7cddfSDavid du Colombier }
17397dd7cddfSDavid du Colombier
17407dd7cddfSDavid du Colombier static void
terminate(PPP * ppp,int kill)17417dd7cddfSDavid du Colombier terminate(PPP *ppp, int kill)
17427dd7cddfSDavid du Colombier {
17437dd7cddfSDavid du Colombier close(ppp->ipfd);
17447dd7cddfSDavid du Colombier ppp->ipfd = -1;
17457dd7cddfSDavid du Colombier close(ppp->ipcfd);
17467dd7cddfSDavid du Colombier ppp->ipcfd = -1;
1747d9306527SDavid du Colombier close(ppp->mediain);
1748d9306527SDavid du Colombier close(ppp->mediaout);
1749d9306527SDavid du Colombier ppp->mediain = -1;
1750d9306527SDavid du Colombier ppp->mediaout = -1;
17517dd7cddfSDavid du Colombier dying = 1;
17527dd7cddfSDavid du Colombier
17537dd7cddfSDavid du Colombier if(kill)
17547dd7cddfSDavid du Colombier postnote(PNGROUP, getpid(), "die");
17557dd7cddfSDavid du Colombier }
17567dd7cddfSDavid du Colombier
17577dd7cddfSDavid du Colombier typedef struct Iphdr Iphdr;
17587dd7cddfSDavid du Colombier struct Iphdr
17597dd7cddfSDavid du Colombier {
17607dd7cddfSDavid du Colombier uchar vihl; /* Version and header length */
17617dd7cddfSDavid du Colombier uchar tos; /* Type of service */
17627dd7cddfSDavid du Colombier uchar length[2]; /* packet length */
17637dd7cddfSDavid du Colombier uchar id[2]; /* Identification */
17647dd7cddfSDavid du Colombier uchar frag[2]; /* Fragment information */
17657dd7cddfSDavid du Colombier uchar ttl; /* Time to live */
17667dd7cddfSDavid du Colombier uchar proto; /* Protocol */
17677dd7cddfSDavid du Colombier uchar cksum[2]; /* Header checksum */
17687dd7cddfSDavid du Colombier uchar src[4]; /* Ip source (uchar ordering unimportant) */
17697dd7cddfSDavid du Colombier uchar dst[4]; /* Ip destination (uchar ordering unimportant) */
17707dd7cddfSDavid du Colombier };
17717dd7cddfSDavid du Colombier
17727dd7cddfSDavid du Colombier static void
ipinproc(PPP * ppp)17737dd7cddfSDavid du Colombier ipinproc(PPP *ppp)
17747dd7cddfSDavid du Colombier {
17757dd7cddfSDavid du Colombier Block *b;
17767dd7cddfSDavid du Colombier int m, n;
17777dd7cddfSDavid du Colombier Iphdr *ip;
17787dd7cddfSDavid du Colombier
17797dd7cddfSDavid du Colombier while(!dying){
17806b6b9ac8SDavid du Colombier
17817dd7cddfSDavid du Colombier b = allocb(Buflen);
17827dd7cddfSDavid du Colombier n = read(ppp->ipfd, b->wptr, b->lim-b->wptr);
17837dd7cddfSDavid du Colombier if(n < 0)
17847dd7cddfSDavid du Colombier break;
17857dd7cddfSDavid du Colombier
17867dd7cddfSDavid du Colombier /* trim packet if there's padding (e.g. from ether) */
17877dd7cddfSDavid du Colombier ip = (Iphdr*)b->rptr;
17887dd7cddfSDavid du Colombier m = nhgets(ip->length);
17897dd7cddfSDavid du Colombier if(m < n && m > 0)
17907dd7cddfSDavid du Colombier n = m;
17917dd7cddfSDavid du Colombier b->wptr += n;
17927dd7cddfSDavid du Colombier
17937dd7cddfSDavid du Colombier if(pppwrite(ppp, b) < 0)
17947dd7cddfSDavid du Colombier break;
17957dd7cddfSDavid du Colombier }
17967dd7cddfSDavid du Colombier }
17977dd7cddfSDavid du Colombier
17987dd7cddfSDavid du Colombier static void
catchdie(void *,char * msg)179959cc4ca5SDavid du Colombier catchdie(void*, char *msg)
180059cc4ca5SDavid du Colombier {
180159cc4ca5SDavid du Colombier if(strstr(msg, "die") != nil)
180259cc4ca5SDavid du Colombier noted(NCONT);
180359cc4ca5SDavid du Colombier else
180459cc4ca5SDavid du Colombier noted(NDFLT);
180559cc4ca5SDavid du Colombier }
180659cc4ca5SDavid du Colombier
180759cc4ca5SDavid du Colombier static void
hexdump(uchar * a,int na)18089a747e4fSDavid du Colombier hexdump(uchar *a, int na)
18099a747e4fSDavid du Colombier {
18109a747e4fSDavid du Colombier int i;
18119a747e4fSDavid du Colombier char buf[80];
18129a747e4fSDavid du Colombier
18139a747e4fSDavid du Colombier fprint(2, "dump %p %d\n", a, na);
18149a747e4fSDavid du Colombier buf[0] = '\0';
18159a747e4fSDavid du Colombier for(i=0; i<na; i++){
18169a747e4fSDavid du Colombier sprint(buf+strlen(buf), " %.2ux", a[i]);
18179a747e4fSDavid du Colombier if(i%16 == 7)
18189a747e4fSDavid du Colombier sprint(buf+strlen(buf), " --");
18199a747e4fSDavid du Colombier if(i%16==15){
18209a747e4fSDavid du Colombier sprint(buf+strlen(buf), "\n");
18219a747e4fSDavid du Colombier write(2, buf, strlen(buf));
18229a747e4fSDavid du Colombier buf[0] = '\0';
18239a747e4fSDavid du Colombier }
18249a747e4fSDavid du Colombier }
18259a747e4fSDavid du Colombier if(i%16){
18269a747e4fSDavid du Colombier sprint(buf+strlen(buf), "\n");
18279a747e4fSDavid du Colombier write(2, buf, strlen(buf));
18289a747e4fSDavid du Colombier }
18299a747e4fSDavid du Colombier }
18309a747e4fSDavid du Colombier
18319a747e4fSDavid du Colombier static void
mediainproc(PPP * ppp)18327dd7cddfSDavid du Colombier mediainproc(PPP *ppp)
18337dd7cddfSDavid du Colombier {
18347dd7cddfSDavid du Colombier Block *b;
18357dd7cddfSDavid du Colombier Ipaddr remote;
18367dd7cddfSDavid du Colombier
183759cc4ca5SDavid du Colombier notify(catchdie);
18387dd7cddfSDavid du Colombier while(!dying){
18397dd7cddfSDavid du Colombier b = pppread(ppp);
18409a747e4fSDavid du Colombier if(b == nil){
18419a747e4fSDavid du Colombier syslog(0, LOG, "pppread return nil");
18427dd7cddfSDavid du Colombier break;
18439a747e4fSDavid du Colombier }
18447dd7cddfSDavid du Colombier ppp->stat.iprecv++;
18457dd7cddfSDavid du Colombier if(ppp->ipcp->state != Sopened) {
18467dd7cddfSDavid du Colombier ppp->stat.iprecvnotup++;
18477dd7cddfSDavid du Colombier freeb(b);
18487dd7cddfSDavid du Colombier continue;
18497dd7cddfSDavid du Colombier }
18507dd7cddfSDavid du Colombier
18517dd7cddfSDavid du Colombier if(server) {
18527dd7cddfSDavid du Colombier v4tov6(remote, b->rptr+12);
18537dd7cddfSDavid du Colombier if(ipcmp(remote, ppp->remote) != 0) {
18547dd7cddfSDavid du Colombier ppp->stat.iprecvbadsrc++;
18557dd7cddfSDavid du Colombier freeb(b);
18567dd7cddfSDavid du Colombier continue;
18577dd7cddfSDavid du Colombier }
18587dd7cddfSDavid du Colombier }
18599a747e4fSDavid du Colombier if(debug > 1){
18609a747e4fSDavid du Colombier netlog("ip write pkt %p %d\n", b->rptr, blen(b));
18619a747e4fSDavid du Colombier hexdump(b->rptr, blen(b));
18629a747e4fSDavid du Colombier }
18637dd7cddfSDavid du Colombier if(write(ppp->ipfd, b->rptr, blen(b)) < 0) {
18649a747e4fSDavid du Colombier syslog(0, LOG, "error writing to pktifc");
18657dd7cddfSDavid du Colombier freeb(b);
18667dd7cddfSDavid du Colombier break;
18677dd7cddfSDavid du Colombier }
18687dd7cddfSDavid du Colombier
18697dd7cddfSDavid du Colombier freeb(b);
18707dd7cddfSDavid du Colombier }
18717dd7cddfSDavid du Colombier
18726b6b9ac8SDavid du Colombier netlog(": remote=%I: ppp shutting down\n", ppp->remote);
18736b6b9ac8SDavid du Colombier syslog(0, LOG, ": remote=%I: ppp shutting down", ppp->remote);
18747dd7cddfSDavid du Colombier syslog(0, LOG, "\t\tppp send = %lud/%lud recv= %lud/%lud",
18757dd7cddfSDavid du Colombier ppp->out.packets, ppp->out.uchars,
18767dd7cddfSDavid du Colombier ppp->in.packets, ppp->in.uchars);
18777dd7cddfSDavid du Colombier syslog(0, LOG, "\t\tip send=%lud", ppp->stat.ipsend);
18787dd7cddfSDavid du Colombier syslog(0, LOG, "\t\tip recv=%lud notup=%lud badsrc=%lud",
18797dd7cddfSDavid du Colombier ppp->stat.iprecv, ppp->stat.iprecvnotup, ppp->stat.iprecvbadsrc);
18807dd7cddfSDavid du Colombier syslog(0, LOG, "\t\tcompress=%lud in=%lud out=%lud reset=%lud",
18817dd7cddfSDavid du Colombier ppp->stat.comp, ppp->stat.compin, ppp->stat.compout, ppp->stat.compreset);
18827dd7cddfSDavid du Colombier syslog(0, LOG, "\t\tuncompress=%lud in=%lud out=%lud reset=%lud",
18837dd7cddfSDavid du Colombier ppp->stat.uncomp, ppp->stat.uncompin, ppp->stat.uncompout,
18847dd7cddfSDavid du Colombier ppp->stat.uncompreset);
18857dd7cddfSDavid du Colombier syslog(0, LOG, "\t\tvjin=%lud vjout=%lud vjfail=%lud",
18867dd7cddfSDavid du Colombier ppp->stat.vjin, ppp->stat.vjout, ppp->stat.vjfail);
18877dd7cddfSDavid du Colombier }
18887dd7cddfSDavid du Colombier
18897dd7cddfSDavid du Colombier /*
18907dd7cddfSDavid du Colombier * link quality management
18917dd7cddfSDavid du Colombier */
18927dd7cddfSDavid du Colombier static void
getlqm(PPP * ppp,Block * b)18937dd7cddfSDavid du Colombier getlqm(PPP *ppp, Block *b)
18947dd7cddfSDavid du Colombier {
18957dd7cddfSDavid du Colombier Qualpkt *p;
18967dd7cddfSDavid du Colombier
18977dd7cddfSDavid du Colombier p = (Qualpkt*)b->rptr;
18987dd7cddfSDavid du Colombier if(BLEN(b) == sizeof(Qualpkt)){
18997dd7cddfSDavid du Colombier ppp->in.reports++;
19007dd7cddfSDavid du Colombier ppp->pout.reports = nhgetl(p->peeroutreports);
19017dd7cddfSDavid du Colombier ppp->pout.packets = nhgetl(p->peeroutpackets);
19027dd7cddfSDavid du Colombier ppp->pout.uchars = nhgetl(p->peeroutuchars);
19037dd7cddfSDavid du Colombier ppp->pin.reports = nhgetl(p->peerinreports);
19047dd7cddfSDavid du Colombier ppp->pin.packets = nhgetl(p->peerinpackets);
19057dd7cddfSDavid du Colombier ppp->pin.discards = nhgetl(p->peerindiscards);
19067dd7cddfSDavid du Colombier ppp->pin.errors = nhgetl(p->peerinerrors);
19077dd7cddfSDavid du Colombier ppp->pin.uchars = nhgetl(p->peerinuchars);
19087dd7cddfSDavid du Colombier
19097dd7cddfSDavid du Colombier /* save our numbers at time of reception */
19107dd7cddfSDavid du Colombier memmove(&ppp->sin, &ppp->in, sizeof(Qualstats));
19117dd7cddfSDavid du Colombier
19127dd7cddfSDavid du Colombier }
19137dd7cddfSDavid du Colombier freeb(b);
19147dd7cddfSDavid du Colombier if(ppp->period == 0)
19157dd7cddfSDavid du Colombier putlqm(ppp);
19167dd7cddfSDavid du Colombier
19177dd7cddfSDavid du Colombier }
19187dd7cddfSDavid du Colombier
19197dd7cddfSDavid du Colombier static void
putlqm(PPP * ppp)19207dd7cddfSDavid du Colombier putlqm(PPP *ppp)
19217dd7cddfSDavid du Colombier {
19227dd7cddfSDavid du Colombier Qualpkt *p;
19237dd7cddfSDavid du Colombier Block *b;
19247dd7cddfSDavid du Colombier
19257dd7cddfSDavid du Colombier b = allocb(sizeof(Qualpkt));
19267dd7cddfSDavid du Colombier b->wptr += sizeof(Qualpkt);
19277dd7cddfSDavid du Colombier p = (Qualpkt*)b->rptr;
19287dd7cddfSDavid du Colombier hnputl(p->magic, 0);
19297dd7cddfSDavid du Colombier
19307dd7cddfSDavid du Colombier /* heresay (what he last told us) */
19317dd7cddfSDavid du Colombier hnputl(p->lastoutreports, ppp->pout.reports);
19327dd7cddfSDavid du Colombier hnputl(p->lastoutpackets, ppp->pout.packets);
19337dd7cddfSDavid du Colombier hnputl(p->lastoutuchars, ppp->pout.uchars);
19347dd7cddfSDavid du Colombier
19357dd7cddfSDavid du Colombier /* our numbers at time of last reception */
19367dd7cddfSDavid du Colombier hnputl(p->peerinreports, ppp->sin.reports);
19377dd7cddfSDavid du Colombier hnputl(p->peerinpackets, ppp->sin.packets);
19387dd7cddfSDavid du Colombier hnputl(p->peerindiscards, ppp->sin.discards);
19397dd7cddfSDavid du Colombier hnputl(p->peerinerrors, ppp->sin.errors);
19407dd7cddfSDavid du Colombier hnputl(p->peerinuchars, ppp->sin.uchars);
19417dd7cddfSDavid du Colombier
19427dd7cddfSDavid du Colombier /* our numbers now */
19437dd7cddfSDavid du Colombier hnputl(p->peeroutreports, ppp->out.reports+1);
19447dd7cddfSDavid du Colombier hnputl(p->peeroutpackets, ppp->out.packets+1);
19457dd7cddfSDavid du Colombier hnputl(p->peeroutuchars, ppp->out.uchars+53/*hack*/);
19467dd7cddfSDavid du Colombier
19477dd7cddfSDavid du Colombier putframe(ppp, Plqm, b);
19487dd7cddfSDavid du Colombier freeb(b);
19497dd7cddfSDavid du Colombier ppp->out.reports++;
19507dd7cddfSDavid du Colombier }
19517dd7cddfSDavid du Colombier
19527dd7cddfSDavid du Colombier /*
19537dd7cddfSDavid du Colombier * init challenge response dialog
19547dd7cddfSDavid du Colombier */
19557dd7cddfSDavid du Colombier static void
chapinit(PPP * ppp)19567dd7cddfSDavid du Colombier chapinit(PPP *ppp)
19577dd7cddfSDavid du Colombier {
19587dd7cddfSDavid du Colombier Block *b;
19597dd7cddfSDavid du Colombier Lcpmsg *m;
19607dd7cddfSDavid du Colombier Chap *c;
19617dd7cddfSDavid du Colombier int len;
19629a747e4fSDavid du Colombier char *aproto;
19637dd7cddfSDavid du Colombier
1964dc5a79c1SDavid du Colombier getauth(ppp);
1965dc5a79c1SDavid du Colombier
19667dd7cddfSDavid du Colombier c = ppp->chap;
19677dd7cddfSDavid du Colombier c->id++;
19687dd7cddfSDavid du Colombier
19699a747e4fSDavid du Colombier switch(c->proto){
19709a747e4fSDavid du Colombier default:
19719a747e4fSDavid du Colombier abort();
19729a747e4fSDavid du Colombier case APmd5:
19739a747e4fSDavid du Colombier aproto = "chap";
19749a747e4fSDavid du Colombier break;
19759a747e4fSDavid du Colombier case APmschap:
19769a747e4fSDavid du Colombier aproto = "mschap";
19779a747e4fSDavid du Colombier break;
19789a747e4fSDavid du Colombier }
19799a747e4fSDavid du Colombier if((c->cs = auth_challenge("proto=%q role=server", aproto)) == nil)
19809a747e4fSDavid du Colombier sysfatal("auth_challenge: %r");
19819a747e4fSDavid du Colombier syslog(0, LOG, ": remote=%I: sending %d byte challenge", ppp->remote, c->cs->nchal);
19829a747e4fSDavid du Colombier len = 4 + 1 + c->cs->nchal + strlen(ppp->chapname);
19837dd7cddfSDavid du Colombier b = alloclcp(Cchallenge, c->id, len, &m);
19847dd7cddfSDavid du Colombier
19859a747e4fSDavid du Colombier *b->wptr++ = c->cs->nchal;
19869a747e4fSDavid du Colombier memmove(b->wptr, c->cs->chal, c->cs->nchal);
19879a747e4fSDavid du Colombier b->wptr += c->cs->nchal;
19887dd7cddfSDavid du Colombier memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));
19897dd7cddfSDavid du Colombier b->wptr += strlen(ppp->chapname);
19907dd7cddfSDavid du Colombier hnputs(m->len, len);
19917dd7cddfSDavid du Colombier putframe(ppp, Pchap, b);
19927dd7cddfSDavid du Colombier freeb(b);
19937dd7cddfSDavid du Colombier
19947dd7cddfSDavid du Colombier c->state = Cchalsent;
19957dd7cddfSDavid du Colombier }
19967dd7cddfSDavid du Colombier
19979a747e4fSDavid du Colombier /*
19989a747e4fSDavid du Colombier * BUG factotum should do this
19999a747e4fSDavid du Colombier */
20009a747e4fSDavid du Colombier enum {
20019a747e4fSDavid du Colombier MShashlen = 16,
20029a747e4fSDavid du Colombier MSresplen = 24,
20039a747e4fSDavid du Colombier MSchallen = 8,
20049a747e4fSDavid du Colombier };
20059a747e4fSDavid du Colombier
20069a747e4fSDavid du Colombier void
desencrypt(uchar data[8],uchar key[7])20079a747e4fSDavid du Colombier desencrypt(uchar data[8], uchar key[7])
20089a747e4fSDavid du Colombier {
20099a747e4fSDavid du Colombier ulong ekey[32];
20109a747e4fSDavid du Colombier
20119a747e4fSDavid du Colombier key_setup(key, ekey);
20129a747e4fSDavid du Colombier block_cipher(ekey, data, 0);
20139a747e4fSDavid du Colombier }
20149a747e4fSDavid du Colombier
20159a747e4fSDavid du Colombier void
nthash(uchar hash[MShashlen],char * passwd)20169a747e4fSDavid du Colombier nthash(uchar hash[MShashlen], char *passwd)
20179a747e4fSDavid du Colombier {
20189a747e4fSDavid du Colombier uchar buf[512];
20199a747e4fSDavid du Colombier int i;
20209a747e4fSDavid du Colombier
20219a747e4fSDavid du Colombier for(i=0; *passwd && i<sizeof(buf); passwd++) {
20229a747e4fSDavid du Colombier buf[i++] = *passwd;
20239a747e4fSDavid du Colombier buf[i++] = 0;
20249a747e4fSDavid du Colombier }
20259a747e4fSDavid du Colombier memset(hash, 0, 16);
20269a747e4fSDavid du Colombier md4(buf, i, hash, 0);
20279a747e4fSDavid du Colombier }
20289a747e4fSDavid du Colombier
20299a747e4fSDavid du Colombier void
mschalresp(uchar resp[MSresplen],uchar hash[MShashlen],uchar chal[MSchallen])20309a747e4fSDavid du Colombier mschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen])
20319a747e4fSDavid du Colombier {
20329a747e4fSDavid du Colombier int i;
20339a747e4fSDavid du Colombier uchar buf[21];
20349a747e4fSDavid du Colombier
20359a747e4fSDavid du Colombier memset(buf, 0, sizeof(buf));
20369a747e4fSDavid du Colombier memcpy(buf, hash, MShashlen);
20379a747e4fSDavid du Colombier
20389a747e4fSDavid du Colombier for(i=0; i<3; i++) {
20399a747e4fSDavid du Colombier memmove(resp+i*MSchallen, chal, MSchallen);
20409a747e4fSDavid du Colombier desencrypt(resp+i*MSchallen, buf+i*7);
20419a747e4fSDavid du Colombier }
20429a747e4fSDavid du Colombier }
20437dd7cddfSDavid du Colombier
20447dd7cddfSDavid du Colombier /*
20457dd7cddfSDavid du Colombier * challenge response dialog
20467dd7cddfSDavid du Colombier */
20477dd7cddfSDavid du Colombier extern int _asrdresp(int, uchar*, int);
20487dd7cddfSDavid du Colombier
20497dd7cddfSDavid du Colombier static void
getchap(PPP * ppp,Block * b)20507dd7cddfSDavid du Colombier getchap(PPP *ppp, Block *b)
20517dd7cddfSDavid du Colombier {
20529a747e4fSDavid du Colombier AuthInfo *ai;
20537dd7cddfSDavid du Colombier Lcpmsg *m;
20549a747e4fSDavid du Colombier int len, vlen, i, id, n, nresp;
20557dd7cddfSDavid du Colombier char md5buf[512], code;
20567dd7cddfSDavid du Colombier Chap *c;
20577dd7cddfSDavid du Colombier Chapreply cr;
20587dd7cddfSDavid du Colombier MSchapreply mscr;
20599a747e4fSDavid du Colombier char uid[PATH];
20609a747e4fSDavid du Colombier uchar digest[16], *p, *resp, sdigest[SHA1dlen];
20619a747e4fSDavid du Colombier uchar mshash[MShashlen], mshash2[MShashlen];
20629a747e4fSDavid du Colombier DigestState *s;
20639a747e4fSDavid du Colombier uchar msresp[2*MSresplen+1];
20647dd7cddfSDavid du Colombier
20657dd7cddfSDavid du Colombier m = (Lcpmsg*)b->rptr;
20667dd7cddfSDavid du Colombier len = nhgets(m->len);
20677dd7cddfSDavid du Colombier if(BLEN(b) < len){
20687dd7cddfSDavid du Colombier syslog(0, LOG, "short chap message");
20697dd7cddfSDavid du Colombier freeb(b);
20707dd7cddfSDavid du Colombier return;
20717dd7cddfSDavid du Colombier }
20727dd7cddfSDavid du Colombier
20737dd7cddfSDavid du Colombier qlock(ppp);
20747dd7cddfSDavid du Colombier
20757dd7cddfSDavid du Colombier switch(m->code){
20767dd7cddfSDavid du Colombier case Cchallenge:
2077dc5a79c1SDavid du Colombier getauth(ppp);
2078dc5a79c1SDavid du Colombier
20797dd7cddfSDavid du Colombier vlen = m->data[0];
20807dd7cddfSDavid du Colombier if(vlen > len - 5) {
20817dd7cddfSDavid du Colombier netlog("PPP: chap: bad challenge len\n");
20827dd7cddfSDavid du Colombier break;
20837dd7cddfSDavid du Colombier }
20847dd7cddfSDavid du Colombier
20859a747e4fSDavid du Colombier id = m->id;
20869a747e4fSDavid du Colombier switch(ppp->chap->proto){
20879a747e4fSDavid du Colombier default:
20889a747e4fSDavid du Colombier abort();
20899a747e4fSDavid du Colombier case APmd5:
20907dd7cddfSDavid du Colombier md5buf[0] = m->id;
20917dd7cddfSDavid du Colombier strcpy(md5buf+1, ppp->secret);
20927dd7cddfSDavid du Colombier n = strlen(ppp->secret) + 1;
20937dd7cddfSDavid du Colombier memmove(md5buf+n, m->data+1, vlen);
20947dd7cddfSDavid du Colombier n += vlen;
20959a747e4fSDavid du Colombier md5((uchar*)md5buf, n, digest, nil);
20969a747e4fSDavid du Colombier resp = digest;
20979a747e4fSDavid du Colombier nresp = 16;
20989a747e4fSDavid du Colombier break;
20999a747e4fSDavid du Colombier case APmschap:
21009a747e4fSDavid du Colombier nthash(mshash, ppp->secret);
21019a747e4fSDavid du Colombier memset(msresp, 0, sizeof msresp);
21029a747e4fSDavid du Colombier mschalresp(msresp+MSresplen, mshash, m->data+1);
21039a747e4fSDavid du Colombier resp = msresp;
21049a747e4fSDavid du Colombier nresp = sizeof msresp;
21059a747e4fSDavid du Colombier nthash(mshash, ppp->secret);
21069a747e4fSDavid du Colombier md4(mshash, 16, mshash2, 0);
21079a747e4fSDavid du Colombier s = sha1(mshash2, 16, 0, 0);
21089a747e4fSDavid du Colombier sha1(mshash2, 16, 0, s);
21099a747e4fSDavid du Colombier sha1(m->data+1, 8, sdigest, s);
21109a747e4fSDavid du Colombier memmove(ppp->key, sdigest, 16);
21119a747e4fSDavid du Colombier break;
21129a747e4fSDavid du Colombier }
21139a747e4fSDavid du Colombier len = 4 + 1 + nresp + strlen(ppp->chapname);
21147dd7cddfSDavid du Colombier freeb(b);
21159a747e4fSDavid du Colombier b = alloclcp(Cresponse, id, len, &m);
21169a747e4fSDavid du Colombier *b->wptr++ = nresp;
21179a747e4fSDavid du Colombier memmove(b->wptr, resp, nresp);
21189a747e4fSDavid du Colombier b->wptr += nresp;
21197dd7cddfSDavid du Colombier memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));
21207dd7cddfSDavid du Colombier b->wptr += strlen(ppp->chapname);
21217dd7cddfSDavid du Colombier hnputs(m->len, len);
21229a747e4fSDavid du Colombier netlog("PPP: sending response len %d\n", len);
21237dd7cddfSDavid du Colombier putframe(ppp, Pchap, b);
21247dd7cddfSDavid du Colombier break;
21257dd7cddfSDavid du Colombier case Cresponse:
21267dd7cddfSDavid du Colombier c = ppp->chap;
21277dd7cddfSDavid du Colombier vlen = m->data[0];
21287dd7cddfSDavid du Colombier if(m->id != c->id) {
21297dd7cddfSDavid du Colombier netlog("PPP: chap: bad response id\n");
21307dd7cddfSDavid du Colombier break;
21317dd7cddfSDavid du Colombier }
21327dd7cddfSDavid du Colombier switch(c->proto) {
21337dd7cddfSDavid du Colombier default:
21347dd7cddfSDavid du Colombier sysfatal("unknown chap protocol: %d", c->proto);
21357dd7cddfSDavid du Colombier case APmd5:
21367dd7cddfSDavid du Colombier if(vlen > len - 5 || vlen != 16) {
21377dd7cddfSDavid du Colombier netlog("PPP: chap: bad response len\n");
21387dd7cddfSDavid du Colombier break;
21397dd7cddfSDavid du Colombier }
21407dd7cddfSDavid du Colombier
21417dd7cddfSDavid du Colombier cr.id = m->id;
21427dd7cddfSDavid du Colombier memmove(cr.resp, m->data+1, 16);
21437dd7cddfSDavid du Colombier memset(uid, 0, sizeof(uid));
21447dd7cddfSDavid du Colombier n = len-5-vlen;
21459a747e4fSDavid du Colombier if(n >= PATH)
21469a747e4fSDavid du Colombier n = PATH-1;
21477dd7cddfSDavid du Colombier memmove(uid, m->data+1+vlen, n);
21489a747e4fSDavid du Colombier c->cs->user = uid;
21499a747e4fSDavid du Colombier c->cs->resp = &cr;
21509a747e4fSDavid du Colombier c->cs->nresp = sizeof cr;
21517dd7cddfSDavid du Colombier break;
21527dd7cddfSDavid du Colombier case APmschap:
21537dd7cddfSDavid du Colombier if(vlen > len - 5 || vlen != 49) {
21547dd7cddfSDavid du Colombier netlog("PPP: chap: bad response len\n");
21557dd7cddfSDavid du Colombier break;
21567dd7cddfSDavid du Colombier }
21577dd7cddfSDavid du Colombier memset(&mscr, 0, sizeof(mscr));
21587dd7cddfSDavid du Colombier memmove(mscr.LMresp, m->data+1, 24);
21597dd7cddfSDavid du Colombier memmove(mscr.NTresp, m->data+24+1, 24);
21607dd7cddfSDavid du Colombier n = len-5-vlen;
21617dd7cddfSDavid du Colombier p = m->data+1+vlen;
21627dd7cddfSDavid du Colombier /* remove domain name */
21637dd7cddfSDavid du Colombier for(i=0; i<n; i++) {
21647dd7cddfSDavid du Colombier if(p[i] == '\\') {
21657dd7cddfSDavid du Colombier p += i+1;
21667dd7cddfSDavid du Colombier n -= i+1;
21677dd7cddfSDavid du Colombier break;
21687dd7cddfSDavid du Colombier }
21697dd7cddfSDavid du Colombier }
21709a747e4fSDavid du Colombier if(n >= PATH)
21719a747e4fSDavid du Colombier n = PATH-1;
21727dd7cddfSDavid du Colombier memset(uid, 0, sizeof(uid));
21737dd7cddfSDavid du Colombier memmove(uid, p, n);
21749a747e4fSDavid du Colombier c->cs->user = uid;
21759a747e4fSDavid du Colombier c->cs->resp = 𝓂
21769a747e4fSDavid du Colombier c->cs->nresp = sizeof mscr;
21777dd7cddfSDavid du Colombier break;
21787dd7cddfSDavid du Colombier }
21797dd7cddfSDavid du Colombier
21809a747e4fSDavid du Colombier 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);
21819a747e4fSDavid du Colombier if((ai = auth_response(c->cs)) == nil || auth_chuid(ai, nil) < 0){
21827dd7cddfSDavid du Colombier c->state = Cunauth;
21837dd7cddfSDavid du Colombier code = Cfailure;
21849a747e4fSDavid du Colombier syslog(0, LOG, ": remote=%I: auth failed: %r, uid=%s", ppp->remote, uid);
21857dd7cddfSDavid du Colombier }else{
21867dd7cddfSDavid du Colombier c->state = Cauthok;
21877dd7cddfSDavid du Colombier code = Csuccess;
21889a747e4fSDavid du Colombier syslog(0, LOG, ": remote=%I: auth ok: uid=%s nsecret=%d", ppp->remote, uid, ai->nsecret);
21899a747e4fSDavid du Colombier if(c->proto == APmschap){
21909a747e4fSDavid du Colombier if(ai->nsecret != sizeof(ppp->key))
21917dd7cddfSDavid du Colombier sysfatal("could not get the encryption key");
21929a747e4fSDavid du Colombier memmove(ppp->key, ai->secret, sizeof(ppp->key));
21937dd7cddfSDavid du Colombier }
21949a747e4fSDavid du Colombier }
21959a747e4fSDavid du Colombier auth_freeAI(ai);
21969a747e4fSDavid du Colombier auth_freechal(c->cs);
21979a747e4fSDavid du Colombier c->cs = nil;
21987dd7cddfSDavid du Colombier freeb(b);
21997dd7cddfSDavid du Colombier
22007dd7cddfSDavid du Colombier /* send reply */
22017dd7cddfSDavid du Colombier len = 4;
22027dd7cddfSDavid du Colombier b = alloclcp(code, c->id, len, &m);
22037dd7cddfSDavid du Colombier hnputs(m->len, len);
22047dd7cddfSDavid du Colombier putframe(ppp, Pchap, b);
22057dd7cddfSDavid du Colombier
22067dd7cddfSDavid du Colombier if(c->state == Cauthok) {
22077dd7cddfSDavid du Colombier setphase(ppp, Pnet);
22087dd7cddfSDavid du Colombier } else {
22097dd7cddfSDavid du Colombier /* restart chapp negotiation */
22107dd7cddfSDavid du Colombier chapinit(ppp);
22117dd7cddfSDavid du Colombier }
22127dd7cddfSDavid du Colombier
22137dd7cddfSDavid du Colombier break;
22147dd7cddfSDavid du Colombier case Csuccess:
22157dd7cddfSDavid du Colombier netlog("ppp: chap succeeded\n");
22167dd7cddfSDavid du Colombier break;
22177dd7cddfSDavid du Colombier case Cfailure:
221859cc4ca5SDavid du Colombier netlog("ppp: chap failed\n");
22197dd7cddfSDavid du Colombier break;
22207dd7cddfSDavid du Colombier default:
22217dd7cddfSDavid du Colombier syslog(0, LOG, "chap code %d?\n", m->code);
22227dd7cddfSDavid du Colombier break;
22237dd7cddfSDavid du Colombier }
22247dd7cddfSDavid du Colombier qunlock(ppp);
22257dd7cddfSDavid du Colombier freeb(b);
22267dd7cddfSDavid du Colombier }
22277dd7cddfSDavid du Colombier
22287dd7cddfSDavid du Colombier static void
putpaprequest(PPP * ppp)222980ee5cbfSDavid du Colombier putpaprequest(PPP *ppp)
223080ee5cbfSDavid du Colombier {
223180ee5cbfSDavid du Colombier Block *b;
223280ee5cbfSDavid du Colombier Lcpmsg *m;
223380ee5cbfSDavid du Colombier Chap *c;
223480ee5cbfSDavid du Colombier int len, nlen, slen;
223580ee5cbfSDavid du Colombier
2236dc5a79c1SDavid du Colombier getauth(ppp);
2237dc5a79c1SDavid du Colombier
223880ee5cbfSDavid du Colombier c = ppp->chap;
223980ee5cbfSDavid du Colombier c->id++;
224080ee5cbfSDavid du Colombier netlog("PPP: pap: send authreq %d %s %s\n", c->id, ppp->chapname, "****");
224180ee5cbfSDavid du Colombier
224280ee5cbfSDavid du Colombier nlen = strlen(ppp->chapname);
224380ee5cbfSDavid du Colombier slen = strlen(ppp->secret);
224480ee5cbfSDavid du Colombier len = 4 + 1 + nlen + 1 + slen;
224580ee5cbfSDavid du Colombier b = alloclcp(Pauthreq, c->id, len, &m);
224680ee5cbfSDavid du Colombier
224780ee5cbfSDavid du Colombier *b->wptr++ = nlen;
224880ee5cbfSDavid du Colombier memmove(b->wptr, ppp->chapname, nlen);
224980ee5cbfSDavid du Colombier b->wptr += nlen;
225080ee5cbfSDavid du Colombier *b->wptr++ = slen;
225180ee5cbfSDavid du Colombier memmove(b->wptr, ppp->secret, slen);
225280ee5cbfSDavid du Colombier b->wptr += slen;
225380ee5cbfSDavid du Colombier hnputs(m->len, len);
225480ee5cbfSDavid du Colombier
225580ee5cbfSDavid du Colombier putframe(ppp, Ppasswd, b);
225680ee5cbfSDavid du Colombier freeb(b);
225780ee5cbfSDavid du Colombier }
225880ee5cbfSDavid du Colombier
225980ee5cbfSDavid du Colombier static void
papinit(PPP * ppp)226080ee5cbfSDavid du Colombier papinit(PPP *ppp)
226180ee5cbfSDavid du Colombier {
226280ee5cbfSDavid du Colombier ppp->chap->id = 0;
226380ee5cbfSDavid du Colombier putpaprequest(ppp);
226480ee5cbfSDavid du Colombier }
226580ee5cbfSDavid du Colombier
226680ee5cbfSDavid du Colombier static void
getpap(PPP * ppp,Block * b)226780ee5cbfSDavid du Colombier getpap(PPP *ppp, Block *b)
226880ee5cbfSDavid du Colombier {
226980ee5cbfSDavid du Colombier Lcpmsg *m;
227080ee5cbfSDavid du Colombier int len;
227180ee5cbfSDavid du Colombier
227280ee5cbfSDavid du Colombier m = (Lcpmsg*)b->rptr;
227380ee5cbfSDavid du Colombier len = 4;
227480ee5cbfSDavid du Colombier if(BLEN(b) < 4 || BLEN(b) < (len = nhgets(m->len))){
227580ee5cbfSDavid du Colombier syslog(0, LOG, "short pap message (%ld < %d)", BLEN(b), len);
227680ee5cbfSDavid du Colombier freeb(b);
227780ee5cbfSDavid du Colombier return;
227880ee5cbfSDavid du Colombier }
227980ee5cbfSDavid du Colombier if(len < sizeof(Lcpmsg))
228080ee5cbfSDavid du Colombier m->data[0] = 0;
228180ee5cbfSDavid du Colombier
228280ee5cbfSDavid du Colombier qlock(ppp);
228380ee5cbfSDavid du Colombier switch(m->code){
228480ee5cbfSDavid du Colombier case Pauthreq:
228580ee5cbfSDavid du Colombier netlog("PPP: pap auth request, not supported\n");
228680ee5cbfSDavid du Colombier break;
228780ee5cbfSDavid du Colombier case Pauthack:
228880ee5cbfSDavid du Colombier if(ppp->phase == Pauth
228980ee5cbfSDavid du Colombier && ppp->chap->proto == APpasswd
229080ee5cbfSDavid du Colombier && m->id <= ppp-> chap->id){
229180ee5cbfSDavid du Colombier netlog("PPP: pap succeeded\n");
229280ee5cbfSDavid du Colombier setphase(ppp, Pnet);
229380ee5cbfSDavid du Colombier }
229480ee5cbfSDavid du Colombier break;
229580ee5cbfSDavid du Colombier case Pauthnak:
229680ee5cbfSDavid du Colombier if(ppp->phase == Pauth
229780ee5cbfSDavid du Colombier && ppp->chap->proto == APpasswd
229880ee5cbfSDavid du Colombier && m->id <= ppp-> chap->id){
229980ee5cbfSDavid du Colombier netlog("PPP: pap failed (%d:%.*s)\n",
230080ee5cbfSDavid du Colombier m->data[0], m->data[0], (char*)m->data+1);
230180ee5cbfSDavid du Colombier terminate(ppp, 0);
230280ee5cbfSDavid du Colombier }
230380ee5cbfSDavid du Colombier break;
230480ee5cbfSDavid du Colombier default:
230580ee5cbfSDavid du Colombier netlog("PPP: unknown pap messsage %d\n", m->code);
230680ee5cbfSDavid du Colombier }
230780ee5cbfSDavid du Colombier qunlock(ppp);
230880ee5cbfSDavid du Colombier freeb(b);
230980ee5cbfSDavid du Colombier }
231080ee5cbfSDavid du Colombier
231180ee5cbfSDavid du Colombier static void
printopts(Pstate * p,Block * b,int send)23127dd7cddfSDavid du Colombier printopts(Pstate *p, Block *b, int send)
23137dd7cddfSDavid du Colombier {
23147dd7cddfSDavid du Colombier Lcpmsg *m;
23157dd7cddfSDavid du Colombier Lcpopt *o;
23167dd7cddfSDavid du Colombier int proto, x, period;
23177dd7cddfSDavid du Colombier uchar *cp;
23187dd7cddfSDavid du Colombier char *code, *dir;
23197dd7cddfSDavid du Colombier
23207dd7cddfSDavid du Colombier m = (Lcpmsg*)b->rptr;
23217dd7cddfSDavid du Colombier switch(m->code) {
23227dd7cddfSDavid du Colombier default: code = "<unknown>"; break;
23237dd7cddfSDavid du Colombier case Lconfreq: code = "confrequest"; break;
23247dd7cddfSDavid du Colombier case Lconfack: code = "confack"; break;
23257dd7cddfSDavid du Colombier case Lconfnak: code = "confnak"; break;
23267dd7cddfSDavid du Colombier case Lconfrej: code = "confreject"; break;
23277dd7cddfSDavid du Colombier }
23287dd7cddfSDavid du Colombier
23297dd7cddfSDavid du Colombier if(send)
23307dd7cddfSDavid du Colombier dir = "send";
23317dd7cddfSDavid du Colombier else
23327dd7cddfSDavid du Colombier dir = "recv";
23337dd7cddfSDavid du Colombier
23347dd7cddfSDavid du Colombier netlog("ppp: %s %s: id=%d\n", dir, code, m->id);
23357dd7cddfSDavid du Colombier
23367dd7cddfSDavid du Colombier for(cp = m->data; cp < b->wptr; cp += o->len){
23377dd7cddfSDavid du Colombier o = (Lcpopt*)cp;
23387dd7cddfSDavid du Colombier if(cp + o->len > b->wptr){
23397dd7cddfSDavid du Colombier netlog("\tbad option length %ux\n", o->type);
23407dd7cddfSDavid du Colombier return;
23417dd7cddfSDavid du Colombier }
23427dd7cddfSDavid du Colombier
23437dd7cddfSDavid du Colombier switch(p->proto){
23447dd7cddfSDavid du Colombier case Plcp:
23457dd7cddfSDavid du Colombier switch(o->type){
23467dd7cddfSDavid du Colombier default:
23477dd7cddfSDavid du Colombier netlog("\tunknown %d len=%d\n", o->type, o->len);
23487dd7cddfSDavid du Colombier break;
23497dd7cddfSDavid du Colombier case Omtu:
23507dd7cddfSDavid du Colombier netlog("\tmtu = %d\n", nhgets(o->data));
23517dd7cddfSDavid du Colombier break;
23527dd7cddfSDavid du Colombier case Octlmap:
23537dd7cddfSDavid du Colombier netlog("\tctlmap = %ux\n", nhgetl(o->data));
23547dd7cddfSDavid du Colombier break;
23557dd7cddfSDavid du Colombier case Oauth:
235659cc4ca5SDavid du Colombier netlog("\tauth = %ux", nhgetl(o->data));
23577dd7cddfSDavid du Colombier proto = nhgets(o->data);
23587dd7cddfSDavid du Colombier switch(proto) {
23597dd7cddfSDavid du Colombier default:
23607dd7cddfSDavid du Colombier netlog("unknown auth proto %d\n", proto);
23617dd7cddfSDavid du Colombier break;
23627dd7cddfSDavid du Colombier case Ppasswd:
23637dd7cddfSDavid du Colombier netlog("password\n");
23647dd7cddfSDavid du Colombier break;
23657dd7cddfSDavid du Colombier case Pchap:
23667dd7cddfSDavid du Colombier netlog("chap %ux\n", o->data[2]);
23677dd7cddfSDavid du Colombier break;
23687dd7cddfSDavid du Colombier }
23697dd7cddfSDavid du Colombier break;
23707dd7cddfSDavid du Colombier case Oquality:
23717dd7cddfSDavid du Colombier proto = nhgets(o->data);
23727dd7cddfSDavid du Colombier switch(proto) {
23737dd7cddfSDavid du Colombier default:
23747dd7cddfSDavid du Colombier netlog("\tunknown quality proto %d\n", proto);
23757dd7cddfSDavid du Colombier break;
23767dd7cddfSDavid du Colombier case Plqm:
23777dd7cddfSDavid du Colombier x = nhgetl(o->data+2)*10;
23787dd7cddfSDavid du Colombier period = (x+Period-1)/Period;
23797dd7cddfSDavid du Colombier netlog("\tlqm period = %d\n", period);
23807dd7cddfSDavid du Colombier break;
23817dd7cddfSDavid du Colombier }
23827dd7cddfSDavid du Colombier case Omagic:
23837dd7cddfSDavid du Colombier netlog("\tmagic = %ux\n", nhgetl(o->data));
23847dd7cddfSDavid du Colombier break;
23857dd7cddfSDavid du Colombier case Opc:
23867dd7cddfSDavid du Colombier netlog("\tprotocol compress\n");
23877dd7cddfSDavid du Colombier break;
23887dd7cddfSDavid du Colombier case Oac:
23897dd7cddfSDavid du Colombier netlog("\taddr compress\n");
23907dd7cddfSDavid du Colombier break;
23917dd7cddfSDavid du Colombier }
23927dd7cddfSDavid du Colombier break;
23937dd7cddfSDavid du Colombier case Pccp:
23947dd7cddfSDavid du Colombier switch(o->type){
23957dd7cddfSDavid du Colombier default:
23967dd7cddfSDavid du Colombier netlog("\tunknown %d len=%d\n", o->type, o->len);
23977dd7cddfSDavid du Colombier break;
23987dd7cddfSDavid du Colombier case Ocoui:
23997dd7cddfSDavid du Colombier netlog("\tOUI\n");
24007dd7cddfSDavid du Colombier break;
24017dd7cddfSDavid du Colombier case Ocstac:
24027dd7cddfSDavid du Colombier netlog("\tstac LZS\n");
24037dd7cddfSDavid du Colombier break;
24047dd7cddfSDavid du Colombier case Ocmppc:
24057dd7cddfSDavid du Colombier netlog("\tMicrosoft PPC len=%d %ux\n", o->len, nhgetl(o->data));
24067dd7cddfSDavid du Colombier break;
24077dd7cddfSDavid du Colombier case Octhwack:
24087dd7cddfSDavid du Colombier netlog("\tThwack\n");
24097dd7cddfSDavid du Colombier break;
24107dd7cddfSDavid du Colombier }
24117dd7cddfSDavid du Colombier break;
24127dd7cddfSDavid du Colombier case Pecp:
24137dd7cddfSDavid du Colombier switch(o->type){
24147dd7cddfSDavid du Colombier default:
24157dd7cddfSDavid du Colombier netlog("\tunknown %d len=%d\n", o->type, o->len);
24167dd7cddfSDavid du Colombier break;
24177dd7cddfSDavid du Colombier case Oeoui:
24187dd7cddfSDavid du Colombier netlog("\tOUI\n");
24197dd7cddfSDavid du Colombier break;
24207dd7cddfSDavid du Colombier case Oedese:
24217dd7cddfSDavid du Colombier netlog("\tDES\n");
24227dd7cddfSDavid du Colombier break;
24237dd7cddfSDavid du Colombier }
24247dd7cddfSDavid du Colombier break;
24257dd7cddfSDavid du Colombier case Pipcp:
24267dd7cddfSDavid du Colombier switch(o->type){
24277dd7cddfSDavid du Colombier default:
24287dd7cddfSDavid du Colombier netlog("\tunknown %d len=%d\n", o->type, o->len);
24297dd7cddfSDavid du Colombier break;
24307dd7cddfSDavid du Colombier case Oipaddrs:
24317dd7cddfSDavid du Colombier netlog("\tip addrs - deprecated\n");
24327dd7cddfSDavid du Colombier break;
24337dd7cddfSDavid du Colombier case Oipcompress:
24347dd7cddfSDavid du Colombier netlog("\tip compress\n");
24357dd7cddfSDavid du Colombier break;
24367dd7cddfSDavid du Colombier case Oipaddr:
24377dd7cddfSDavid du Colombier netlog("\tip addr %V\n", o->data);
24387dd7cddfSDavid du Colombier break;
24397dd7cddfSDavid du Colombier case Oipdns:
24407dd7cddfSDavid du Colombier netlog("\tdns addr %V\n", o->data);
24417dd7cddfSDavid du Colombier break;
24427dd7cddfSDavid du Colombier case Oipwins:
24437dd7cddfSDavid du Colombier netlog("\twins addr %V\n", o->data);
24447dd7cddfSDavid du Colombier break;
24457dd7cddfSDavid du Colombier case Oipdns2:
24467dd7cddfSDavid du Colombier netlog("\tdns2 addr %V\n", o->data);
24477dd7cddfSDavid du Colombier break;
24487dd7cddfSDavid du Colombier case Oipwins2:
24497dd7cddfSDavid du Colombier netlog("\twins2 addr %V\n", o->data);
24507dd7cddfSDavid du Colombier break;
24517dd7cddfSDavid du Colombier }
24527dd7cddfSDavid du Colombier break;
24537dd7cddfSDavid du Colombier }
24547dd7cddfSDavid du Colombier }
24557dd7cddfSDavid du Colombier }
24567dd7cddfSDavid du Colombier
24577dd7cddfSDavid du Colombier static void
sendtermreq(PPP * ppp,Pstate * p)24587dd7cddfSDavid du Colombier sendtermreq(PPP *ppp, Pstate *p)
24597dd7cddfSDavid du Colombier {
24607dd7cddfSDavid du Colombier Block *b;
24617dd7cddfSDavid du Colombier Lcpmsg *m;
24627dd7cddfSDavid du Colombier
24637dd7cddfSDavid du Colombier p->termid = ++(p->id);
24647dd7cddfSDavid du Colombier b = alloclcp(Ltermreq, p->termid, 4, &m);
24657dd7cddfSDavid du Colombier hnputs(m->len, 4);
24667dd7cddfSDavid du Colombier putframe(ppp, p->proto, b);
24677dd7cddfSDavid du Colombier freeb(b);
24687dd7cddfSDavid du Colombier newstate(ppp, p, Sclosing);
24697dd7cddfSDavid du Colombier }
24707dd7cddfSDavid du Colombier
24717dd7cddfSDavid du Colombier static void
sendechoreq(PPP * ppp,Pstate * p)24727dd7cddfSDavid du Colombier sendechoreq(PPP *ppp, Pstate *p)
24737dd7cddfSDavid du Colombier {
24747dd7cddfSDavid du Colombier Block *b;
24757dd7cddfSDavid du Colombier Lcpmsg *m;
24767dd7cddfSDavid du Colombier
24777dd7cddfSDavid du Colombier p->termid = ++(p->id);
24787dd7cddfSDavid du Colombier b = alloclcp(Lechoreq, p->id, 4, &m);
24797dd7cddfSDavid du Colombier hnputs(m->len, 4);
24807dd7cddfSDavid du Colombier putframe(ppp, p->proto, b);
24817dd7cddfSDavid du Colombier freeb(b);
24827dd7cddfSDavid du Colombier }
24837dd7cddfSDavid du Colombier
24847dd7cddfSDavid du Colombier enum
24857dd7cddfSDavid du Colombier {
24867dd7cddfSDavid du Colombier CtrlD = 0x4,
24877dd7cddfSDavid du Colombier CtrlE = 0x5,
24887dd7cddfSDavid du Colombier CtrlO = 0xf,
24897dd7cddfSDavid du Colombier Cr = 13,
24907dd7cddfSDavid du Colombier View = 0x80,
24917dd7cddfSDavid du Colombier };
24927dd7cddfSDavid du Colombier
24937dd7cddfSDavid du Colombier int conndone;
24947dd7cddfSDavid du Colombier
24957dd7cddfSDavid du Colombier static void
xfer(int fd)24967dd7cddfSDavid du Colombier xfer(int fd)
24977dd7cddfSDavid du Colombier {
24987dd7cddfSDavid du Colombier int i, n;
24997dd7cddfSDavid du Colombier uchar xbuf[128];
25007dd7cddfSDavid du Colombier
25017dd7cddfSDavid du Colombier for(;;) {
25027dd7cddfSDavid du Colombier n = read(fd, xbuf, sizeof(xbuf));
25037dd7cddfSDavid du Colombier if(n < 0)
25047dd7cddfSDavid du Colombier break;
25057dd7cddfSDavid du Colombier if(conndone)
25067dd7cddfSDavid du Colombier break;
25077dd7cddfSDavid du Colombier for(i = 0; i < n; i++)
25087dd7cddfSDavid du Colombier if(xbuf[i] == Cr)
25097dd7cddfSDavid du Colombier xbuf[i] = ' ';
25107dd7cddfSDavid du Colombier write(1, xbuf, n);
25117dd7cddfSDavid du Colombier }
25127dd7cddfSDavid du Colombier close(fd);
25137dd7cddfSDavid du Colombier }
25147dd7cddfSDavid du Colombier
251539734e7eSDavid du Colombier static int
readcr(int fd,char * buf,int nbuf)251639734e7eSDavid du Colombier readcr(int fd, char *buf, int nbuf)
251739734e7eSDavid du Colombier {
251839734e7eSDavid du Colombier char c;
251939734e7eSDavid du Colombier int n, tot;
252039734e7eSDavid du Colombier
252139734e7eSDavid du Colombier tot = 0;
252239734e7eSDavid du Colombier while((n=read(fd, &c, 1)) == 1){
252339734e7eSDavid du Colombier if(c == '\n'){
252439734e7eSDavid du Colombier buf[tot] = 0;
252539734e7eSDavid du Colombier return tot;
252639734e7eSDavid du Colombier }
252739734e7eSDavid du Colombier buf[tot++] = c;
252839734e7eSDavid du Colombier if(tot == nbuf)
252939734e7eSDavid du Colombier sysfatal("line too long in readcr");
253039734e7eSDavid du Colombier }
253139734e7eSDavid du Colombier return n;
253239734e7eSDavid du Colombier }
253339734e7eSDavid du Colombier
25347dd7cddfSDavid du Colombier static void
connect(int fd,int cfd)25357dd7cddfSDavid du Colombier connect(int fd, int cfd)
25367dd7cddfSDavid du Colombier {
25377dd7cddfSDavid du Colombier int n, ctl;
25387dd7cddfSDavid du Colombier char xbuf[128];
25397dd7cddfSDavid du Colombier
25403ff48bf5SDavid du Colombier if (chatfile) {
25413ff48bf5SDavid du Colombier int chatfd, lineno, nb;
25423ff48bf5SDavid du Colombier char *buf, *p, *s, response[128];
25433ff48bf5SDavid du Colombier Dir *dir;
25443ff48bf5SDavid du Colombier
25453ff48bf5SDavid du Colombier if ((chatfd = open(chatfile, OREAD)) < 0)
25463ff48bf5SDavid du Colombier sysfatal("cannot open %s: %r", chatfile);
25473ff48bf5SDavid du Colombier
25483ff48bf5SDavid du Colombier if ((dir = dirfstat(chatfd)) == nil)
25493ff48bf5SDavid du Colombier sysfatal("cannot fstat %s: %r",chatfile);
25503ff48bf5SDavid du Colombier
25513ff48bf5SDavid du Colombier buf = (char *)malloc(dir->length + 1);
25523ff48bf5SDavid du Colombier assert(buf);
25533ff48bf5SDavid du Colombier
25543ff48bf5SDavid du Colombier if ((nb = read(chatfd, buf, dir->length)) < 0)
25553ff48bf5SDavid du Colombier sysfatal("cannot read chatfile %s: %r", chatfile);
25563ff48bf5SDavid du Colombier assert(nb == dir->length);
25573ff48bf5SDavid du Colombier buf[dir->length] = '\0';
25583ff48bf5SDavid du Colombier free(dir);
25593ff48bf5SDavid du Colombier close(chatfd);
25603ff48bf5SDavid du Colombier
25613ff48bf5SDavid du Colombier p = buf;
25623ff48bf5SDavid du Colombier lineno = 0;
2563eed6406fSDavid du Colombier for(;;) {
25643ff48bf5SDavid du Colombier char *_args[3];
25653ff48bf5SDavid du Colombier
25663ff48bf5SDavid du Colombier if ((s = strchr(p, '\n')) == nil)
25673ff48bf5SDavid du Colombier break;
25683ff48bf5SDavid du Colombier *s++ = '\0';
25693ff48bf5SDavid du Colombier
25703ff48bf5SDavid du Colombier lineno++;
25713ff48bf5SDavid du Colombier
25723ff48bf5SDavid du Colombier if (*p == '#') {
25733ff48bf5SDavid du Colombier p = s;
25743ff48bf5SDavid du Colombier continue;
25753ff48bf5SDavid du Colombier }
25763ff48bf5SDavid du Colombier
25773ff48bf5SDavid du Colombier if (tokenize(p, _args, 3) != 2)
25783ff48bf5SDavid du Colombier sysfatal("invalid line %d (line expected: 'send' 'expect')",
25793ff48bf5SDavid du Colombier lineno);
25803ff48bf5SDavid du Colombier
25813ff48bf5SDavid du Colombier if (debug)
25823ff48bf5SDavid du Colombier print("sending %s, expecting %s\n", _args[0], _args[1]);
25833ff48bf5SDavid du Colombier
258439734e7eSDavid du Colombier if(strlen(_args[0])){
258539734e7eSDavid du Colombier nb = fprint(fd, "%s\r", _args[0]);
258639734e7eSDavid du Colombier assert(nb > 0);
258739734e7eSDavid du Colombier }
25883ff48bf5SDavid du Colombier
25893ff48bf5SDavid du Colombier if (strlen(_args[1]) > 0) {
259039734e7eSDavid du Colombier if ((nb = readcr(fd, response, sizeof response-1)) < 0)
25913ff48bf5SDavid du Colombier sysfatal("cannot read response from: %r");
25923ff48bf5SDavid du Colombier
25933ff48bf5SDavid du Colombier if (debug)
25943ff48bf5SDavid du Colombier print("response %s\n", response);
25953ff48bf5SDavid du Colombier
25963ff48bf5SDavid du Colombier if (nb == 0)
259714cc0f53SDavid du Colombier sysfatal("eof on input?");
25983ff48bf5SDavid du Colombier
25993ff48bf5SDavid du Colombier if (cistrstr(response, _args[1]) == nil)
260014cc0f53SDavid du Colombier sysfatal("expected %s, got %s", _args[1], response);
26013ff48bf5SDavid du Colombier }
26023ff48bf5SDavid du Colombier p = s;
26033ff48bf5SDavid du Colombier }
26043ff48bf5SDavid du Colombier free(buf);
26053ff48bf5SDavid du Colombier return;
26063ff48bf5SDavid du Colombier }
26073ff48bf5SDavid du Colombier
26087dd7cddfSDavid du Colombier print("Connect to file system now, type ctrl-d when done.\n");
26097dd7cddfSDavid du Colombier print("...(Use the view or down arrow key to send a break)\n");
26107dd7cddfSDavid du Colombier print("...(Use ctrl-e to set even parity or ctrl-o for odd)\n");
26117dd7cddfSDavid du Colombier
26127dd7cddfSDavid du Colombier ctl = open("/dev/consctl", OWRITE);
26137dd7cddfSDavid du Colombier if(ctl < 0)
26147dd7cddfSDavid du Colombier sysfatal("opening consctl");
26157dd7cddfSDavid du Colombier fprint(ctl, "rawon");
26167dd7cddfSDavid du Colombier
26177dd7cddfSDavid du Colombier fd = dup(fd, -1);
26187dd7cddfSDavid du Colombier conndone = 0;
26197dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
26207dd7cddfSDavid du Colombier case -1:
26217dd7cddfSDavid du Colombier sysfatal("forking xfer");
26227dd7cddfSDavid du Colombier case 0:
26237dd7cddfSDavid du Colombier xfer(fd);
26247dd7cddfSDavid du Colombier _exits(nil);
26257dd7cddfSDavid du Colombier }
26267dd7cddfSDavid du Colombier
26277dd7cddfSDavid du Colombier for(;;){
26287dd7cddfSDavid du Colombier read(0, xbuf, 1);
26297dd7cddfSDavid du Colombier switch(xbuf[0]&0xff) {
26307dd7cddfSDavid du Colombier case CtrlD: /* done */
26317dd7cddfSDavid du Colombier conndone = 1;
26327dd7cddfSDavid du Colombier close(ctl);
26337dd7cddfSDavid du Colombier print("\n");
26347dd7cddfSDavid du Colombier return;
26357dd7cddfSDavid du Colombier case CtrlE: /* set even parity */
26367dd7cddfSDavid du Colombier fprint(cfd, "pe");
26377dd7cddfSDavid du Colombier break;
26387dd7cddfSDavid du Colombier case CtrlO: /* set odd parity */
26397dd7cddfSDavid du Colombier fprint(cfd, "po");
26407dd7cddfSDavid du Colombier break;
26417dd7cddfSDavid du Colombier case View: /* send a break */
26427dd7cddfSDavid du Colombier fprint(cfd, "k500");
26437dd7cddfSDavid du Colombier break;
26447dd7cddfSDavid du Colombier default:
26457dd7cddfSDavid du Colombier n = write(fd, xbuf, 1);
26467dd7cddfSDavid du Colombier if(n < 0) {
26479a747e4fSDavid du Colombier errstr(xbuf, sizeof(xbuf));
26487dd7cddfSDavid du Colombier conndone = 1;
26497dd7cddfSDavid du Colombier close(ctl);
26507dd7cddfSDavid du Colombier print("[remote write error (%s)]\n", xbuf);
26517dd7cddfSDavid du Colombier return;
26527dd7cddfSDavid du Colombier }
26537dd7cddfSDavid du Colombier }
26547dd7cddfSDavid du Colombier }
26557dd7cddfSDavid du Colombier }
26567dd7cddfSDavid du Colombier
26577dd7cddfSDavid du Colombier int interactive;
26587dd7cddfSDavid du Colombier
26597dd7cddfSDavid du Colombier void
usage(void)26607dd7cddfSDavid du Colombier usage(void)
26617dd7cddfSDavid du Colombier {
2662*4f81ea25SDavid du Colombier fprint(2, "usage: ppp [-CPSacdfu] [-b baud] [-k keyspec] [-m mtu] "
2663*4f81ea25SDavid du Colombier "[-M chatfile] [-p dev] [-x netmntpt] [-t modemcmd] "
2664*4f81ea25SDavid du Colombier "[local-addr [remote-addr]]\n");
26657dd7cddfSDavid du Colombier exits("usage");
26667dd7cddfSDavid du Colombier }
26677dd7cddfSDavid du Colombier
26687dd7cddfSDavid du Colombier void
main(int argc,char ** argv)26697dd7cddfSDavid du Colombier main(int argc, char **argv)
26707dd7cddfSDavid du Colombier {
2671d9306527SDavid du Colombier int mtu, baud, framing, user, mediain, mediaout, cfd;
26727dd7cddfSDavid du Colombier Ipaddr ipaddr, remip;
2673bedadc12SDavid du Colombier char *dev, *modemcmd;
26747dd7cddfSDavid du Colombier char net[128];
26757dd7cddfSDavid du Colombier PPP *ppp;
26767dd7cddfSDavid du Colombier char buf[128];
26777dd7cddfSDavid du Colombier
26786b6b9ac8SDavid du Colombier rfork(RFREND|RFNOTEG|RFNAMEG);
26797dd7cddfSDavid du Colombier
26809a747e4fSDavid du Colombier fmtinstall('I', eipfmt);
26819a747e4fSDavid du Colombier fmtinstall('V', eipfmt);
26829a747e4fSDavid du Colombier fmtinstall('E', eipfmt);
26837dd7cddfSDavid du Colombier
26847dd7cddfSDavid du Colombier dev = nil;
26857dd7cddfSDavid du Colombier
26867dd7cddfSDavid du Colombier invalidate(ipaddr);
26877dd7cddfSDavid du Colombier invalidate(remip);
26887dd7cddfSDavid du Colombier
26897dd7cddfSDavid du Colombier mtu = Defmtu;
26907dd7cddfSDavid du Colombier baud = 0;
26917dd7cddfSDavid du Colombier framing = 0;
26927dd7cddfSDavid du Colombier setnetmtpt(net, sizeof(net), nil);
26937dd7cddfSDavid du Colombier user = 0;
26947dd7cddfSDavid du Colombier modemcmd = nil;
26957dd7cddfSDavid du Colombier
26967dd7cddfSDavid du Colombier ARGBEGIN{
2697*4f81ea25SDavid du Colombier case 'a':
2698*4f81ea25SDavid du Colombier noauth = 1;
2699*4f81ea25SDavid du Colombier break;
27007dd7cddfSDavid du Colombier case 'b':
2701bedadc12SDavid du Colombier baud = atoi(EARGF(usage()));
27027dd7cddfSDavid du Colombier if(baud < 0)
27037dd7cddfSDavid du Colombier baud = 0;
27047dd7cddfSDavid du Colombier break;
270559cc4ca5SDavid du Colombier case 'c':
270659cc4ca5SDavid du Colombier nocompress = 1;
270759cc4ca5SDavid du Colombier break;
270859cc4ca5SDavid du Colombier case 'C':
270959cc4ca5SDavid du Colombier noipcompress = 1;
271059cc4ca5SDavid du Colombier break;
271159cc4ca5SDavid du Colombier case 'd':
271259cc4ca5SDavid du Colombier debug++;
271359cc4ca5SDavid du Colombier break;
271459cc4ca5SDavid du Colombier case 'f':
271559cc4ca5SDavid du Colombier framing = 1;
271659cc4ca5SDavid du Colombier break;
27179a747e4fSDavid du Colombier case 'F':
27189a747e4fSDavid du Colombier pppframing = 0;
27199a747e4fSDavid du Colombier break;
2720bedadc12SDavid du Colombier case 'k':
2721bedadc12SDavid du Colombier keyspec = EARGF(usage());
2722bedadc12SDavid du Colombier break;
27237dd7cddfSDavid du Colombier case 'm':
2724bedadc12SDavid du Colombier mtu = atoi(EARGF(usage()));
27257dd7cddfSDavid du Colombier if(mtu < Minmtu)
27267dd7cddfSDavid du Colombier mtu = Minmtu;
27277dd7cddfSDavid du Colombier if(mtu > Maxmtu)
27287dd7cddfSDavid du Colombier mtu = Maxmtu;
27297dd7cddfSDavid du Colombier break;
27303ff48bf5SDavid du Colombier case 'M':
27313ff48bf5SDavid du Colombier chatfile = EARGF(usage());
27323ff48bf5SDavid du Colombier break;
27337dd7cddfSDavid du Colombier case 'p':
2734bedadc12SDavid du Colombier dev = EARGF(usage());
27357dd7cddfSDavid du Colombier break;
273659cc4ca5SDavid du Colombier case 'P':
273759cc4ca5SDavid du Colombier primary = 1;
27387dd7cddfSDavid du Colombier break;
27397dd7cddfSDavid du Colombier case 'S':
27407dd7cddfSDavid du Colombier server = 1;
27417dd7cddfSDavid du Colombier break;
27427dd7cddfSDavid du Colombier case 't':
2743bedadc12SDavid du Colombier modemcmd = EARGF(usage());
27447dd7cddfSDavid du Colombier break;
274559cc4ca5SDavid du Colombier case 'u':
274659cc4ca5SDavid du Colombier user = 1;
274759cc4ca5SDavid du Colombier break;
274859cc4ca5SDavid du Colombier case 'x':
2749bedadc12SDavid du Colombier setnetmtpt(net, sizeof net, EARGF(usage()));
275059cc4ca5SDavid du Colombier break;
27517dd7cddfSDavid du Colombier default:
2752bedadc12SDavid du Colombier fprint(2, "unknown option %c\n", ARGC());
2753bedadc12SDavid du Colombier usage();
27547dd7cddfSDavid du Colombier }ARGEND;
27557dd7cddfSDavid du Colombier
27567dd7cddfSDavid du Colombier switch(argc){
27577dd7cddfSDavid du Colombier case 2:
2758ea58ad6fSDavid du Colombier if (parseip(remip, argv[1]) == -1)
2759ea58ad6fSDavid du Colombier sysfatal("bad remote ip %s", argv[1]);
27607dd7cddfSDavid du Colombier case 1:
2761ea58ad6fSDavid du Colombier if (parseip(ipaddr, argv[0]) == -1)
2762ea58ad6fSDavid du Colombier sysfatal("bad ip %s", argv[0]);
27637dd7cddfSDavid du Colombier case 0:
27647dd7cddfSDavid du Colombier break;
27657dd7cddfSDavid du Colombier default:
27667dd7cddfSDavid du Colombier usage();
27677dd7cddfSDavid du Colombier }
27687dd7cddfSDavid du Colombier
27697dd7cddfSDavid du Colombier nip = nipifcs(net);
277059cc4ca5SDavid du Colombier if(nip == 0 && !server)
277159cc4ca5SDavid du Colombier primary = 1;
27727dd7cddfSDavid du Colombier
27737dd7cddfSDavid du Colombier if(dev != nil){
2774d9306527SDavid du Colombier mediain = open(dev, ORDWR);
2775d9306527SDavid du Colombier if(mediain < 0){
277659cc4ca5SDavid du Colombier if(strchr(dev, '!')){
2777d9306527SDavid du Colombier if((mediain = dial(dev, 0, 0, &cfd)) == -1){
277859cc4ca5SDavid du Colombier fprint(2, "ppp: couldn't dial %s: %r\n", dev);
277959cc4ca5SDavid du Colombier exits(dev);
278059cc4ca5SDavid du Colombier }
278159cc4ca5SDavid du Colombier } else {
27827dd7cddfSDavid du Colombier fprint(2, "ppp: couldn't open %s\n", dev);
27837dd7cddfSDavid du Colombier exits(dev);
27847dd7cddfSDavid du Colombier }
278559cc4ca5SDavid du Colombier } else {
27867dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%sctl", dev);
27877dd7cddfSDavid du Colombier cfd = open(buf, ORDWR);
278859cc4ca5SDavid du Colombier }
27897dd7cddfSDavid du Colombier if(cfd > 0){
27907dd7cddfSDavid du Colombier if(baud)
27917dd7cddfSDavid du Colombier fprint(cfd, "b%d", baud);
27927dd7cddfSDavid du Colombier fprint(cfd, "m1"); /* cts/rts flow control (and fifo's) on */
2793223a736eSDavid du Colombier fprint(cfd, "q64000"); /* increase q size to 64k */
27947dd7cddfSDavid du Colombier fprint(cfd, "n1"); /* nonblocking writes on */
27957dd7cddfSDavid du Colombier fprint(cfd, "r1"); /* rts on */
27967dd7cddfSDavid du Colombier fprint(cfd, "d1"); /* dtr on */
279759cc4ca5SDavid du Colombier fprint(cfd, "c1"); /* dcdhup on */
279839734e7eSDavid du Colombier if(user || chatfile)
2799d9306527SDavid du Colombier connect(mediain, cfd);
28007dd7cddfSDavid du Colombier close(cfd);
28017dd7cddfSDavid du Colombier } else {
280239734e7eSDavid du Colombier if(user || chatfile)
2803d9306527SDavid du Colombier connect(mediain, -1);
28047dd7cddfSDavid du Colombier }
2805d9306527SDavid du Colombier mediaout = mediain;
28067dd7cddfSDavid du Colombier } else {
2807d9306527SDavid du Colombier mediain = open("/fd/0", OREAD);
2808d9306527SDavid du Colombier if(mediain < 0){
28097dd7cddfSDavid du Colombier fprint(2, "ppp: couldn't open /fd/0\n");
28107dd7cddfSDavid du Colombier exits("/fd/0");
28117dd7cddfSDavid du Colombier }
2812d9306527SDavid du Colombier mediaout = open("/fd/1", OWRITE);
2813d9306527SDavid du Colombier if(mediaout < 0){
2814d9306527SDavid du Colombier fprint(2, "ppp: couldn't open /fd/0\n");
2815d9306527SDavid du Colombier exits("/fd/1");
2816d9306527SDavid du Colombier }
28177dd7cddfSDavid du Colombier }
28187dd7cddfSDavid du Colombier
2819d9306527SDavid du Colombier if(modemcmd != nil && mediaout >= 0)
2820d9306527SDavid du Colombier fprint(mediaout, "%s\r", modemcmd);
28217dd7cddfSDavid du Colombier
28227dd7cddfSDavid du Colombier ppp = mallocz(sizeof(*ppp), 1);
2823bedadc12SDavid du Colombier pppopen(ppp, mediain, mediaout, net, ipaddr, remip, mtu, framing);
28247dd7cddfSDavid du Colombier
28257dd7cddfSDavid du Colombier /* wait until ip is configured */
282674f16c81SDavid du Colombier rendezvous((void*)Rmagic, 0);
28277dd7cddfSDavid du Colombier
2828dc5a79c1SDavid du Colombier if(primary){
28297dd7cddfSDavid du Colombier /* create a /net/ndb entry */
28307dd7cddfSDavid du Colombier putndb(ppp, net);
28317dd7cddfSDavid du Colombier }
28327dd7cddfSDavid du Colombier
28337dd7cddfSDavid du Colombier exits(0);
28347dd7cddfSDavid du Colombier }
28357dd7cddfSDavid du Colombier
28367dd7cddfSDavid du Colombier void
netlog(char * fmt,...)28377dd7cddfSDavid du Colombier netlog(char *fmt, ...)
28387dd7cddfSDavid du Colombier {
28397dd7cddfSDavid du Colombier va_list arg;
28403ff48bf5SDavid du Colombier char *m;
28413ff48bf5SDavid du Colombier static long start;
28423ff48bf5SDavid du Colombier long now;
28433ff48bf5SDavid du Colombier
28446b6b9ac8SDavid du Colombier if(debug == 0)
28456b6b9ac8SDavid du Colombier return;
28466b6b9ac8SDavid du Colombier
28473ff48bf5SDavid du Colombier now = time(0);
28483ff48bf5SDavid du Colombier if(start == 0)
28493ff48bf5SDavid du Colombier start = now;
28507dd7cddfSDavid du Colombier
28517dd7cddfSDavid du Colombier va_start(arg, fmt);
28523ff48bf5SDavid du Colombier m = vsmprint(fmt, arg);
28533ff48bf5SDavid du Colombier fprint(2, "%ld %s", now-start, m);
28543ff48bf5SDavid du Colombier free(m);
28557dd7cddfSDavid du Colombier va_end(arg);
28567dd7cddfSDavid du Colombier }
28577dd7cddfSDavid du Colombier
28587dd7cddfSDavid du Colombier /*
28597dd7cddfSDavid du Colombier * return non-zero if this is a valid v4 address
28607dd7cddfSDavid du Colombier */
28617dd7cddfSDavid du Colombier static int
validv4(Ipaddr addr)28627dd7cddfSDavid du Colombier validv4(Ipaddr addr)
28637dd7cddfSDavid du Colombier {
28647dd7cddfSDavid du Colombier return memcmp(addr, v4prefix, IPv4off) == 0 && memcmp(addr, v4prefix, IPaddrlen) != 0;
28657dd7cddfSDavid du Colombier }
28667dd7cddfSDavid du Colombier
28677dd7cddfSDavid du Colombier static void
invalidate(Ipaddr addr)28687dd7cddfSDavid du Colombier invalidate(Ipaddr addr)
28697dd7cddfSDavid du Colombier {
28707dd7cddfSDavid du Colombier ipmove(addr, IPnoaddr);
28717dd7cddfSDavid du Colombier }
28727dd7cddfSDavid du Colombier
28737dd7cddfSDavid du Colombier /*
28747dd7cddfSDavid du Colombier * return number of networks
28757dd7cddfSDavid du Colombier */
28767dd7cddfSDavid du Colombier static int
nipifcs(char * net)28777dd7cddfSDavid du Colombier nipifcs(char *net)
28787dd7cddfSDavid du Colombier {
28799a747e4fSDavid du Colombier static Ipifc *ifc;
28809a747e4fSDavid du Colombier Ipifc *nifc;
28819a747e4fSDavid du Colombier Iplifc *lifc;
28827dd7cddfSDavid du Colombier int n;
28837dd7cddfSDavid du Colombier
28847dd7cddfSDavid du Colombier n = 0;
28859a747e4fSDavid du Colombier ifc = readipifc(net, ifc, -1);
28869a747e4fSDavid du Colombier for(nifc = ifc; nifc != nil; nifc = nifc->next)
28879a747e4fSDavid du Colombier for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next)
28887dd7cddfSDavid du Colombier n++;
28897dd7cddfSDavid du Colombier return n;
28907dd7cddfSDavid du Colombier }
28917dd7cddfSDavid du Colombier
28927dd7cddfSDavid du Colombier /*
28937dd7cddfSDavid du Colombier * make an ndb entry and put it into /net/ndb for the servers to see
28947dd7cddfSDavid du Colombier */
28957dd7cddfSDavid du Colombier static void
putndb(PPP * ppp,char * net)28967dd7cddfSDavid du Colombier putndb(PPP *ppp, char *net)
28977dd7cddfSDavid du Colombier {
28987dd7cddfSDavid du Colombier char buf[1024];
28997dd7cddfSDavid du Colombier char file[64];
29007dd7cddfSDavid du Colombier char *p, *e;
29017dd7cddfSDavid du Colombier int fd;
29027dd7cddfSDavid du Colombier
29037dd7cddfSDavid du Colombier e = buf + sizeof(buf);
29047dd7cddfSDavid du Colombier p = buf;
29057dd7cddfSDavid du Colombier p = seprint(p, e, "ip=%I ipmask=255.255.255.255 ipgw=%I\n", ppp->local,
29067dd7cddfSDavid du Colombier ppp->remote);
29077dd7cddfSDavid du Colombier if(validv4(ppp->dns[0]))
2908312a1df1SDavid du Colombier p = seprint(p, e, "\tdns=%I\n", ppp->dns[0]);
29097dd7cddfSDavid du Colombier if(validv4(ppp->dns[1]))
2910312a1df1SDavid du Colombier p = seprint(p, e, "\tdns=%I\n", ppp->dns[1]);
29117dd7cddfSDavid du Colombier if(validv4(ppp->wins[0]))
2912312a1df1SDavid du Colombier p = seprint(p, e, "\twins=%I\n", ppp->wins[0]);
29137dd7cddfSDavid du Colombier if(validv4(ppp->wins[1]))
2914312a1df1SDavid du Colombier p = seprint(p, e, "\twins=%I\n", ppp->wins[1]);
291590630c3aSDavid du Colombier seprint(file, file+sizeof file, "%s/ndb", net);
29167dd7cddfSDavid du Colombier fd = open(file, OWRITE);
29177dd7cddfSDavid du Colombier if(fd < 0)
29187dd7cddfSDavid du Colombier return;
29197dd7cddfSDavid du Colombier write(fd, buf, p-buf);
29207dd7cddfSDavid du Colombier close(fd);
292190630c3aSDavid du Colombier seprint(file, file+sizeof file, "%s/cs", net);
292290630c3aSDavid du Colombier fd = open(file, OWRITE);
292390630c3aSDavid du Colombier write(fd, "refresh", 7);
292490630c3aSDavid du Colombier close(fd);
292590630c3aSDavid du Colombier seprint(file, file+sizeof file, "%s/dns", net);
292690630c3aSDavid du Colombier fd = open(file, OWRITE);
292790630c3aSDavid du Colombier write(fd, "refresh", 7);
292890630c3aSDavid du Colombier close(fd);
29297dd7cddfSDavid du Colombier }
2930dc5a79c1SDavid du Colombier
2931dc5a79c1SDavid du Colombier static void
getauth(PPP * ppp)2932dc5a79c1SDavid du Colombier getauth(PPP *ppp)
2933dc5a79c1SDavid du Colombier {
2934dc5a79c1SDavid du Colombier UserPasswd *up;
2935dc5a79c1SDavid du Colombier
2936dc5a79c1SDavid du Colombier if(*ppp->chapname)
2937dc5a79c1SDavid du Colombier return;
2938dc5a79c1SDavid du Colombier
2939dc5a79c1SDavid du Colombier up = auth_getuserpasswd(auth_getkey,"proto=pass service=ppp %s", keyspec);
2940dc5a79c1SDavid du Colombier if(up != nil){
2941dc5a79c1SDavid du Colombier strcpy(ppp->chapname, up->user);
2942dc5a79c1SDavid du Colombier strcpy(ppp->secret, up->passwd);
2943dc5a79c1SDavid du Colombier }
2944dc5a79c1SDavid du Colombier }
2945