ccp.c revision 28679
117680Spst/*
239300Sfenner *	   PPP Compression Control Protocol (CCP) Module
317680Spst *
417680Spst *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
517680Spst *
617680Spst *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
717680Spst *
817680Spst * Redistribution and use in source and binary forms are permitted
917680Spst * provided that the above copyright notice and this paragraph are
1017680Spst * duplicated in all such forms and that any documentation,
1117680Spst * advertising materials, and other materials related to such
1217680Spst * distribution and use acknowledge that the software was developed
1317680Spst * by the Internet Initiative Japan, Inc.  The name of the
1417680Spst * IIJ may not be used to endorse or promote products derived
1517680Spst * from this software without specific prior written permission.
1617680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1717680Spst * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1817680Spst * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1917680Spst *
2056896Sfenner * $Id: ccp.c,v 1.14 1997/08/20 23:47:40 brian Exp $
2156896Sfenner *
2217680Spst *	TODO:
2317680Spst *		o Support other compression protocols
2417680Spst */
2526183Sfenner#include "fsm.h"
2656896Sfenner#include "lcpproto.h"
2717680Spst#include "lcp.h"
2817680Spst#include "ccp.h"
2956896Sfenner#include "phase.h"
3056896Sfenner#include "loadalias.h"
3156896Sfenner#include "vars.h"
3256896Sfenner#include "pred.h"
3317680Spst
3417680Spststruct ccpstate CcpInfo;
3517680Spst
3617680Spststatic void CcpSendConfigReq(struct fsm *);
3717680Spststatic void CcpSendTerminateReq(struct fsm * fp);
3817680Spststatic void CcpSendTerminateAck(struct fsm * fp);
3917680Spststatic void CcpDecodeConfig(u_char * cp, int flen, int mode);
4017680Spststatic void CcpLayerStart(struct fsm *);
4117680Spststatic void CcpLayerFinish(struct fsm *);
4217680Spststatic void CcpLayerUp(struct fsm *);
4317680Spststatic void CcpLayerDown(struct fsm *);
4421262Swollmanstatic void CcpInitRestartCounter(struct fsm *);
4517680Spst
4617680Spst#define	REJECTED(p, x)	(p->his_reject & (1<<x))
4717680Spst
4817680Spststruct fsm CcpFsm = {
4917680Spst  "CCP",
5017680Spst  PROTO_CCP,
5117680Spst  CCP_MAXCODE,
5239300Sfenner  OPEN_ACTIVE,
5317680Spst  ST_INITIAL,
5439300Sfenner  0, 0, 0,
5539300Sfenner  0,
5617680Spst  {0, 0, 0, NULL, NULL, NULL},
5739300Sfenner  {0, 0, 0, NULL, NULL, NULL},
5817680Spst  LogCCP,
5917680Spst
6017680Spst  CcpLayerUp,
6156896Sfenner  CcpLayerDown,
6217680Spst  CcpLayerStart,
6317680Spst  CcpLayerFinish,
6417680Spst  CcpInitRestartCounter,
6517680Spst  CcpSendConfigReq,
6617680Spst  CcpSendTerminateReq,
6717680Spst  CcpSendTerminateAck,
6817680Spst  CcpDecodeConfig,
6917680Spst};
7017680Spst
7117680Spststatic char const *cftypes[] = {
7217680Spst   /*  0 */ "OUI", "PRED1", "PRED2", "PUDDLE",
7317680Spst   /*  4 */ "???", "???", "???", "???",
7417680Spst   /*  8 */ "???", "???", "???", "???",
7517680Spst   /* 12 */ "???", "???", "???", "???",
7617680Spst   /* 16 */ "HWPPC", "STAC", "MSPPC", "GAND",
7717680Spst   /* 20 */ "V42BIS", "BSD",
7817680Spst};
7917680Spst
8017680Spstint
8117680SpstReportCcpStatus()
8217680Spst{
8317680Spst  struct ccpstate *icp = &CcpInfo;
8417680Spst  struct fsm *fp = &CcpFsm;
8517680Spst
8617680Spst  if (VarTerm) {
8717680Spst    fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
8817680Spst    fprintf(VarTerm, "myproto = %s, hisproto = %s\n",
8917680Spst	    cftypes[icp->want_proto], cftypes[icp->his_proto]);
9017680Spst    fprintf(VarTerm, "Input: %ld --> %ld,  Output: %ld --> %ld\n",
9117680Spst	    icp->orgin, icp->compin, icp->orgout, icp->compout);
9217680Spst  }
9317680Spst  return 0;
9417680Spst}
9517680Spst
9617680Spstvoid
9717680SpstCcpInit()
9817680Spst{
9917680Spst  struct ccpstate *icp = &CcpInfo;
10017680Spst
10117680Spst  FsmInit(&CcpFsm);
10217680Spst  bzero(icp, sizeof(struct ccpstate));
10317680Spst  if (Enabled(ConfPred1))
10417680Spst    icp->want_proto = TY_PRED1;
10517680Spst  CcpFsm.maxconfig = 10;
10617680Spst}
10717680Spst
10817680Spststatic void
10917680SpstCcpInitRestartCounter(struct fsm * fp)
11056896Sfenner{
11156896Sfenner  fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
11256896Sfenner  fp->restart = 5;
11356896Sfenner}
11456896Sfenner
11556896Sfennerstatic void
11656896SfennerCcpSendConfigReq(struct fsm * fp)
11756896Sfenner{
11856896Sfenner  u_char *cp;
11956896Sfenner  struct ccpstate *icp = &CcpInfo;
12056896Sfenner
12156896Sfenner  cp = ReqBuff;
12256896Sfenner  LogPrintf(LogCCP, "CcpSendConfigReq\n");
12356896Sfenner  if (icp->want_proto && !REJECTED(icp, TY_PRED1)) {
12456896Sfenner    *cp++ = TY_PRED1;
12556896Sfenner    *cp++ = 2;
12656896Sfenner  }
12756896Sfenner  FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
12856896Sfenner}
12956896Sfenner
13056896Sfennervoid
13117680SpstCcpSendResetReq(struct fsm * fp)
13217680Spst{
13317680Spst  Pred1Init(1);			/* Initialize Input part */
13417680Spst  LogPrintf(LogCCP, "CcpSendResetReq\n");
13517680Spst  FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
13617680Spst}
13717680Spst
13817680Spststatic void
13917680SpstCcpSendTerminateReq(struct fsm * fp)
14017680Spst{
14117680Spst  /* XXX: No code yet */
14217680Spst}
14317680Spst
14417680Spststatic void
14517680SpstCcpSendTerminateAck(struct fsm * fp)
14617680Spst{
14717680Spst  LogPrintf(LogCCP, "CcpSendTerminateAck\n");
14817680Spst  FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
14917680Spst}
15017680Spst
15117680Spstvoid
15217680SpstCcpRecvResetReq(struct fsm * fp)
15317680Spst{
15417680Spst  Pred1Init(2);			/* Initialize Output part */
15517680Spst}
15617680Spst
15717680Spststatic void
15817680SpstCcpLayerStart(struct fsm * fp)
15917680Spst{
16017680Spst  LogPrintf(LogCCP, "CcpLayerStart.\n");
16117680Spst}
16217680Spst
16317680Spststatic void
16417680SpstCcpLayerFinish(struct fsm * fp)
16517680Spst{
16617680Spst  LogPrintf(LogCCP, "CcpLayerFinish.\n");
16717680Spst}
16817680Spst
16917680Spststatic void
17017680SpstCcpLayerDown(struct fsm * fp)
17117680Spst{
17217680Spst  LogPrintf(LogCCP, "CcpLayerDown.\n");
17317680Spst}
17417680Spst
17517680Spst/*
17617680Spst *  Called when CCP has reached to OPEN state
17717680Spst */
17817680Spststatic void
17917680SpstCcpLayerUp(struct fsm * fp)
18017680Spst{
18117680Spst  LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state);
18217680Spst  LogPrintf(LogCCP, "myproto = %d, hisproto = %d\n",
18317680Spst	    CcpInfo.want_proto, CcpInfo.his_proto);
18417680Spst  Pred1Init(3);			/* Initialize Input and Output */
18517680Spst}
18617680Spst
18717680Spstvoid
18817680SpstCcpUp()
18917680Spst{
19017680Spst  FsmUp(&CcpFsm);
19117680Spst  LogPrintf(LogCCP, "CCP Up event!!\n");
19217680Spst}
19317680Spst
19417680Spstvoid
19517680SpstCcpOpen()
19617680Spst{
19717680Spst  if (Enabled(ConfPred1))
19817680Spst    FsmOpen(&CcpFsm);
19917680Spst}
20017680Spst
20117680Spststatic void
20217680SpstCcpDecodeConfig(u_char * cp, int plen, int mode)
20317680Spst{
20417680Spst  int type, length;
20517680Spst  char tbuff[100];
20617680Spst
20717680Spst  ackp = AckBuff;
20817680Spst  nakp = NakBuff;
20917680Spst  rejp = RejBuff;
21017680Spst
21117680Spst  while (plen >= sizeof(struct fsmconfig)) {
21217680Spst    if (plen < 0)
21317680Spst      break;
21417680Spst    type = *cp;
21517680Spst    length = cp[1];
21617680Spst    if (type <= TY_BSD)
21717680Spst      snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
21817680Spst    else
21917680Spst      snprintf(tbuff, sizeof(tbuff), " ");
22017680Spst
22117680Spst    LogPrintf(LogCCP, "%s\n", tbuff);
22217680Spst
22317680Spst    switch (type) {
22417680Spst    case TY_PRED1:
22517680Spst      switch (mode) {
22617680Spst      case MODE_REQ:
22717680Spst	if (Acceptable(ConfPred1)) {
22817680Spst	  bcopy(cp, ackp, length);
22917680Spst	  ackp += length;
23017680Spst	  CcpInfo.his_proto = type;
23117680Spst	} else {
23217680Spst	  bcopy(cp, rejp, length);
23317680Spst	  rejp += length;
23417680Spst	}
23517680Spst	break;
23617680Spst      case MODE_NAK:
23717680Spst      case MODE_REJ:
23817680Spst	CcpInfo.his_reject |= (1 << type);
23917680Spst	CcpInfo.want_proto = 0;
24017680Spst	break;
24117680Spst      }
24217680Spst      break;
24317680Spst    case TY_BSD:
24417680Spst    default:
24517680Spst      CcpInfo.my_reject |= (1 << type);
24617680Spst      bcopy(cp, rejp, length);
24717680Spst      rejp += length;
24817680Spst      break;
24956896Sfenner    }
25056896Sfenner    plen -= length;
25156896Sfenner    cp += length;
25256896Sfenner  }
25356896Sfenner}
25456896Sfenner
25556896Sfennervoid
25656896SfennerCcpInput(struct mbuf * bp)
25739300Sfenner{
25839300Sfenner  if (phase == PHASE_NETWORK)
25939300Sfenner    FsmInput(&CcpFsm, bp);
26039300Sfenner  else {
26139300Sfenner    LogPrintf(LogERROR, "Unexpected CCP in phase %d\n", phase);
26239300Sfenner    pfree(bp);
26339300Sfenner  }
26439300Sfenner}
26539300Sfenner