lcp.c revision 28461
162607Sitojun/* 262607Sitojun * PPP Link Control Protocol (LCP) Module 355163Sshin * 455163Sshin * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 555163Sshin * 655163Sshin * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 762607Sitojun * 855163Sshin * Redistribution and use in source and binary forms are permitted 955163Sshin * provided that the above copyright notice and this paragraph are 1055163Sshin * duplicated in all such forms and that any documentation, 1155163Sshin * advertising materials, and other materials related to such 1255163Sshin * distribution and use acknowledge that the software was developed 1355163Sshin * by the Internet Initiative Japan, Inc. The name of the 1455163Sshin * IIJ may not be used to endorse or promote products derived 1555163Sshin * from this software without specific prior written permission. 1655163Sshin * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1755163Sshin * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1855163Sshin * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1962607Sitojun * 2055163Sshin * $Id: lcp.c,v 1.25 1997/08/01 02:02:28 brian Exp $ 2155163Sshin * 2255163Sshin * TODO: 2355163Sshin * o Validate magic number received from peer. 2455163Sshin * o Limit data field length by MRU 2555163Sshin */ 2655163Sshin#include <sys/time.h> 2755163Sshin#include "fsm.h" 2855163Sshin#include "lcp.h" 2955163Sshin#include "ipcp.h" 3055163Sshin#include "lcpproto.h" 3155163Sshin#include "os.h" 3255163Sshin#include "hdlc.h" 3355163Sshin#include "ccp.h" 3462607Sitojun#include "lqr.h" 3555163Sshin#include "phase.h" 3655163Sshin#include "loadalias.h" 3755163Sshin#include "vars.h" 3855163Sshin#include "auth.h" 3955163Sshin#include <arpa/inet.h> 4055163Sshin 4155163Sshinextern void IpcpUp(); 4255163Sshinextern void IpcpOpen(); 4355163Sshinextern void SetLinkParams(struct lcpstate *); 4455163Sshinextern void Prompt(); 4555163Sshinextern void StopIdleTimer(); 4655163Sshinextern void OsLinkdown(); 4755163Sshinextern void Cleanup(); 4855163Sshinextern struct pppTimer IpcpReportTimer; 4955163Sshinextern int randinit; 5055163Sshin 5162607Sitojunstruct lcpstate LcpInfo; 5255163Sshin 5355163Sshinstatic void LcpSendConfigReq(struct fsm *); 5455163Sshinstatic void LcpSendTerminateReq(struct fsm *fp); 5555163Sshinstatic void LcpSendTerminateAck(struct fsm *fp); 5655163Sshinstatic void LcpDecodeConfig(u_char *cp, int flen,int mode); 5755163Sshinstatic void LcpInitRestartCounter(struct fsm *); 5855163Sshinstatic void LcpLayerUp(struct fsm *); 5955163Sshinstatic void LcpLayerDown(struct fsm *); 6062607Sitojunstatic void LcpLayerStart(struct fsm *); 6155163Sshinstatic void LcpLayerFinish(struct fsm *); 6262607Sitojun 6355163Sshinextern int ModemSpeed(); 6462607Sitojun 6555163Sshin#define REJECTED(p, x) (p->his_reject & (1<<x)) 6662607Sitojun 6762607Sitojunstatic char *cftypes[] = { 6862607Sitojun "???", "MRU", "ACCMAP", "AUTHPROTO", "QUALPROTO", "MAGICNUM", 6955163Sshin "RESERVED", "PROTOCOMP", "ACFCOMP", "FCSALT", "SDP", 7062607Sitojun}; 7162607Sitojun 7255163Sshinstruct fsm LcpFsm = { 7355163Sshin "LCP", /* Name of protocol */ 7455163Sshin PROTO_LCP, /* Protocol Number */ 7555163Sshin LCP_MAXCODE, 7655163Sshin OPEN_ACTIVE, 7762607Sitojun ST_INITIAL, /* State of machine */ 7862607Sitojun 0, 0, 0, 7962607Sitojun 0, 8055163Sshin { 0, 0, 0, NULL, NULL, NULL }, 8155163Sshin { 0, 0, 0, NULL, NULL, NULL }, 8255163Sshin LogLCP, 8355163Sshin 8455163Sshin LcpLayerUp, 8555163Sshin LcpLayerDown, 8655163Sshin LcpLayerStart, 8755163Sshin LcpLayerFinish, 8855163Sshin LcpInitRestartCounter, 8955163Sshin LcpSendConfigReq, 9055163Sshin LcpSendTerminateReq, 9155163Sshin LcpSendTerminateAck, 9255163Sshin LcpDecodeConfig, 9355163Sshin}; 9462607Sitojun 9555163Sshinstatic struct pppTimer LcpReportTimer; 9662607Sitojun 9755163Sshinchar *PhaseNames[] = { 9855163Sshin "Dead", "Establish", "Authenticate", "Network", "Terminate" 9955163Sshin}; 10055163Sshin 10155163Sshinvoid 10255163SshinNewPhase(new) 10355163Sshinint new; 10455163Sshin{ 10555163Sshin struct lcpstate *lcp = &LcpInfo; 10655163Sshin 10755163Sshin phase = new; 10855163Sshin LogPrintf(LogPHASE, "NewPhase: %s\n", PhaseNames[phase]); 10955163Sshin switch (phase) { 11055163Sshin case PHASE_AUTHENTICATE: 11155163Sshin lcp->auth_ineed = lcp->want_auth; 11255163Sshin lcp->auth_iwait = lcp->his_auth; 11355163Sshin if (lcp->his_auth || lcp->want_auth) { 11455163Sshin LogPrintf(LogPHASE, " his = %x, mine = %x\n", lcp->his_auth, lcp->want_auth); 11555163Sshin if (lcp->his_auth == PROTO_PAP) 11655163Sshin StartAuthChallenge(&AuthPapInfo); 11755163Sshin if (lcp->want_auth == PROTO_CHAP) 11855163Sshin StartAuthChallenge(&AuthChapInfo); 11955163Sshin } else 12055163Sshin NewPhase(PHASE_NETWORK); 12155163Sshin break; 12255163Sshin case PHASE_NETWORK: 12355163Sshin IpcpUp(); 12462607Sitojun IpcpOpen(); 12555163Sshin CcpUp(); 12655163Sshin CcpOpen(); 12755163Sshin break; 12855163Sshin case PHASE_DEAD: 12955163Sshin if (mode & MODE_DIRECT) 13055163Sshin Cleanup(EX_DEAD); 13155163Sshin if (mode & MODE_BACKGROUND && reconnectState != RECON_TRUE) 13255163Sshin Cleanup(EX_DEAD); 13355163Sshin break; 13455163Sshin } 13555163Sshin} 13655163Sshin 13755163Sshinstatic void 13855163SshinLcpReportTime() 13955163Sshin{ 14055163Sshin if (LogIsKept(LogDEBUG)) { 14155163Sshin time_t t; 14255163Sshin 14355163Sshin time(&t); 14455163Sshin LogPrintf(LogDEBUG, "LcpReportTime: %s", ctime(&t)); 14555163Sshin } 14655163Sshin StopTimer(&LcpReportTimer); 14755163Sshin LcpReportTimer.state = TIMER_STOPPED; 14855163Sshin StartTimer(&LcpReportTimer); 14955163Sshin HdlcErrorCheck(); 15055163Sshin} 15155163Sshin 15255163Sshinint 15355163SshinReportLcpStatus() 15455163Sshin{ 15555163Sshin struct lcpstate *lcp = &LcpInfo; 15655163Sshin struct fsm *fp = &LcpFsm; 15755163Sshin 15855163Sshin if (!VarTerm) 15955163Sshin return 1; 16055163Sshin 16155163Sshin fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]); 16255163Sshin fprintf(VarTerm, 16355163Sshin " his side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n" 16455163Sshin " REJECT %04lx\n", 16555163Sshin lcp->his_mru, lcp->his_accmap, lcp->his_protocomp, lcp->his_acfcomp, 16655163Sshin lcp->his_magic, lcp->his_reject); 16755163Sshin fprintf(VarTerm, 16862607Sitojun " my side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n" 16962607Sitojun " REJECT %04lx\n", 17055163Sshin lcp->want_mru, lcp->want_accmap, lcp->want_protocomp, lcp->want_acfcomp, 17155163Sshin lcp->want_magic, lcp->my_reject); 17255163Sshin fprintf(VarTerm, "\nDefaults: MRU = %ld, ACCMAP = %08x\t", VarMRU, VarAccmap); 17355163Sshin fprintf(VarTerm, "Open Mode: %s\n", (VarOpenMode == OPEN_ACTIVE)? "active" : "passive"); 17455163Sshin return 0; 17555163Sshin} 17655163Sshin 17755163Sshin/* 17855163Sshin * Generate random number which will be used as magic number. 17955163Sshin */ 18055163Sshinu_long 18155163SshinGenerateMagic() 18255163Sshin{ 18355163Sshin if (!randinit) { 18462607Sitojun randinit = 1; 18555163Sshin srandomdev(); 18655163Sshin } 18755163Sshin 18855163Sshin return (random()); 18955163Sshin} 19055163Sshin 19155163Sshinvoid 19255163SshinLcpInit() 19355163Sshin{ 19455163Sshin struct lcpstate *lcp = &LcpInfo; 19555163Sshin 19655163Sshin FsmInit(&LcpFsm); 19755163Sshin HdlcInit(); 19855163Sshin 19955163Sshin bzero(lcp, sizeof(struct lcpstate)); 20055163Sshin lcp->want_mru = VarMRU; 20155163Sshin lcp->his_mru = DEF_MRU; 20255163Sshin lcp->his_accmap = 0xffffffff; 20355163Sshin lcp->want_accmap = VarAccmap; 20455163Sshin lcp->want_magic = GenerateMagic(); 20555163Sshin lcp->want_auth = lcp->his_auth = 0; 20662607Sitojun if (Enabled(ConfChap)) 20762607Sitojun lcp->want_auth = PROTO_CHAP; 20862607Sitojun else if (Enabled(ConfPap)) 20962607Sitojun lcp->want_auth = PROTO_PAP; 21062607Sitojun if (Enabled(ConfLqr)) lcp->want_lqrperiod = VarLqrTimeout * 100; 21155163Sshin if (Enabled(ConfAcfcomp)) lcp->want_acfcomp = 1; 21255163Sshin if (Enabled(ConfProtocomp)) lcp->want_protocomp = 1; 21355163Sshin LcpFsm.maxconfig = 10; 21455163Sshin} 21555163Sshin 21655163Sshinstatic void 21755163SshinLcpInitRestartCounter(fp) 21855163Sshinstruct fsm *fp; 21962607Sitojun{ 22055163Sshin fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 22155163Sshin fp->restart = 5; 22255163Sshin} 22355163Sshin 22455163Sshinvoid 22555163SshinPutConfValue(cpp, types, type, len, val) 22655163Sshinu_char **cpp; 22755163Sshinchar **types; 22855163Sshinu_char type; 22955163Sshinint len; 23055163Sshinu_long val; 23162607Sitojun{ 23255163Sshin u_char *cp; 23355163Sshin struct in_addr ina; 23455163Sshin 23555163Sshin cp = *cpp; 23655163Sshin *cp++ = type; *cp++ = len; 23755163Sshin if (len == 6) { 23855163Sshin if (type == TY_IPADDR) { 23955163Sshin ina.s_addr = htonl(val); 24055163Sshin LogPrintf(LogLCP, " %s [%d] %s\n", 24155163Sshin types[type], len, inet_ntoa(ina)); 24255163Sshin } else { 24355163Sshin LogPrintf(LogLCP, " %s [%d] %08x\n", types[type], len, val); 24455163Sshin } 24555163Sshin *cp++ = (val >> 24) & 0377; 24655163Sshin *cp++ = (val >> 16) & 0377; 24755163Sshin } else 24855163Sshin LogPrintf(LogLCP, " %s [%d] %d\n", types[type], len, val); 24955163Sshin *cp++ = (val >> 8) & 0377; 25055163Sshin *cp++ = val & 0377; 25155163Sshin *cpp = cp; 25255163Sshin} 25355163Sshin 25455163Sshinstatic void 25555163SshinLcpSendConfigReq(fp) 25655163Sshinstruct fsm *fp; 25755163Sshin{ 25855163Sshin u_char *cp; 25955163Sshin struct lcpstate *lcp = &LcpInfo; 26055163Sshin struct lqrreq *req; 26155163Sshin 26255163Sshin LogPrintf(LogLCP, "LcpSendConfigReq\n"); 26355163Sshin cp = ReqBuff; 26455163Sshin if (!DEV_IS_SYNC) { 26555163Sshin if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) { 26655163Sshin *cp++ = TY_ACFCOMP; *cp++ = 2; 26755163Sshin LogPrintf(LogLCP, " %s\n", cftypes[TY_ACFCOMP]); 26855163Sshin } 26955163Sshin if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) { 27055163Sshin *cp++ = TY_PROTOCOMP; *cp++ = 2; 27155163Sshin LogPrintf(LogLCP, " %s\n", cftypes[TY_PROTOCOMP]); 27255163Sshin } 27355163Sshin if (!REJECTED(lcp, TY_ACCMAP)) 27455163Sshin PutConfValue(&cp, cftypes, TY_ACCMAP, 6, lcp->want_accmap); 27555163Sshin } 27655163Sshin if (!REJECTED(lcp, TY_MRU)) 27755163Sshin PutConfValue(&cp, cftypes, TY_MRU, 4, lcp->want_mru); 27855163Sshin if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) 27962607Sitojun PutConfValue(&cp, cftypes, TY_MAGICNUM, 6, lcp->want_magic); 28055163Sshin if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) { 28155163Sshin req = (struct lqrreq *)cp; 28255163Sshin req->type = TY_QUALPROTO; req->length = sizeof(struct lqrreq); 28355163Sshin req->proto = htons(PROTO_LQR); 28455163Sshin req->period = htonl(lcp->want_lqrperiod); 28555163Sshin cp += sizeof(struct lqrreq); 28655163Sshin LogPrintf(LogLCP, " %s (%d)\n", cftypes[TY_QUALPROTO], lcp->want_lqrperiod); 28755163Sshin } 28855163Sshin switch (lcp->want_auth) { 28955163Sshin case PROTO_PAP: 29055163Sshin PutConfValue(&cp, cftypes, TY_AUTHPROTO, 4, lcp->want_auth); 29155163Sshin break; 29255163Sshin case PROTO_CHAP: 29355163Sshin PutConfValue(&cp, cftypes, TY_AUTHPROTO, 5, lcp->want_auth); 29455163Sshin *cp++ = 5; /* Use MD5 */ 29562607Sitojun break; 29655163Sshin } 29762607Sitojun FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 29862607Sitojun} 29955163Sshin 30055163Sshinvoid 30155163SshinLcpSendProtoRej(option, count) 30255163Sshinu_char *option; 30362607Sitojunint count; 30462607Sitojun{ 30562607Sitojun struct fsm *fp = &LcpFsm; 30655163Sshin 30755163Sshin LogPrintf(LogLCP, "LcpSendProtoRej\n"); 30855163Sshin FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count); 30955163Sshin} 31055163Sshin 31162607Sitojunstatic void 31255163SshinLcpSendTerminateReq(fp) 31362607Sitojunstruct fsm *fp; 31462607Sitojun{ 31555163Sshin /* Most thins are done in fsm layer. Nothing to to. */ 31662607Sitojun} 31762607Sitojun 31862607Sitojunstatic void 31962607SitojunLcpSendTerminateAck(fp) 32062607Sitojunstruct fsm *fp; 32162607Sitojun{ 32262607Sitojun LogPrintf(LogLCP, "LcpSendTerminateAck.\n"); 32362607Sitojun FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 32462607Sitojun} 32562607Sitojun 32655163Sshinstatic void 32755163SshinLcpLayerStart(fp) 32855163Sshinstruct fsm *fp; 32962607Sitojun{ 33055163Sshin LogPrintf(LogLCP, "LcpLayerStart\n"); 33155163Sshin NewPhase(PHASE_ESTABLISH); 33255163Sshin} 33355163Sshin 33455163Sshinstatic void 33555163SshinStopAllTimers() 33655163Sshin{ 33755163Sshin StopTimer(&LcpReportTimer); 33855163Sshin StopTimer(&IpcpReportTimer); 33955163Sshin StopIdleTimer(); 34055163Sshin StopTimer(&AuthPapInfo.authtimer); 34155163Sshin StopTimer(&AuthChapInfo.authtimer); 34255163Sshin StopLqrTimer(); 34355163Sshin} 34455163Sshin 34555163Sshinstatic void 34655163SshinLcpLayerFinish(fp) 34755163Sshinstruct fsm *fp; 34855163Sshin{ 34955163Sshin LogPrintf(LogLCP, "LcpLayerFinish\n"); 35055163Sshin OsCloseLink(1); 35155163Sshin NewPhase(PHASE_DEAD); 35255163Sshin StopAllTimers(); 35355163Sshin (void)OsInterfaceDown(0); 35455163Sshin Prompt(); 35555163Sshin} 35655163Sshin 35755163Sshinstatic void 35855163SshinLcpLayerUp(fp) 35955163Sshinstruct fsm *fp; 36055163Sshin{ 36155163Sshin LogPrintf(LogLCP, "LcpLayerUp\n"); 36255163Sshin OsSetInterfaceParams(23, LcpInfo.his_mru, ModemSpeed()); 36355163Sshin SetLinkParams(&LcpInfo); 36455163Sshin 36555163Sshin NewPhase(PHASE_AUTHENTICATE); 36662607Sitojun 36755163Sshin StartLqm(); 36855163Sshin StopTimer(&LcpReportTimer); 36962607Sitojun LcpReportTimer.state = TIMER_STOPPED; 37062607Sitojun LcpReportTimer.load = 60 * SECTICKS; 37162607Sitojun LcpReportTimer.func = LcpReportTime; 37262607Sitojun StartTimer(&LcpReportTimer); 37362607Sitojun} 37462607Sitojun 37555163Sshinstatic void 37655163SshinLcpLayerDown(fp) 37755163Sshinstruct fsm *fp; 37855163Sshin{ 37955163Sshin LogPrintf(LogLCP, "LcpLayerDown\n"); 38055163Sshin StopAllTimers(); 38155163Sshin OsLinkdown(); 38255163Sshin NewPhase(PHASE_TERMINATE); 38355163Sshin} 38462607Sitojun 38555163Sshinvoid 38655163SshinLcpUp() 38755163Sshin{ 38855163Sshin FsmUp(&LcpFsm); 38955163Sshin} 39055163Sshin 39155163Sshinvoid 39255163SshinLcpDown() /* Sudden death */ 39355163Sshin{ 39455163Sshin NewPhase(PHASE_DEAD); 39555163Sshin StopAllTimers(); 39655163Sshin FsmDown(&LcpFsm); 39755163Sshin} 39855163Sshin 39955163Sshinvoid 40055163SshinLcpOpen(mode) 40155163Sshinint mode; 40255163Sshin{ 40355163Sshin LcpFsm.open_mode = mode; 40455163Sshin FsmOpen(&LcpFsm); 40555163Sshin} 40655163Sshin 40755163Sshinvoid 40855163SshinLcpClose() 40955163Sshin{ 41055163Sshin FsmClose(&LcpFsm); 41155163Sshin} 41255163Sshin 41355163Sshin/* 41455163Sshin * XXX: Should validate option length 41555163Sshin */ 41655163Sshinstatic void 41755163SshinLcpDecodeConfig(cp, plen, mode) 41855163Sshinu_char *cp; 41955163Sshinint plen; 42055163Sshinint mode; 42155163Sshin{ 42255163Sshin char *request; 42355163Sshin int type, length, mru; 42455163Sshin u_long *lp, magic, accmap; 42555163Sshin u_short *sp, proto; 42655163Sshin struct lqrreq *req; 42755163Sshin 42855163Sshin ackp = AckBuff; 42955163Sshin nakp = NakBuff; 43055163Sshin rejp = RejBuff; 43155163Sshin 43255163Sshin while (plen >= sizeof(struct fsmconfig)) { 43355163Sshin type = *cp; 43455163Sshin length = cp[1]; 43555163Sshin if (type <= TY_ACFCOMP) 43655163Sshin request = cftypes[type]; 43755163Sshin else 43855163Sshin request = "???"; 43955163Sshin 44055163Sshin switch (type) { 44155163Sshin case TY_MRU: 44255163Sshin sp = (u_short *)(cp + 2); 44355163Sshin mru = htons(*sp); 44455163Sshin LogPrintf(LogLCP, " %s %d\n", request, mru); 44555163Sshin 44655163Sshin switch (mode) { 44755163Sshin case MODE_REQ: 44855163Sshin if (mru > MAX_MRU) { 44955163Sshin *sp = htons(MAX_MRU); 45055163Sshin bcopy(cp, nakp, 4); nakp += 4; 45155163Sshin } else if (mru < MIN_MRU) { 45255163Sshin *sp = htons(MIN_MRU); 45355163Sshin bcopy(cp, nakp, 4); nakp += 4; 45455163Sshin } else { 45562607Sitojun LcpInfo.his_mru = mru; 45655163Sshin bcopy(cp, ackp, 4); ackp += 4; 45755163Sshin } 45855163Sshin break; 45955163Sshin case MODE_NAK: 46055163Sshin if (mru >= MIN_MRU || mru <= MAX_MRU) 46155163Sshin LcpInfo.want_mru = mru; 46255163Sshin break; 46355163Sshin case MODE_REJ: 46455163Sshin LcpInfo.his_reject |= (1 << type); 46555163Sshin break; 46655163Sshin } 46755163Sshin break; 46855163Sshin case TY_ACCMAP: 46955163Sshin lp = (u_long *)(cp + 2); 47055163Sshin accmap = htonl(*lp); 47155163Sshin LogPrintf(LogLCP, " %s %08x\n", request, accmap); 47255163Sshin 47355163Sshin switch (mode) { 47455163Sshin case MODE_REQ: 47555163Sshin LcpInfo.his_accmap = accmap; 47655163Sshin bcopy(cp, ackp, 6); ackp += 6; 47755163Sshin break; 47855163Sshin case MODE_NAK: 47955163Sshin LcpInfo.want_accmap = accmap; 48055163Sshin break; 48155163Sshin case MODE_REJ: 48255163Sshin LcpInfo.his_reject |= (1 << type); 48355163Sshin break; 48455163Sshin } 48555163Sshin break; 48655163Sshin case TY_AUTHPROTO: 48755163Sshin sp = (u_short *)(cp + 2); 48855163Sshin proto = ntohs(*sp); 48955163Sshin LogPrintf(LogLCP, " %s proto = %04x\n", request, proto); 49055163Sshin 49155163Sshin switch (mode) { 49255163Sshin case MODE_REQ: 49355163Sshin switch (proto) { 49455163Sshin case PROTO_PAP: 49555163Sshin if (length != 4) { 49655163Sshin LogPrintf(LogLCP, " %s bad length (%d)\n", request, length); 49755163Sshin goto reqreject; 49855163Sshin } 49955163Sshin if (Acceptable(ConfPap)) { 50055163Sshin LcpInfo.his_auth = proto; 50155163Sshin bcopy(cp, ackp, length); ackp += length; 50255163Sshin } else if (Acceptable(ConfChap)) { 50355163Sshin *nakp++ = *cp; *nakp++ = 5; 50455163Sshin *nakp++ = (unsigned char)(PROTO_CHAP >> 8); 50555163Sshin *nakp++ = (unsigned char)PROTO_CHAP; 50655163Sshin *nakp++ = 5; 50755163Sshin } else 50855163Sshin goto reqreject; 50955163Sshin break; 51055163Sshin case PROTO_CHAP: 51155163Sshin if (length < 5) { 51255163Sshin LogPrintf(LogLCP, " %s bad length (%d)\n", request, length); 51355163Sshin goto reqreject; 51455163Sshin } 51555163Sshin if (Acceptable(ConfChap) && cp[4] == 5) { 51655163Sshin LcpInfo.his_auth = proto; 51755163Sshin bcopy(cp, ackp, length); ackp += length; 51855163Sshin } else if (Acceptable(ConfPap)) { 51962607Sitojun *nakp++ = *cp; *nakp++ = 4; 52055163Sshin *nakp++ = (unsigned char)(PROTO_PAP >> 8); 52162607Sitojun *nakp++ = (unsigned char)PROTO_PAP; 52255163Sshin } else 52355163Sshin goto reqreject; 52455163Sshin break; 52555163Sshin default: 52655163Sshin LogPrintf(LogLCP, " %s not implemented, NAK.\n", request); 52755163Sshin bcopy(cp, nakp, length); 52855163Sshin nakp += length; 52955163Sshin break; 53055163Sshin } 53155163Sshin break; 53255163Sshin case MODE_NAK: 53355163Sshin break; 53455163Sshin case MODE_REJ: 53555163Sshin LcpInfo.his_reject |= (1 << type); 53655163Sshin break; 53755163Sshin } 53855163Sshin break; 53955163Sshin case TY_QUALPROTO: 54055163Sshin req = (struct lqrreq *)cp; 54155163Sshin LogPrintf(LogLCP, " %s proto: %x, interval: %dms\n", 54255163Sshin request, ntohs(req->proto), ntohl(req->period)*10); 54355163Sshin switch (mode) { 54455163Sshin case MODE_REQ: 54555163Sshin if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr)) 54655163Sshin goto reqreject; 54755163Sshin else { 54855163Sshin LcpInfo.his_lqrperiod = ntohl(req->period); 54955163Sshin if (LcpInfo.his_lqrperiod < 500) 55055163Sshin LcpInfo.his_lqrperiod = 500; 55155163Sshin req->period = htonl(LcpInfo.his_lqrperiod); 55255163Sshin bcopy(cp, ackp, length); ackp += length; 55355163Sshin } 55462607Sitojun break; 55555163Sshin case MODE_NAK: 55662607Sitojun break; 55762607Sitojun case MODE_REJ: 55862607Sitojun LcpInfo.his_reject |= (1 << type); 55962607Sitojun break; 56062607Sitojun } 56162607Sitojun break; 56262607Sitojun case TY_MAGICNUM: 56355163Sshin lp = (u_long *)(cp + 2); 56462607Sitojun magic = ntohl(*lp); 56562607Sitojun LogPrintf(LogLCP, " %s %08x\n", request, magic); 56655163Sshin 56755163Sshin switch (mode) { 56855163Sshin case MODE_REQ: 56955163Sshin if (LcpInfo.want_magic) { 57055163Sshin /* Validate magic number */ 57155163Sshin if (magic == LcpInfo.want_magic) { 57255163Sshin LogPrintf(LogLCP, "Magic is same (%08x)\n", magic); 57355163Sshin LcpInfo.want_magic = GenerateMagic(); 57455163Sshin bcopy(cp, nakp, 6); 57555163Sshin nakp += 6; 57655163Sshin } else { 57755163Sshin LcpInfo.his_magic = magic; 57855163Sshin bcopy(cp, ackp, length); ackp += length; 57955163Sshin } 58055163Sshin } else { 58155163Sshin LcpInfo.my_reject |= (1 << type); 58255163Sshin goto reqreject; 58355163Sshin } 58455163Sshin break; 58555163Sshin case MODE_NAK: 58655163Sshin LogPrintf(LogLCP, " %s magic %08x has NAKed\n", request, magic); 58755163Sshin LcpInfo.want_magic = GenerateMagic(); 58855163Sshin break; 58955163Sshin case MODE_REJ: 59055163Sshin LogPrintf(LogLCP, " %s magic has REJected\n", request); 59155163Sshin LcpInfo.want_magic = 0; 59262607Sitojun LcpInfo.his_reject |= (1 << type); 59362607Sitojun break; 59455163Sshin } 59555163Sshin break; 59655163Sshin case TY_PROTOCOMP: 59755163Sshin LogPrintf(LogLCP, " %s\n", request); 59855163Sshin 59955163Sshin switch (mode) { 60055163Sshin case MODE_REQ: 60155163Sshin if (Acceptable(ConfProtocomp)) { 60255163Sshin LcpInfo.his_protocomp = 1; 60355163Sshin bcopy(cp, ackp, 2); ackp += 2; 60455163Sshin } else { 60555163Sshin#ifdef OLDMST 60655163Sshin /* 60755163Sshin * MorningStar before v1.3 needs NAK 60855163Sshin */ 60955163Sshin bcopy(cp, nakp, 2); nakp += 2; 61055163Sshin#else 61155163Sshin bcopy(cp, rejp, 2); rejp += 2; 61255163Sshin LcpInfo.my_reject |= (1 << type); 61355163Sshin#endif 61455163Sshin } 61555163Sshin break; 61655163Sshin case MODE_NAK: 61755163Sshin case MODE_REJ: 61855163Sshin LcpInfo.want_protocomp = 0; 61955163Sshin LcpInfo.his_reject |= (1 << type); 62055163Sshin break; 62162607Sitojun } 62255163Sshin break; 62355163Sshin case TY_ACFCOMP: 62455163Sshin LogPrintf(LogLCP, " %s\n", request); 62555163Sshin switch (mode) { 62655163Sshin case MODE_REQ: 62755163Sshin if (Acceptable(ConfAcfcomp)) { 62855163Sshin LcpInfo.his_acfcomp = 1; 62955163Sshin bcopy(cp, ackp, 2); 63055163Sshin ackp += 2; 63155163Sshin } else { 63255163Sshin#ifdef OLDMST 63355163Sshin /* 63455163Sshin * MorningStar before v1.3 needs NAK 63555163Sshin */ 63655163Sshin bcopy(cp, nakp, 2); 63755163Sshin nakp += 2; 63855163Sshin#else 63955163Sshin bcopy(cp, rejp, 2); 64055163Sshin rejp += 2; 64155163Sshin LcpInfo.my_reject |= (1 << type); 64255163Sshin#endif 64355163Sshin } 64455163Sshin break; 64555163Sshin case MODE_NAK: 64655163Sshin case MODE_REJ: 64755163Sshin LcpInfo.want_acfcomp = 0; 64855163Sshin LcpInfo.his_reject |= (1 << type); 64955163Sshin break; 65055163Sshin } 65155163Sshin break; 65255163Sshin case TY_SDP: 65355163Sshin LogPrintf(LogLCP, " %s\n", request); 65455163Sshin switch (mode) { 65555163Sshin case MODE_REQ: 65655163Sshin case MODE_NAK: 65755163Sshin case MODE_REJ: 65855163Sshin break; 65955163Sshin } 66055163Sshin break; 66155163Sshin default: 66255163Sshin LogPrintf(LogLCP, " ???[%02x]\n", type); 66355163Sshin if (mode == MODE_REQ) { 66455163Sshinreqreject: 66555163Sshin bcopy(cp, rejp, length); 66655163Sshin rejp += length; 66755163Sshin LcpInfo.my_reject |= (1 << type); 66855163Sshin } 66962607Sitojun break; 67062607Sitojun } 67155163Sshin /* to avoid inf. loop */ 67255163Sshin if (length == 0) { 67355163Sshin LogPrintf(LogLCP, "LCP size zero\n"); 67455163Sshin break; 67562607Sitojun } 67655163Sshin 67755163Sshin plen -= length; 67855163Sshin cp += length; 67955163Sshin } 68055163Sshin} 68155163Sshin 68255163Sshinvoid 68355163SshinLcpInput(struct mbuf *bp) 68455163Sshin{ 68555163Sshin FsmInput(&LcpFsm, bp); 68655163Sshin} 68755163Sshin