xref: /freebsd/usr.sbin/ppp/ipcp.c (revision 9780ef311da5ca37faea2cb23bcb7d2cf0dc96e9)
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  *
209780ef31SBrian Somers  * $Id: ipcp.c,v 1.33 1997/10/29 01:19:40 brian Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *	TODO:
23af57ed9fSAtsushi Murai  *		o More RFC1772 backwoard compatibility
24af57ed9fSAtsushi Murai  */
2575240ed1SBrian Somers #include <sys/param.h>
265b4c5b00SBrian Somers #include <netinet/in_systm.h>
275b4c5b00SBrian Somers #include <netinet/in.h>
285b4c5b00SBrian Somers #include <netinet/ip.h>
295b4c5b00SBrian Somers #include <arpa/inet.h>
305b4c5b00SBrian Somers #include <sys/socket.h>
3175240ed1SBrian Somers #include <netdb.h>
3275240ed1SBrian Somers 
335b4c5b00SBrian Somers #include <limits.h>
3475240ed1SBrian Somers #include <stdio.h>
3575240ed1SBrian Somers #include <string.h>
3675240ed1SBrian Somers #include <unistd.h>
3775240ed1SBrian Somers 
3875240ed1SBrian Somers #include "mbuf.h"
3975240ed1SBrian Somers #include "log.h"
4075240ed1SBrian Somers #include "defs.h"
4175240ed1SBrian Somers #include "timer.h"
42af57ed9fSAtsushi Murai #include "fsm.h"
43af57ed9fSAtsushi Murai #include "lcpproto.h"
44af57ed9fSAtsushi Murai #include "lcp.h"
45af57ed9fSAtsushi Murai #include "ipcp.h"
46af57ed9fSAtsushi Murai #include "slcompress.h"
47af57ed9fSAtsushi Murai #include "os.h"
48af57ed9fSAtsushi Murai #include "phase.h"
496ed9fb2fSBrian Somers #include "loadalias.h"
5075240ed1SBrian Somers #include "command.h"
51af57ed9fSAtsushi Murai #include "vars.h"
5275240ed1SBrian Somers #include "vjcomp.h"
536eaa6ac5SBrian Somers #include "ip.h"
54af57ed9fSAtsushi Murai 
55927145beSBrian Somers #ifndef NOMSEXT
5675240ed1SBrian Somers struct in_addr ns_entries[2];
5775240ed1SBrian Somers struct in_addr nbns_entries[2];
58927145beSBrian Somers #endif
59d8e55738SJordan K. Hubbard 
6075240ed1SBrian Somers struct ipcpstate IpcpInfo;
6175240ed1SBrian Somers struct in_range  DefMyAddress;
6275240ed1SBrian Somers struct in_range  DefHisAddress;
6375240ed1SBrian Somers struct in_addr   TriggerAddress;
6475240ed1SBrian Somers int HaveTriggerAddress;
6575240ed1SBrian Somers struct pppTimer IpcpReportTimer;
6675240ed1SBrian Somers 
67927145beSBrian Somers static void IpcpSendConfigReq(struct fsm *);
68927145beSBrian Somers static void IpcpSendTerminateAck(struct fsm *);
69927145beSBrian Somers static void IpcpSendTerminateReq(struct fsm *);
70927145beSBrian Somers static void IpcpDecodeConfig(u_char *, int, int);
71927145beSBrian Somers static void IpcpLayerStart(struct fsm *);
72927145beSBrian Somers static void IpcpLayerFinish(struct fsm *);
73927145beSBrian Somers static void IpcpLayerUp(struct fsm *);
74927145beSBrian Somers static void IpcpLayerDown(struct fsm *);
75927145beSBrian Somers static void IpcpInitRestartCounter(struct fsm *);
7675240ed1SBrian Somers static int  IpcpOctetsIn(void);
7775240ed1SBrian Somers static int  IpcpOctetsOut(void);
78af57ed9fSAtsushi Murai 
79af57ed9fSAtsushi Murai static int lastInOctets, lastOutOctets;
805b4c5b00SBrian Somers static int StartingIpIn, StartingIpOut;
81af57ed9fSAtsushi Murai 
82af57ed9fSAtsushi Murai #define	REJECTED(p, x)	(p->his_reject & (1<<x))
83af57ed9fSAtsushi Murai 
84af57ed9fSAtsushi Murai struct fsm IpcpFsm = {
85af57ed9fSAtsushi Murai   "IPCP",
86af57ed9fSAtsushi Murai   PROTO_IPCP,
87af57ed9fSAtsushi Murai   IPCP_MAXCODE,
88af57ed9fSAtsushi Murai   OPEN_ACTIVE,
89af57ed9fSAtsushi Murai   ST_INITIAL,
90af57ed9fSAtsushi Murai   0, 0, 0,
91af57ed9fSAtsushi Murai 
92af57ed9fSAtsushi Murai   0,
93af57ed9fSAtsushi Murai   {0, 0, 0, NULL, NULL, NULL},
94cb611434SBrian Somers   {0, 0, 0, NULL, NULL, NULL},
95cb611434SBrian Somers   LogIPCP,
96af57ed9fSAtsushi Murai 
97af57ed9fSAtsushi Murai   IpcpLayerUp,
98af57ed9fSAtsushi Murai   IpcpLayerDown,
99af57ed9fSAtsushi Murai   IpcpLayerStart,
100af57ed9fSAtsushi Murai   IpcpLayerFinish,
101af57ed9fSAtsushi Murai   IpcpInitRestartCounter,
102af57ed9fSAtsushi Murai   IpcpSendConfigReq,
103af57ed9fSAtsushi Murai   IpcpSendTerminateReq,
104af57ed9fSAtsushi Murai   IpcpSendTerminateAck,
105af57ed9fSAtsushi Murai   IpcpDecodeConfig,
106af57ed9fSAtsushi Murai };
107af57ed9fSAtsushi Murai 
108af57ed9fSAtsushi Murai static char *cftypes[] = {
109af57ed9fSAtsushi Murai   "???", "IPADDRS", "COMPPROTO", "IPADDR",
110af57ed9fSAtsushi Murai };
111af57ed9fSAtsushi Murai 
112af57ed9fSAtsushi Murai /*
113af57ed9fSAtsushi Murai  * Function called every second. Updates connection period and idle period,
114af57ed9fSAtsushi Murai  * also update LQR information.
115af57ed9fSAtsushi Murai  */
116af57ed9fSAtsushi Murai static void
117af57ed9fSAtsushi Murai IpcpReportFunc()
118af57ed9fSAtsushi Murai {
119af57ed9fSAtsushi Murai   ipConnectSecs++;
120af57ed9fSAtsushi Murai   if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets)
121af57ed9fSAtsushi Murai     ipIdleSecs++;
122af57ed9fSAtsushi Murai   lastInOctets = ipInOctets;
123af57ed9fSAtsushi Murai   lastOutOctets = ipOutOctets;
124af57ed9fSAtsushi Murai   StopTimer(&IpcpReportTimer);
125af57ed9fSAtsushi Murai   IpcpReportTimer.state = TIMER_STOPPED;
126af57ed9fSAtsushi Murai   StartTimer(&IpcpReportTimer);
127af57ed9fSAtsushi Murai }
128af57ed9fSAtsushi Murai 
129af57ed9fSAtsushi Murai static void
130af57ed9fSAtsushi Murai IpcpStartReport()
131af57ed9fSAtsushi Murai {
132af57ed9fSAtsushi Murai   ipIdleSecs = ipConnectSecs = 0;
133af57ed9fSAtsushi Murai   StopTimer(&IpcpReportTimer);
134af57ed9fSAtsushi Murai   IpcpReportTimer.state = TIMER_STOPPED;
135af57ed9fSAtsushi Murai   IpcpReportTimer.load = SECTICKS;
136af57ed9fSAtsushi Murai   IpcpReportTimer.func = IpcpReportFunc;
137af57ed9fSAtsushi Murai   StartTimer(&IpcpReportTimer);
138af57ed9fSAtsushi Murai }
139af57ed9fSAtsushi Murai 
140274e766cSBrian Somers int
141af57ed9fSAtsushi Murai ReportIpcpStatus()
142af57ed9fSAtsushi Murai {
143af57ed9fSAtsushi Murai   struct ipcpstate *icp = &IpcpInfo;
144af57ed9fSAtsushi Murai   struct fsm *fp = &IpcpFsm;
145af57ed9fSAtsushi Murai 
146927145beSBrian Somers   if (!VarTerm)
147290281edSAndrey A. Chernov     return 1;
148927145beSBrian Somers   fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
149927145beSBrian Somers   fprintf(VarTerm, " his side: %s, %lx\n",
150927145beSBrian Somers 	  inet_ntoa(icp->his_ipaddr), icp->his_compproto);
151927145beSBrian Somers   fprintf(VarTerm, " my  side: %s, %lx\n",
152927145beSBrian Somers 	  inet_ntoa(icp->want_ipaddr), icp->want_compproto);
1535b4c5b00SBrian Somers   fprintf(VarTerm, "Connected: %d secs, idle: %d secs\n\n",
1545b4c5b00SBrian Somers 	  ipConnectSecs, ipIdleSecs);
1555b4c5b00SBrian Somers   fprintf(VarTerm, " %d octets in, %d octets out\n",
1565b4c5b00SBrian Somers 	  IpcpOctetsIn(), IpcpOctetsOut());
1575b4c5b00SBrian Somers 
158927145beSBrian Somers   fprintf(VarTerm, "Defaults:\n");
159927145beSBrian Somers   fprintf(VarTerm, " My Address:  %s/%d\n",
160927145beSBrian Somers 	  inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
161927145beSBrian Somers   fprintf(VarTerm, " His Address: %s/%d\n",
162927145beSBrian Somers 	  inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
1633f6fd923SBrian Somers   if (HaveTriggerAddress)
1643f6fd923SBrian Somers     fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress));
1653f6fd923SBrian Somers   else
1663f6fd923SBrian Somers     fprintf(VarTerm, " Negotiation(trigger): MYADDR\n");
167927145beSBrian Somers 
168927145beSBrian Somers   return 0;
169af57ed9fSAtsushi Murai }
170af57ed9fSAtsushi Murai 
171af57ed9fSAtsushi Murai void
172af57ed9fSAtsushi Murai IpcpDefAddress()
173af57ed9fSAtsushi Murai {
174af57ed9fSAtsushi Murai   struct hostent *hp;
175af57ed9fSAtsushi Murai   char name[200];
176af57ed9fSAtsushi Murai 
17775240ed1SBrian Somers   memset(&DefMyAddress, '\0', sizeof(DefMyAddress));
17875240ed1SBrian Somers   memset(&DefHisAddress, '\0', sizeof(DefHisAddress));
1793f6fd923SBrian Somers   TriggerAddress.s_addr = 0;
1803f6fd923SBrian Somers   HaveTriggerAddress = 0;
181af57ed9fSAtsushi Murai   if (gethostname(name, sizeof(name)) == 0) {
182af57ed9fSAtsushi Murai     hp = gethostbyname(name);
183af57ed9fSAtsushi Murai     if (hp && hp->h_addrtype == AF_INET) {
18475240ed1SBrian Somers       memcpy(&DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length);
185af57ed9fSAtsushi Murai     }
186af57ed9fSAtsushi Murai   }
187af57ed9fSAtsushi Murai }
188af57ed9fSAtsushi Murai 
189af57ed9fSAtsushi Murai void
190af57ed9fSAtsushi Murai IpcpInit()
191af57ed9fSAtsushi Murai {
192af57ed9fSAtsushi Murai   struct ipcpstate *icp = &IpcpInfo;
193af57ed9fSAtsushi Murai 
194af57ed9fSAtsushi Murai   FsmInit(&IpcpFsm);
19575240ed1SBrian Somers   memset(icp, '\0', sizeof(struct ipcpstate));
196af57ed9fSAtsushi Murai   if ((mode & MODE_DEDICATED) && !dstsystem) {
197af57ed9fSAtsushi Murai     icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
198af57ed9fSAtsushi Murai   } else {
199af57ed9fSAtsushi Murai     icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
200af57ed9fSAtsushi Murai     icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
201af57ed9fSAtsushi Murai   }
202549d663dSAtsushi Murai 
203549d663dSAtsushi Murai   /*
2045b4c5b00SBrian Somers    * Some implementations of PPP require that we send a
2055b4c5b00SBrian Somers    * *special* value as our address, even though the rfc specifies
2065b4c5b00SBrian Somers    * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
207549d663dSAtsushi Murai    */
2083f6fd923SBrian Somers   if (HaveTriggerAddress) {
2093f6fd923SBrian Somers     icp->want_ipaddr.s_addr = TriggerAddress.s_addr;
210cb611434SBrian Somers     LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress));
211549d663dSAtsushi Murai   }
212af57ed9fSAtsushi Murai   if (Enabled(ConfVjcomp))
213ee5c6273SBrian Somers     icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8) | 1;
214af57ed9fSAtsushi Murai   else
215af57ed9fSAtsushi Murai     icp->want_compproto = 0;
216af57ed9fSAtsushi Murai   icp->heis1172 = 0;
217af57ed9fSAtsushi Murai   IpcpFsm.maxconfig = 10;
2185b4c5b00SBrian Somers   StartingIpIn = ipInOctets;
2195b4c5b00SBrian Somers   StartingIpOut = ipOutOctets;
220af57ed9fSAtsushi Murai }
221af57ed9fSAtsushi Murai 
222af57ed9fSAtsushi Murai static void
223944f7098SBrian Somers IpcpInitRestartCounter(struct fsm * fp)
224af57ed9fSAtsushi Murai {
22553c9f6c0SAtsushi Murai   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
226af57ed9fSAtsushi Murai   fp->restart = 5;
227af57ed9fSAtsushi Murai }
228af57ed9fSAtsushi Murai 
229af57ed9fSAtsushi Murai static void
230944f7098SBrian Somers IpcpSendConfigReq(struct fsm * fp)
231af57ed9fSAtsushi Murai {
232af57ed9fSAtsushi Murai   u_char *cp;
233af57ed9fSAtsushi Murai   struct ipcpstate *icp = &IpcpInfo;
234af57ed9fSAtsushi Murai 
235af57ed9fSAtsushi Murai   cp = ReqBuff;
236cb611434SBrian Somers   LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
23753c9f6c0SAtsushi Murai   if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR))
238af57ed9fSAtsushi Murai     PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr));
239af57ed9fSAtsushi Murai   if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
240af57ed9fSAtsushi Murai     if (icp->heis1172)
241af57ed9fSAtsushi Murai       PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16);
242af57ed9fSAtsushi Murai     else
243af57ed9fSAtsushi Murai       PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
244af57ed9fSAtsushi Murai   }
245af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
246af57ed9fSAtsushi Murai }
247af57ed9fSAtsushi Murai 
248af57ed9fSAtsushi Murai static void
249944f7098SBrian Somers IpcpSendTerminateReq(struct fsm * fp)
250af57ed9fSAtsushi Murai {
251af57ed9fSAtsushi Murai   /* XXX: No code yet */
252af57ed9fSAtsushi Murai }
253af57ed9fSAtsushi Murai 
254af57ed9fSAtsushi Murai static void
255944f7098SBrian Somers IpcpSendTerminateAck(struct fsm * fp)
256af57ed9fSAtsushi Murai {
257cb611434SBrian Somers   LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
258af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
259af57ed9fSAtsushi Murai }
260af57ed9fSAtsushi Murai 
261af57ed9fSAtsushi Murai static void
262944f7098SBrian Somers IpcpLayerStart(struct fsm * fp)
263af57ed9fSAtsushi Murai {
264cb611434SBrian Somers   LogPrintf(LogIPCP, "IpcpLayerStart.\n");
265af57ed9fSAtsushi Murai }
266af57ed9fSAtsushi Murai 
267af57ed9fSAtsushi Murai static void
268944f7098SBrian Somers IpcpLayerFinish(struct fsm * fp)
269af57ed9fSAtsushi Murai {
270cb611434SBrian Somers   LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
27125aa96acSBrian Somers   reconnect(RECON_FALSE);
272af57ed9fSAtsushi Murai   LcpClose();
273af57ed9fSAtsushi Murai   NewPhase(PHASE_TERMINATE);
274af57ed9fSAtsushi Murai }
275af57ed9fSAtsushi Murai 
27675240ed1SBrian Somers static int
2775b4c5b00SBrian Somers IpcpOctetsIn()
2785b4c5b00SBrian Somers {
2795b4c5b00SBrian Somers   return ipInOctets < StartingIpIn ?
2805b4c5b00SBrian Somers     INT_MAX - StartingIpIn + ipInOctets - INT_MIN + 1 :
2815b4c5b00SBrian Somers     ipInOctets - StartingIpIn;
2825b4c5b00SBrian Somers }
2835b4c5b00SBrian Somers 
28475240ed1SBrian Somers static int
2855b4c5b00SBrian Somers IpcpOctetsOut()
2865b4c5b00SBrian Somers {
2875b4c5b00SBrian Somers   return ipOutOctets < StartingIpOut ?
2885b4c5b00SBrian Somers     INT_MAX - StartingIpOut + ipOutOctets - INT_MIN + 1 :
2895b4c5b00SBrian Somers     ipOutOctets - StartingIpOut;
2905b4c5b00SBrian Somers }
2915b4c5b00SBrian Somers 
292af57ed9fSAtsushi Murai static void
293944f7098SBrian Somers IpcpLayerDown(struct fsm * fp)
294af57ed9fSAtsushi Murai {
295cb611434SBrian Somers   LogPrintf(LogIPCP, "IpcpLayerDown.\n");
2965b4c5b00SBrian Somers   LogPrintf(LogIPCP, "%d octets in, %d octets out\n",
2975b4c5b00SBrian Somers 	    IpcpOctetsIn(), IpcpOctetsOut());
298af57ed9fSAtsushi Murai   StopTimer(&IpcpReportTimer);
2990fe7ca31SBrian Somers   Prompt();
300af57ed9fSAtsushi Murai }
301af57ed9fSAtsushi Murai 
302af57ed9fSAtsushi Murai /*
303af57ed9fSAtsushi Murai  *  Called when IPCP has reached to OPEN state
304af57ed9fSAtsushi Murai  */
305af57ed9fSAtsushi Murai static void
306944f7098SBrian Somers IpcpLayerUp(struct fsm * fp)
307af57ed9fSAtsushi Murai {
308af57ed9fSAtsushi Murai   char tbuff[100];
309af57ed9fSAtsushi Murai 
310274e766cSBrian Somers   Prompt();
311cb611434SBrian Somers   LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
31299c02d39SWarner Losh   snprintf(tbuff, sizeof(tbuff), "myaddr = %s ",
31399c02d39SWarner Losh 	   inet_ntoa(IpcpInfo.want_ipaddr));
31403604f35SBrian Somers 
31503604f35SBrian Somers   if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP)
31603604f35SBrian Somers     VjInit((IpcpInfo.his_compproto >> 8) & 255);
31703604f35SBrian Somers 
318cb611434SBrian Somers   LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
319927145beSBrian Somers 	    tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
320274e766cSBrian Somers   if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask) < 0) {
321927145beSBrian Somers     if (VarTerm)
322927145beSBrian Somers       LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
323274e766cSBrian Somers     return;
324274e766cSBrian Somers   }
3254eb8b164SBrian Somers   if (mode & MODE_ALIAS)
326944f7098SBrian Somers     VarPacketAliasSetAddress(IpcpInfo.want_ipaddr);
327af57ed9fSAtsushi Murai   OsLinkup();
3285b4c5b00SBrian Somers   StartingIpIn = ipInOctets;
3295b4c5b00SBrian Somers   StartingIpOut = ipOutOctets;
330af57ed9fSAtsushi Murai   IpcpStartReport();
331af57ed9fSAtsushi Murai   StartIdleTimer();
332af57ed9fSAtsushi Murai }
333af57ed9fSAtsushi Murai 
334af57ed9fSAtsushi Murai void
335af57ed9fSAtsushi Murai IpcpUp()
336af57ed9fSAtsushi Murai {
337af57ed9fSAtsushi Murai   FsmUp(&IpcpFsm);
338cb611434SBrian Somers   LogPrintf(LogIPCP, "IPCP Up event!!\n");
339af57ed9fSAtsushi Murai }
340af57ed9fSAtsushi Murai 
341af57ed9fSAtsushi Murai void
342af57ed9fSAtsushi Murai IpcpOpen()
343af57ed9fSAtsushi Murai {
344af57ed9fSAtsushi Murai   FsmOpen(&IpcpFsm);
345af57ed9fSAtsushi Murai }
346af57ed9fSAtsushi Murai 
347af57ed9fSAtsushi Murai static int
348944f7098SBrian Somers AcceptableAddr(struct in_range * prange, struct in_addr ipaddr)
349af57ed9fSAtsushi Murai {
350afc7fa2cSBrian Somers   LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr));
351afc7fa2cSBrian Somers   LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr));
352927145beSBrian Somers   LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
353927145beSBrian Somers   LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
354927145beSBrian Somers 		  mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
355057df964SBrian Somers   return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
356057df964SBrian Somers     (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
357af57ed9fSAtsushi Murai }
358af57ed9fSAtsushi Murai 
359af57ed9fSAtsushi Murai static void
3609780ef31SBrian Somers IpcpDecodeConfig(u_char * cp, int plen, int mode_type)
361af57ed9fSAtsushi Murai {
36253c9f6c0SAtsushi Murai   int type, length;
363af57ed9fSAtsushi Murai   u_long *lp, compproto;
364af57ed9fSAtsushi Murai   struct compreq *pcomp;
365d8e55738SJordan K. Hubbard   struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
366af57ed9fSAtsushi Murai   char tbuff[100];
36799c02d39SWarner Losh   char tbuff2[100];
368af57ed9fSAtsushi Murai 
369af57ed9fSAtsushi Murai   ackp = AckBuff;
370af57ed9fSAtsushi Murai   nakp = NakBuff;
371af57ed9fSAtsushi Murai   rejp = RejBuff;
372af57ed9fSAtsushi Murai 
373af57ed9fSAtsushi Murai   while (plen >= sizeof(struct fsmconfig)) {
374af57ed9fSAtsushi Murai     type = *cp;
375af57ed9fSAtsushi Murai     length = cp[1];
376af57ed9fSAtsushi Murai     if (type <= TY_IPADDR)
37799c02d39SWarner Losh       snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
378af57ed9fSAtsushi Murai     else
37999c02d39SWarner Losh       snprintf(tbuff, sizeof(tbuff), " ");
380af57ed9fSAtsushi Murai 
381af57ed9fSAtsushi Murai     switch (type) {
382af57ed9fSAtsushi Murai     case TY_IPADDR:		/* RFC1332 */
383af57ed9fSAtsushi Murai       lp = (u_long *) (cp + 2);
384af57ed9fSAtsushi Murai       ipaddr.s_addr = *lp;
385cb611434SBrian Somers       LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
386af57ed9fSAtsushi Murai 
3879780ef31SBrian Somers       switch (mode_type) {
388af57ed9fSAtsushi Murai       case MODE_REQ:
389af57ed9fSAtsushi Murai 	if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
390af57ed9fSAtsushi Murai 	  /*
391944f7098SBrian Somers 	   * If destination address is not acceptable, insist to use what we
392944f7098SBrian Somers 	   * want to use.
393af57ed9fSAtsushi Murai 	   */
39475240ed1SBrian Somers 	  memcpy(nakp, cp, 2);
39575240ed1SBrian Somers 	  memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length);
396af57ed9fSAtsushi Murai 	  nakp += length;
397af57ed9fSAtsushi Murai 	  break;
398af57ed9fSAtsushi Murai 	}
399af57ed9fSAtsushi Murai 	IpcpInfo.his_ipaddr = ipaddr;
40075240ed1SBrian Somers 	memcpy(ackp, cp, length);
401af57ed9fSAtsushi Murai 	ackp += length;
402af57ed9fSAtsushi Murai 	break;
403af57ed9fSAtsushi Murai       case MODE_NAK:
404af57ed9fSAtsushi Murai 	if (AcceptableAddr(&DefMyAddress, ipaddr)) {
405944f7098SBrian Somers 
406af57ed9fSAtsushi Murai 	  /*
407af57ed9fSAtsushi Murai 	   * Use address suggested by peer.
408af57ed9fSAtsushi Murai 	   */
409afc7fa2cSBrian Somers 	  snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff,
410afc7fa2cSBrian Somers 		   inet_ntoa(IpcpInfo.want_ipaddr));
411cb611434SBrian Somers 	  LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
412af57ed9fSAtsushi Murai 	  IpcpInfo.want_ipaddr = ipaddr;
413af57ed9fSAtsushi Murai 	}
414af57ed9fSAtsushi Murai 	break;
415af57ed9fSAtsushi Murai       case MODE_REJ:
416af57ed9fSAtsushi Murai 	IpcpInfo.his_reject |= (1 << type);
417af57ed9fSAtsushi Murai 	break;
418af57ed9fSAtsushi Murai       }
419af57ed9fSAtsushi Murai       break;
420af57ed9fSAtsushi Murai     case TY_COMPPROTO:
421af57ed9fSAtsushi Murai       lp = (u_long *) (cp + 2);
422af57ed9fSAtsushi Murai       compproto = htonl(*lp);
423cb611434SBrian Somers       LogPrintf(LogIPCP, "%s %08x\n", tbuff, compproto);
424af57ed9fSAtsushi Murai 
4259780ef31SBrian Somers       switch (mode_type) {
426af57ed9fSAtsushi Murai       case MODE_REQ:
427af57ed9fSAtsushi Murai 	if (!Acceptable(ConfVjcomp)) {
42875240ed1SBrian Somers 	  memcpy(rejp, cp, length);
429af57ed9fSAtsushi Murai 	  rejp += length;
430af57ed9fSAtsushi Murai 	} else {
431af57ed9fSAtsushi Murai 	  pcomp = (struct compreq *) (cp + 2);
432af57ed9fSAtsushi Murai 	  switch (length) {
433af57ed9fSAtsushi Murai 	  case 4:		/* RFC1172 */
434af57ed9fSAtsushi Murai 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
4354ef16f24SBrian Somers 	      LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
436af57ed9fSAtsushi Murai 	      IpcpInfo.heis1172 = 1;
437af57ed9fSAtsushi Murai 	      IpcpInfo.his_compproto = compproto;
43875240ed1SBrian Somers 	      memcpy(ackp, cp, length);
439af57ed9fSAtsushi Murai 	      ackp += length;
440af57ed9fSAtsushi Murai 	    } else {
44175240ed1SBrian Somers 	      memcpy(nakp, cp, 2);
442af57ed9fSAtsushi Murai 	      pcomp->proto = htons(PROTO_VJCOMP);
44375240ed1SBrian Somers 	      memcpy(nakp+2, &pcomp, 2);
444af57ed9fSAtsushi Murai 	      nakp += length;
445af57ed9fSAtsushi Murai 	    }
446af57ed9fSAtsushi Murai 	    break;
447af57ed9fSAtsushi Murai 	  case 6:		/* RFC1332 */
448af57ed9fSAtsushi Murai 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
449af57ed9fSAtsushi Murai 		&& pcomp->slots < MAX_STATES && pcomp->slots > 2) {
450af57ed9fSAtsushi Murai 	      IpcpInfo.his_compproto = compproto;
451af57ed9fSAtsushi Murai 	      IpcpInfo.heis1172 = 0;
45275240ed1SBrian Somers 	      memcpy(ackp, cp, length);
453af57ed9fSAtsushi Murai 	      ackp += length;
454af57ed9fSAtsushi Murai 	    } else {
45575240ed1SBrian Somers 	      memcpy(nakp, cp, 2);
456af57ed9fSAtsushi Murai 	      pcomp->proto = htons(PROTO_VJCOMP);
457af57ed9fSAtsushi Murai 	      pcomp->slots = MAX_STATES - 1;
458af57ed9fSAtsushi Murai 	      pcomp->compcid = 0;
45975240ed1SBrian Somers 	      memcpy(nakp+2, &pcomp, sizeof(pcomp));
460af57ed9fSAtsushi Murai 	      nakp += length;
461af57ed9fSAtsushi Murai 	    }
462af57ed9fSAtsushi Murai 	    break;
463af57ed9fSAtsushi Murai 	  default:
46475240ed1SBrian Somers 	    memcpy(rejp, cp, length);
465af57ed9fSAtsushi Murai 	    rejp += length;
466af57ed9fSAtsushi Murai 	    break;
467af57ed9fSAtsushi Murai 	  }
468af57ed9fSAtsushi Murai 	}
469af57ed9fSAtsushi Murai 	break;
470af57ed9fSAtsushi Murai       case MODE_NAK:
471cb611434SBrian Somers 	LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
472af57ed9fSAtsushi Murai 		  tbuff, IpcpInfo.want_compproto, compproto);
473af57ed9fSAtsushi Murai 	IpcpInfo.want_compproto = compproto;
474af57ed9fSAtsushi Murai 	break;
475af57ed9fSAtsushi Murai       case MODE_REJ:
476af57ed9fSAtsushi Murai 	IpcpInfo.his_reject |= (1 << type);
477af57ed9fSAtsushi Murai 	break;
478af57ed9fSAtsushi Murai       }
479af57ed9fSAtsushi Murai       break;
480af57ed9fSAtsushi Murai     case TY_IPADDRS:		/* RFC1172 */
481af57ed9fSAtsushi Murai       lp = (u_long *) (cp + 2);
482af57ed9fSAtsushi Murai       ipaddr.s_addr = *lp;
483af57ed9fSAtsushi Murai       lp = (u_long *) (cp + 6);
484af57ed9fSAtsushi Murai       dstipaddr.s_addr = *lp;
485afc7fa2cSBrian Somers       snprintf(tbuff2, sizeof(tbuff2), "%s %s,", tbuff, inet_ntoa(ipaddr));
486afc7fa2cSBrian Somers       LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
487af57ed9fSAtsushi Murai 
4889780ef31SBrian Somers       switch (mode_type) {
489af57ed9fSAtsushi Murai       case MODE_REQ:
490af57ed9fSAtsushi Murai 	IpcpInfo.his_ipaddr = ipaddr;
491af57ed9fSAtsushi Murai 	IpcpInfo.want_ipaddr = dstipaddr;
49275240ed1SBrian Somers 	memcpy(ackp, cp, length);
493af57ed9fSAtsushi Murai 	ackp += length;
494af57ed9fSAtsushi Murai 	break;
495af57ed9fSAtsushi Murai       case MODE_NAK:
496afc7fa2cSBrian Somers         snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s", tbuff,
497afc7fa2cSBrian Somers 		 inet_ntoa(IpcpInfo.want_ipaddr));
498afc7fa2cSBrian Somers 	LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
499af57ed9fSAtsushi Murai 	IpcpInfo.want_ipaddr = ipaddr;
500af57ed9fSAtsushi Murai 	IpcpInfo.his_ipaddr = dstipaddr;
501af57ed9fSAtsushi Murai 	break;
502af57ed9fSAtsushi Murai       case MODE_REJ:
503af57ed9fSAtsushi Murai 	IpcpInfo.his_reject |= (1 << type);
504af57ed9fSAtsushi Murai 	break;
505af57ed9fSAtsushi Murai       }
506af57ed9fSAtsushi Murai       break;
507d8e55738SJordan K. Hubbard 
508d8e55738SJordan K. Hubbard       /*
509d8e55738SJordan K. Hubbard        * MS extensions for MS's PPP
510d8e55738SJordan K. Hubbard        */
511d8e55738SJordan K. Hubbard 
512927145beSBrian Somers #ifndef NOMSEXT
513d8e55738SJordan K. Hubbard     case TY_PRIMARY_DNS:	/* MS PPP DNS negotiation hack */
514d8e55738SJordan K. Hubbard     case TY_SECONDARY_DNS:
515d8e55738SJordan K. Hubbard       if (!Enabled(ConfMSExt)) {
516cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
517d8e55738SJordan K. Hubbard 	IpcpInfo.my_reject |= (1 << type);
51875240ed1SBrian Somers 	memcpy(rejp, cp, length);
519d8e55738SJordan K. Hubbard 	rejp += length;
520d8e55738SJordan K. Hubbard 	break;
521d8e55738SJordan K. Hubbard       }
5229780ef31SBrian Somers       switch (mode_type) {
523d8e55738SJordan K. Hubbard       case MODE_REQ:
524d8e55738SJordan K. Hubbard 	lp = (u_long *) (cp + 2);
525d8e55738SJordan K. Hubbard 	dnsstuff.s_addr = *lp;
526d8e55738SJordan K. Hubbard 	ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS) ? 1 : 0)].s_addr;
527944f7098SBrian Somers 	if (dnsstuff.s_addr != ms_info_req.s_addr) {
528944f7098SBrian Somers 
529d8e55738SJordan K. Hubbard 	  /*
530944f7098SBrian Somers 	   * So the client has got the DNS stuff wrong (first request) so
531afc7fa2cSBrian Somers 	   * we'll tell 'em how it is
532d8e55738SJordan K. Hubbard 	   */
53375240ed1SBrian Somers 	  memcpy(nakp, cp, 2);	/* copy first two (type/length) */
534cb611434SBrian Somers 	  LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n",
535d8e55738SJordan K. Hubbard 		    type,
536d8e55738SJordan K. Hubbard 		    inet_ntoa(dnsstuff),
537d8e55738SJordan K. Hubbard 		    inet_ntoa(ms_info_req));
53875240ed1SBrian Somers 	  memcpy(nakp+2, &ms_info_req, length);
539d8e55738SJordan K. Hubbard 	  nakp += length;
540d8e55738SJordan K. Hubbard 	  break;
541d8e55738SJordan K. Hubbard 	}
542944f7098SBrian Somers 
543d8e55738SJordan K. Hubbard 	/*
544944f7098SBrian Somers 	 * Otherwise they have it right (this time) so we send a ack packet
545944f7098SBrian Somers 	 * back confirming it... end of story
546d8e55738SJordan K. Hubbard 	 */
547cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n",
548d8e55738SJordan K. Hubbard 		  type,
549d8e55738SJordan K. Hubbard 		  inet_ntoa(ms_info_req));
55075240ed1SBrian Somers 	memcpy(ackp, cp, length);
551d8e55738SJordan K. Hubbard 	ackp += length;
552d8e55738SJordan K. Hubbard 	break;
553d8e55738SJordan K. Hubbard       case MODE_NAK:		/* what does this mean?? */
554cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type);
555d8e55738SJordan K. Hubbard 	break;
556d8e55738SJordan K. Hubbard       case MODE_REJ:		/* confused?? me to :) */
557cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type);
558d8e55738SJordan K. Hubbard 	break;
559d8e55738SJordan K. Hubbard       }
560d8e55738SJordan K. Hubbard       break;
561d8e55738SJordan K. Hubbard 
562d8e55738SJordan K. Hubbard     case TY_PRIMARY_NBNS:	/* MS PPP NetBIOS nameserver hack */
563d8e55738SJordan K. Hubbard     case TY_SECONDARY_NBNS:
564d8e55738SJordan K. Hubbard       if (!Enabled(ConfMSExt)) {
565cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n");
566d8e55738SJordan K. Hubbard 	IpcpInfo.my_reject |= (1 << type);
56775240ed1SBrian Somers 	memcpy(rejp, cp, length);
568d8e55738SJordan K. Hubbard 	rejp += length;
569d8e55738SJordan K. Hubbard 	break;
570d8e55738SJordan K. Hubbard       }
5719780ef31SBrian Somers       switch (mode_type) {
572d8e55738SJordan K. Hubbard       case MODE_REQ:
573d8e55738SJordan K. Hubbard 	lp = (u_long *) (cp + 2);
574d8e55738SJordan K. Hubbard 	dnsstuff.s_addr = *lp;
575d8e55738SJordan K. Hubbard 	ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS) ? 1 : 0)].s_addr;
576944f7098SBrian Somers 	if (dnsstuff.s_addr != ms_info_req.s_addr) {
57775240ed1SBrian Somers 	  memcpy(nakp, cp, 2);
57875240ed1SBrian Somers 	  memcpy(nakp+2, &ms_info_req.s_addr, length);
579cb611434SBrian Somers 	  LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
580d8e55738SJordan K. Hubbard 		    type,
581d8e55738SJordan K. Hubbard 		    inet_ntoa(dnsstuff),
582d8e55738SJordan K. Hubbard 		    inet_ntoa(ms_info_req));
583d8e55738SJordan K. Hubbard 	  nakp += length;
584d8e55738SJordan K. Hubbard 	  break;
585d8e55738SJordan K. Hubbard 	}
586cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
587d8e55738SJordan K. Hubbard 		  type,
588d8e55738SJordan K. Hubbard 		  inet_ntoa(ms_info_req));
58975240ed1SBrian Somers 	memcpy(ackp, cp, length);
590d8e55738SJordan K. Hubbard 	ackp += length;
591d8e55738SJordan K. Hubbard 	break;
592d8e55738SJordan K. Hubbard       case MODE_NAK:
593cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
594d8e55738SJordan K. Hubbard 	break;
595d8e55738SJordan K. Hubbard       case MODE_REJ:
596cb611434SBrian Somers 	LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
597d8e55738SJordan K. Hubbard 	break;
598d8e55738SJordan K. Hubbard       }
599d8e55738SJordan K. Hubbard       break;
600d8e55738SJordan K. Hubbard 
601927145beSBrian Somers #endif
602d8e55738SJordan K. Hubbard 
603af57ed9fSAtsushi Murai     default:
604af57ed9fSAtsushi Murai       IpcpInfo.my_reject |= (1 << type);
60575240ed1SBrian Somers       memcpy(rejp, cp, length);
606af57ed9fSAtsushi Murai       rejp += length;
607af57ed9fSAtsushi Murai       break;
608af57ed9fSAtsushi Murai     }
609af57ed9fSAtsushi Murai     plen -= length;
610af57ed9fSAtsushi Murai     cp += length;
611af57ed9fSAtsushi Murai   }
612af57ed9fSAtsushi Murai }
613af57ed9fSAtsushi Murai 
614af57ed9fSAtsushi Murai void
615af57ed9fSAtsushi Murai IpcpInput(struct mbuf * bp)
616af57ed9fSAtsushi Murai {
617af57ed9fSAtsushi Murai   FsmInput(&IpcpFsm, bp);
618af57ed9fSAtsushi Murai }
619