ipcp.c revision 8857
16059Samurai/* 26059Samurai * PPP IP Control Protocol (IPCP) Module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 208857Srgrimes * $Id: ipcp.c,v 1.3 1995/03/11 15:18:44 amurai Exp $ 218857Srgrimes * 226059Samurai * TODO: 236059Samurai * o More RFC1772 backwoard compatibility 246059Samurai */ 256059Samurai#include "fsm.h" 266059Samurai#include "lcpproto.h" 276059Samurai#include "lcp.h" 286059Samurai#include "ipcp.h" 296059Samurai#include <netdb.h> 306059Samurai#include <netinet/in_systm.h> 316059Samurai#include <netinet/ip.h> 326059Samurai#include <arpa/inet.h> 336059Samurai#include <sys/socket.h> 346059Samurai#include "slcompress.h" 356059Samurai#include "os.h" 366059Samurai#include "phase.h" 376059Samurai#include "vars.h" 386059Samurai 396059Samuraiextern void PutConfValue(); 406059Samuraiextern void Prompt(); 416059Samuraiextern struct in_addr ifnetmask; 426059Samurai 436059Samuraistruct ipcpstate IpcpInfo; 446059Samuraistruct in_range DefMyAddress, DefHisAddress; 456059Samurai 466735Samuraistatic void IpcpSendConfigReq __P((struct fsm *)); 476735Samuraistatic void IpcpSendTerminateAck __P((struct fsm *)); 486735Samuraistatic void IpcpSendTerminateReq __P((struct fsm *)); 496735Samuraistatic void IpcpDecodeConfig __P((u_char *, int, int)); 506735Samuraistatic void IpcpLayerStart __P((struct fsm *)); 516735Samuraistatic void IpcpLayerFinish __P((struct fsm *)); 526735Samuraistatic void IpcpLayerUp __P((struct fsm *)); 536735Samuraistatic void IpcpLayerDown __P((struct fsm *)); 546735Samuraistatic void IpcpInitRestartCounter __P((struct fsm *)); 556059Samurai 567001Samuraistruct pppTimer IpcpReportTimer; 576059Samurai 586059Samuraistatic int lastInOctets, lastOutOctets; 596059Samurai 606059Samurai#define REJECTED(p, x) (p->his_reject & (1<<x)) 616059Samurai 626059Samuraistruct fsm IpcpFsm = { 636059Samurai "IPCP", 646059Samurai PROTO_IPCP, 656059Samurai IPCP_MAXCODE, 666059Samurai OPEN_ACTIVE, 676059Samurai ST_INITIAL, 686059Samurai 0, 0, 0, 696059Samurai 706059Samurai 0, 716059Samurai { 0, 0, 0, NULL, NULL, NULL }, 726059Samurai 736059Samurai IpcpLayerUp, 746059Samurai IpcpLayerDown, 756059Samurai IpcpLayerStart, 766059Samurai IpcpLayerFinish, 776059Samurai IpcpInitRestartCounter, 786059Samurai IpcpSendConfigReq, 796059Samurai IpcpSendTerminateReq, 806059Samurai IpcpSendTerminateAck, 816059Samurai IpcpDecodeConfig, 826059Samurai}; 836059Samurai 846059Samuraistatic char *cftypes[] = { 856059Samurai "???", "IPADDRS", "COMPPROTO", "IPADDR", 866059Samurai}; 876059Samurai 886059Samurai/* 896059Samurai * Function called every second. Updates connection period and idle period, 906059Samurai * also update LQR information. 916059Samurai */ 926059Samuraistatic void 936059SamuraiIpcpReportFunc() 946059Samurai{ 956059Samurai ipConnectSecs++; 966059Samurai if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets) 976059Samurai ipIdleSecs++; 986059Samurai lastInOctets = ipInOctets; 996059Samurai lastOutOctets = ipOutOctets; 1006059Samurai StopTimer(&IpcpReportTimer); 1016059Samurai IpcpReportTimer.state = TIMER_STOPPED; 1026059Samurai StartTimer(&IpcpReportTimer); 1036059Samurai} 1046059Samurai 1056059Samuraistatic void 1066059SamuraiIpcpStartReport() 1076059Samurai{ 1086059Samurai ipIdleSecs = ipConnectSecs = 0; 1096059Samurai StopTimer(&IpcpReportTimer); 1106059Samurai IpcpReportTimer.state = TIMER_STOPPED; 1116059Samurai IpcpReportTimer.load = SECTICKS; 1126059Samurai IpcpReportTimer.func = IpcpReportFunc; 1136059Samurai StartTimer(&IpcpReportTimer); 1146059Samurai} 1156059Samurai 1166059Samuraivoid 1176059SamuraiReportIpcpStatus() 1186059Samurai{ 1196059Samurai struct ipcpstate *icp = &IpcpInfo; 1206059Samurai struct fsm *fp = &IpcpFsm; 1216059Samurai 1226059Samurai printf("%s [%s]\n", fp->name, StateNames[fp->state]); 1236059Samurai printf(" his side: %s, %x\n", 1246059Samurai inet_ntoa(icp->his_ipaddr), icp->his_compproto); 1256059Samurai printf(" my side: %s, %x\n", 1266059Samurai inet_ntoa(icp->want_ipaddr), icp->want_compproto); 1276059Samurai printf("connected: %d secs, idle: %d secs\n\n", ipConnectSecs, ipIdleSecs); 1286059Samurai printf("Defaults: My Address: %s/%d ", 1296059Samurai inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width); 1306059Samurai printf("His Address: %s/%d\n", 1316059Samurai inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width); 1326059Samurai} 1336059Samurai 1346059Samuraivoid 1356059SamuraiIpcpDefAddress() 1366059Samurai{ 1376059Samurai struct hostent *hp; 1386059Samurai char name[200]; 1396059Samurai 1406059Samurai bzero(&DefMyAddress, sizeof(DefMyAddress)); 1416059Samurai bzero(&DefHisAddress, sizeof(DefHisAddress)); 1426059Samurai if (gethostname(name, sizeof(name)) == 0) { 1436059Samurai hp = gethostbyname(name); 1446059Samurai if (hp && hp->h_addrtype == AF_INET) { 1456059Samurai bcopy(hp->h_addr, (char *)&DefMyAddress.ipaddr.s_addr, hp->h_length); 1466059Samurai } 1476059Samurai } 1486059Samurai} 1496059Samurai 1506059Samuraivoid 1516059SamuraiIpcpInit() 1526059Samurai{ 1536059Samurai struct ipcpstate *icp = &IpcpInfo; 1546059Samurai 1556059Samurai FsmInit(&IpcpFsm); 1566059Samurai bzero(icp, sizeof(struct ipcpstate)); 1576059Samurai if ((mode & MODE_DEDICATED) && !dstsystem) { 1586059Samurai icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0; 1596059Samurai } else { 1606059Samurai icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr; 1616059Samurai icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr; 1626059Samurai } 1636059Samurai if (icp->want_ipaddr.s_addr == 0) 1646059Samurai icp->want_ipaddr.s_addr = htonl(0xc0000001); 1656059Samurai if (Enabled(ConfVjcomp)) 1666059Samurai icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8); 1676059Samurai else 1686059Samurai icp->want_compproto = 0; 1696059Samurai icp->heis1172 = 0; 1706059Samurai IpcpFsm.maxconfig = 10; 1716059Samurai} 1726059Samurai 1736059Samuraistatic void 1746059SamuraiIpcpInitRestartCounter(fp) 1756059Samuraistruct fsm *fp; 1766059Samurai{ 1776735Samurai fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 1786059Samurai fp->restart = 5; 1796059Samurai} 1806059Samurai 1816059Samuraistatic void 1826059SamuraiIpcpSendConfigReq(fp) 1836059Samuraistruct fsm *fp; 1846059Samurai{ 1856059Samurai u_char *cp; 1866059Samurai struct ipcpstate *icp = &IpcpInfo; 1876059Samurai 1886059Samurai cp = ReqBuff; 1896059Samurai LogPrintf(LOG_LCP, "%s: SendConfigReq\n", fp->name); 1906735Samurai if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR)) 1916735Samurai PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr)); 1926059Samurai if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) { 1936059Samurai if (icp->heis1172) 1946059Samurai PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16); 1956059Samurai else 1966059Samurai PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto); 1976059Samurai } 1986059Samurai FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 1996059Samurai} 2006059Samurai 2016059Samuraistatic void 2026059SamuraiIpcpSendTerminateReq(fp) 2036059Samuraistruct fsm *fp; 2046059Samurai{ 2056059Samurai /* XXX: No code yet */ 2066059Samurai} 2076059Samurai 2086059Samuraistatic void 2096059SamuraiIpcpSendTerminateAck(fp) 2106059Samuraistruct fsm *fp; 2116059Samurai{ 2126059Samurai LogPrintf(LOG_LCP, " %s: SendTerminateAck\n", fp->name); 2136059Samurai FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 2146059Samurai} 2156059Samurai 2166059Samuraistatic void 2176059SamuraiIpcpLayerStart(fp) 2186059Samuraistruct fsm *fp; 2196059Samurai{ 2206059Samurai LogPrintf(LOG_LCP, "%s: LayerStart.\n", fp->name); 2216059Samurai} 2226059Samurai 2236059Samuraistatic void 2246059SamuraiIpcpLayerFinish(fp) 2256059Samuraistruct fsm *fp; 2266059Samurai{ 2276059Samurai LogPrintf(LOG_LCP, "%s: LayerFinish.\n", fp->name); 2286059Samurai LcpClose(); 2296059Samurai NewPhase(PHASE_TERMINATE); 2306059Samurai} 2316059Samurai 2326059Samuraistatic void 2336059SamuraiIpcpLayerDown(fp) 2346059Samuraistruct fsm *fp; 2356059Samurai{ 2366059Samurai LogPrintf(LOG_LCP, "%s: LayerDown.\n", fp->name); 2376059Samurai StopTimer(&IpcpReportTimer); 2386059Samurai} 2396059Samurai 2406059Samurai/* 2416059Samurai * Called when IPCP has reached to OPEN state 2426059Samurai */ 2436059Samuraistatic void 2446059SamuraiIpcpLayerUp(fp) 2456059Samuraistruct fsm *fp; 2466059Samurai{ 2476059Samurai char tbuff[100]; 2486059Samurai 2496059Samurai#ifdef VERBOSE 2506059Samurai fprintf(stderr, "%s: LayerUp(%d).\r\n", fp->name, fp->state); 2516059Samurai#endif 2526059Samurai Prompt(1); 2536059Samurai LogPrintf(LOG_LCP, "%s: LayerUp.\n", fp->name); 2546059Samurai sprintf(tbuff, "myaddr = %s ", inet_ntoa(IpcpInfo.want_ipaddr)); 2556059Samurai LogPrintf(LOG_LCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(IpcpInfo.his_ipaddr)); 2566059Samurai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 2576059Samurai OsLinkup(); 2586059Samurai IpcpStartReport(); 2596059Samurai StartIdleTimer(); 2606059Samurai} 2616059Samurai 2626059Samuraivoid 2636059SamuraiIpcpUp() 2646059Samurai{ 2656059Samurai FsmUp(&IpcpFsm); 2666059Samurai LogPrintf(LOG_LCP, "IPCP Up event!!\n"); 2676059Samurai} 2686059Samurai 2696059Samuraivoid 2706059SamuraiIpcpOpen() 2716059Samurai{ 2726059Samurai FsmOpen(&IpcpFsm); 2736059Samurai} 2746059Samurai 2756059Samuraistatic int 2766059SamuraiAcceptableAddr(prange, ipaddr) 2776059Samuraistruct in_range *prange; 2786059Samuraistruct in_addr ipaddr; 2796059Samurai{ 2806059Samurai#ifdef DEBUG 2816059Samurai logprintf("requested = %x ", htonl(ipaddr.s_addr)); 2826059Samurai logprintf("range = %x", htonl(prange->ipaddr.s_addr)); 2836059Samurai logprintf("/%x\n", htonl(prange->mask.s_addr)); 2846059Samurai logprintf("%x, %x\n", htonl(prange->ipaddr.s_addr & prange->mask.s_addr), 2856059Samurai htonl(ipaddr.s_addr & prange->mask.s_addr)); 2866059Samurai#endif 2876059Samurai return((prange->ipaddr.s_addr & prange->mask.s_addr) == 2886059Samurai (ipaddr.s_addr & prange->mask.s_addr)); 2896059Samurai} 2906059Samurai 2916059Samuraistatic void 2926735SamuraiIpcpDecodeConfig(cp, plen, mode) 2936735Samuraiu_char *cp; 2946735Samuraiint plen; 2956059Samuraiint mode; 2966059Samurai{ 2976735Samurai int type, length; 2986059Samurai u_long *lp, compproto; 2996059Samurai struct compreq *pcomp; 3006059Samurai struct in_addr ipaddr, dstipaddr; 3016059Samurai char tbuff[100]; 3026059Samurai 3036059Samurai ackp = AckBuff; 3046059Samurai nakp = NakBuff; 3056059Samurai rejp = RejBuff; 3066059Samurai 3076059Samurai while (plen >= sizeof(struct fsmconfig)) { 3086059Samurai if (plen < 0) 3096059Samurai break; 3106059Samurai type = *cp; 3116059Samurai length = cp[1]; 3126059Samurai if (type <= TY_IPADDR) 3136059Samurai sprintf(tbuff, " %s[%d] ", cftypes[type], length); 3146059Samurai else 3156059Samurai sprintf(tbuff, " "); 3166059Samurai 3176059Samurai switch (type) { 3186059Samurai case TY_IPADDR: /* RFC1332 */ 3196059Samurai lp = (u_long *)(cp + 2); 3206059Samurai ipaddr.s_addr = *lp; 3216059Samurai LogPrintf(LOG_LCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 3226059Samurai 3236059Samurai switch (mode) { 3246059Samurai case MODE_REQ: 3256059Samurai if (!AcceptableAddr(&DefHisAddress, ipaddr)) { 3266059Samurai /* 3276059Samurai * If destination address is not acceptable, insist to use 3286059Samurai * what we want to use. 3296059Samurai */ 3306059Samurai bcopy(cp, nakp, 2); 3316059Samurai bcopy(&IpcpInfo.his_ipaddr.s_addr, nakp+2, length); 3326059Samurai nakp += length; 3336059Samurai break; 3348857Srgrimes 3356059Samurai } 3366059Samurai IpcpInfo.his_ipaddr = ipaddr; 3376059Samurai bcopy(cp, ackp, length); 3386059Samurai ackp += length; 3396059Samurai break; 3406059Samurai case MODE_NAK: 3416059Samurai if (AcceptableAddr(&DefMyAddress, ipaddr)) { 3426059Samurai /* 3436059Samurai * Use address suggested by peer. 3446059Samurai */ 3456059Samurai sprintf(tbuff+50, "%s changing address: %s ", tbuff, inet_ntoa(IpcpInfo.want_ipaddr)); 3466059Samurai LogPrintf(LOG_LCP, "%s --> %s\n", tbuff+50, inet_ntoa(ipaddr)); 3476059Samurai IpcpInfo.want_ipaddr = ipaddr; 3486059Samurai } 3496059Samurai break; 3506059Samurai case MODE_REJ: 3516059Samurai IpcpInfo.his_reject |= (1 << type); 3526059Samurai break; 3536059Samurai } 3546059Samurai break; 3556059Samurai case TY_COMPPROTO: 3566059Samurai lp = (u_long *)(cp + 2); 3576059Samurai compproto = htonl(*lp); 3586059Samurai LogPrintf(LOG_LCP, "%s %08x\n", tbuff, compproto); 3596059Samurai 3606059Samurai switch (mode) { 3616059Samurai case MODE_REQ: 3626059Samurai if (!Acceptable(ConfVjcomp)) { 3636059Samurai bcopy(cp, rejp, length); 3646059Samurai rejp += length; 3656059Samurai } else { 3666059Samurai pcomp = (struct compreq *)(cp + 2); 3676059Samurai switch (length) { 3686059Samurai case 4: /* RFC1172 */ 3696059Samurai if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 3706059Samurai logprintf("** Peer is speaking RFC1172 compression protocol **\n"); 3716059Samurai IpcpInfo.heis1172 = 1; 3726059Samurai IpcpInfo.his_compproto = compproto; 3736059Samurai bcopy(cp, ackp, length); 3746059Samurai ackp += length; 3756059Samurai } else { 3766059Samurai bcopy(cp, nakp, 2); 3776059Samurai pcomp->proto = htons(PROTO_VJCOMP); 3786059Samurai bcopy(&pcomp, nakp + 2, 2); 3796059Samurai nakp += length; 3806059Samurai } 3816059Samurai break; 3826059Samurai case 6: /* RFC1332 */ 3836059Samurai if (ntohs(pcomp->proto) == PROTO_VJCOMP 3846059Samurai && pcomp->slots < MAX_STATES && pcomp->slots > 2) { 3856059Samurai IpcpInfo.his_compproto = compproto; 3866059Samurai IpcpInfo.heis1172 = 0; 3876059Samurai bcopy(cp, ackp, length); 3886059Samurai ackp += length; 3896059Samurai } else { 3906059Samurai bcopy(cp, nakp, 2); 3916059Samurai pcomp->proto = htons(PROTO_VJCOMP); 3926059Samurai pcomp->slots = MAX_STATES - 1; 3936059Samurai pcomp->compcid = 0; 3946059Samurai bcopy(&pcomp, nakp + 2, sizeof(pcomp)); 3956059Samurai nakp += length; 3966059Samurai } 3976059Samurai break; 3986059Samurai default: 3996059Samurai bcopy(cp, rejp, length); 4006059Samurai rejp += length; 4016059Samurai break; 4026059Samurai } 4036059Samurai } 4046059Samurai break; 4056059Samurai case MODE_NAK: 4066059Samurai LogPrintf(LOG_LCP, "%s changing compproto: %08x --> %08x\n", 4076059Samurai tbuff, IpcpInfo.want_compproto, compproto); 4086059Samurai IpcpInfo.want_compproto = compproto; 4096059Samurai break; 4106059Samurai case MODE_REJ: 4116059Samurai IpcpInfo.his_reject |= (1 << type); 4126059Samurai break; 4136059Samurai } 4146059Samurai break; 4156059Samurai case TY_IPADDRS: /* RFC1172 */ 4166059Samurai lp = (u_long *)(cp + 2); 4176059Samurai ipaddr.s_addr = *lp; 4186059Samurai lp = (u_long *)(cp + 6); 4196059Samurai dstipaddr.s_addr = *lp; 4206059Samurai LogPrintf(LOG_LCP, "%s %s, ", tbuff, inet_ntoa(ipaddr)); 4216059Samurai LogPrintf(LOG_LCP, "%s\n", inet_ntoa(dstipaddr)); 4226059Samurai 4236059Samurai switch (mode) { 4246059Samurai case MODE_REQ: 4256059Samurai IpcpInfo.his_ipaddr = ipaddr; 4266059Samurai IpcpInfo.want_ipaddr = dstipaddr; 4276059Samurai bcopy(cp, ackp, length); 4286059Samurai ackp += length; 4296059Samurai break; 4306059Samurai case MODE_NAK: 4316059Samurai LogPrintf(LOG_LCP, "%s changing address: %s ", 4326059Samurai tbuff, inet_ntoa(IpcpInfo.want_ipaddr)); 4336059Samurai LogPrintf(LOG_LCP, "--> %s\n", inet_ntoa(ipaddr)); 4346059Samurai IpcpInfo.want_ipaddr = ipaddr; 4356059Samurai IpcpInfo.his_ipaddr = dstipaddr; 4366059Samurai break; 4376059Samurai case MODE_REJ: 4386059Samurai IpcpInfo.his_reject |= (1 << type); 4396059Samurai break; 4406059Samurai } 4416059Samurai break; 4426059Samurai default: 4436059Samurai IpcpInfo.my_reject |= (1 << type); 4446059Samurai bcopy(cp, rejp, length); 4456059Samurai rejp += length; 4466059Samurai break; 4476059Samurai } 4486059Samurai plen -= length; 4496059Samurai cp += length; 4506059Samurai } 4516059Samurai} 4526059Samurai 4536059Samuraivoid 4546059SamuraiIpcpInput(struct mbuf *bp) 4556059Samurai{ 4566059Samurai FsmInput(&IpcpFsm, bp); 4576059Samurai} 458