ccp.c revision 31343
1/* 2 * PPP Compression Control Protocol (CCP) Module 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id: ccp.c,v 1.19 1997/11/14 15:39:14 brian Exp $ 21 * 22 * TODO: 23 * o Support other compression protocols 24 */ 25#include <sys/param.h> 26#include <netinet/in.h> 27 28#include <stdio.h> 29#include <string.h> 30 31#include "command.h" 32#include "mbuf.h" 33#include "log.h" 34#include "defs.h" 35#include "timer.h" 36#include "fsm.h" 37#include "lcpproto.h" 38#include "lcp.h" 39#include "ccp.h" 40#include "phase.h" 41#include "loadalias.h" 42#include "vars.h" 43#include "pred.h" 44 45struct ccpstate CcpInfo; 46 47static void CcpSendConfigReq(struct fsm *); 48static void CcpSendTerminateReq(struct fsm *); 49static void CcpSendTerminateAck(struct fsm *); 50static void CcpDecodeConfig(u_char *, int, int); 51static void CcpLayerStart(struct fsm *); 52static void CcpLayerFinish(struct fsm *); 53static void CcpLayerUp(struct fsm *); 54static void CcpLayerDown(struct fsm *); 55static void CcpInitRestartCounter(struct fsm *); 56 57#define REJECTED(p, x) (p->his_reject & (1<<x)) 58 59struct fsm CcpFsm = { 60 "CCP", 61 PROTO_CCP, 62 CCP_MAXCODE, 63 OPEN_ACTIVE, 64 ST_INITIAL, 65 0, 0, 0, 66 0, 67 {0, 0, 0, NULL, NULL, NULL}, 68 {0, 0, 0, NULL, NULL, NULL}, 69 LogCCP, 70 71 CcpLayerUp, 72 CcpLayerDown, 73 CcpLayerStart, 74 CcpLayerFinish, 75 CcpInitRestartCounter, 76 CcpSendConfigReq, 77 CcpSendTerminateReq, 78 CcpSendTerminateAck, 79 CcpDecodeConfig, 80}; 81 82static char const *cftypes[] = { 83 /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 84 "OUI", /* 0: OUI */ 85 "PRED1", /* 1: Predictor type 1 */ 86 "PRED2", /* 2: Predictor type 2 */ 87 "PUDDLE", /* 3: Puddle Jumber */ 88 "???", "???", "???", "???", "???", "???", 89 "???", "???", "???", "???", "???", "???", 90 "HWPPC", /* 16: Hewlett-Packard PPC */ 91 "STAC", /* 17: Stac Electronics LZS */ 92 "MSPPC", /* 18: Microsoft PPC */ 93 "GAND", /* 19: Gandalf FZA */ 94 "V42BIS", /* 20: ARG->DATA.42bis compression */ 95 "BSD", /* BSD LZW Compress */ 96}; 97 98#define NCFTYPES (sizeof(cftypes)/sizeof(char *)) 99 100int 101ReportCcpStatus(struct cmdargs const *arg) 102{ 103 struct ccpstate *icp = &CcpInfo; 104 struct fsm *fp = &CcpFsm; 105 106 if (VarTerm) { 107 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]); 108 fprintf(VarTerm, "myproto = %s, hisproto = %s\n", 109 cftypes[icp->want_proto], cftypes[icp->his_proto]); 110 fprintf(VarTerm, "Input: %ld --> %ld, Output: %ld --> %ld\n", 111 icp->orgin, icp->compin, icp->orgout, icp->compout); 112 } 113 return 0; 114} 115 116void 117CcpInit() 118{ 119 struct ccpstate *icp = &CcpInfo; 120 121 FsmInit(&CcpFsm); 122 memset(icp, '\0', sizeof(struct ccpstate)); 123 if (Enabled(ConfPred1)) 124 icp->want_proto = TY_PRED1; 125 CcpFsm.maxconfig = 10; 126} 127 128static void 129CcpInitRestartCounter(struct fsm *fp) 130{ 131 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 132 fp->restart = 5; 133} 134 135static void 136CcpSendConfigReq(struct fsm *fp) 137{ 138 u_char *cp; 139 struct ccpstate *icp = &CcpInfo; 140 141 cp = ReqBuff; 142 LogPrintf(LogCCP, "CcpSendConfigReq\n"); 143 if (icp->want_proto && !REJECTED(icp, TY_PRED1)) { 144 *cp++ = TY_PRED1; 145 *cp++ = 2; 146 } 147 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 148} 149 150void 151CcpSendResetReq(struct fsm *fp) 152{ 153 LogPrintf(LogCCP, "CcpSendResetReq\n"); 154 FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 155} 156 157static void 158CcpSendTerminateReq(struct fsm *fp) 159{ 160 /* XXX: No code yet */ 161} 162 163static void 164CcpSendTerminateAck(struct fsm *fp) 165{ 166 LogPrintf(LogCCP, "CcpSendTerminateAck\n"); 167 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 168} 169 170void 171CcpRecvResetReq(struct fsm *fp) 172{ 173 Pred1Init(2); /* Initialize Output part */ 174} 175 176static void 177CcpLayerStart(struct fsm *fp) 178{ 179 LogPrintf(LogCCP, "CcpLayerStart.\n"); 180} 181 182static void 183CcpLayerFinish(struct fsm *fp) 184{ 185 LogPrintf(LogCCP, "CcpLayerFinish.\n"); 186} 187 188static void 189CcpLayerDown(struct fsm *fp) 190{ 191 LogPrintf(LogCCP, "CcpLayerDown.\n"); 192} 193 194/* 195 * Called when CCP has reached to OPEN state 196 */ 197static void 198CcpLayerUp(struct fsm *fp) 199{ 200 LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state); 201 LogPrintf(LogCCP, "myproto = %d, hisproto = %d\n", 202 CcpInfo.want_proto, CcpInfo.his_proto); 203 Pred1Init(3); /* Initialize Input and Output */ 204} 205 206void 207CcpUp() 208{ 209 FsmUp(&CcpFsm); 210 LogPrintf(LogCCP, "CCP Up event!!\n"); 211} 212 213void 214CcpOpen() 215{ 216 if (Enabled(ConfPred1)) 217 FsmOpen(&CcpFsm); 218} 219 220static void 221CcpDecodeConfig(u_char *cp, int plen, int mode_type) 222{ 223 int type, length; 224 char tbuff[100]; 225 226 ackp = AckBuff; 227 nakp = NakBuff; 228 rejp = RejBuff; 229 230 while (plen >= sizeof(struct fsmconfig)) { 231 if (plen < 0) 232 break; 233 type = *cp; 234 length = cp[1]; 235 if (type < NCFTYPES) 236 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length); 237 else 238 snprintf(tbuff, sizeof(tbuff), " "); 239 240 LogPrintf(LogCCP, "%s\n", tbuff); 241 242 switch (type) { 243 case TY_PRED1: 244 switch (mode_type) { 245 case MODE_REQ: 246 if (Acceptable(ConfPred1)) { 247 memcpy(ackp, cp, length); 248 ackp += length; 249 CcpInfo.his_proto = type; 250 } else { 251 memcpy(rejp, cp, length); 252 rejp += length; 253 } 254 break; 255 case MODE_NAK: 256 case MODE_REJ: 257 CcpInfo.his_reject |= (1 << type); 258 CcpInfo.want_proto = 0; 259 break; 260 } 261 break; 262 case TY_BSD: 263 default: 264 CcpInfo.my_reject |= (1 << type); 265 memcpy(rejp, cp, length); 266 rejp += length; 267 break; 268 } 269 plen -= length; 270 cp += length; 271 } 272} 273 274void 275CcpInput(struct mbuf *bp) 276{ 277 if (phase == PHASE_NETWORK) 278 FsmInput(&CcpFsm, bp); 279 else { 280 if (phase > PHASE_NETWORK) 281 LogPrintf(LogERROR, "Unexpected CCP in phase %d\n", phase); 282 pfree(bp); 283 } 284} 285