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