xref: /freebsd/usr.sbin/ppp/ccp.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
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.12 1997/05/26 00:43:56 brian 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 "loadalias.h"
31 #include "vars.h"
32 #include "pred.h"
33 
34 struct ccpstate CcpInfo;
35 
36 static void CcpSendConfigReq(struct fsm *);
37 static void CcpSendTerminateReq(struct fsm *fp);
38 static void CcpSendTerminateAck(struct fsm *fp);
39 static void CcpDecodeConfig(u_char *cp, int flen, int mode);
40 static void CcpLayerStart(struct fsm *);
41 static void CcpLayerFinish(struct fsm *);
42 static void CcpLayerUp(struct fsm *);
43 static void CcpLayerDown(struct fsm *);
44 static void CcpInitRestartCounter(struct fsm *);
45 
46 #define	REJECTED(p, x)	(p->his_reject & (1<<x))
47 
48 struct 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 
70 static 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 
79 int
80 ReportCcpStatus()
81 {
82   struct ccpstate *icp = &CcpInfo;
83   struct fsm *fp = &CcpFsm;
84 
85   if (VarTerm) {
86     fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
87     fprintf(VarTerm, "myproto = %s, hisproto = %s\n",
88 	    cftypes[icp->want_proto], cftypes[icp->his_proto]);
89     fprintf(VarTerm, "Input: %ld --> %ld,  Output: %ld --> %ld\n",
90 	    icp->orgin, icp->compin, icp->orgout, icp->compout);
91   }
92   return 0;
93 }
94 
95 void
96 CcpInit()
97 {
98   struct ccpstate *icp = &CcpInfo;
99 
100   FsmInit(&CcpFsm);
101   bzero(icp, sizeof(struct ccpstate));
102   if (Enabled(ConfPred1))
103     icp->want_proto = TY_PRED1;
104   CcpFsm.maxconfig = 10;
105 }
106 
107 static void
108 CcpInitRestartCounter(fp)
109 struct fsm *fp;
110 {
111   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
112   fp->restart = 5;
113 }
114 
115 static void
116 CcpSendConfigReq(fp)
117 struct fsm *fp;
118 {
119   u_char *cp;
120   struct ccpstate *icp = &CcpInfo;
121 
122   cp = ReqBuff;
123   LogPrintf(LogLCP, "CcpSendConfigReq\n");
124   if (icp->want_proto && !REJECTED(icp, TY_PRED1)) {
125     *cp++ = TY_PRED1; *cp++ = 2;
126   }
127   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
128 }
129 
130 void
131 CcpSendResetReq(fp)
132 struct fsm *fp;
133 {
134   Pred1Init(1);		/* Initialize Input part */
135   LogPrintf(LogLCP, "CcpSendResetReq\n");
136   FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
137 }
138 
139 static void
140 CcpSendTerminateReq(fp)
141 struct fsm *fp;
142 {
143   /* XXX: No code yet */
144 }
145 
146 static void
147 CcpSendTerminateAck(fp)
148 struct fsm *fp;
149 {
150   LogPrintf(LogLCP, "CcpSendTerminateAck\n");
151   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
152 }
153 
154 void
155 CcpRecvResetReq(fp)
156 struct fsm *fp;
157 {
158   Pred1Init(2);		/* Initialize Output part */
159 }
160 
161 static void
162 CcpLayerStart(fp)
163 struct fsm *fp;
164 {
165   LogPrintf(LogLCP, "CcpLayerStart.\n");
166 }
167 
168 static void
169 CcpLayerFinish(fp)
170 struct fsm *fp;
171 {
172   LogPrintf(LogLCP, "CcpLayerFinish.\n");
173 }
174 
175 static void
176 CcpLayerDown(fp)
177 struct fsm *fp;
178 {
179   LogPrintf(LogLCP, "CcpLayerDown.\n");
180 }
181 
182 /*
183  *  Called when CCP has reached to OPEN state
184  */
185 static void
186 CcpLayerUp(fp)
187 struct fsm *fp;
188 {
189   LogPrintf(LogLCP, "CcpLayerUp(%d).\n", fp->state);
190   LogPrintf(LogLCP, "myproto = %d, hisproto = %d\n",
191 	CcpInfo.want_proto, CcpInfo.his_proto);
192   Pred1Init(3);		/* Initialize Input and Output */
193 }
194 
195 void
196 CcpUp()
197 {
198   FsmUp(&CcpFsm);
199   LogPrintf(LogLCP, "CCP Up event!!\n");
200 }
201 
202 void
203 CcpOpen()
204 {
205   if (Enabled(ConfPred1))
206     FsmOpen(&CcpFsm);
207 }
208 
209 static void
210 CcpDecodeConfig(cp, plen, mode)
211 u_char *cp;
212 int plen;
213 int mode;
214 {
215   int type, length;
216   char tbuff[100];
217 
218   ackp = AckBuff;
219   nakp = NakBuff;
220   rejp = RejBuff;
221 
222   while (plen >= sizeof(struct fsmconfig)) {
223     if (plen < 0)
224       break;
225     type = *cp;
226     length = cp[1];
227     if (type <= TY_BSD)
228       snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
229     else
230       snprintf(tbuff, sizeof(tbuff), " ");
231 
232     LogPrintf(LogLCP, "%s\n", tbuff);
233 
234     switch (type) {
235     case TY_PRED1:
236       switch (mode) {
237       case MODE_REQ:
238 	if (Acceptable(ConfPred1)) {
239 	  bcopy(cp, ackp, length);
240 	  ackp += length;
241 	  CcpInfo.his_proto = type;
242 	} else {
243 	  bcopy(cp, rejp, length);
244 	  rejp += length;
245 	}
246 	break;
247       case MODE_NAK:
248       case MODE_REJ:
249 	CcpInfo.his_reject |= (1 << type);
250 	CcpInfo.want_proto = 0;
251 	break;
252       }
253       break;
254     case TY_BSD:
255     default:
256       CcpInfo.my_reject |= (1 << type);
257       bcopy(cp, rejp, length);
258       rejp += length;
259       break;
260     }
261     plen -= length;
262     cp += length;
263   }
264 }
265 
266 void
267 CcpInput(struct mbuf *bp)
268 {
269   if (phase == PHASE_NETWORK)
270     FsmInput(&CcpFsm, bp);
271   else {
272     LogPrintf(LogERROR, "Unexpected CCP in phase %d\n", phase);
273     pfree(bp);
274   }
275 }
276