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.15 1997/08/25 00:29:06 brian Exp $ 21 * 22 * TODO: 23 * o Support other compression protocols 24 */ 25 #include "fsm.h" 26 #include "lcpproto.h" 27 #include "lcp.h" 28 #include "ccp.h" 29 #include "phase.h" 30 #include "loadalias.h" 31 #include "vars.h" 32 #include "pred.h" 33 34 struct ccpstate CcpInfo; 35 36 static void CcpSendConfigReq(struct fsm *); 37 static void CcpSendTerminateReq(struct fsm * fp); 38 static void CcpSendTerminateAck(struct fsm * fp); 39 static void CcpDecodeConfig(u_char * cp, int flen, int mode); 40 static void CcpLayerStart(struct fsm *); 41 static void CcpLayerFinish(struct fsm *); 42 static void CcpLayerUp(struct fsm *); 43 static void CcpLayerDown(struct fsm *); 44 static void CcpInitRestartCounter(struct fsm *); 45 46 #define REJECTED(p, x) (p->his_reject & (1<<x)) 47 48 struct fsm CcpFsm = { 49 "CCP", 50 PROTO_CCP, 51 CCP_MAXCODE, 52 OPEN_ACTIVE, 53 ST_INITIAL, 54 0, 0, 0, 55 0, 56 {0, 0, 0, NULL, NULL, NULL}, 57 {0, 0, 0, NULL, NULL, NULL}, 58 LogCCP, 59 60 CcpLayerUp, 61 CcpLayerDown, 62 CcpLayerStart, 63 CcpLayerFinish, 64 CcpInitRestartCounter, 65 CcpSendConfigReq, 66 CcpSendTerminateReq, 67 CcpSendTerminateAck, 68 CcpDecodeConfig, 69 }; 70 71 static char const *cftypes[] = { 72 /* 0 */ "OUI", "PRED1", "PRED2", "PUDDLE", 73 /* 4 */ "???", "???", "???", "???", 74 /* 8 */ "???", "???", "???", "???", 75 /* 12 */ "???", "???", "???", "???", 76 /* 16 */ "HWPPC", "STAC", "MSPPC", "GAND", 77 /* 20 */ "V42BIS", "BSD", 78 }; 79 80 int 81 ReportCcpStatus() 82 { 83 struct ccpstate *icp = &CcpInfo; 84 struct fsm *fp = &CcpFsm; 85 86 if (VarTerm) { 87 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]); 88 fprintf(VarTerm, "myproto = %s, hisproto = %s\n", 89 cftypes[icp->want_proto], cftypes[icp->his_proto]); 90 fprintf(VarTerm, "Input: %ld --> %ld, Output: %ld --> %ld\n", 91 icp->orgin, icp->compin, icp->orgout, icp->compout); 92 } 93 return 0; 94 } 95 96 void 97 CcpInit() 98 { 99 struct ccpstate *icp = &CcpInfo; 100 101 FsmInit(&CcpFsm); 102 bzero(icp, sizeof(struct ccpstate)); 103 if (Enabled(ConfPred1)) 104 icp->want_proto = TY_PRED1; 105 CcpFsm.maxconfig = 10; 106 } 107 108 static void 109 CcpInitRestartCounter(struct fsm * fp) 110 { 111 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 112 fp->restart = 5; 113 } 114 115 static void 116 CcpSendConfigReq(struct fsm * fp) 117 { 118 u_char *cp; 119 struct ccpstate *icp = &CcpInfo; 120 121 cp = ReqBuff; 122 LogPrintf(LogCCP, "CcpSendConfigReq\n"); 123 if (icp->want_proto && !REJECTED(icp, TY_PRED1)) { 124 *cp++ = TY_PRED1; 125 *cp++ = 2; 126 } 127 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 128 } 129 130 void 131 CcpSendResetReq(struct fsm * fp) 132 { 133 LogPrintf(LogCCP, "CcpSendResetReq\n"); 134 FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 135 } 136 137 static void 138 CcpSendTerminateReq(struct fsm * fp) 139 { 140 /* XXX: No code yet */ 141 } 142 143 static void 144 CcpSendTerminateAck(struct fsm * fp) 145 { 146 LogPrintf(LogCCP, "CcpSendTerminateAck\n"); 147 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 148 } 149 150 void 151 CcpRecvResetReq(struct fsm * fp) 152 { 153 Pred1Init(2); /* Initialize Output part */ 154 } 155 156 static void 157 CcpLayerStart(struct fsm * fp) 158 { 159 LogPrintf(LogCCP, "CcpLayerStart.\n"); 160 } 161 162 static void 163 CcpLayerFinish(struct fsm * fp) 164 { 165 LogPrintf(LogCCP, "CcpLayerFinish.\n"); 166 } 167 168 static void 169 CcpLayerDown(struct fsm * fp) 170 { 171 LogPrintf(LogCCP, "CcpLayerDown.\n"); 172 } 173 174 /* 175 * Called when CCP has reached to OPEN state 176 */ 177 static void 178 CcpLayerUp(struct fsm * fp) 179 { 180 LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state); 181 LogPrintf(LogCCP, "myproto = %d, hisproto = %d\n", 182 CcpInfo.want_proto, CcpInfo.his_proto); 183 Pred1Init(3); /* Initialize Input and Output */ 184 } 185 186 void 187 CcpUp() 188 { 189 FsmUp(&CcpFsm); 190 LogPrintf(LogCCP, "CCP Up event!!\n"); 191 } 192 193 void 194 CcpOpen() 195 { 196 if (Enabled(ConfPred1)) 197 FsmOpen(&CcpFsm); 198 } 199 200 static void 201 CcpDecodeConfig(u_char * cp, int plen, int mode) 202 { 203 int type, length; 204 char tbuff[100]; 205 206 ackp = AckBuff; 207 nakp = NakBuff; 208 rejp = RejBuff; 209 210 while (plen >= sizeof(struct fsmconfig)) { 211 if (plen < 0) 212 break; 213 type = *cp; 214 length = cp[1]; 215 if (type <= TY_BSD) 216 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length); 217 else 218 snprintf(tbuff, sizeof(tbuff), " "); 219 220 LogPrintf(LogCCP, "%s\n", tbuff); 221 222 switch (type) { 223 case TY_PRED1: 224 switch (mode) { 225 case MODE_REQ: 226 if (Acceptable(ConfPred1)) { 227 bcopy(cp, ackp, length); 228 ackp += length; 229 CcpInfo.his_proto = type; 230 } else { 231 bcopy(cp, rejp, length); 232 rejp += length; 233 } 234 break; 235 case MODE_NAK: 236 case MODE_REJ: 237 CcpInfo.his_reject |= (1 << type); 238 CcpInfo.want_proto = 0; 239 break; 240 } 241 break; 242 case TY_BSD: 243 default: 244 CcpInfo.my_reject |= (1 << type); 245 bcopy(cp, rejp, length); 246 rejp += length; 247 break; 248 } 249 plen -= length; 250 cp += length; 251 } 252 } 253 254 void 255 CcpInput(struct mbuf * bp) 256 { 257 if (phase == PHASE_NETWORK) 258 FsmInput(&CcpFsm, bp); 259 else { 260 if (phase > PHASE_NETWORK) 261 LogPrintf(LogERROR, "Unexpected CCP in phase %d\n", phase); 262 pfree(bp); 263 } 264 } 265