Deleted Added
full compact
ipcp.c (31171) ipcp.c (31272)
1/*
2 * PPP IP Control Protocol (IPCP) Module
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, 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 *
1/*
2 * PPP IP Control Protocol (IPCP) Module
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, 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: ipcp.c,v 1.35 1997/11/11 22:58:11 brian Exp $
20 * $Id: ipcp.c,v 1.36 1997/11/14 15:39:14 brian Exp $
21 *
22 * TODO:
23 * o More RFC1772 backwoard compatibility
24 */
25#include <sys/param.h>
26#include <netinet/in_systm.h>
27#include <netinet/in.h>
28#include <netinet/ip.h>
29#include <arpa/inet.h>
30#include <sys/socket.h>
31#include <netdb.h>
32
33#include <limits.h>
34#include <stdio.h>
35#include <string.h>
21 *
22 * TODO:
23 * o More RFC1772 backwoard compatibility
24 */
25#include <sys/param.h>
26#include <netinet/in_systm.h>
27#include <netinet/in.h>
28#include <netinet/ip.h>
29#include <arpa/inet.h>
30#include <sys/socket.h>
31#include <netdb.h>
32
33#include <limits.h>
34#include <stdio.h>
35#include <string.h>
36#include <time.h>
36#include <unistd.h>
37
38#include "mbuf.h"
39#include "log.h"
40#include "defs.h"
41#include "timer.h"
42#include "fsm.h"
43#include "lcpproto.h"
44#include "lcp.h"
45#include "ipcp.h"
46#include "slcompress.h"
47#include "os.h"
48#include "phase.h"
49#include "loadalias.h"
50#include "command.h"
51#include "vars.h"
52#include "vjcomp.h"
53#include "ip.h"
37#include <unistd.h>
38
39#include "mbuf.h"
40#include "log.h"
41#include "defs.h"
42#include "timer.h"
43#include "fsm.h"
44#include "lcpproto.h"
45#include "lcp.h"
46#include "ipcp.h"
47#include "slcompress.h"
48#include "os.h"
49#include "phase.h"
50#include "loadalias.h"
51#include "command.h"
52#include "vars.h"
53#include "vjcomp.h"
54#include "ip.h"
55#include "throughput.h"
54
55#ifndef NOMSEXT
56struct in_addr ns_entries[2];
57struct in_addr nbns_entries[2];
58#endif
59
60struct ipcpstate IpcpInfo;
61struct in_range DefMyAddress;
62struct in_range DefHisAddress;
63struct in_addr TriggerAddress;
64int HaveTriggerAddress;
56
57#ifndef NOMSEXT
58struct in_addr ns_entries[2];
59struct in_addr nbns_entries[2];
60#endif
61
62struct ipcpstate IpcpInfo;
63struct in_range DefMyAddress;
64struct in_range DefHisAddress;
65struct in_addr TriggerAddress;
66int HaveTriggerAddress;
65struct pppTimer IpcpReportTimer;
66
67static void IpcpSendConfigReq(struct fsm *);
68static void IpcpSendTerminateAck(struct fsm *);
69static void IpcpSendTerminateReq(struct fsm *);
70static void IpcpDecodeConfig(u_char *, int, int);
71static void IpcpLayerStart(struct fsm *);
72static void IpcpLayerFinish(struct fsm *);
73static void IpcpLayerUp(struct fsm *);
74static void IpcpLayerDown(struct fsm *);
75static void IpcpInitRestartCounter(struct fsm *);
67
68static void IpcpSendConfigReq(struct fsm *);
69static void IpcpSendTerminateAck(struct fsm *);
70static void IpcpSendTerminateReq(struct fsm *);
71static void IpcpDecodeConfig(u_char *, int, int);
72static void IpcpLayerStart(struct fsm *);
73static void IpcpLayerFinish(struct fsm *);
74static void IpcpLayerUp(struct fsm *);
75static void IpcpLayerDown(struct fsm *);
76static void IpcpInitRestartCounter(struct fsm *);
76static int IpcpOctetsIn(void);
77static int IpcpOctetsOut(void);
78
77
79static int lastInOctets, lastOutOctets;
80static int StartingIpIn, StartingIpOut;
81
82#define REJECTED(p, x) (p->his_reject & (1<<x))
83
84struct fsm IpcpFsm = {
85 "IPCP",
86 PROTO_IPCP,
87 IPCP_MAXCODE,
88 OPEN_ACTIVE,
89 ST_INITIAL,
90 0, 0, 0,
91
92 0,
93 {0, 0, 0, NULL, NULL, NULL},
94 {0, 0, 0, NULL, NULL, NULL},
95 LogIPCP,
96
97 IpcpLayerUp,
98 IpcpLayerDown,
99 IpcpLayerStart,
100 IpcpLayerFinish,
101 IpcpInitRestartCounter,
102 IpcpSendConfigReq,
103 IpcpSendTerminateReq,
104 IpcpSendTerminateAck,
105 IpcpDecodeConfig,
106};
107
108static char *cftypes[] = {
109 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
110 "???",
111 "IPADDRS", /* 1: IP-Addresses */ /* deprecated */
112 "COMPPROTO", /* 2: IP-Compression-Protocol */
113 "IPADDR", /* 3: IP-Address */
114};
115
116#define NCFTYPES (sizeof(cftypes)/sizeof(char *))
117
118static char *cftypes128[] = {
119 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
120 "???",
121 "PRIDNS", /* 129: Primary DNS Server Address */
122 "PRINBNS", /* 130: Primary NBNS Server Address */
123 "SECDNS", /* 131: Secondary DNS Server Address */
124 "SECNBNS", /* 132: Secondary NBNS Server Address */
125};
126
127#define NCFTYPES128 (sizeof(cftypes)/sizeof(char *))
128
78#define REJECTED(p, x) (p->his_reject & (1<<x))
79
80struct fsm IpcpFsm = {
81 "IPCP",
82 PROTO_IPCP,
83 IPCP_MAXCODE,
84 OPEN_ACTIVE,
85 ST_INITIAL,
86 0, 0, 0,
87
88 0,
89 {0, 0, 0, NULL, NULL, NULL},
90 {0, 0, 0, NULL, NULL, NULL},
91 LogIPCP,
92
93 IpcpLayerUp,
94 IpcpLayerDown,
95 IpcpLayerStart,
96 IpcpLayerFinish,
97 IpcpInitRestartCounter,
98 IpcpSendConfigReq,
99 IpcpSendTerminateReq,
100 IpcpSendTerminateAck,
101 IpcpDecodeConfig,
102};
103
104static char *cftypes[] = {
105 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
106 "???",
107 "IPADDRS", /* 1: IP-Addresses */ /* deprecated */
108 "COMPPROTO", /* 2: IP-Compression-Protocol */
109 "IPADDR", /* 3: IP-Address */
110};
111
112#define NCFTYPES (sizeof(cftypes)/sizeof(char *))
113
114static char *cftypes128[] = {
115 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
116 "???",
117 "PRIDNS", /* 129: Primary DNS Server Address */
118 "PRINBNS", /* 130: Primary NBNS Server Address */
119 "SECDNS", /* 131: Secondary DNS Server Address */
120 "SECNBNS", /* 132: Secondary NBNS Server Address */
121};
122
123#define NCFTYPES128 (sizeof(cftypes)/sizeof(char *))
124
129/*
130 * Function called every second. Updates connection period and idle period,
131 * also update LQR information.
132 */
133static void
134IpcpReportFunc()
125struct pppThroughput throughput;
126
127void
128IpcpAddInOctets(int n)
135{
129{
136 ipConnectSecs++;
137 if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets)
138 ipIdleSecs++;
139 lastInOctets = ipInOctets;
140 lastOutOctets = ipOutOctets;
141 StopTimer(&IpcpReportTimer);
142 IpcpReportTimer.state = TIMER_STOPPED;
143 StartTimer(&IpcpReportTimer);
130 throughput_addin(&throughput, n);
144}
145
131}
132
146static void
147IpcpStartReport()
133void
134IpcpAddOutOctets(int n)
148{
135{
149 ipIdleSecs = ipConnectSecs = 0;
150 StopTimer(&IpcpReportTimer);
151 IpcpReportTimer.state = TIMER_STOPPED;
152 IpcpReportTimer.load = SECTICKS;
153 IpcpReportTimer.func = IpcpReportFunc;
154 StartTimer(&IpcpReportTimer);
136 throughput_addout(&throughput, n);
155}
156
157int
158ReportIpcpStatus()
159{
160 struct ipcpstate *icp = &IpcpInfo;
161 struct fsm *fp = &IpcpFsm;
162
163 if (!VarTerm)
164 return 1;
165 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
166 fprintf(VarTerm, " his side: %s, %lx\n",
167 inet_ntoa(icp->his_ipaddr), icp->his_compproto);
168 fprintf(VarTerm, " my side: %s, %lx\n",
169 inet_ntoa(icp->want_ipaddr), icp->want_compproto);
137}
138
139int
140ReportIpcpStatus()
141{
142 struct ipcpstate *icp = &IpcpInfo;
143 struct fsm *fp = &IpcpFsm;
144
145 if (!VarTerm)
146 return 1;
147 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
148 fprintf(VarTerm, " his side: %s, %lx\n",
149 inet_ntoa(icp->his_ipaddr), icp->his_compproto);
150 fprintf(VarTerm, " my side: %s, %lx\n",
151 inet_ntoa(icp->want_ipaddr), icp->want_compproto);
170 fprintf(VarTerm, "Connected: %d secs, idle: %d secs\n\n",
171 ipConnectSecs, ipIdleSecs);
172 fprintf(VarTerm, " %d octets in, %d octets out\n",
173 IpcpOctetsIn(), IpcpOctetsOut());
174
175 fprintf(VarTerm, "Defaults:\n");
176 fprintf(VarTerm, " My Address: %s/%d\n",
177 inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
178 fprintf(VarTerm, " His Address: %s/%d\n",
179 inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
180 if (HaveTriggerAddress)
181 fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress));
182 else
183 fprintf(VarTerm, " Negotiation(trigger): MYADDR\n");
184
152
153 fprintf(VarTerm, "Defaults:\n");
154 fprintf(VarTerm, " My Address: %s/%d\n",
155 inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
156 fprintf(VarTerm, " His Address: %s/%d\n",
157 inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
158 if (HaveTriggerAddress)
159 fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress));
160 else
161 fprintf(VarTerm, " Negotiation(trigger): MYADDR\n");
162
163 fprintf(VarTerm, "\n");
164 throughput_disp(&throughput, VarTerm);
165
185 return 0;
186}
187
188void
189IpcpDefAddress()
190{
191 struct hostent *hp;
192 char name[200];
193
194 memset(&DefMyAddress, '\0', sizeof(DefMyAddress));
195 memset(&DefHisAddress, '\0', sizeof(DefHisAddress));
196 TriggerAddress.s_addr = 0;
197 HaveTriggerAddress = 0;
198 if (gethostname(name, sizeof(name)) == 0) {
199 hp = gethostbyname(name);
200 if (hp && hp->h_addrtype == AF_INET) {
201 memcpy(&DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length);
202 }
203 }
204}
205
206void
207IpcpInit()
208{
209 struct ipcpstate *icp = &IpcpInfo;
210
211 FsmInit(&IpcpFsm);
212 memset(icp, '\0', sizeof(struct ipcpstate));
213 if ((mode & MODE_DEDICATED) && !GetLabel()) {
214 icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
215 } else {
216 icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
217 icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
218 }
219
220 /*
221 * Some implementations of PPP require that we send a
222 * *special* value as our address, even though the rfc specifies
223 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
224 */
225 if (HaveTriggerAddress) {
226 icp->want_ipaddr.s_addr = TriggerAddress.s_addr;
227 LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress));
228 }
229 if (Enabled(ConfVjcomp))
230 icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8) | 1;
231 else
232 icp->want_compproto = 0;
233 icp->heis1172 = 0;
234 IpcpFsm.maxconfig = 10;
166 return 0;
167}
168
169void
170IpcpDefAddress()
171{
172 struct hostent *hp;
173 char name[200];
174
175 memset(&DefMyAddress, '\0', sizeof(DefMyAddress));
176 memset(&DefHisAddress, '\0', sizeof(DefHisAddress));
177 TriggerAddress.s_addr = 0;
178 HaveTriggerAddress = 0;
179 if (gethostname(name, sizeof(name)) == 0) {
180 hp = gethostbyname(name);
181 if (hp && hp->h_addrtype == AF_INET) {
182 memcpy(&DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length);
183 }
184 }
185}
186
187void
188IpcpInit()
189{
190 struct ipcpstate *icp = &IpcpInfo;
191
192 FsmInit(&IpcpFsm);
193 memset(icp, '\0', sizeof(struct ipcpstate));
194 if ((mode & MODE_DEDICATED) && !GetLabel()) {
195 icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
196 } else {
197 icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
198 icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
199 }
200
201 /*
202 * Some implementations of PPP require that we send a
203 * *special* value as our address, even though the rfc specifies
204 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
205 */
206 if (HaveTriggerAddress) {
207 icp->want_ipaddr.s_addr = TriggerAddress.s_addr;
208 LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress));
209 }
210 if (Enabled(ConfVjcomp))
211 icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8) | 1;
212 else
213 icp->want_compproto = 0;
214 icp->heis1172 = 0;
215 IpcpFsm.maxconfig = 10;
235 StartingIpIn = ipInOctets;
236 StartingIpOut = ipOutOctets;
216 throughput_init(&throughput);
237}
238
239static void
240IpcpInitRestartCounter(struct fsm * fp)
241{
242 fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
243 fp->restart = 5;
244}
245
246static void
247IpcpSendConfigReq(struct fsm * fp)
248{
249 u_char *cp;
250 struct ipcpstate *icp = &IpcpInfo;
251
252 cp = ReqBuff;
253 LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
254 if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR))
255 PutConfValue(LogIPCP, &cp, cftypes, TY_IPADDR, 6,
256 ntohl(icp->want_ipaddr.s_addr));
257 if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
258 if (icp->heis1172)
259 PutConfValue(LogIPCP, &cp, cftypes, TY_COMPPROTO, 4,
260 icp->want_compproto >> 16);
261 else
262 PutConfValue(LogIPCP, &cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
263 }
264 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
265}
266
267static void
268IpcpSendTerminateReq(struct fsm * fp)
269{
270 /* XXX: No code yet */
271}
272
273static void
274IpcpSendTerminateAck(struct fsm * fp)
275{
276 LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
277 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
278}
279
280static void
281IpcpLayerStart(struct fsm * fp)
282{
283 LogPrintf(LogIPCP, "IpcpLayerStart.\n");
284}
285
286static void
287IpcpLayerFinish(struct fsm * fp)
288{
289 LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
290 reconnect(RECON_FALSE);
291 LcpClose();
292 NewPhase(PHASE_TERMINATE);
293}
294
217}
218
219static void
220IpcpInitRestartCounter(struct fsm * fp)
221{
222 fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
223 fp->restart = 5;
224}
225
226static void
227IpcpSendConfigReq(struct fsm * fp)
228{
229 u_char *cp;
230 struct ipcpstate *icp = &IpcpInfo;
231
232 cp = ReqBuff;
233 LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
234 if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR))
235 PutConfValue(LogIPCP, &cp, cftypes, TY_IPADDR, 6,
236 ntohl(icp->want_ipaddr.s_addr));
237 if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
238 if (icp->heis1172)
239 PutConfValue(LogIPCP, &cp, cftypes, TY_COMPPROTO, 4,
240 icp->want_compproto >> 16);
241 else
242 PutConfValue(LogIPCP, &cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
243 }
244 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
245}
246
247static void
248IpcpSendTerminateReq(struct fsm * fp)
249{
250 /* XXX: No code yet */
251}
252
253static void
254IpcpSendTerminateAck(struct fsm * fp)
255{
256 LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
257 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
258}
259
260static void
261IpcpLayerStart(struct fsm * fp)
262{
263 LogPrintf(LogIPCP, "IpcpLayerStart.\n");
264}
265
266static void
267IpcpLayerFinish(struct fsm * fp)
268{
269 LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
270 reconnect(RECON_FALSE);
271 LcpClose();
272 NewPhase(PHASE_TERMINATE);
273}
274
295static int
296IpcpOctetsIn()
297{
298 return ipInOctets < StartingIpIn ?
299 INT_MAX - StartingIpIn + ipInOctets - INT_MIN + 1 :
300 ipInOctets - StartingIpIn;
301}
302
303static int
304IpcpOctetsOut()
305{
306 return ipOutOctets < StartingIpOut ?
307 INT_MAX - StartingIpOut + ipOutOctets - INT_MIN + 1 :
308 ipOutOctets - StartingIpOut;
309}
310
311static void
312IpcpLayerDown(struct fsm * fp)
313{
314 LogPrintf(LogIPCP, "IpcpLayerDown.\n");
275static void
276IpcpLayerDown(struct fsm * fp)
277{
278 LogPrintf(LogIPCP, "IpcpLayerDown.\n");
315 LogPrintf(LogIPCP, "%d octets in, %d octets out\n",
316 IpcpOctetsIn(), IpcpOctetsOut());
317 StopTimer(&IpcpReportTimer);
318 Prompt();
279 throughput_stop(&throughput);
280 throughput_log(&throughput, LogIPCP, NULL);
319}
320
321/*
322 * Called when IPCP has reached to OPEN state
323 */
324static void
325IpcpLayerUp(struct fsm * fp)
326{
327 char tbuff[100];
328
329 Prompt();
330 LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
331 snprintf(tbuff, sizeof(tbuff), "myaddr = %s ",
332 inet_ntoa(IpcpInfo.want_ipaddr));
333
334 if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP)
335 VjInit((IpcpInfo.his_compproto >> 8) & 255);
336
337 LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
338 tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
339 if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask) < 0) {
340 if (VarTerm)
341 LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
342 return;
343 }
344 if (mode & MODE_ALIAS)
345 VarPacketAliasSetAddress(IpcpInfo.want_ipaddr);
346 OsLinkup();
281}
282
283/*
284 * Called when IPCP has reached to OPEN state
285 */
286static void
287IpcpLayerUp(struct fsm * fp)
288{
289 char tbuff[100];
290
291 Prompt();
292 LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
293 snprintf(tbuff, sizeof(tbuff), "myaddr = %s ",
294 inet_ntoa(IpcpInfo.want_ipaddr));
295
296 if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP)
297 VjInit((IpcpInfo.his_compproto >> 8) & 255);
298
299 LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
300 tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
301 if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask) < 0) {
302 if (VarTerm)
303 LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
304 return;
305 }
306 if (mode & MODE_ALIAS)
307 VarPacketAliasSetAddress(IpcpInfo.want_ipaddr);
308 OsLinkup();
347 StartingIpIn = ipInOctets;
348 StartingIpOut = ipOutOctets;
349 IpcpStartReport();
309 throughput_start(&throughput);
350 StartIdleTimer();
351}
352
353void
354IpcpUp()
355{
356 FsmUp(&IpcpFsm);
357 LogPrintf(LogIPCP, "IPCP Up event!!\n");
358}
359
360void
361IpcpOpen()
362{
363 FsmOpen(&IpcpFsm);
364}
365
366static int
367AcceptableAddr(struct in_range * prange, struct in_addr ipaddr)
368{
369 LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr));
370 LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr));
371 LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
372 LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
373 mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
374 return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
375 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
376}
377
378static void
379IpcpDecodeConfig(u_char * cp, int plen, int mode_type)
380{
381 int type, length;
382 u_long *lp, compproto;
383 struct compreq *pcomp;
384 struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
385 char tbuff[100];
386 char tbuff2[100];
387
388 ackp = AckBuff;
389 nakp = NakBuff;
390 rejp = RejBuff;
391
392 while (plen >= sizeof(struct fsmconfig)) {
393 type = *cp;
394 length = cp[1];
395 if (type < NCFTYPES)
396 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
397 else if (type > 128 && type < 128 + NCFTYPES128)
398 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes128[type], length);
399 else
400 snprintf(tbuff, sizeof(tbuff), " ??? ");
401
402 switch (type) {
403 case TY_IPADDR: /* RFC1332 */
404 lp = (u_long *) (cp + 2);
405 ipaddr.s_addr = *lp;
406 LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
407
408 switch (mode_type) {
409 case MODE_REQ:
410 if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
411 /*
412 * If destination address is not acceptable, insist to use what we
413 * want to use.
414 */
415 memcpy(nakp, cp, 2);
416 memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length);
417 nakp += length;
418 break;
419 }
420 IpcpInfo.his_ipaddr = ipaddr;
421 memcpy(ackp, cp, length);
422 ackp += length;
423 break;
424 case MODE_NAK:
425 if (AcceptableAddr(&DefMyAddress, ipaddr)) {
426
427 /*
428 * Use address suggested by peer.
429 */
430 snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff,
431 inet_ntoa(IpcpInfo.want_ipaddr));
432 LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
433 IpcpInfo.want_ipaddr = ipaddr;
434 }
435 break;
436 case MODE_REJ:
437 IpcpInfo.his_reject |= (1 << type);
438 break;
439 }
440 break;
441 case TY_COMPPROTO:
442 lp = (u_long *) (cp + 2);
443 compproto = htonl(*lp);
444 LogPrintf(LogIPCP, "%s %08x\n", tbuff, compproto);
445
446 switch (mode_type) {
447 case MODE_REQ:
448 if (!Acceptable(ConfVjcomp)) {
449 memcpy(rejp, cp, length);
450 rejp += length;
451 } else {
452 pcomp = (struct compreq *) (cp + 2);
453 switch (length) {
454 case 4: /* RFC1172 */
455 if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
456 LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
457 IpcpInfo.heis1172 = 1;
458 IpcpInfo.his_compproto = compproto;
459 memcpy(ackp, cp, length);
460 ackp += length;
461 } else {
462 memcpy(nakp, cp, 2);
463 pcomp->proto = htons(PROTO_VJCOMP);
464 memcpy(nakp+2, &pcomp, 2);
465 nakp += length;
466 }
467 break;
468 case 6: /* RFC1332 */
469 if (ntohs(pcomp->proto) == PROTO_VJCOMP
470 && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
471 IpcpInfo.his_compproto = compproto;
472 IpcpInfo.heis1172 = 0;
473 memcpy(ackp, cp, length);
474 ackp += length;
475 } else {
476 memcpy(nakp, cp, 2);
477 pcomp->proto = htons(PROTO_VJCOMP);
478 pcomp->slots = MAX_STATES - 1;
479 pcomp->compcid = 0;
480 memcpy(nakp+2, &pcomp, sizeof(pcomp));
481 nakp += length;
482 }
483 break;
484 default:
485 memcpy(rejp, cp, length);
486 rejp += length;
487 break;
488 }
489 }
490 break;
491 case MODE_NAK:
492 LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
493 tbuff, IpcpInfo.want_compproto, compproto);
494 IpcpInfo.want_compproto = compproto;
495 break;
496 case MODE_REJ:
497 IpcpInfo.his_reject |= (1 << type);
498 break;
499 }
500 break;
501 case TY_IPADDRS: /* RFC1172 */
502 lp = (u_long *) (cp + 2);
503 ipaddr.s_addr = *lp;
504 lp = (u_long *) (cp + 6);
505 dstipaddr.s_addr = *lp;
506 snprintf(tbuff2, sizeof(tbuff2), "%s %s,", tbuff, inet_ntoa(ipaddr));
507 LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
508
509 switch (mode_type) {
510 case MODE_REQ:
511 IpcpInfo.his_ipaddr = ipaddr;
512 IpcpInfo.want_ipaddr = dstipaddr;
513 memcpy(ackp, cp, length);
514 ackp += length;
515 break;
516 case MODE_NAK:
517 snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s", tbuff,
518 inet_ntoa(IpcpInfo.want_ipaddr));
519 LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
520 IpcpInfo.want_ipaddr = ipaddr;
521 IpcpInfo.his_ipaddr = dstipaddr;
522 break;
523 case MODE_REJ:
524 IpcpInfo.his_reject |= (1 << type);
525 break;
526 }
527 break;
528
529 /*
530 * MS extensions for MS's PPP
531 */
532
533#ifndef NOMSEXT
534 case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */
535 case TY_SECONDARY_DNS:
536 if (!Enabled(ConfMSExt)) {
537 LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
538 IpcpInfo.my_reject |= (1 << type);
539 memcpy(rejp, cp, length);
540 rejp += length;
541 break;
542 }
543 switch (mode_type) {
544 case MODE_REQ:
545 lp = (u_long *) (cp + 2);
546 dnsstuff.s_addr = *lp;
547 ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS) ? 1 : 0)].s_addr;
548 if (dnsstuff.s_addr != ms_info_req.s_addr) {
549
550 /*
551 * So the client has got the DNS stuff wrong (first request) so
552 * we'll tell 'em how it is
553 */
554 memcpy(nakp, cp, 2); /* copy first two (type/length) */
555 LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n",
556 type,
557 inet_ntoa(dnsstuff),
558 inet_ntoa(ms_info_req));
559 memcpy(nakp+2, &ms_info_req, length);
560 nakp += length;
561 break;
562 }
563
564 /*
565 * Otherwise they have it right (this time) so we send a ack packet
566 * back confirming it... end of story
567 */
568 LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n",
569 type,
570 inet_ntoa(ms_info_req));
571 memcpy(ackp, cp, length);
572 ackp += length;
573 break;
574 case MODE_NAK: /* what does this mean?? */
575 LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type);
576 break;
577 case MODE_REJ: /* confused?? me to :) */
578 LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type);
579 break;
580 }
581 break;
582
583 case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */
584 case TY_SECONDARY_NBNS:
585 if (!Enabled(ConfMSExt)) {
586 LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n");
587 IpcpInfo.my_reject |= (1 << type);
588 memcpy(rejp, cp, length);
589 rejp += length;
590 break;
591 }
592 switch (mode_type) {
593 case MODE_REQ:
594 lp = (u_long *) (cp + 2);
595 dnsstuff.s_addr = *lp;
596 ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS) ? 1 : 0)].s_addr;
597 if (dnsstuff.s_addr != ms_info_req.s_addr) {
598 memcpy(nakp, cp, 2);
599 memcpy(nakp+2, &ms_info_req.s_addr, length);
600 LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
601 type,
602 inet_ntoa(dnsstuff),
603 inet_ntoa(ms_info_req));
604 nakp += length;
605 break;
606 }
607 LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
608 type,
609 inet_ntoa(ms_info_req));
610 memcpy(ackp, cp, length);
611 ackp += length;
612 break;
613 case MODE_NAK:
614 LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
615 break;
616 case MODE_REJ:
617 LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
618 break;
619 }
620 break;
621
622#endif
623
624 default:
625 IpcpInfo.my_reject |= (1 << type);
626 memcpy(rejp, cp, length);
627 rejp += length;
628 break;
629 }
630 plen -= length;
631 cp += length;
632 }
633}
634
635void
636IpcpInput(struct mbuf * bp)
637{
638 FsmInput(&IpcpFsm, bp);
639}
310 StartIdleTimer();
311}
312
313void
314IpcpUp()
315{
316 FsmUp(&IpcpFsm);
317 LogPrintf(LogIPCP, "IPCP Up event!!\n");
318}
319
320void
321IpcpOpen()
322{
323 FsmOpen(&IpcpFsm);
324}
325
326static int
327AcceptableAddr(struct in_range * prange, struct in_addr ipaddr)
328{
329 LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr));
330 LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr));
331 LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
332 LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
333 mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
334 return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
335 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
336}
337
338static void
339IpcpDecodeConfig(u_char * cp, int plen, int mode_type)
340{
341 int type, length;
342 u_long *lp, compproto;
343 struct compreq *pcomp;
344 struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
345 char tbuff[100];
346 char tbuff2[100];
347
348 ackp = AckBuff;
349 nakp = NakBuff;
350 rejp = RejBuff;
351
352 while (plen >= sizeof(struct fsmconfig)) {
353 type = *cp;
354 length = cp[1];
355 if (type < NCFTYPES)
356 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
357 else if (type > 128 && type < 128 + NCFTYPES128)
358 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes128[type], length);
359 else
360 snprintf(tbuff, sizeof(tbuff), " ??? ");
361
362 switch (type) {
363 case TY_IPADDR: /* RFC1332 */
364 lp = (u_long *) (cp + 2);
365 ipaddr.s_addr = *lp;
366 LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
367
368 switch (mode_type) {
369 case MODE_REQ:
370 if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
371 /*
372 * If destination address is not acceptable, insist to use what we
373 * want to use.
374 */
375 memcpy(nakp, cp, 2);
376 memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length);
377 nakp += length;
378 break;
379 }
380 IpcpInfo.his_ipaddr = ipaddr;
381 memcpy(ackp, cp, length);
382 ackp += length;
383 break;
384 case MODE_NAK:
385 if (AcceptableAddr(&DefMyAddress, ipaddr)) {
386
387 /*
388 * Use address suggested by peer.
389 */
390 snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff,
391 inet_ntoa(IpcpInfo.want_ipaddr));
392 LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
393 IpcpInfo.want_ipaddr = ipaddr;
394 }
395 break;
396 case MODE_REJ:
397 IpcpInfo.his_reject |= (1 << type);
398 break;
399 }
400 break;
401 case TY_COMPPROTO:
402 lp = (u_long *) (cp + 2);
403 compproto = htonl(*lp);
404 LogPrintf(LogIPCP, "%s %08x\n", tbuff, compproto);
405
406 switch (mode_type) {
407 case MODE_REQ:
408 if (!Acceptable(ConfVjcomp)) {
409 memcpy(rejp, cp, length);
410 rejp += length;
411 } else {
412 pcomp = (struct compreq *) (cp + 2);
413 switch (length) {
414 case 4: /* RFC1172 */
415 if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
416 LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
417 IpcpInfo.heis1172 = 1;
418 IpcpInfo.his_compproto = compproto;
419 memcpy(ackp, cp, length);
420 ackp += length;
421 } else {
422 memcpy(nakp, cp, 2);
423 pcomp->proto = htons(PROTO_VJCOMP);
424 memcpy(nakp+2, &pcomp, 2);
425 nakp += length;
426 }
427 break;
428 case 6: /* RFC1332 */
429 if (ntohs(pcomp->proto) == PROTO_VJCOMP
430 && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
431 IpcpInfo.his_compproto = compproto;
432 IpcpInfo.heis1172 = 0;
433 memcpy(ackp, cp, length);
434 ackp += length;
435 } else {
436 memcpy(nakp, cp, 2);
437 pcomp->proto = htons(PROTO_VJCOMP);
438 pcomp->slots = MAX_STATES - 1;
439 pcomp->compcid = 0;
440 memcpy(nakp+2, &pcomp, sizeof(pcomp));
441 nakp += length;
442 }
443 break;
444 default:
445 memcpy(rejp, cp, length);
446 rejp += length;
447 break;
448 }
449 }
450 break;
451 case MODE_NAK:
452 LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
453 tbuff, IpcpInfo.want_compproto, compproto);
454 IpcpInfo.want_compproto = compproto;
455 break;
456 case MODE_REJ:
457 IpcpInfo.his_reject |= (1 << type);
458 break;
459 }
460 break;
461 case TY_IPADDRS: /* RFC1172 */
462 lp = (u_long *) (cp + 2);
463 ipaddr.s_addr = *lp;
464 lp = (u_long *) (cp + 6);
465 dstipaddr.s_addr = *lp;
466 snprintf(tbuff2, sizeof(tbuff2), "%s %s,", tbuff, inet_ntoa(ipaddr));
467 LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
468
469 switch (mode_type) {
470 case MODE_REQ:
471 IpcpInfo.his_ipaddr = ipaddr;
472 IpcpInfo.want_ipaddr = dstipaddr;
473 memcpy(ackp, cp, length);
474 ackp += length;
475 break;
476 case MODE_NAK:
477 snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s", tbuff,
478 inet_ntoa(IpcpInfo.want_ipaddr));
479 LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
480 IpcpInfo.want_ipaddr = ipaddr;
481 IpcpInfo.his_ipaddr = dstipaddr;
482 break;
483 case MODE_REJ:
484 IpcpInfo.his_reject |= (1 << type);
485 break;
486 }
487 break;
488
489 /*
490 * MS extensions for MS's PPP
491 */
492
493#ifndef NOMSEXT
494 case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */
495 case TY_SECONDARY_DNS:
496 if (!Enabled(ConfMSExt)) {
497 LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
498 IpcpInfo.my_reject |= (1 << type);
499 memcpy(rejp, cp, length);
500 rejp += length;
501 break;
502 }
503 switch (mode_type) {
504 case MODE_REQ:
505 lp = (u_long *) (cp + 2);
506 dnsstuff.s_addr = *lp;
507 ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS) ? 1 : 0)].s_addr;
508 if (dnsstuff.s_addr != ms_info_req.s_addr) {
509
510 /*
511 * So the client has got the DNS stuff wrong (first request) so
512 * we'll tell 'em how it is
513 */
514 memcpy(nakp, cp, 2); /* copy first two (type/length) */
515 LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n",
516 type,
517 inet_ntoa(dnsstuff),
518 inet_ntoa(ms_info_req));
519 memcpy(nakp+2, &ms_info_req, length);
520 nakp += length;
521 break;
522 }
523
524 /*
525 * Otherwise they have it right (this time) so we send a ack packet
526 * back confirming it... end of story
527 */
528 LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n",
529 type,
530 inet_ntoa(ms_info_req));
531 memcpy(ackp, cp, length);
532 ackp += length;
533 break;
534 case MODE_NAK: /* what does this mean?? */
535 LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type);
536 break;
537 case MODE_REJ: /* confused?? me to :) */
538 LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type);
539 break;
540 }
541 break;
542
543 case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */
544 case TY_SECONDARY_NBNS:
545 if (!Enabled(ConfMSExt)) {
546 LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n");
547 IpcpInfo.my_reject |= (1 << type);
548 memcpy(rejp, cp, length);
549 rejp += length;
550 break;
551 }
552 switch (mode_type) {
553 case MODE_REQ:
554 lp = (u_long *) (cp + 2);
555 dnsstuff.s_addr = *lp;
556 ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS) ? 1 : 0)].s_addr;
557 if (dnsstuff.s_addr != ms_info_req.s_addr) {
558 memcpy(nakp, cp, 2);
559 memcpy(nakp+2, &ms_info_req.s_addr, length);
560 LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
561 type,
562 inet_ntoa(dnsstuff),
563 inet_ntoa(ms_info_req));
564 nakp += length;
565 break;
566 }
567 LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
568 type,
569 inet_ntoa(ms_info_req));
570 memcpy(ackp, cp, length);
571 ackp += length;
572 break;
573 case MODE_NAK:
574 LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
575 break;
576 case MODE_REJ:
577 LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
578 break;
579 }
580 break;
581
582#endif
583
584 default:
585 IpcpInfo.my_reject |= (1 << type);
586 memcpy(rejp, cp, length);
587 rejp += length;
588 break;
589 }
590 plen -= length;
591 cp += length;
592 }
593}
594
595void
596IpcpInput(struct mbuf * bp)
597{
598 FsmInput(&IpcpFsm, bp);
599}