ccp.c revision 31962
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.25 1997/12/17 21:21:53 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#include "deflate.h" 45 46struct ccpstate CcpInfo; 47 48static void CcpSendConfigReq(struct fsm *); 49static void CcpSendTerminateReq(struct fsm *); 50static void CcpSendTerminateAck(struct fsm *); 51static void CcpDecodeConfig(u_char *, int, int); 52static void CcpLayerStart(struct fsm *); 53static void CcpLayerFinish(struct fsm *); 54static void CcpLayerUp(struct fsm *); 55static void CcpLayerDown(struct fsm *); 56static void CcpInitRestartCounter(struct fsm *); 57 58struct fsm CcpFsm = { 59 "CCP", 60 PROTO_CCP, 61 CCP_MAXCODE, 62 OPEN_ACTIVE, 63 ST_INITIAL, 64 0, 0, 0, 65 0, 66 {0, 0, 0, NULL, NULL, NULL}, 67 {0, 0, 0, NULL, NULL, NULL}, 68 LogCCP, 69 70 CcpLayerUp, 71 CcpLayerDown, 72 CcpLayerStart, 73 CcpLayerFinish, 74 CcpInitRestartCounter, 75 CcpSendConfigReq, 76 CcpSendTerminateReq, 77 CcpSendTerminateAck, 78 CcpDecodeConfig, 79}; 80 81static char const *cftypes[] = { 82 /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 83 "OUI", /* 0: OUI */ 84 "PRED1", /* 1: Predictor type 1 */ 85 "PRED2", /* 2: Predictor type 2 */ 86 "PUDDLE", /* 3: Puddle Jumber */ 87 "???", "???", "???", "???", "???", "???", 88 "???", "???", "???", "???", "???", "???", 89 "HWPPC", /* 16: Hewlett-Packard PPC */ 90 "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 91 "MSPPC", /* 18: Microsoft PPC */ 92 "GAND", /* 19: Gandalf FZA (rfc1993) */ 93 "V42BIS", /* 20: ARG->DATA.42bis compression */ 94 "BSD", /* 21: BSD LZW Compress */ 95 "???", 96 "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 97 "MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */ 98 /* 24: Deflate (according to pppd-2.3.1) */ 99 "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 100 "DEFLATE", /* 26: Deflate (rfc1979) */ 101}; 102 103#define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 104 105static const char * 106protoname(int proto) 107{ 108 if (proto < 0 || proto > NCFTYPES) 109 return "none"; 110 return cftypes[proto]; 111} 112 113/* We support these algorithms, and Req them in the given order */ 114static const struct ccp_algorithm *algorithm[] = { 115 &DeflateAlgorithm, 116 &Pred1Algorithm, 117 &PppdDeflateAlgorithm 118}; 119 120static int in_algorithm = -1; 121static int out_algorithm = -1; 122#define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 123 124int 125ReportCcpStatus(struct cmdargs const *arg) 126{ 127 if (VarTerm) { 128 fprintf(VarTerm, "%s [%s]\n", CcpFsm.name, StateNames[CcpFsm.state]); 129 fprintf(VarTerm, "My protocol = %s, His protocol = %s\n", 130 protoname(CcpInfo.my_proto), protoname(CcpInfo.his_proto)); 131 fprintf(VarTerm, "Output: %ld --> %ld, Input: %ld --> %ld\n", 132 CcpInfo.uncompout, CcpInfo.compout, 133 CcpInfo.compin, CcpInfo.uncompin); 134 } 135 return 0; 136} 137 138static void 139ccpstateInit(void) 140{ 141 memset(&CcpInfo, '\0', sizeof CcpInfo); 142 CcpInfo.his_proto = CcpInfo.my_proto = -1; 143 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) { 144 (*algorithm[in_algorithm]->i.Term)(); 145 in_algorithm = -1; 146 } 147 if (out_algorithm >= 0 && out_algorithm < NALGORITHMS) { 148 (*algorithm[out_algorithm]->o.Term)(); 149 out_algorithm = -1; 150 } 151} 152 153void 154CcpInit() 155{ 156 FsmInit(&CcpFsm); 157 ccpstateInit(); 158 CcpFsm.maxconfig = 10; 159} 160 161static void 162CcpInitRestartCounter(struct fsm *fp) 163{ 164 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 165 fp->restart = 5; 166} 167 168static void 169CcpSendConfigReq(struct fsm *fp) 170{ 171 u_char *cp; 172 int f; 173 174 LogPrintf(LogCCP, "CcpSendConfigReq\n"); 175 cp = ReqBuff; 176 CcpInfo.my_proto = -1; 177 out_algorithm = -1; 178 for (f = 0; f < NALGORITHMS; f++) 179 if (Enabled(algorithm[f]->Conf) && !REJECTED(&CcpInfo, algorithm[f]->id)) { 180 struct lcp_opt o; 181 182 (*algorithm[f]->o.Get)(&o); 183 cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id], 184 (*algorithm[f]->Disp)(&o)); 185 CcpInfo.my_proto = o.id; 186 out_algorithm = f; 187 } 188 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 189} 190 191void 192CcpSendResetReq(struct fsm *fp) 193{ 194 LogPrintf(LogCCP, "CcpSendResetReq\n"); 195 FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 196} 197 198static void 199CcpSendTerminateReq(struct fsm *fp) 200{ 201 /* XXX: No code yet */ 202} 203 204static void 205CcpSendTerminateAck(struct fsm *fp) 206{ 207 LogPrintf(LogCCP, "CcpSendTerminateAck\n"); 208 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 209} 210 211void 212CcpRecvResetReq(struct fsm *fp) 213{ 214 if (out_algorithm >= 0 && out_algorithm < NALGORITHMS) 215 (*algorithm[out_algorithm]->o.Reset)(); 216} 217 218static void 219CcpLayerStart(struct fsm *fp) 220{ 221 LogPrintf(LogCCP, "CcpLayerStart.\n"); 222} 223 224static void 225CcpLayerFinish(struct fsm *fp) 226{ 227 LogPrintf(LogCCP, "CcpLayerFinish.\n"); 228 ccpstateInit(); 229} 230 231static void 232CcpLayerDown(struct fsm *fp) 233{ 234 LogPrintf(LogCCP, "CcpLayerDown.\n"); 235 ccpstateInit(); 236} 237 238/* 239 * Called when CCP has reached the OPEN state 240 */ 241static void 242CcpLayerUp(struct fsm *fp) 243{ 244 LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state); 245 LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", 246 protoname(CcpInfo.my_proto), CcpInfo.my_proto, 247 protoname(CcpInfo.his_proto), CcpInfo.his_proto); 248 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) 249 (*algorithm[in_algorithm]->i.Init)(); 250 if (out_algorithm >= 0 && out_algorithm < NALGORITHMS) 251 (*algorithm[out_algorithm]->o.Init)(); 252} 253 254void 255CcpUp() 256{ 257 FsmUp(&CcpFsm); 258 LogPrintf(LogCCP, "CCP Up event!!\n"); 259} 260 261void 262CcpOpen() 263{ 264 int f; 265 266 for (f = 0; f < NALGORITHMS; f++) 267 if (Enabled(algorithm[f]->Conf)) { 268 CcpFsm.open_mode = OPEN_ACTIVE; 269 FsmOpen(&CcpFsm); 270 break; 271 } 272 273 if (f == NALGORITHMS) 274 for (f = 0; f < NALGORITHMS; f++) 275 if (Acceptable(algorithm[f]->Conf)) { 276 CcpFsm.open_mode = OPEN_PASSIVE; 277 FsmOpen(&CcpFsm); 278 break; 279 } 280} 281 282static void 283CcpDecodeConfig(u_char *cp, int plen, int mode_type) 284{ 285 int type, length; 286 int f; 287 288 ackp = AckBuff; 289 nakp = NakBuff; 290 rejp = RejBuff; 291 292 while (plen >= sizeof(struct fsmconfig)) { 293 type = *cp; 294 length = cp[1]; 295 if (type < NCFTYPES) 296 LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length); 297 else 298 LogPrintf(LogCCP, " ???[%d]\n", length); 299 300 for (f = NALGORITHMS-1; f > -1; f--) 301 if (algorithm[f]->id == type) 302 break; 303 304 if (f == -1) { 305 /* Don't understand that :-( */ 306 if (mode_type == MODE_REQ) { 307 CcpInfo.my_reject |= (1 << type); 308 memcpy(rejp, cp, length); 309 rejp += length; 310 } 311 } else { 312 struct lcp_opt o; 313 314 switch (mode_type) { 315 case MODE_REQ: 316 if (Acceptable(algorithm[f]->Conf) && in_algorithm == -1) { 317 memcpy(&o, cp, length); 318 switch ((*algorithm[f]->i.Set)(&o)) { 319 case MODE_REJ: 320 memcpy(rejp, &o, o.len); 321 rejp += o.len; 322 break; 323 case MODE_NAK: 324 memcpy(nakp, &o, o.len); 325 nakp += o.len; 326 break; 327 case MODE_ACK: 328 memcpy(ackp, cp, length); 329 ackp += length; 330 CcpInfo.his_proto = type; 331 in_algorithm = f; /* This one'll do ! */ 332 break; 333 } 334 } else { 335 memcpy(rejp, cp, length); 336 rejp += length; 337 } 338 break; 339 case MODE_NAK: 340 memcpy(&o, cp, length); 341 if ((*algorithm[f]->o.Set)(&o) == MODE_ACK) 342 CcpInfo.my_proto = algorithm[f]->id; 343 else { 344 CcpInfo.his_reject |= (1 << type); 345 CcpInfo.my_proto = -1; 346 } 347 break; 348 case MODE_REJ: 349 CcpInfo.his_reject |= (1 << type); 350 CcpInfo.my_proto = -1; 351 break; 352 } 353 } 354 355 plen -= length; 356 cp += length; 357 } 358 359 if (rejp != RejBuff) { 360 ackp = AckBuff; /* let's not send both ! */ 361 CcpInfo.his_proto = -1; 362 in_algorithm = -1; 363 } 364} 365 366void 367CcpInput(struct mbuf *bp) 368{ 369 if (phase == PHASE_NETWORK) 370 FsmInput(&CcpFsm, bp); 371 else { 372 if (phase > PHASE_NETWORK) 373 LogPrintf(LogCCP, "Error: Unexpected CCP in phase %d\n", phase); 374 pfree(bp); 375 } 376} 377 378void 379CcpResetInput() 380{ 381 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) 382 (*algorithm[in_algorithm]->i.Reset)(); 383} 384 385int 386CcpOutput(int pri, u_short proto, struct mbuf *m) 387{ 388 if (out_algorithm >= 0 && out_algorithm < NALGORITHMS) 389 return (*algorithm[out_algorithm]->o.Write)(pri, proto, m); 390 return 0; 391} 392 393struct mbuf * 394CompdInput(u_short *proto, struct mbuf *m) 395{ 396 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) 397 return (*algorithm[in_algorithm]->i.Read)(proto, m); 398 return NULL; 399} 400 401void 402CcpDictSetup(u_short proto, struct mbuf *m) 403{ 404 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) 405 (*algorithm[in_algorithm]->i.DictSetup)(proto, m); 406} 407