ccp.c revision 31690
1112158Sdas/* 2112158Sdas * PPP Compression Control Protocol (CCP) Module 3112158Sdas * 4112158Sdas * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5112158Sdas * 6112158Sdas * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 7112158Sdas * 8112158Sdas * Redistribution and use in source and binary forms are permitted 9112158Sdas * provided that the above copyright notice and this paragraph are 10112158Sdas * duplicated in all such forms and that any documentation, 11112158Sdas * advertising materials, and other materials related to such 12112158Sdas * distribution and use acknowledge that the software was developed 13112158Sdas * by the Internet Initiative Japan, Inc. The name of the 14112158Sdas * IIJ may not be used to endorse or promote products derived 15112158Sdas * from this software without specific prior written permission. 16112158Sdas * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17112158Sdas * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18112158Sdas * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19112158Sdas * 20112158Sdas * $Id: ccp.c,v 1.23 1997/12/04 18:49:32 brian Exp $ 21112158Sdas * 22112158Sdas * TODO: 23112158Sdas * o Support other compression protocols 24112158Sdas */ 25112158Sdas#include <sys/param.h> 26112158Sdas#include <netinet/in.h> 27112158Sdas 28112158Sdas#include <stdio.h> 29165743Sdas#include <string.h> 30165743Sdas 31112158Sdas#include "command.h" 32112158Sdas#include "mbuf.h" 33112158Sdas#include "log.h" 34112158Sdas#include "defs.h" 35112158Sdas#include "timer.h" 36187808Sdas#include "fsm.h" 37112158Sdas#include "lcpproto.h" 38187808Sdas#include "lcp.h" 39112158Sdas#include "ccp.h" 40112158Sdas#include "phase.h" 41187808Sdas#include "loadalias.h" 42112158Sdas#include "vars.h" 43112158Sdas#include "pred.h" 44112158Sdas#include "deflate.h" 45187808Sdas 46187808Sdasstruct ccpstate CcpInfo; 47187808Sdas 48187808Sdasstatic void CcpSendConfigReq(struct fsm *); 49187808Sdasstatic void CcpSendTerminateReq(struct fsm *); 50112158Sdasstatic void CcpSendTerminateAck(struct fsm *); 51112158Sdasstatic void CcpDecodeConfig(u_char *, int, int); 52112158Sdasstatic void CcpLayerStart(struct fsm *); 53112158Sdasstatic void CcpLayerFinish(struct fsm *); 54112158Sdasstatic void CcpLayerUp(struct fsm *); 55112158Sdasstatic void CcpLayerDown(struct fsm *); 56112158Sdasstatic void CcpInitRestartCounter(struct fsm *); 57112158Sdas 58112158Sdasstruct fsm CcpFsm = { 59112158Sdas "CCP", 60112158Sdas PROTO_CCP, 61112158Sdas CCP_MAXCODE, 62112158Sdas OPEN_ACTIVE, 63112158Sdas ST_INITIAL, 64112158Sdas 0, 0, 0, 65112158Sdas 0, 66112158Sdas {0, 0, 0, NULL, NULL, NULL}, 67112158Sdas {0, 0, 0, NULL, NULL, NULL}, 68112158Sdas LogCCP, 69112158Sdas 70112158Sdas CcpLayerUp, 71112158Sdas CcpLayerDown, 72112158Sdas CcpLayerStart, 73112158Sdas CcpLayerFinish, 74112158Sdas CcpInitRestartCounter, 75112158Sdas CcpSendConfigReq, 76112158Sdas CcpSendTerminateReq, 77112158Sdas CcpSendTerminateAck, 78112158Sdas CcpDecodeConfig, 79112158Sdas}; 80112158Sdas 81112158Sdasstatic char const *cftypes[] = { 82112158Sdas /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 83112158Sdas "OUI", /* 0: OUI */ 84112158Sdas "PRED1", /* 1: Predictor type 1 */ 85112158Sdas "PRED2", /* 2: Predictor type 2 */ 86112158Sdas "PUDDLE", /* 3: Puddle Jumber */ 87112158Sdas "???", "???", "???", "???", "???", "???", 88112158Sdas "???", "???", "???", "???", "???", "???", 89112158Sdas "HWPPC", /* 16: Hewlett-Packard PPC */ 90112158Sdas "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 91187808Sdas "MSPPC", /* 18: Microsoft PPC */ 92187808Sdas "GAND", /* 19: Gandalf FZA (rfc1993) */ 93112158Sdas "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(char *)) 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(struct ccpstate)); 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 if (plen < 0) 294 break; 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