xref: /freebsd/usr.sbin/ppp/ccp.c (revision 02f2e93b60c2b91feac8f45c4c889a5a8e40d8a2)
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.16 1997/09/10 21:33:31 brian Exp $
21  *
22  *	TODO:
23  *		o Support other compression protocols
24  */
25 #include <sys/param.h>
26 #include <netinet/in.h>
27 
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "mbuf.h"
32 #include "log.h"
33 #include "defs.h"
34 #include "timer.h"
35 #include "fsm.h"
36 #include "lcpproto.h"
37 #include "lcp.h"
38 #include "ccp.h"
39 #include "phase.h"
40 #include "loadalias.h"
41 #include "command.h"
42 #include "vars.h"
43 #include "pred.h"
44 
45 struct ccpstate CcpInfo;
46 
47 static void CcpSendConfigReq(struct fsm *);
48 static void CcpSendTerminateReq(struct fsm *);
49 static void CcpSendTerminateAck(struct fsm *);
50 static void CcpDecodeConfig(u_char *, int, int);
51 static void CcpLayerStart(struct fsm *);
52 static void CcpLayerFinish(struct fsm *);
53 static void CcpLayerUp(struct fsm *);
54 static void CcpLayerDown(struct fsm *);
55 static void CcpInitRestartCounter(struct fsm *);
56 
57 #define	REJECTED(p, x)	(p->his_reject & (1<<x))
58 
59 struct fsm CcpFsm = {
60   "CCP",
61   PROTO_CCP,
62   CCP_MAXCODE,
63   OPEN_ACTIVE,
64   ST_INITIAL,
65   0, 0, 0,
66   0,
67   {0, 0, 0, NULL, NULL, NULL},
68   {0, 0, 0, NULL, NULL, NULL},
69   LogCCP,
70 
71   CcpLayerUp,
72   CcpLayerDown,
73   CcpLayerStart,
74   CcpLayerFinish,
75   CcpInitRestartCounter,
76   CcpSendConfigReq,
77   CcpSendTerminateReq,
78   CcpSendTerminateAck,
79   CcpDecodeConfig,
80 };
81 
82 static char const *cftypes[] = {
83    /*  0 */ "OUI", "PRED1", "PRED2", "PUDDLE",
84    /*  4 */ "???", "???", "???", "???",
85    /*  8 */ "???", "???", "???", "???",
86    /* 12 */ "???", "???", "???", "???",
87    /* 16 */ "HWPPC", "STAC", "MSPPC", "GAND",
88    /* 20 */ "V42BIS", "BSD",
89 };
90 
91 int
92 ReportCcpStatus()
93 {
94   struct ccpstate *icp = &CcpInfo;
95   struct fsm *fp = &CcpFsm;
96 
97   if (VarTerm) {
98     fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
99     fprintf(VarTerm, "myproto = %s, hisproto = %s\n",
100 	    cftypes[icp->want_proto], cftypes[icp->his_proto]);
101     fprintf(VarTerm, "Input: %ld --> %ld,  Output: %ld --> %ld\n",
102 	    icp->orgin, icp->compin, icp->orgout, icp->compout);
103   }
104   return 0;
105 }
106 
107 void
108 CcpInit()
109 {
110   struct ccpstate *icp = &CcpInfo;
111 
112   FsmInit(&CcpFsm);
113   memset(icp, '\0', sizeof(struct ccpstate));
114   if (Enabled(ConfPred1))
115     icp->want_proto = TY_PRED1;
116   CcpFsm.maxconfig = 10;
117 }
118 
119 static void
120 CcpInitRestartCounter(struct fsm *fp)
121 {
122   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
123   fp->restart = 5;
124 }
125 
126 static void
127 CcpSendConfigReq(struct fsm *fp)
128 {
129   u_char *cp;
130   struct ccpstate *icp = &CcpInfo;
131 
132   cp = ReqBuff;
133   LogPrintf(LogCCP, "CcpSendConfigReq\n");
134   if (icp->want_proto && !REJECTED(icp, TY_PRED1)) {
135     *cp++ = TY_PRED1;
136     *cp++ = 2;
137   }
138   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
139 }
140 
141 void
142 CcpSendResetReq(struct fsm *fp)
143 {
144   LogPrintf(LogCCP, "CcpSendResetReq\n");
145   FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
146 }
147 
148 static void
149 CcpSendTerminateReq(struct fsm *fp)
150 {
151   /* XXX: No code yet */
152 }
153 
154 static void
155 CcpSendTerminateAck(struct fsm *fp)
156 {
157   LogPrintf(LogCCP, "CcpSendTerminateAck\n");
158   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
159 }
160 
161 void
162 CcpRecvResetReq(struct fsm *fp)
163 {
164   Pred1Init(2);			/* Initialize Output part */
165 }
166 
167 static void
168 CcpLayerStart(struct fsm *fp)
169 {
170   LogPrintf(LogCCP, "CcpLayerStart.\n");
171 }
172 
173 static void
174 CcpLayerFinish(struct fsm *fp)
175 {
176   LogPrintf(LogCCP, "CcpLayerFinish.\n");
177 }
178 
179 static void
180 CcpLayerDown(struct fsm *fp)
181 {
182   LogPrintf(LogCCP, "CcpLayerDown.\n");
183 }
184 
185 /*
186  *  Called when CCP has reached to OPEN state
187  */
188 static void
189 CcpLayerUp(struct fsm *fp)
190 {
191   LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state);
192   LogPrintf(LogCCP, "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(LogCCP, "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(u_char *cp, int plen, int mode)
213 {
214   int type, length;
215   char tbuff[100];
216 
217   ackp = AckBuff;
218   nakp = NakBuff;
219   rejp = RejBuff;
220 
221   while (plen >= sizeof(struct fsmconfig)) {
222     if (plen < 0)
223       break;
224     type = *cp;
225     length = cp[1];
226     if (type <= TY_BSD)
227       snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
228     else
229       snprintf(tbuff, sizeof(tbuff), " ");
230 
231     LogPrintf(LogCCP, "%s\n", tbuff);
232 
233     switch (type) {
234     case TY_PRED1:
235       switch (mode) {
236       case MODE_REQ:
237 	if (Acceptable(ConfPred1)) {
238 	  memcpy(ackp, cp, length);
239 	  ackp += length;
240 	  CcpInfo.his_proto = type;
241 	} else {
242 	  memcpy(rejp, cp, length);
243 	  rejp += length;
244 	}
245 	break;
246       case MODE_NAK:
247       case MODE_REJ:
248 	CcpInfo.his_reject |= (1 << type);
249 	CcpInfo.want_proto = 0;
250 	break;
251       }
252       break;
253     case TY_BSD:
254     default:
255       CcpInfo.my_reject |= (1 << type);
256       memcpy(rejp, cp, length);
257       rejp += length;
258       break;
259     }
260     plen -= length;
261     cp += length;
262   }
263 }
264 
265 void
266 CcpInput(struct mbuf *bp)
267 {
268   if (phase == PHASE_NETWORK)
269     FsmInput(&CcpFsm, bp);
270   else {
271     if (phase > PHASE_NETWORK)
272       LogPrintf(LogERROR, "Unexpected CCP in phase %d\n", phase);
273     pfree(bp);
274   }
275 }
276