ccp.c revision 32246
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.26 1997/12/24 09:28:52 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 = { -1, -1 }; 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 if (CcpInfo.in_init) 142 (*algorithm[in_algorithm]->i.Term)(); 143 if (CcpInfo.out_init) 144 (*algorithm[out_algorithm]->o.Term)(); 145 in_algorithm = -1; 146 out_algorithm = -1; 147 memset(&CcpInfo, '\0', sizeof CcpInfo); 148 CcpInfo.his_proto = CcpInfo.my_proto = -1; 149} 150 151void 152CcpInit() 153{ 154 FsmInit(&CcpFsm); 155 ccpstateInit(); 156 CcpFsm.maxconfig = 10; 157} 158 159static void 160CcpInitRestartCounter(struct fsm *fp) 161{ 162 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 163 fp->restart = 5; 164} 165 166static void 167CcpSendConfigReq(struct fsm *fp) 168{ 169 u_char *cp; 170 int f; 171 172 LogPrintf(LogCCP, "CcpSendConfigReq\n"); 173 cp = ReqBuff; 174 CcpInfo.my_proto = -1; 175 out_algorithm = -1; 176 for (f = 0; f < NALGORITHMS; f++) 177 if (Enabled(algorithm[f]->Conf) && !REJECTED(&CcpInfo, algorithm[f]->id)) { 178 struct lcp_opt o; 179 180 (*algorithm[f]->o.Get)(&o); 181 cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id], 182 (*algorithm[f]->Disp)(&o)); 183 CcpInfo.my_proto = o.id; 184 out_algorithm = f; 185 } 186 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 187} 188 189void 190CcpSendResetReq(struct fsm *fp) 191{ 192 LogPrintf(LogCCP, "CcpSendResetReq\n"); 193 FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 194} 195 196static void 197CcpSendTerminateReq(struct fsm *fp) 198{ 199 /* XXX: No code yet */ 200} 201 202static void 203CcpSendTerminateAck(struct fsm *fp) 204{ 205 LogPrintf(LogCCP, "CcpSendTerminateAck\n"); 206 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 207} 208 209void 210CcpRecvResetReq(struct fsm *fp) 211{ 212 if (out_algorithm >= 0 && out_algorithm < NALGORITHMS) 213 (*algorithm[out_algorithm]->o.Reset)(); 214} 215 216static void 217CcpLayerStart(struct fsm *fp) 218{ 219 LogPrintf(LogCCP, "CcpLayerStart.\n"); 220} 221 222static void 223CcpLayerFinish(struct fsm *fp) 224{ 225 LogPrintf(LogCCP, "CcpLayerFinish.\n"); 226 ccpstateInit(); 227} 228 229static void 230CcpLayerDown(struct fsm *fp) 231{ 232 LogPrintf(LogCCP, "CcpLayerDown.\n"); 233 ccpstateInit(); 234} 235 236/* 237 * Called when CCP has reached the OPEN state 238 */ 239static void 240CcpLayerUp(struct fsm *fp) 241{ 242 LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state); 243 LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", 244 protoname(CcpInfo.my_proto), CcpInfo.my_proto, 245 protoname(CcpInfo.his_proto), CcpInfo.his_proto); 246 if (!CcpInfo.in_init && in_algorithm >= 0 && in_algorithm < NALGORITHMS) { 247 (*algorithm[in_algorithm]->i.Init)(); 248 CcpInfo.in_init = 1; 249 } 250 if (!CcpInfo.out_init && out_algorithm >= 0 && out_algorithm < NALGORITHMS) { 251 (*algorithm[out_algorithm]->o.Init)(); 252 CcpInfo.out_init = 1; 253 } 254} 255 256void 257CcpUp() 258{ 259 FsmUp(&CcpFsm); 260 LogPrintf(LogCCP, "CCP Up event!!\n"); 261} 262 263void 264CcpOpen() 265{ 266 int f; 267 268 for (f = 0; f < NALGORITHMS; f++) 269 if (Enabled(algorithm[f]->Conf)) { 270 CcpFsm.open_mode = OPEN_ACTIVE; 271 FsmOpen(&CcpFsm); 272 break; 273 } 274 275 if (f == NALGORITHMS) 276 for (f = 0; f < NALGORITHMS; f++) 277 if (Acceptable(algorithm[f]->Conf)) { 278 CcpFsm.open_mode = OPEN_PASSIVE; 279 FsmOpen(&CcpFsm); 280 break; 281 } 282} 283 284static void 285CcpDecodeConfig(u_char *cp, int plen, int mode_type) 286{ 287 int type, length; 288 int f; 289 290 ackp = AckBuff; 291 nakp = NakBuff; 292 rejp = RejBuff; 293 294 while (plen >= sizeof(struct fsmconfig)) { 295 type = *cp; 296 length = cp[1]; 297 if (type < NCFTYPES) 298 LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length); 299 else 300 LogPrintf(LogCCP, " ???[%d]\n", length); 301 302 for (f = NALGORITHMS-1; f > -1; f--) 303 if (algorithm[f]->id == type) 304 break; 305 306 if (f == -1) { 307 /* Don't understand that :-( */ 308 if (mode_type == MODE_REQ) { 309 CcpInfo.my_reject |= (1 << type); 310 memcpy(rejp, cp, length); 311 rejp += length; 312 } 313 } else { 314 struct lcp_opt o; 315 316 switch (mode_type) { 317 case MODE_REQ: 318 if (Acceptable(algorithm[f]->Conf) && in_algorithm == -1) { 319 memcpy(&o, cp, length); 320 switch ((*algorithm[f]->i.Set)(&o)) { 321 case MODE_REJ: 322 memcpy(rejp, &o, o.len); 323 rejp += o.len; 324 break; 325 case MODE_NAK: 326 memcpy(nakp, &o, o.len); 327 nakp += o.len; 328 break; 329 case MODE_ACK: 330 memcpy(ackp, cp, length); 331 ackp += length; 332 CcpInfo.his_proto = type; 333 in_algorithm = f; /* This one'll do ! */ 334 break; 335 } 336 } else { 337 memcpy(rejp, cp, length); 338 rejp += length; 339 } 340 break; 341 case MODE_NAK: 342 memcpy(&o, cp, length); 343 if ((*algorithm[f]->o.Set)(&o) == MODE_ACK) 344 CcpInfo.my_proto = algorithm[f]->id; 345 else { 346 CcpInfo.his_reject |= (1 << type); 347 CcpInfo.my_proto = -1; 348 } 349 break; 350 case MODE_REJ: 351 CcpInfo.his_reject |= (1 << type); 352 CcpInfo.my_proto = -1; 353 break; 354 } 355 } 356 357 plen -= length; 358 cp += length; 359 } 360 361 if (rejp != RejBuff) { 362 ackp = AckBuff; /* let's not send both ! */ 363 CcpInfo.his_proto = -1; 364 in_algorithm = -1; 365 } 366} 367 368void 369CcpInput(struct mbuf *bp) 370{ 371 if (phase == PHASE_NETWORK) 372 FsmInput(&CcpFsm, bp); 373 else { 374 if (phase > PHASE_NETWORK) 375 LogPrintf(LogCCP, "Error: Unexpected CCP in phase %d\n", phase); 376 pfree(bp); 377 } 378} 379 380void 381CcpResetInput() 382{ 383 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) 384 (*algorithm[in_algorithm]->i.Reset)(); 385} 386 387int 388CcpOutput(int pri, u_short proto, struct mbuf *m) 389{ 390 if (out_algorithm >= 0 && out_algorithm < NALGORITHMS) 391 return (*algorithm[out_algorithm]->o.Write)(pri, proto, m); 392 return 0; 393} 394 395struct mbuf * 396CompdInput(u_short *proto, struct mbuf *m) 397{ 398 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) 399 return (*algorithm[in_algorithm]->i.Read)(proto, m); 400 return NULL; 401} 402 403void 404CcpDictSetup(u_short proto, struct mbuf *m) 405{ 406 if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) 407 (*algorithm[in_algorithm]->i.DictSetup)(proto, m); 408} 409