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