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