xref: /freebsd/usr.sbin/ppp/ipcp.c (revision af57ed9fdcc4e2a81940fc2243c0d3949fc0e00f)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *	PPP IP Control Protocol (IPCP) Module
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
20af57ed9fSAtsushi Murai  * $Id:$
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *	TODO:
23af57ed9fSAtsushi Murai  *		o More RFC1772 backwoard compatibility
24af57ed9fSAtsushi Murai  */
25af57ed9fSAtsushi Murai #include "fsm.h"
26af57ed9fSAtsushi Murai #include "lcpproto.h"
27af57ed9fSAtsushi Murai #include "lcp.h"
28af57ed9fSAtsushi Murai #include "ipcp.h"
29af57ed9fSAtsushi Murai #include <netdb.h>
30af57ed9fSAtsushi Murai #include <netinet/in_systm.h>
31af57ed9fSAtsushi Murai #include <netinet/ip.h>
32af57ed9fSAtsushi Murai #include <arpa/inet.h>
33af57ed9fSAtsushi Murai #include <sys/socket.h>
34af57ed9fSAtsushi Murai #include "slcompress.h"
35af57ed9fSAtsushi Murai #include "os.h"
36af57ed9fSAtsushi Murai #include "phase.h"
37af57ed9fSAtsushi Murai #include "vars.h"
38af57ed9fSAtsushi Murai 
39af57ed9fSAtsushi Murai extern void PutConfValue();
40af57ed9fSAtsushi Murai extern void Prompt();
41af57ed9fSAtsushi Murai extern struct in_addr ifnetmask;
42af57ed9fSAtsushi Murai 
43af57ed9fSAtsushi Murai struct ipcpstate IpcpInfo;
44af57ed9fSAtsushi Murai struct in_range DefMyAddress, DefHisAddress;
45af57ed9fSAtsushi Murai 
46af57ed9fSAtsushi Murai static void IpcpSendConfigReq(struct fsm *);
47af57ed9fSAtsushi Murai static void IpcpSendTerminateAck(struct fsm *);
48af57ed9fSAtsushi Murai static void IpcpSendTerminateReq(struct fsm *);
49af57ed9fSAtsushi Murai static void IpcpDecodeConfig();
50af57ed9fSAtsushi Murai static void IpcpLayerStart(struct fsm *);
51af57ed9fSAtsushi Murai static void IpcpLayerFinish(struct fsm *);
52af57ed9fSAtsushi Murai static void IpcpLayerUp(struct fsm *);
53af57ed9fSAtsushi Murai static void IpcpLayerDown(struct fsm *);
54af57ed9fSAtsushi Murai static void IpcpInitRestartCounter(struct fsm *);
55af57ed9fSAtsushi Murai 
56af57ed9fSAtsushi Murai static struct pppTimer IpcpReportTimer;
57af57ed9fSAtsushi Murai 
58af57ed9fSAtsushi Murai static int lastInOctets, lastOutOctets;
59af57ed9fSAtsushi Murai 
60af57ed9fSAtsushi Murai #define	REJECTED(p, x)	(p->his_reject & (1<<x))
61af57ed9fSAtsushi Murai 
62af57ed9fSAtsushi Murai struct fsm IpcpFsm = {
63af57ed9fSAtsushi Murai   "IPCP",
64af57ed9fSAtsushi Murai   PROTO_IPCP,
65af57ed9fSAtsushi Murai   IPCP_MAXCODE,
66af57ed9fSAtsushi Murai   OPEN_ACTIVE,
67af57ed9fSAtsushi Murai   ST_INITIAL,
68af57ed9fSAtsushi Murai   0, 0, 0,
69af57ed9fSAtsushi Murai 
70af57ed9fSAtsushi Murai   0,
71af57ed9fSAtsushi Murai   { 0, 0, 0, NULL, NULL, NULL },
72af57ed9fSAtsushi Murai 
73af57ed9fSAtsushi Murai   IpcpLayerUp,
74af57ed9fSAtsushi Murai   IpcpLayerDown,
75af57ed9fSAtsushi Murai   IpcpLayerStart,
76af57ed9fSAtsushi Murai   IpcpLayerFinish,
77af57ed9fSAtsushi Murai   IpcpInitRestartCounter,
78af57ed9fSAtsushi Murai   IpcpSendConfigReq,
79af57ed9fSAtsushi Murai   IpcpSendTerminateReq,
80af57ed9fSAtsushi Murai   IpcpSendTerminateAck,
81af57ed9fSAtsushi Murai   IpcpDecodeConfig,
82af57ed9fSAtsushi Murai };
83af57ed9fSAtsushi Murai 
84af57ed9fSAtsushi Murai static char *cftypes[] = {
85af57ed9fSAtsushi Murai   "???", "IPADDRS", "COMPPROTO", "IPADDR",
86af57ed9fSAtsushi Murai };
87af57ed9fSAtsushi Murai 
88af57ed9fSAtsushi Murai /*
89af57ed9fSAtsushi Murai  * Function called every second. Updates connection period and idle period,
90af57ed9fSAtsushi Murai  * also update LQR information.
91af57ed9fSAtsushi Murai  */
92af57ed9fSAtsushi Murai static void
93af57ed9fSAtsushi Murai IpcpReportFunc()
94af57ed9fSAtsushi Murai {
95af57ed9fSAtsushi Murai   ipConnectSecs++;
96af57ed9fSAtsushi Murai   if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets)
97af57ed9fSAtsushi Murai     ipIdleSecs++;
98af57ed9fSAtsushi Murai   lastInOctets = ipInOctets;
99af57ed9fSAtsushi Murai   lastOutOctets = ipOutOctets;
100af57ed9fSAtsushi Murai   StopTimer(&IpcpReportTimer);
101af57ed9fSAtsushi Murai   IpcpReportTimer.state = TIMER_STOPPED;
102af57ed9fSAtsushi Murai   StartTimer(&IpcpReportTimer);
103af57ed9fSAtsushi Murai }
104af57ed9fSAtsushi Murai 
105af57ed9fSAtsushi Murai static void
106af57ed9fSAtsushi Murai IpcpStartReport()
107af57ed9fSAtsushi Murai {
108af57ed9fSAtsushi Murai   ipIdleSecs = ipConnectSecs = 0;
109af57ed9fSAtsushi Murai   StopTimer(&IpcpReportTimer);
110af57ed9fSAtsushi Murai   IpcpReportTimer.state = TIMER_STOPPED;
111af57ed9fSAtsushi Murai   IpcpReportTimer.load = SECTICKS;
112af57ed9fSAtsushi Murai   IpcpReportTimer.func = IpcpReportFunc;
113af57ed9fSAtsushi Murai   StartTimer(&IpcpReportTimer);
114af57ed9fSAtsushi Murai }
115af57ed9fSAtsushi Murai 
116af57ed9fSAtsushi Murai void
117af57ed9fSAtsushi Murai ReportIpcpStatus()
118af57ed9fSAtsushi Murai {
119af57ed9fSAtsushi Murai   struct ipcpstate *icp = &IpcpInfo;
120af57ed9fSAtsushi Murai   struct fsm *fp = &IpcpFsm;
121af57ed9fSAtsushi Murai 
122af57ed9fSAtsushi Murai   printf("%s [%s]\n", fp->name, StateNames[fp->state]);
123af57ed9fSAtsushi Murai   printf(" his side: %s, %x\n",
124af57ed9fSAtsushi Murai      inet_ntoa(icp->his_ipaddr), icp->his_compproto);
125af57ed9fSAtsushi Murai   printf(" my  side: %s, %x\n",
126af57ed9fSAtsushi Murai      inet_ntoa(icp->want_ipaddr), icp->want_compproto);
127af57ed9fSAtsushi Murai   printf("connected: %d secs, idle: %d secs\n\n", ipConnectSecs, ipIdleSecs);
128af57ed9fSAtsushi Murai   printf("Defaults:  My Address: %s/%d  ",
129af57ed9fSAtsushi Murai      inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
130af57ed9fSAtsushi Murai   printf("His Address: %s/%d\n",
131af57ed9fSAtsushi Murai      inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
132af57ed9fSAtsushi Murai }
133af57ed9fSAtsushi Murai 
134af57ed9fSAtsushi Murai void
135af57ed9fSAtsushi Murai IpcpDefAddress()
136af57ed9fSAtsushi Murai {
137af57ed9fSAtsushi Murai   struct hostent *hp;
138af57ed9fSAtsushi Murai   char name[200];
139af57ed9fSAtsushi Murai 
140af57ed9fSAtsushi Murai   bzero(&DefMyAddress, sizeof(DefMyAddress));
141af57ed9fSAtsushi Murai   bzero(&DefHisAddress, sizeof(DefHisAddress));
142af57ed9fSAtsushi Murai   if (gethostname(name, sizeof(name)) == 0) {
143af57ed9fSAtsushi Murai       hp = gethostbyname(name);
144af57ed9fSAtsushi Murai       if (hp && hp->h_addrtype == AF_INET) {
145af57ed9fSAtsushi Murai 	bcopy(hp->h_addr, (char *)&DefMyAddress.ipaddr.s_addr, hp->h_length);
146af57ed9fSAtsushi Murai       }
147af57ed9fSAtsushi Murai   }
148af57ed9fSAtsushi Murai }
149af57ed9fSAtsushi Murai 
150af57ed9fSAtsushi Murai void
151af57ed9fSAtsushi Murai IpcpInit()
152af57ed9fSAtsushi Murai {
153af57ed9fSAtsushi Murai   struct ipcpstate *icp = &IpcpInfo;
154af57ed9fSAtsushi Murai 
155af57ed9fSAtsushi Murai   FsmInit(&IpcpFsm);
156af57ed9fSAtsushi Murai   bzero(icp, sizeof(struct ipcpstate));
157af57ed9fSAtsushi Murai   if ((mode & MODE_DEDICATED) && !dstsystem) {
158af57ed9fSAtsushi Murai     icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
159af57ed9fSAtsushi Murai   } else {
160af57ed9fSAtsushi Murai     icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
161af57ed9fSAtsushi Murai     icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
162af57ed9fSAtsushi Murai   }
163af57ed9fSAtsushi Murai   if (icp->want_ipaddr.s_addr == 0)
164af57ed9fSAtsushi Murai     icp->want_ipaddr.s_addr = htonl(0xc0000001);
165af57ed9fSAtsushi Murai   if (Enabled(ConfVjcomp))
166af57ed9fSAtsushi Murai     icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8);
167af57ed9fSAtsushi Murai   else
168af57ed9fSAtsushi Murai     icp->want_compproto = 0;
169af57ed9fSAtsushi Murai   icp->heis1172 = 0;
170af57ed9fSAtsushi Murai   IpcpFsm.maxconfig = 10;
171af57ed9fSAtsushi Murai }
172af57ed9fSAtsushi Murai 
173af57ed9fSAtsushi Murai static void
174af57ed9fSAtsushi Murai IpcpInitRestartCounter(fp)
175af57ed9fSAtsushi Murai struct fsm *fp;
176af57ed9fSAtsushi Murai {
177af57ed9fSAtsushi Murai   fp->FsmTimer.load = 3 * SECTICKS;
178af57ed9fSAtsushi Murai   fp->restart = 5;
179af57ed9fSAtsushi Murai }
180af57ed9fSAtsushi Murai 
181af57ed9fSAtsushi Murai static void
182af57ed9fSAtsushi Murai IpcpSendConfigReq(fp)
183af57ed9fSAtsushi Murai struct fsm *fp;
184af57ed9fSAtsushi Murai {
185af57ed9fSAtsushi Murai   u_char *cp;
186af57ed9fSAtsushi Murai   struct ipcpstate *icp = &IpcpInfo;
187af57ed9fSAtsushi Murai 
188af57ed9fSAtsushi Murai   cp = ReqBuff;
189af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, "%s: SendConfigReq\n", fp->name);
190af57ed9fSAtsushi Murai   PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr));
191af57ed9fSAtsushi Murai   if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
192af57ed9fSAtsushi Murai     if (icp->heis1172)
193af57ed9fSAtsushi Murai       PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16);
194af57ed9fSAtsushi Murai     else
195af57ed9fSAtsushi Murai       PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
196af57ed9fSAtsushi Murai   }
197af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
198af57ed9fSAtsushi Murai }
199af57ed9fSAtsushi Murai 
200af57ed9fSAtsushi Murai static void
201af57ed9fSAtsushi Murai IpcpSendTerminateReq(fp)
202af57ed9fSAtsushi Murai struct fsm *fp;
203af57ed9fSAtsushi Murai {
204af57ed9fSAtsushi Murai   /* XXX: No code yet */
205af57ed9fSAtsushi Murai }
206af57ed9fSAtsushi Murai 
207af57ed9fSAtsushi Murai static void
208af57ed9fSAtsushi Murai IpcpSendTerminateAck(fp)
209af57ed9fSAtsushi Murai struct fsm *fp;
210af57ed9fSAtsushi Murai {
211af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, "  %s: SendTerminateAck\n", fp->name);
212af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
213af57ed9fSAtsushi Murai }
214af57ed9fSAtsushi Murai 
215af57ed9fSAtsushi Murai static void
216af57ed9fSAtsushi Murai IpcpLayerStart(fp)
217af57ed9fSAtsushi Murai struct fsm *fp;
218af57ed9fSAtsushi Murai {
219af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, "%s: LayerStart.\n", fp->name);
220af57ed9fSAtsushi Murai }
221af57ed9fSAtsushi Murai 
222af57ed9fSAtsushi Murai static void
223af57ed9fSAtsushi Murai IpcpLayerFinish(fp)
224af57ed9fSAtsushi Murai struct fsm *fp;
225af57ed9fSAtsushi Murai {
226af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, "%s: LayerFinish.\n", fp->name);
227af57ed9fSAtsushi Murai   LcpClose();
228af57ed9fSAtsushi Murai   NewPhase(PHASE_TERMINATE);
229af57ed9fSAtsushi Murai }
230af57ed9fSAtsushi Murai 
231af57ed9fSAtsushi Murai static void
232af57ed9fSAtsushi Murai IpcpLayerDown(fp)
233af57ed9fSAtsushi Murai struct fsm *fp;
234af57ed9fSAtsushi Murai {
235af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, "%s: LayerDown.\n", fp->name);
236af57ed9fSAtsushi Murai   StopTimer(&IpcpReportTimer);
237af57ed9fSAtsushi Murai }
238af57ed9fSAtsushi Murai 
239af57ed9fSAtsushi Murai /*
240af57ed9fSAtsushi Murai  *  Called when IPCP has reached to OPEN state
241af57ed9fSAtsushi Murai  */
242af57ed9fSAtsushi Murai static void
243af57ed9fSAtsushi Murai IpcpLayerUp(fp)
244af57ed9fSAtsushi Murai struct fsm *fp;
245af57ed9fSAtsushi Murai {
246af57ed9fSAtsushi Murai   char tbuff[100];
247af57ed9fSAtsushi Murai 
248af57ed9fSAtsushi Murai #ifdef VERBOSE
249af57ed9fSAtsushi Murai   fprintf(stderr, "%s: LayerUp(%d).\r\n", fp->name, fp->state);
250af57ed9fSAtsushi Murai #endif
251af57ed9fSAtsushi Murai   Prompt(1);
252af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, "%s: LayerUp.\n", fp->name);
253af57ed9fSAtsushi Murai   sprintf(tbuff, "myaddr = %s ", inet_ntoa(IpcpInfo.want_ipaddr));
254af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
255af57ed9fSAtsushi Murai   OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask);
256af57ed9fSAtsushi Murai   OsLinkup();
257af57ed9fSAtsushi Murai   IpcpStartReport();
258af57ed9fSAtsushi Murai   StartIdleTimer();
259af57ed9fSAtsushi Murai }
260af57ed9fSAtsushi Murai 
261af57ed9fSAtsushi Murai void
262af57ed9fSAtsushi Murai IpcpUp()
263af57ed9fSAtsushi Murai {
264af57ed9fSAtsushi Murai   FsmUp(&IpcpFsm);
265af57ed9fSAtsushi Murai   LogPrintf(LOG_LCP, "IPCP Up event!!\n");
266af57ed9fSAtsushi Murai }
267af57ed9fSAtsushi Murai 
268af57ed9fSAtsushi Murai void
269af57ed9fSAtsushi Murai IpcpOpen()
270af57ed9fSAtsushi Murai {
271af57ed9fSAtsushi Murai   FsmOpen(&IpcpFsm);
272af57ed9fSAtsushi Murai }
273af57ed9fSAtsushi Murai 
274af57ed9fSAtsushi Murai static int
275af57ed9fSAtsushi Murai AcceptableAddr(prange, ipaddr)
276af57ed9fSAtsushi Murai struct in_range *prange;
277af57ed9fSAtsushi Murai struct in_addr ipaddr;
278af57ed9fSAtsushi Murai {
279af57ed9fSAtsushi Murai #ifdef DEBUG
280af57ed9fSAtsushi Murai   logprintf("requested = %x ", htonl(ipaddr.s_addr));
281af57ed9fSAtsushi Murai   logprintf("range = %x", htonl(prange->ipaddr.s_addr));
282af57ed9fSAtsushi Murai   logprintf("/%x\n", htonl(prange->mask.s_addr));
283af57ed9fSAtsushi Murai   logprintf("%x, %x\n", htonl(prange->ipaddr.s_addr & prange->mask.s_addr),
284af57ed9fSAtsushi Murai     htonl(ipaddr.s_addr & prange->mask.s_addr));
285af57ed9fSAtsushi Murai #endif
286af57ed9fSAtsushi Murai   return((prange->ipaddr.s_addr & prange->mask.s_addr) ==
287af57ed9fSAtsushi Murai 	(ipaddr.s_addr & prange->mask.s_addr));
288af57ed9fSAtsushi Murai }
289af57ed9fSAtsushi Murai 
290af57ed9fSAtsushi Murai static void
291af57ed9fSAtsushi Murai IpcpDecodeConfig(bp, mode)
292af57ed9fSAtsushi Murai struct mbuf *bp;
293af57ed9fSAtsushi Murai int mode;
294af57ed9fSAtsushi Murai {
295af57ed9fSAtsushi Murai   u_char *cp;
296af57ed9fSAtsushi Murai   int plen, type, length;
297af57ed9fSAtsushi Murai   u_long *lp, compproto;
298af57ed9fSAtsushi Murai   struct compreq *pcomp;
299af57ed9fSAtsushi Murai   struct in_addr ipaddr, dstipaddr;
300af57ed9fSAtsushi Murai   char tbuff[100];
301af57ed9fSAtsushi Murai 
302af57ed9fSAtsushi Murai   plen = plength(bp);
303af57ed9fSAtsushi Murai 
304af57ed9fSAtsushi Murai   cp = MBUF_CTOP(bp);
305af57ed9fSAtsushi Murai   ackp = AckBuff;
306af57ed9fSAtsushi Murai   nakp = NakBuff;
307af57ed9fSAtsushi Murai   rejp = RejBuff;
308af57ed9fSAtsushi Murai 
309af57ed9fSAtsushi Murai   while (plen >= sizeof(struct fsmconfig)) {
310af57ed9fSAtsushi Murai     if (plen < 0)
311af57ed9fSAtsushi Murai       break;
312af57ed9fSAtsushi Murai     type = *cp;
313af57ed9fSAtsushi Murai     length = cp[1];
314af57ed9fSAtsushi Murai     if (type <= TY_IPADDR)
315af57ed9fSAtsushi Murai       sprintf(tbuff, " %s[%d] ", cftypes[type], length);
316af57ed9fSAtsushi Murai     else
317af57ed9fSAtsushi Murai       sprintf(tbuff, " ");
318af57ed9fSAtsushi Murai 
319af57ed9fSAtsushi Murai     switch (type) {
320af57ed9fSAtsushi Murai     case TY_IPADDR:		/* RFC1332 */
321af57ed9fSAtsushi Murai       lp = (u_long *)(cp + 2);
322af57ed9fSAtsushi Murai       ipaddr.s_addr = *lp;
323af57ed9fSAtsushi Murai       LogPrintf(LOG_LCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
324af57ed9fSAtsushi Murai 
325af57ed9fSAtsushi Murai       switch (mode) {
326af57ed9fSAtsushi Murai       case MODE_REQ:
327af57ed9fSAtsushi Murai 	if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
328af57ed9fSAtsushi Murai           /*
329af57ed9fSAtsushi Murai            * If destination address is not acceptable, insist to use
330af57ed9fSAtsushi Murai            * what we want to use.
331af57ed9fSAtsushi Murai            */
332af57ed9fSAtsushi Murai 	  bcopy(cp, nakp, 2);
333af57ed9fSAtsushi Murai           bcopy(&IpcpInfo.his_ipaddr.s_addr, nakp+2, length);
334af57ed9fSAtsushi Murai           nakp += length;
335af57ed9fSAtsushi Murai           break;
336af57ed9fSAtsushi Murai 
337af57ed9fSAtsushi Murai 	}
338af57ed9fSAtsushi Murai 	IpcpInfo.his_ipaddr = ipaddr;
339af57ed9fSAtsushi Murai 	bcopy(cp, ackp, length);
340af57ed9fSAtsushi Murai 	ackp += length;
341af57ed9fSAtsushi Murai 	break;
342af57ed9fSAtsushi Murai       case MODE_NAK:
343af57ed9fSAtsushi Murai 	if (AcceptableAddr(&DefMyAddress, ipaddr)) {
344af57ed9fSAtsushi Murai           /*
345af57ed9fSAtsushi Murai            * Use address suggested by peer.
346af57ed9fSAtsushi Murai            */
347af57ed9fSAtsushi Murai 	  sprintf(tbuff+50, "%s changing address: %s ", tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
348af57ed9fSAtsushi Murai 	  LogPrintf(LOG_LCP, "%s --> %s\n", tbuff+50, inet_ntoa(ipaddr));
349af57ed9fSAtsushi Murai 	  IpcpInfo.want_ipaddr = ipaddr;
350af57ed9fSAtsushi Murai 	}
351af57ed9fSAtsushi Murai 	break;
352af57ed9fSAtsushi Murai       case MODE_REJ:
353af57ed9fSAtsushi Murai 	IpcpInfo.his_reject |= (1 << type);
354af57ed9fSAtsushi Murai 	break;
355af57ed9fSAtsushi Murai       }
356af57ed9fSAtsushi Murai       break;
357af57ed9fSAtsushi Murai     case TY_COMPPROTO:
358af57ed9fSAtsushi Murai       lp = (u_long *)(cp + 2);
359af57ed9fSAtsushi Murai       compproto = htonl(*lp);
360af57ed9fSAtsushi Murai       LogPrintf(LOG_LCP, "%s %08x\n", tbuff, compproto);
361af57ed9fSAtsushi Murai 
362af57ed9fSAtsushi Murai       switch (mode) {
363af57ed9fSAtsushi Murai       case MODE_REQ:
364af57ed9fSAtsushi Murai 	if (!Acceptable(ConfVjcomp)) {
365af57ed9fSAtsushi Murai 	  bcopy(cp, rejp, length);
366af57ed9fSAtsushi Murai 	  rejp += length;
367af57ed9fSAtsushi Murai 	} else {
368af57ed9fSAtsushi Murai 	  pcomp = (struct compreq *)(cp + 2);
369af57ed9fSAtsushi Murai 	  switch (length) {
370af57ed9fSAtsushi Murai 	  case 4:	/* RFC1172 */
371af57ed9fSAtsushi Murai 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
372af57ed9fSAtsushi Murai 	      logprintf("** Peer is speaking RFC1172 compression protocol **\n");
373af57ed9fSAtsushi Murai 	      IpcpInfo.heis1172 = 1;
374af57ed9fSAtsushi Murai 	      IpcpInfo.his_compproto = compproto;
375af57ed9fSAtsushi Murai 	      bcopy(cp, ackp, length);
376af57ed9fSAtsushi Murai 	      ackp += length;
377af57ed9fSAtsushi Murai 	    } else {
378af57ed9fSAtsushi Murai 	      bcopy(cp, nakp, 2);
379af57ed9fSAtsushi Murai 	      pcomp->proto = htons(PROTO_VJCOMP);
380af57ed9fSAtsushi Murai 	      bcopy(&pcomp, nakp + 2, 2);
381af57ed9fSAtsushi Murai 	      nakp += length;
382af57ed9fSAtsushi Murai 	    }
383af57ed9fSAtsushi Murai 	    break;
384af57ed9fSAtsushi Murai 	  case 6: 	/* RFC1332 */
385af57ed9fSAtsushi Murai 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
386af57ed9fSAtsushi Murai 	        && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
387af57ed9fSAtsushi Murai 	      IpcpInfo.his_compproto = compproto;
388af57ed9fSAtsushi Murai 	      IpcpInfo.heis1172 = 0;
389af57ed9fSAtsushi Murai 	      bcopy(cp, ackp, length);
390af57ed9fSAtsushi Murai 	      ackp += length;
391af57ed9fSAtsushi Murai 	    } else {
392af57ed9fSAtsushi Murai 	      bcopy(cp, nakp, 2);
393af57ed9fSAtsushi Murai 	      pcomp->proto = htons(PROTO_VJCOMP);
394af57ed9fSAtsushi Murai 	      pcomp->slots = MAX_STATES - 1;
395af57ed9fSAtsushi Murai 	      pcomp->compcid = 0;
396af57ed9fSAtsushi Murai 	      bcopy(&pcomp, nakp + 2, sizeof(pcomp));
397af57ed9fSAtsushi Murai 	      nakp += length;
398af57ed9fSAtsushi Murai 	    }
399af57ed9fSAtsushi Murai 	    break;
400af57ed9fSAtsushi Murai 	  default:
401af57ed9fSAtsushi Murai 	    bcopy(cp, rejp, length);
402af57ed9fSAtsushi Murai 	    rejp += length;
403af57ed9fSAtsushi Murai 	    break;
404af57ed9fSAtsushi Murai 	  }
405af57ed9fSAtsushi Murai 	}
406af57ed9fSAtsushi Murai 	break;
407af57ed9fSAtsushi Murai       case MODE_NAK:
408af57ed9fSAtsushi Murai 	LogPrintf(LOG_LCP, "%s changing compproto: %08x --> %08x\n",
409af57ed9fSAtsushi Murai 	  tbuff, IpcpInfo.want_compproto, compproto);
410af57ed9fSAtsushi Murai 	IpcpInfo.want_compproto = compproto;
411af57ed9fSAtsushi Murai 	break;
412af57ed9fSAtsushi Murai       case MODE_REJ:
413af57ed9fSAtsushi Murai 	IpcpInfo.his_reject |= (1 << type);
414af57ed9fSAtsushi Murai 	break;
415af57ed9fSAtsushi Murai       }
416af57ed9fSAtsushi Murai       break;
417af57ed9fSAtsushi Murai     case TY_IPADDRS:	/* RFC1172 */
418af57ed9fSAtsushi Murai       lp = (u_long *)(cp + 2);
419af57ed9fSAtsushi Murai       ipaddr.s_addr = *lp;
420af57ed9fSAtsushi Murai       lp = (u_long *)(cp + 6);
421af57ed9fSAtsushi Murai       dstipaddr.s_addr = *lp;
422af57ed9fSAtsushi Murai       LogPrintf(LOG_LCP, "%s %s, ", tbuff, inet_ntoa(ipaddr));
423af57ed9fSAtsushi Murai       LogPrintf(LOG_LCP, "%s\n", inet_ntoa(dstipaddr));
424af57ed9fSAtsushi Murai 
425af57ed9fSAtsushi Murai       switch (mode) {
426af57ed9fSAtsushi Murai       case MODE_REQ:
427af57ed9fSAtsushi Murai 	IpcpInfo.his_ipaddr = ipaddr;
428af57ed9fSAtsushi Murai 	IpcpInfo.want_ipaddr = dstipaddr;
429af57ed9fSAtsushi Murai 	bcopy(cp, ackp, length);
430af57ed9fSAtsushi Murai 	ackp += length;
431af57ed9fSAtsushi Murai 	break;
432af57ed9fSAtsushi Murai       case MODE_NAK:
433af57ed9fSAtsushi Murai 	LogPrintf(LOG_LCP, "%s changing address: %s ",
434af57ed9fSAtsushi Murai 	  tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
435af57ed9fSAtsushi Murai 	LogPrintf(LOG_LCP, "--> %s\n", inet_ntoa(ipaddr));
436af57ed9fSAtsushi Murai 	IpcpInfo.want_ipaddr = ipaddr;
437af57ed9fSAtsushi Murai 	IpcpInfo.his_ipaddr = dstipaddr;
438af57ed9fSAtsushi Murai 	break;
439af57ed9fSAtsushi Murai       case MODE_REJ:
440af57ed9fSAtsushi Murai 	IpcpInfo.his_reject |= (1 << type);
441af57ed9fSAtsushi Murai 	break;
442af57ed9fSAtsushi Murai       }
443af57ed9fSAtsushi Murai       break;
444af57ed9fSAtsushi Murai     default:
445af57ed9fSAtsushi Murai       IpcpInfo.my_reject |= (1 << type);
446af57ed9fSAtsushi Murai       bcopy(cp, rejp, length);
447af57ed9fSAtsushi Murai       rejp += length;
448af57ed9fSAtsushi Murai       break;
449af57ed9fSAtsushi Murai     }
450af57ed9fSAtsushi Murai     plen -= length;
451af57ed9fSAtsushi Murai     cp += length;
452af57ed9fSAtsushi Murai   }
453af57ed9fSAtsushi Murai }
454af57ed9fSAtsushi Murai 
455af57ed9fSAtsushi Murai void
456af57ed9fSAtsushi Murai IpcpInput(struct mbuf *bp)
457af57ed9fSAtsushi Murai {
458af57ed9fSAtsushi Murai   FsmInput(&IpcpFsm, bp);
459af57ed9fSAtsushi Murai }
460