ccp.c revision 25630
11854Swollman/*
222993Speter *	   PPP Compression Control Protocol (CCP) Module
31573Srgrimes *
41573Srgrimes *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
52049Scsgr *
68870Srgrimes *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
72049Scsgr *
81573Srgrimes * Redistribution and use in source and binary forms are permitted
91854Swollman * provided that the above copyright notice and this paragraph are
101573Srgrimes * duplicated in all such forms and that any documentation,
111573Srgrimes * advertising materials, and other materials related to such
121573Srgrimes * 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.10 1997/02/22 16:10:03 peter Exp $
21 *
22 *	TODO:
23 *		o Support other compression protocols
24 */
25#include "fsm.h"
26#include "lcpproto.h"
27#include "lcp.h"
28#include "ccp.h"
29#include "phase.h"
30#include "vars.h"
31#include "pred.h"
32#include "cdefs.h"
33
34struct ccpstate CcpInfo;
35
36static void CcpSendConfigReq __P((struct fsm *));
37static void CcpSendTerminateReq __P((struct fsm *fp));
38static void CcpSendTerminateAck __P((struct fsm *fp));
39static void CcpDecodeConfig __P((u_char *cp, int flen, int mode));
40static void CcpLayerStart __P((struct fsm *));
41static void CcpLayerFinish __P((struct fsm *));
42static void CcpLayerUp __P((struct fsm *));
43static void CcpLayerDown __P((struct fsm *));
44static void CcpInitRestartCounter __P((struct fsm *));
45
46#define	REJECTED(p, x)	(p->his_reject & (1<<x))
47
48struct fsm CcpFsm = {
49  "CCP",
50  PROTO_CCP,
51  CCP_MAXCODE,
52  OPEN_ACTIVE,
53  ST_INITIAL,
54  0, 0, 0,
55
56  0,
57  { 0, 0, 0, NULL, NULL, NULL },
58
59  CcpLayerUp,
60  CcpLayerDown,
61  CcpLayerStart,
62  CcpLayerFinish,
63  CcpInitRestartCounter,
64  CcpSendConfigReq,
65  CcpSendTerminateReq,
66  CcpSendTerminateAck,
67  CcpDecodeConfig,
68};
69
70static char const *cftypes[] = {
71/*  0 */  "OUI",    "PRED1", "PRED2", "PUDDLE",
72/*  4 */  "???",    "???",   "???",   "???",
73/*  8 */  "???",    "???",   "???",   "???",
74/* 12 */  "???",    "???",   "???",   "???",
75/* 16 */  "HWPPC",  "STAC",  "MSPPC", "GAND",
76/* 20 */  "V42BIS", "BSD",
77};
78
79int
80ReportCcpStatus()
81{
82  struct ccpstate *icp = &CcpInfo;
83  struct fsm *fp = &CcpFsm;
84
85  printf("%s [%s]\n", fp->name, StateNames[fp->state]);
86  printf("myproto = %s, hisproto = %s\n",
87	cftypes[icp->want_proto], cftypes[icp->his_proto]);
88  printf("Input: %ld --> %ld,  Output: %ld --> %ld\n",
89	icp->orgin, icp->compin, icp->orgout, icp->compout);
90  return 0;
91}
92
93void
94CcpInit()
95{
96  struct ccpstate *icp = &CcpInfo;
97
98  FsmInit(&CcpFsm);
99  bzero(icp, sizeof(struct ccpstate));
100  if (Enabled(ConfPred1))
101    icp->want_proto = TY_PRED1;
102  CcpFsm.maxconfig = 10;
103}
104
105static void
106CcpInitRestartCounter(fp)
107struct fsm *fp;
108{
109  fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
110  fp->restart = 5;
111}
112
113static void
114CcpSendConfigReq(fp)
115struct fsm *fp;
116{
117  u_char *cp;
118  struct ccpstate *icp = &CcpInfo;
119
120  cp = ReqBuff;
121  LogPrintf(LOG_LCP_BIT, "%s: SendConfigReq\n", fp->name);
122  if (icp->want_proto && !REJECTED(icp, TY_PRED1)) {
123    *cp++ = TY_PRED1; *cp++ = 2;
124  }
125  FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
126}
127
128void
129CcpSendResetReq(fp)
130struct fsm *fp;
131{
132  Pred1Init(1);		/* Initialize Input part */
133  LogPrintf(LOG_LCP_BIT, "%s: SendResetReq\n", fp->name);
134  FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
135}
136
137static void
138CcpSendTerminateReq(fp)
139struct fsm *fp;
140{
141  /* XXX: No code yet */
142}
143
144static void
145CcpSendTerminateAck(fp)
146struct fsm *fp;
147{
148  LogPrintf(LOG_LCP_BIT, "  %s: SendTerminateAck\n", fp->name);
149  FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
150}
151
152void
153CcpRecvResetReq(fp)
154struct fsm *fp;
155{
156  Pred1Init(2);		/* Initialize Output part */
157}
158
159static void
160CcpLayerStart(fp)
161struct fsm *fp;
162{
163  LogPrintf(LOG_LCP_BIT, "%s: LayerStart.\n", fp->name);
164}
165
166static void
167CcpLayerFinish(fp)
168struct fsm *fp;
169{
170  LogPrintf(LOG_LCP_BIT, "%s: LayerFinish.\n", fp->name);
171}
172
173static void
174CcpLayerDown(fp)
175struct fsm *fp;
176{
177  LogPrintf(LOG_LCP_BIT, "%s: LayerDown.\n", fp->name);
178}
179
180/*
181 *  Called when CCP has reached to OPEN state
182 */
183static void
184CcpLayerUp(fp)
185struct fsm *fp;
186{
187#ifdef VERBOSE
188  fprintf(stderr, "%s: LayerUp(%d).\r\n", fp->name, fp->state);
189#endif
190  LogPrintf(LOG_LCP_BIT, "%s: LayerUp.\n", fp->name);
191  LogPrintf(LOG_LCP_BIT, "myproto = %d, hisproto = %d\n",
192	CcpInfo.want_proto, CcpInfo.his_proto);
193  Pred1Init(3);		/* Initialize Input and Output */
194}
195
196void
197CcpUp()
198{
199  FsmUp(&CcpFsm);
200  LogPrintf(LOG_LCP_BIT, "CCP Up event!!\n");
201}
202
203void
204CcpOpen()
205{
206  if (Enabled(ConfPred1))
207    FsmOpen(&CcpFsm);
208}
209
210static void
211CcpDecodeConfig(cp, plen, mode)
212u_char *cp;
213int plen;
214int mode;
215{
216  int type, length;
217  char tbuff[100];
218
219  ackp = AckBuff;
220  nakp = NakBuff;
221  rejp = RejBuff;
222
223  while (plen >= sizeof(struct fsmconfig)) {
224    if (plen < 0)
225      break;
226    type = *cp;
227    length = cp[1];
228    if (type <= TY_BSD)
229      snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
230    else
231      snprintf(tbuff, sizeof(tbuff), " ");
232
233    LogPrintf(LOG_LCP_BIT, "%s\n", tbuff);
234
235    switch (type) {
236    case TY_PRED1:
237      switch (mode) {
238      case MODE_REQ:
239	if (Acceptable(ConfPred1)) {
240	  bcopy(cp, ackp, length);
241	  ackp += length;
242	  CcpInfo.his_proto = type;
243	} else {
244	  bcopy(cp, rejp, length);
245	  rejp += length;
246	}
247	break;
248      case MODE_NAK:
249      case MODE_REJ:
250	CcpInfo.his_reject |= (1 << type);
251	CcpInfo.want_proto = 0;
252	break;
253      }
254      break;
255    case TY_BSD:
256    default:
257      CcpInfo.my_reject |= (1 << type);
258      bcopy(cp, rejp, length);
259      rejp += length;
260      break;
261    }
262    plen -= length;
263    cp += length;
264  }
265}
266
267void
268CcpInput(struct mbuf *bp)
269{
270  if (phase == PHASE_NETWORK)
271    FsmInput(&CcpFsm, bp);
272  else {
273    logprintf("ccp in phase %d\n", phase);
274    pfree(bp);
275  }
276}
277