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