Deleted Added
full compact
lcp.c (78189) lcp.c (78410)
1/*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
1/*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/usr.sbin/ppp/lcp.c 78189 2001-06-13 21:52:19Z brian $
28 * $FreeBSD: head/usr.sbin/ppp/lcp.c 78410 2001-06-18 14:59:36Z brian $
29 */
30
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <sys/un.h>
36
37#include <signal.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <termios.h>
42#include <unistd.h>
43
44#include "layer.h"
45#include "ua.h"
46#include "defs.h"
47#include "command.h"
48#include "mbuf.h"
49#include "log.h"
50#include "timer.h"
51#include "fsm.h"
52#include "iplist.h"
53#include "throughput.h"
54#include "proto.h"
55#include "descriptor.h"
56#include "lqr.h"
57#include "hdlc.h"
58#include "lcp.h"
59#include "ccp.h"
60#include "async.h"
61#include "link.h"
62#include "physical.h"
63#include "prompt.h"
64#include "slcompress.h"
65#include "ipcp.h"
66#include "filter.h"
67#include "mp.h"
68#include "chat.h"
69#include "auth.h"
70#include "chap.h"
71#include "cbcp.h"
72#include "datalink.h"
73#ifndef NORADIUS
74#include "radius.h"
75#endif
76#include "bundle.h"
77
78/* for received LQRs */
79struct lqrreq {
80 u_char type;
81 u_char length;
82 u_short proto; /* Quality protocol */
83 u_int32_t period; /* Reporting interval */
84};
85
86static int LcpLayerUp(struct fsm *);
87static void LcpLayerDown(struct fsm *);
88static void LcpLayerStart(struct fsm *);
89static void LcpLayerFinish(struct fsm *);
90static void LcpInitRestartCounter(struct fsm *, int);
91static void LcpSendConfigReq(struct fsm *);
92static void LcpSentTerminateReq(struct fsm *);
93static void LcpSendTerminateAck(struct fsm *, u_char);
94static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
95 struct fsm_decode *);
96
97static struct fsm_callbacks lcp_Callbacks = {
98 LcpLayerUp,
99 LcpLayerDown,
100 LcpLayerStart,
101 LcpLayerFinish,
102 LcpInitRestartCounter,
103 LcpSendConfigReq,
104 LcpSentTerminateReq,
105 LcpSendTerminateAck,
106 LcpDecodeConfig,
107 fsm_NullRecvResetReq,
108 fsm_NullRecvResetAck
109};
110
111static const char * const lcp_TimerNames[] =
112 {"LCP restart", "LCP openmode", "LCP stopped"};
113
114static const char *
115protoname(int proto)
116{
117 static const char * const cftypes[] = {
118 /* Check out the latest ``Assigned numbers'' rfc (1700) */
119 NULL,
120 "MRU", /* 1: Maximum-Receive-Unit */
121 "ACCMAP", /* 2: Async-Control-Character-Map */
122 "AUTHPROTO", /* 3: Authentication-Protocol */
123 "QUALPROTO", /* 4: Quality-Protocol */
124 "MAGICNUM", /* 5: Magic-Number */
125 "RESERVED", /* 6: RESERVED */
126 "PROTOCOMP", /* 7: Protocol-Field-Compression */
127 "ACFCOMP", /* 8: Address-and-Control-Field-Compression */
128 "FCSALT", /* 9: FCS-Alternatives */
129 "SDP", /* 10: Self-Describing-Pad */
130 "NUMMODE", /* 11: Numbered-Mode */
131 "MULTIPROC", /* 12: Multi-Link-Procedure */
132 "CALLBACK", /* 13: Callback */
133 "CONTIME", /* 14: Connect-Time */
134 "COMPFRAME", /* 15: Compound-Frames */
135 "NDE", /* 16: Nominal-Data-Encapsulation */
136 "MRRU", /* 17: Multilink-MRRU */
137 "SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */
138 "ENDDISC", /* 19: Multilink-Endpoint-Discriminator */
139 "PROPRIETRY", /* 20: Proprietary */
140 "DCEID", /* 21: DCE-Identifier */
141 "MULTIPP", /* 22: Multi-Link-Plus-Procedure */
142 "LDBACP", /* 23: Link Discriminator for BACP */
143 };
144
145 if (proto < 0 || proto > sizeof cftypes / sizeof *cftypes ||
146 cftypes[proto] == NULL)
147 return HexStr(proto, NULL, 0);
148
149 return cftypes[proto];
150}
151
152int
153lcp_ReportStatus(struct cmdargs const *arg)
154{
155 struct link *l;
156 struct lcp *lcp;
157
158 l = command_ChooseLink(arg);
159 lcp = &l->lcp;
160
161 prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
162 State2Nam(lcp->fsm.state));
163 prompt_Printf(arg->prompt,
164 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
165 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
166 lcp->his_mru, (u_long)lcp->his_accmap,
167 lcp->his_protocomp ? "on" : "off",
168 lcp->his_acfcomp ? "on" : "off",
169 (u_long)lcp->his_magic, lcp->his_mrru,
170 lcp->his_shortseq ? "on" : "off", lcp->his_reject);
171 prompt_Printf(arg->prompt,
172 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
173 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
174 lcp->want_mru, (u_long)lcp->want_accmap,
175 lcp->want_protocomp ? "on" : "off",
176 lcp->want_acfcomp ? "on" : "off",
177 (u_long)lcp->want_magic, lcp->want_mrru,
178 lcp->want_shortseq ? "on" : "off", lcp->my_reject);
179
29 */
30
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <sys/un.h>
36
37#include <signal.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <termios.h>
42#include <unistd.h>
43
44#include "layer.h"
45#include "ua.h"
46#include "defs.h"
47#include "command.h"
48#include "mbuf.h"
49#include "log.h"
50#include "timer.h"
51#include "fsm.h"
52#include "iplist.h"
53#include "throughput.h"
54#include "proto.h"
55#include "descriptor.h"
56#include "lqr.h"
57#include "hdlc.h"
58#include "lcp.h"
59#include "ccp.h"
60#include "async.h"
61#include "link.h"
62#include "physical.h"
63#include "prompt.h"
64#include "slcompress.h"
65#include "ipcp.h"
66#include "filter.h"
67#include "mp.h"
68#include "chat.h"
69#include "auth.h"
70#include "chap.h"
71#include "cbcp.h"
72#include "datalink.h"
73#ifndef NORADIUS
74#include "radius.h"
75#endif
76#include "bundle.h"
77
78/* for received LQRs */
79struct lqrreq {
80 u_char type;
81 u_char length;
82 u_short proto; /* Quality protocol */
83 u_int32_t period; /* Reporting interval */
84};
85
86static int LcpLayerUp(struct fsm *);
87static void LcpLayerDown(struct fsm *);
88static void LcpLayerStart(struct fsm *);
89static void LcpLayerFinish(struct fsm *);
90static void LcpInitRestartCounter(struct fsm *, int);
91static void LcpSendConfigReq(struct fsm *);
92static void LcpSentTerminateReq(struct fsm *);
93static void LcpSendTerminateAck(struct fsm *, u_char);
94static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
95 struct fsm_decode *);
96
97static struct fsm_callbacks lcp_Callbacks = {
98 LcpLayerUp,
99 LcpLayerDown,
100 LcpLayerStart,
101 LcpLayerFinish,
102 LcpInitRestartCounter,
103 LcpSendConfigReq,
104 LcpSentTerminateReq,
105 LcpSendTerminateAck,
106 LcpDecodeConfig,
107 fsm_NullRecvResetReq,
108 fsm_NullRecvResetAck
109};
110
111static const char * const lcp_TimerNames[] =
112 {"LCP restart", "LCP openmode", "LCP stopped"};
113
114static const char *
115protoname(int proto)
116{
117 static const char * const cftypes[] = {
118 /* Check out the latest ``Assigned numbers'' rfc (1700) */
119 NULL,
120 "MRU", /* 1: Maximum-Receive-Unit */
121 "ACCMAP", /* 2: Async-Control-Character-Map */
122 "AUTHPROTO", /* 3: Authentication-Protocol */
123 "QUALPROTO", /* 4: Quality-Protocol */
124 "MAGICNUM", /* 5: Magic-Number */
125 "RESERVED", /* 6: RESERVED */
126 "PROTOCOMP", /* 7: Protocol-Field-Compression */
127 "ACFCOMP", /* 8: Address-and-Control-Field-Compression */
128 "FCSALT", /* 9: FCS-Alternatives */
129 "SDP", /* 10: Self-Describing-Pad */
130 "NUMMODE", /* 11: Numbered-Mode */
131 "MULTIPROC", /* 12: Multi-Link-Procedure */
132 "CALLBACK", /* 13: Callback */
133 "CONTIME", /* 14: Connect-Time */
134 "COMPFRAME", /* 15: Compound-Frames */
135 "NDE", /* 16: Nominal-Data-Encapsulation */
136 "MRRU", /* 17: Multilink-MRRU */
137 "SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */
138 "ENDDISC", /* 19: Multilink-Endpoint-Discriminator */
139 "PROPRIETRY", /* 20: Proprietary */
140 "DCEID", /* 21: DCE-Identifier */
141 "MULTIPP", /* 22: Multi-Link-Plus-Procedure */
142 "LDBACP", /* 23: Link Discriminator for BACP */
143 };
144
145 if (proto < 0 || proto > sizeof cftypes / sizeof *cftypes ||
146 cftypes[proto] == NULL)
147 return HexStr(proto, NULL, 0);
148
149 return cftypes[proto];
150}
151
152int
153lcp_ReportStatus(struct cmdargs const *arg)
154{
155 struct link *l;
156 struct lcp *lcp;
157
158 l = command_ChooseLink(arg);
159 lcp = &l->lcp;
160
161 prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
162 State2Nam(lcp->fsm.state));
163 prompt_Printf(arg->prompt,
164 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
165 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
166 lcp->his_mru, (u_long)lcp->his_accmap,
167 lcp->his_protocomp ? "on" : "off",
168 lcp->his_acfcomp ? "on" : "off",
169 (u_long)lcp->his_magic, lcp->his_mrru,
170 lcp->his_shortseq ? "on" : "off", lcp->his_reject);
171 prompt_Printf(arg->prompt,
172 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
173 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
174 lcp->want_mru, (u_long)lcp->want_accmap,
175 lcp->want_protocomp ? "on" : "off",
176 lcp->want_acfcomp ? "on" : "off",
177 (u_long)lcp->want_magic, lcp->want_mrru,
178 lcp->want_shortseq ? "on" : "off", lcp->my_reject);
179
180 prompt_Printf(arg->prompt, "\n Defaults: MRU = %d, ", lcp->cfg.mru);
180 prompt_Printf(arg->prompt, "\n Defaults: MRU = %d (max %d), ",
181 lcp->cfg.mru, lcp->cfg.max_mru);
182 if (lcp->cfg.mtu)
183 prompt_Printf(arg->prompt, "MTU = %d (max %d), ",
184 lcp->cfg.mtu, lcp->cfg.max_mtu);
185 else
186 prompt_Printf(arg->prompt, "MTU = any (max %d), ", lcp->cfg.max_mtu);
181 prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
182 prompt_Printf(arg->prompt, " LQR period = %us, ",
183 lcp->cfg.lqrperiod);
184 prompt_Printf(arg->prompt, "Open Mode = %s",
185 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
186 if (lcp->cfg.openmode > 0)
187 prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
188 prompt_Printf(arg->prompt, "\n FSM retry = %us, max %u Config"
189 " REQ%s, %u Term REQ%s\n", lcp->cfg.fsm.timeout,
190 lcp->cfg.fsm.maxreq, lcp->cfg.fsm.maxreq == 1 ? "" : "s",
191 lcp->cfg.fsm.maxtrm, lcp->cfg.fsm.maxtrm == 1 ? "" : "s");
192 prompt_Printf(arg->prompt, " Ident: %s\n", lcp->cfg.ident);
193 prompt_Printf(arg->prompt, "\n Negotiation:\n");
194 prompt_Printf(arg->prompt, " ACFCOMP = %s\n",
195 command_ShowNegval(lcp->cfg.acfcomp));
196 prompt_Printf(arg->prompt, " CHAP = %s\n",
197 command_ShowNegval(lcp->cfg.chap05));
198#ifdef HAVE_DES
199 prompt_Printf(arg->prompt, " CHAP80 = %s\n",
200 command_ShowNegval(lcp->cfg.chap80nt));
201 prompt_Printf(arg->prompt, " LANMan = %s\n",
202 command_ShowNegval(lcp->cfg.chap80lm));
203 prompt_Printf(arg->prompt, " CHAP81 = %s\n",
204 command_ShowNegval(lcp->cfg.chap81));
205#endif
206 prompt_Printf(arg->prompt, " LQR = %s\n",
207 command_ShowNegval(lcp->cfg.lqr));
208 prompt_Printf(arg->prompt, " PAP = %s\n",
209 command_ShowNegval(lcp->cfg.pap));
210 prompt_Printf(arg->prompt, " PROTOCOMP = %s\n",
211 command_ShowNegval(lcp->cfg.protocomp));
212
213 return 0;
214}
215
216static u_int32_t
217GenerateMagic(void)
218{
219 /* Generate random number which will be used as magic number */
220 randinit();
221 return random();
222}
223
224void
225lcp_SetupCallbacks(struct lcp *lcp)
226{
227 lcp->fsm.fn = &lcp_Callbacks;
228 lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
229 lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
230 lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
231}
232
233void
234lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
235 const struct fsm_parent *parent)
236{
237 /* Initialise ourselves */
238 int mincode = parent ? 1 : LCP_MINMPCODE;
239
240 fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, LogLCP,
241 bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
242
243 lcp->cfg.mru = DEF_MRU;
187 prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
188 prompt_Printf(arg->prompt, " LQR period = %us, ",
189 lcp->cfg.lqrperiod);
190 prompt_Printf(arg->prompt, "Open Mode = %s",
191 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
192 if (lcp->cfg.openmode > 0)
193 prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
194 prompt_Printf(arg->prompt, "\n FSM retry = %us, max %u Config"
195 " REQ%s, %u Term REQ%s\n", lcp->cfg.fsm.timeout,
196 lcp->cfg.fsm.maxreq, lcp->cfg.fsm.maxreq == 1 ? "" : "s",
197 lcp->cfg.fsm.maxtrm, lcp->cfg.fsm.maxtrm == 1 ? "" : "s");
198 prompt_Printf(arg->prompt, " Ident: %s\n", lcp->cfg.ident);
199 prompt_Printf(arg->prompt, "\n Negotiation:\n");
200 prompt_Printf(arg->prompt, " ACFCOMP = %s\n",
201 command_ShowNegval(lcp->cfg.acfcomp));
202 prompt_Printf(arg->prompt, " CHAP = %s\n",
203 command_ShowNegval(lcp->cfg.chap05));
204#ifdef HAVE_DES
205 prompt_Printf(arg->prompt, " CHAP80 = %s\n",
206 command_ShowNegval(lcp->cfg.chap80nt));
207 prompt_Printf(arg->prompt, " LANMan = %s\n",
208 command_ShowNegval(lcp->cfg.chap80lm));
209 prompt_Printf(arg->prompt, " CHAP81 = %s\n",
210 command_ShowNegval(lcp->cfg.chap81));
211#endif
212 prompt_Printf(arg->prompt, " LQR = %s\n",
213 command_ShowNegval(lcp->cfg.lqr));
214 prompt_Printf(arg->prompt, " PAP = %s\n",
215 command_ShowNegval(lcp->cfg.pap));
216 prompt_Printf(arg->prompt, " PROTOCOMP = %s\n",
217 command_ShowNegval(lcp->cfg.protocomp));
218
219 return 0;
220}
221
222static u_int32_t
223GenerateMagic(void)
224{
225 /* Generate random number which will be used as magic number */
226 randinit();
227 return random();
228}
229
230void
231lcp_SetupCallbacks(struct lcp *lcp)
232{
233 lcp->fsm.fn = &lcp_Callbacks;
234 lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
235 lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
236 lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
237}
238
239void
240lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
241 const struct fsm_parent *parent)
242{
243 /* Initialise ourselves */
244 int mincode = parent ? 1 : LCP_MINMPCODE;
245
246 fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, LogLCP,
247 bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
248
249 lcp->cfg.mru = DEF_MRU;
250 lcp->cfg.max_mru = MAX_MRU;
251 lcp->cfg.mtu = 0;
252 lcp->cfg.max_mtu = MAX_MTU;
244 lcp->cfg.accmap = 0;
245 lcp->cfg.openmode = 1;
246 lcp->cfg.lqrperiod = DEF_LQRPERIOD;
247 lcp->cfg.fsm.timeout = DEF_FSMRETRY;
248 lcp->cfg.fsm.maxreq = DEF_FSMTRIES;
249 lcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
250
251 lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
252 lcp->cfg.chap05 = NEG_ACCEPTED;
253#ifdef HAVE_DES
254 lcp->cfg.chap80nt = NEG_ACCEPTED;
255 lcp->cfg.chap80lm = NEG_ACCEPTED;
256 lcp->cfg.chap81 = NEG_ACCEPTED;
257#endif
258 lcp->cfg.lqr = NEG_ACCEPTED;
259 lcp->cfg.pap = NEG_ACCEPTED;
260 lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
261 *lcp->cfg.ident = '\0';
262
263 lcp_Setup(lcp, lcp->cfg.openmode);
264}
265
266void
267lcp_Setup(struct lcp *lcp, int openmode)
268{
253 lcp->cfg.accmap = 0;
254 lcp->cfg.openmode = 1;
255 lcp->cfg.lqrperiod = DEF_LQRPERIOD;
256 lcp->cfg.fsm.timeout = DEF_FSMRETRY;
257 lcp->cfg.fsm.maxreq = DEF_FSMTRIES;
258 lcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
259
260 lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
261 lcp->cfg.chap05 = NEG_ACCEPTED;
262#ifdef HAVE_DES
263 lcp->cfg.chap80nt = NEG_ACCEPTED;
264 lcp->cfg.chap80lm = NEG_ACCEPTED;
265 lcp->cfg.chap81 = NEG_ACCEPTED;
266#endif
267 lcp->cfg.lqr = NEG_ACCEPTED;
268 lcp->cfg.pap = NEG_ACCEPTED;
269 lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
270 *lcp->cfg.ident = '\0';
271
272 lcp_Setup(lcp, lcp->cfg.openmode);
273}
274
275void
276lcp_Setup(struct lcp *lcp, int openmode)
277{
278 struct physical *p = link2physical(lcp->fsm.link);
279 int phmtu = p ? physical_DeviceMTU(p) : 0;
280
269 lcp->fsm.open_mode = openmode;
270
281 lcp->fsm.open_mode = openmode;
282
271 lcp->his_mru = lcp->fsm.bundle->cfg.mtu;
272 if (!lcp->his_mru || lcp->his_mru > DEF_MRU)
273 lcp->his_mru = DEF_MRU;
283 lcp->his_mru = DEF_MRU;
274 lcp->his_mrru = 0;
275 lcp->his_magic = 0;
276 lcp->his_lqrperiod = 0;
277 lcp->his_acfcomp = 0;
278 lcp->his_auth = 0;
279 lcp->his_authtype = 0;
280 lcp->his_callback.opmask = 0;
281 lcp->his_shortseq = 0;
282
283 lcp->want_mru = lcp->cfg.mru;
284 lcp->his_mrru = 0;
285 lcp->his_magic = 0;
286 lcp->his_lqrperiod = 0;
287 lcp->his_acfcomp = 0;
288 lcp->his_auth = 0;
289 lcp->his_authtype = 0;
290 lcp->his_callback.opmask = 0;
291 lcp->his_shortseq = 0;
292
293 lcp->want_mru = lcp->cfg.mru;
294 if (phmtu && lcp->want_mru > phmtu)
295 lcp->want_mru = phmtu;
284 lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
285 lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
286 lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
287
288 if (lcp->fsm.parent) {
296 lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
297 lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
298 lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
299
300 if (lcp->fsm.parent) {
289 struct physical *p = link2physical(lcp->fsm.link);
290
291 lcp->his_accmap = 0xffffffff;
292 lcp->want_accmap = lcp->cfg.accmap;
293 lcp->his_protocomp = 0;
294 lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
295 lcp->want_magic = GenerateMagic();
296
297 if (IsEnabled(lcp->cfg.chap05)) {
298 lcp->want_auth = PROTO_CHAP;
299 lcp->want_authtype = 0x05;
300#ifdef HAVE_DES
301 } else if (IsEnabled(lcp->cfg.chap80nt) ||
302 IsEnabled(lcp->cfg.chap80lm)) {
303 lcp->want_auth = PROTO_CHAP;
304 lcp->want_authtype = 0x80;
305 } else if (IsEnabled(lcp->cfg.chap81)) {
306 lcp->want_auth = PROTO_CHAP;
307 lcp->want_authtype = 0x81;
308#endif
309 } else if (IsEnabled(lcp->cfg.pap)) {
310 lcp->want_auth = PROTO_PAP;
311 lcp->want_authtype = 0;
312 } else {
313 lcp->want_auth = 0;
314 lcp->want_authtype = 0;
315 }
316
317 if (p->type != PHYS_DIRECT)
318 memcpy(&lcp->want_callback, &p->dl->cfg.callback,
319 sizeof(struct callback));
320 else
321 lcp->want_callback.opmask = 0;
322 lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
323 lcp->cfg.lqrperiod * 100 : 0;
324 } else {
325 lcp->his_accmap = lcp->want_accmap = 0;
326 lcp->his_protocomp = lcp->want_protocomp = 1;
327 lcp->want_magic = 0;
328 lcp->want_auth = 0;
329 lcp->want_authtype = 0;
330 lcp->want_callback.opmask = 0;
331 lcp->want_lqrperiod = 0;
332 }
333
334 lcp->his_reject = lcp->my_reject = 0;
335 lcp->auth_iwait = lcp->auth_ineed = 0;
336 lcp->LcpFailedMagic = 0;
337}
338
339static void
340LcpInitRestartCounter(struct fsm *fp, int what)
341{
342 /* Set fsm timer load */
343 struct lcp *lcp = fsm2lcp(fp);
344
345 fp->FsmTimer.load = lcp->cfg.fsm.timeout * SECTICKS;
346 switch (what) {
347 case FSM_REQ_TIMER:
348 fp->restart = lcp->cfg.fsm.maxreq;
349 break;
350 case FSM_TRM_TIMER:
351 fp->restart = lcp->cfg.fsm.maxtrm;
352 break;
353 default:
354 fp->restart = 1;
355 break;
356 }
357}
358
359static void
360LcpSendConfigReq(struct fsm *fp)
361{
362 /* Send config REQ please */
363 struct physical *p = link2physical(fp->link);
364 struct lcp *lcp = fsm2lcp(fp);
365 u_char buff[200];
366 struct lcp_opt *o;
367 struct mp *mp;
368 u_int16_t proto;
369
370 if (!p) {
371 log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
372 fp->link->name);
373 return;
374 }
375
376 o = (struct lcp_opt *)buff;
377 if (!physical_IsSync(p)) {
378 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
379 INC_LCP_OPT(TY_ACFCOMP, 2, o);
380
381 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
382 INC_LCP_OPT(TY_PROTOCOMP, 2, o);
383
384 if (!REJECTED(lcp, TY_ACCMAP)) {
385 ua_htonl(&lcp->want_accmap, o->data);
386 INC_LCP_OPT(TY_ACCMAP, 6, o);
387 }
388 }
389
390 if (!REJECTED(lcp, TY_MRU)) {
391 ua_htons(&lcp->want_mru, o->data);
392 INC_LCP_OPT(TY_MRU, 4, o);
393 }
394
395 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
396 ua_htonl(&lcp->want_magic, o->data);
397 INC_LCP_OPT(TY_MAGICNUM, 6, o);
398 }
399
400 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
401 proto = PROTO_LQR;
402 ua_htons(&proto, o->data);
403 ua_htonl(&lcp->want_lqrperiod, o->data + 2);
404 INC_LCP_OPT(TY_QUALPROTO, 8, o);
405 }
406
407 switch (lcp->want_auth) {
408 case PROTO_PAP:
409 proto = PROTO_PAP;
410 ua_htons(&proto, o->data);
411 INC_LCP_OPT(TY_AUTHPROTO, 4, o);
412 break;
413
414 case PROTO_CHAP:
415 proto = PROTO_CHAP;
416 ua_htons(&proto, o->data);
417 o->data[2] = lcp->want_authtype;
418 INC_LCP_OPT(TY_AUTHPROTO, 5, o);
419 break;
420 }
421
422 if (!REJECTED(lcp, TY_CALLBACK)) {
423 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
424 *o->data = CALLBACK_AUTH;
425 INC_LCP_OPT(TY_CALLBACK, 3, o);
426 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
427 *o->data = CALLBACK_CBCP;
428 INC_LCP_OPT(TY_CALLBACK, 3, o);
429 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
430 int sz = strlen(lcp->want_callback.msg);
431
432 if (sz > sizeof o->data - 1) {
433 sz = sizeof o->data - 1;
434 log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz);
435 }
436 *o->data = CALLBACK_E164;
437 memcpy(o->data + 1, lcp->want_callback.msg, sz);
438 INC_LCP_OPT(TY_CALLBACK, sz + 3, o);
439 }
440 }
441
442 if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
443 ua_htons(&lcp->want_mrru, o->data);
444 INC_LCP_OPT(TY_MRRU, 4, o);
445
446 if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
447 INC_LCP_OPT(TY_SHORTSEQ, 2, o);
448 }
449
450 mp = &lcp->fsm.bundle->ncp.mp;
451 if (mp->cfg.enddisc.class != 0 && IsEnabled(mp->cfg.negenddisc) &&
452 !REJECTED(lcp, TY_ENDDISC)) {
453 *o->data = mp->cfg.enddisc.class;
454 memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
455 INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
456 }
457
458 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
459 MB_LCPOUT);
460}
461
462void
463lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
464{
465 /* Don't understand `option' */
466 fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count,
467 MB_LCPOUT);
468}
469
470int
471lcp_SendIdentification(struct lcp *lcp)
472{
473 static u_char id; /* Use a private id */
474 u_char msg[DEF_MRU - 3];
475 const char *argv[2];
476 char *exp[2];
477
478 if (*lcp->cfg.ident == '\0')
479 return 0;
480
481 argv[0] = lcp->cfg.ident;
482 argv[1] = NULL;
483
484 command_Expand(exp, 1, argv, lcp->fsm.bundle, 1, getpid());
485
486 ua_htonl(&lcp->want_magic, msg);
487 strncpy(msg + 4, exp[0], sizeof msg - 5);
488 msg[sizeof msg - 1] = '\0';
489
490 log_Printf(LogLCP, "Sending ident magic %08x text %s\n", lcp->want_magic,
491 msg + 4);
492 fsm_Output(&lcp->fsm, CODE_IDENT, id++, msg, 4 + strlen(msg + 4), MB_LCPOUT);
493
494 free(exp[0]);
495 return 1;
496}
497
498void
499lcp_RecvIdentification(struct lcp *lcp, char *data)
500{
501 log_Printf(LogLCP, "Received ident: %s\n", data);
502}
503
504static void
505LcpSentTerminateReq(struct fsm *fp)
506{
507 /* Term REQ just sent by FSM */
508}
509
510static void
511LcpSendTerminateAck(struct fsm *fp, u_char id)
512{
513 /* Send Term ACK please */
514 struct physical *p = link2physical(fp->link);
515
516 if (p && p->dl->state == DATALINK_CBCP)
517 cbcp_ReceiveTerminateReq(p);
518
519 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_LCPOUT);
520}
521
522static void
523LcpLayerStart(struct fsm *fp)
524{
525 /* We're about to start up ! */
526 struct lcp *lcp = fsm2lcp(fp);
527
528 log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
529 lcp->LcpFailedMagic = 0;
530 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
531}
532
533static void
534LcpLayerFinish(struct fsm *fp)
535{
536 /* We're now down */
537 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
538}
539
540static int
541LcpLayerUp(struct fsm *fp)
542{
543 /* We're now up */
544 struct physical *p = link2physical(fp->link);
545 struct lcp *lcp = fsm2lcp(fp);
546
547 log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
548 async_SetLinkParams(&p->async, lcp);
549 lqr_Start(lcp);
550 hdlc_StartTimer(&p->hdlc);
551 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
552
553 lcp_SendIdentification(lcp);
554
555 return 1;
556}
557
558static void
559LcpLayerDown(struct fsm *fp)
560{
561 /* About to come down */
562 struct physical *p = link2physical(fp->link);
563
564 log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
565 hdlc_StopTimer(&p->hdlc);
566 lqr_StopTimer(p);
567 lcp_Setup(fsm2lcp(fp), 0);
568}
569
570static int
571E164ok(struct callback *cb, char *req, int sz)
572{
573 char list[sizeof cb->msg], *next;
574 int len;
575
576 if (!strcmp(cb->msg, "*"))
577 return 1;
578
579 strncpy(list, cb->msg, sizeof list - 1);
580 list[sizeof list - 1] = '\0';
581 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
582 len = strlen(next);
583 if (sz == len && !memcmp(list, req, sz))
584 return 1;
585 }
586 return 0;
587}
588
589static void
590LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
591 struct fsm_decode *dec)
592{
593 /* Deal with incoming PROTO_LCP */
594 struct lcp *lcp = fsm2lcp(fp);
301 lcp->his_accmap = 0xffffffff;
302 lcp->want_accmap = lcp->cfg.accmap;
303 lcp->his_protocomp = 0;
304 lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
305 lcp->want_magic = GenerateMagic();
306
307 if (IsEnabled(lcp->cfg.chap05)) {
308 lcp->want_auth = PROTO_CHAP;
309 lcp->want_authtype = 0x05;
310#ifdef HAVE_DES
311 } else if (IsEnabled(lcp->cfg.chap80nt) ||
312 IsEnabled(lcp->cfg.chap80lm)) {
313 lcp->want_auth = PROTO_CHAP;
314 lcp->want_authtype = 0x80;
315 } else if (IsEnabled(lcp->cfg.chap81)) {
316 lcp->want_auth = PROTO_CHAP;
317 lcp->want_authtype = 0x81;
318#endif
319 } else if (IsEnabled(lcp->cfg.pap)) {
320 lcp->want_auth = PROTO_PAP;
321 lcp->want_authtype = 0;
322 } else {
323 lcp->want_auth = 0;
324 lcp->want_authtype = 0;
325 }
326
327 if (p->type != PHYS_DIRECT)
328 memcpy(&lcp->want_callback, &p->dl->cfg.callback,
329 sizeof(struct callback));
330 else
331 lcp->want_callback.opmask = 0;
332 lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
333 lcp->cfg.lqrperiod * 100 : 0;
334 } else {
335 lcp->his_accmap = lcp->want_accmap = 0;
336 lcp->his_protocomp = lcp->want_protocomp = 1;
337 lcp->want_magic = 0;
338 lcp->want_auth = 0;
339 lcp->want_authtype = 0;
340 lcp->want_callback.opmask = 0;
341 lcp->want_lqrperiod = 0;
342 }
343
344 lcp->his_reject = lcp->my_reject = 0;
345 lcp->auth_iwait = lcp->auth_ineed = 0;
346 lcp->LcpFailedMagic = 0;
347}
348
349static void
350LcpInitRestartCounter(struct fsm *fp, int what)
351{
352 /* Set fsm timer load */
353 struct lcp *lcp = fsm2lcp(fp);
354
355 fp->FsmTimer.load = lcp->cfg.fsm.timeout * SECTICKS;
356 switch (what) {
357 case FSM_REQ_TIMER:
358 fp->restart = lcp->cfg.fsm.maxreq;
359 break;
360 case FSM_TRM_TIMER:
361 fp->restart = lcp->cfg.fsm.maxtrm;
362 break;
363 default:
364 fp->restart = 1;
365 break;
366 }
367}
368
369static void
370LcpSendConfigReq(struct fsm *fp)
371{
372 /* Send config REQ please */
373 struct physical *p = link2physical(fp->link);
374 struct lcp *lcp = fsm2lcp(fp);
375 u_char buff[200];
376 struct lcp_opt *o;
377 struct mp *mp;
378 u_int16_t proto;
379
380 if (!p) {
381 log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
382 fp->link->name);
383 return;
384 }
385
386 o = (struct lcp_opt *)buff;
387 if (!physical_IsSync(p)) {
388 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
389 INC_LCP_OPT(TY_ACFCOMP, 2, o);
390
391 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
392 INC_LCP_OPT(TY_PROTOCOMP, 2, o);
393
394 if (!REJECTED(lcp, TY_ACCMAP)) {
395 ua_htonl(&lcp->want_accmap, o->data);
396 INC_LCP_OPT(TY_ACCMAP, 6, o);
397 }
398 }
399
400 if (!REJECTED(lcp, TY_MRU)) {
401 ua_htons(&lcp->want_mru, o->data);
402 INC_LCP_OPT(TY_MRU, 4, o);
403 }
404
405 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
406 ua_htonl(&lcp->want_magic, o->data);
407 INC_LCP_OPT(TY_MAGICNUM, 6, o);
408 }
409
410 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
411 proto = PROTO_LQR;
412 ua_htons(&proto, o->data);
413 ua_htonl(&lcp->want_lqrperiod, o->data + 2);
414 INC_LCP_OPT(TY_QUALPROTO, 8, o);
415 }
416
417 switch (lcp->want_auth) {
418 case PROTO_PAP:
419 proto = PROTO_PAP;
420 ua_htons(&proto, o->data);
421 INC_LCP_OPT(TY_AUTHPROTO, 4, o);
422 break;
423
424 case PROTO_CHAP:
425 proto = PROTO_CHAP;
426 ua_htons(&proto, o->data);
427 o->data[2] = lcp->want_authtype;
428 INC_LCP_OPT(TY_AUTHPROTO, 5, o);
429 break;
430 }
431
432 if (!REJECTED(lcp, TY_CALLBACK)) {
433 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
434 *o->data = CALLBACK_AUTH;
435 INC_LCP_OPT(TY_CALLBACK, 3, o);
436 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
437 *o->data = CALLBACK_CBCP;
438 INC_LCP_OPT(TY_CALLBACK, 3, o);
439 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
440 int sz = strlen(lcp->want_callback.msg);
441
442 if (sz > sizeof o->data - 1) {
443 sz = sizeof o->data - 1;
444 log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz);
445 }
446 *o->data = CALLBACK_E164;
447 memcpy(o->data + 1, lcp->want_callback.msg, sz);
448 INC_LCP_OPT(TY_CALLBACK, sz + 3, o);
449 }
450 }
451
452 if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
453 ua_htons(&lcp->want_mrru, o->data);
454 INC_LCP_OPT(TY_MRRU, 4, o);
455
456 if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
457 INC_LCP_OPT(TY_SHORTSEQ, 2, o);
458 }
459
460 mp = &lcp->fsm.bundle->ncp.mp;
461 if (mp->cfg.enddisc.class != 0 && IsEnabled(mp->cfg.negenddisc) &&
462 !REJECTED(lcp, TY_ENDDISC)) {
463 *o->data = mp->cfg.enddisc.class;
464 memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
465 INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
466 }
467
468 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
469 MB_LCPOUT);
470}
471
472void
473lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
474{
475 /* Don't understand `option' */
476 fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count,
477 MB_LCPOUT);
478}
479
480int
481lcp_SendIdentification(struct lcp *lcp)
482{
483 static u_char id; /* Use a private id */
484 u_char msg[DEF_MRU - 3];
485 const char *argv[2];
486 char *exp[2];
487
488 if (*lcp->cfg.ident == '\0')
489 return 0;
490
491 argv[0] = lcp->cfg.ident;
492 argv[1] = NULL;
493
494 command_Expand(exp, 1, argv, lcp->fsm.bundle, 1, getpid());
495
496 ua_htonl(&lcp->want_magic, msg);
497 strncpy(msg + 4, exp[0], sizeof msg - 5);
498 msg[sizeof msg - 1] = '\0';
499
500 log_Printf(LogLCP, "Sending ident magic %08x text %s\n", lcp->want_magic,
501 msg + 4);
502 fsm_Output(&lcp->fsm, CODE_IDENT, id++, msg, 4 + strlen(msg + 4), MB_LCPOUT);
503
504 free(exp[0]);
505 return 1;
506}
507
508void
509lcp_RecvIdentification(struct lcp *lcp, char *data)
510{
511 log_Printf(LogLCP, "Received ident: %s\n", data);
512}
513
514static void
515LcpSentTerminateReq(struct fsm *fp)
516{
517 /* Term REQ just sent by FSM */
518}
519
520static void
521LcpSendTerminateAck(struct fsm *fp, u_char id)
522{
523 /* Send Term ACK please */
524 struct physical *p = link2physical(fp->link);
525
526 if (p && p->dl->state == DATALINK_CBCP)
527 cbcp_ReceiveTerminateReq(p);
528
529 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_LCPOUT);
530}
531
532static void
533LcpLayerStart(struct fsm *fp)
534{
535 /* We're about to start up ! */
536 struct lcp *lcp = fsm2lcp(fp);
537
538 log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
539 lcp->LcpFailedMagic = 0;
540 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
541}
542
543static void
544LcpLayerFinish(struct fsm *fp)
545{
546 /* We're now down */
547 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
548}
549
550static int
551LcpLayerUp(struct fsm *fp)
552{
553 /* We're now up */
554 struct physical *p = link2physical(fp->link);
555 struct lcp *lcp = fsm2lcp(fp);
556
557 log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
558 async_SetLinkParams(&p->async, lcp);
559 lqr_Start(lcp);
560 hdlc_StartTimer(&p->hdlc);
561 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
562
563 lcp_SendIdentification(lcp);
564
565 return 1;
566}
567
568static void
569LcpLayerDown(struct fsm *fp)
570{
571 /* About to come down */
572 struct physical *p = link2physical(fp->link);
573
574 log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
575 hdlc_StopTimer(&p->hdlc);
576 lqr_StopTimer(p);
577 lcp_Setup(fsm2lcp(fp), 0);
578}
579
580static int
581E164ok(struct callback *cb, char *req, int sz)
582{
583 char list[sizeof cb->msg], *next;
584 int len;
585
586 if (!strcmp(cb->msg, "*"))
587 return 1;
588
589 strncpy(list, cb->msg, sizeof list - 1);
590 list[sizeof list - 1] = '\0';
591 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
592 len = strlen(next);
593 if (sz == len && !memcmp(list, req, sz))
594 return 1;
595 }
596 return 0;
597}
598
599static void
600LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
601 struct fsm_decode *dec)
602{
603 /* Deal with incoming PROTO_LCP */
604 struct lcp *lcp = fsm2lcp(fp);
595 int type, length, sz, pos, op, callback_req;
605 int type, length, sz, pos, op, callback_req, mru_req;
596 u_int32_t magic, accmap;
606 u_int32_t magic, accmap;
597 u_short mtu, mru, proto;
607 u_short mru, phmtu, proto;
598 struct lqrreq *req;
599 char request[20], desc[22];
600 struct mp *mp;
601 struct physical *p = link2physical(fp->link);
602
608 struct lqrreq *req;
609 char request[20], desc[22];
610 struct mp *mp;
611 struct physical *p = link2physical(fp->link);
612
603 sz = op = callback_req = 0;
613 sz = op = callback_req = mru_req = 0;
604
605 while (plen >= sizeof(struct fsmconfig)) {
606 type = *cp;
607 length = cp[1];
608
609 snprintf(request, sizeof request, " %s[%d]", protoname(type), length);
610
611 if (length < 2) {
612 log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request);
613 break;
614 }
615
616 switch (type) {
617 case TY_MRRU:
618 mp = &lcp->fsm.bundle->ncp.mp;
619 ua_ntohs(cp + 2, &mru);
620 log_Printf(LogLCP, "%s %u\n", request, mru);
621
622 switch (mode_type) {
623 case MODE_REQ:
624 if (mp->cfg.mrru) {
625 if (REJECTED(lcp, TY_MRRU))
626 /* Ignore his previous reject so that we REQ next time */
627 lcp->his_reject &= ~(1 << type);
628
614
615 while (plen >= sizeof(struct fsmconfig)) {
616 type = *cp;
617 length = cp[1];
618
619 snprintf(request, sizeof request, " %s[%d]", protoname(type), length);
620
621 if (length < 2) {
622 log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request);
623 break;
624 }
625
626 switch (type) {
627 case TY_MRRU:
628 mp = &lcp->fsm.bundle->ncp.mp;
629 ua_ntohs(cp + 2, &mru);
630 log_Printf(LogLCP, "%s %u\n", request, mru);
631
632 switch (mode_type) {
633 case MODE_REQ:
634 if (mp->cfg.mrru) {
635 if (REJECTED(lcp, TY_MRRU))
636 /* Ignore his previous reject so that we REQ next time */
637 lcp->his_reject &= ~(1 << type);
638
629 if (mru < MIN_MRU) {
639 if (mru > MAX_MRU) {
640 /* Push him down to MAX_MRU */
641 lcp->his_mrru = MAX_MRU;
642 memcpy(dec->nakend, cp, 2);
643 ua_htons(&lcp->his_mrru, dec->nakend + 2);
644 dec->nakend += 4;
645 } else if (mru < MIN_MRU) {
630 /* Push him up to MIN_MRU */
631 lcp->his_mrru = MIN_MRU;
632 memcpy(dec->nakend, cp, 2);
633 ua_htons(&lcp->his_mrru, dec->nakend + 2);
634 dec->nakend += 4;
635 } else {
636 lcp->his_mrru = mru;
637 memcpy(dec->ackend, cp, 4);
638 dec->ackend += 4;
639 }
640 break;
641 } else
642 goto reqreject;
643 break;
644 case MODE_NAK:
645 if (mp->cfg.mrru) {
646 if (REJECTED(lcp, TY_MRRU))
647 /* Must have changed his mind ! */
648 lcp->his_reject &= ~(1 << type);
649
650 if (mru > MAX_MRU)
651 lcp->want_mrru = MAX_MRU;
652 else if (mru < MIN_MRU)
653 lcp->want_mrru = MIN_MRU;
654 else
655 lcp->want_mrru = mru;
656 }
657 /* else we honour our config and don't send the suggested REQ */
658 break;
659 case MODE_REJ:
660 lcp->his_reject |= (1 << type);
661 lcp->want_mrru = 0; /* Ah well, no multilink :-( */
662 break;
663 }
664 break;
665
666 case TY_MRU:
646 /* Push him up to MIN_MRU */
647 lcp->his_mrru = MIN_MRU;
648 memcpy(dec->nakend, cp, 2);
649 ua_htons(&lcp->his_mrru, dec->nakend + 2);
650 dec->nakend += 4;
651 } else {
652 lcp->his_mrru = mru;
653 memcpy(dec->ackend, cp, 4);
654 dec->ackend += 4;
655 }
656 break;
657 } else
658 goto reqreject;
659 break;
660 case MODE_NAK:
661 if (mp->cfg.mrru) {
662 if (REJECTED(lcp, TY_MRRU))
663 /* Must have changed his mind ! */
664 lcp->his_reject &= ~(1 << type);
665
666 if (mru > MAX_MRU)
667 lcp->want_mrru = MAX_MRU;
668 else if (mru < MIN_MRU)
669 lcp->want_mrru = MIN_MRU;
670 else
671 lcp->want_mrru = mru;
672 }
673 /* else we honour our config and don't send the suggested REQ */
674 break;
675 case MODE_REJ:
676 lcp->his_reject |= (1 << type);
677 lcp->want_mrru = 0; /* Ah well, no multilink :-( */
678 break;
679 }
680 break;
681
682 case TY_MRU:
683 mru_req = 1;
667 ua_ntohs(cp + 2, &mru);
668 log_Printf(LogLCP, "%s %d\n", request, mru);
669
670 switch (mode_type) {
671 case MODE_REQ:
684 ua_ntohs(cp + 2, &mru);
685 log_Printf(LogLCP, "%s %d\n", request, mru);
686
687 switch (mode_type) {
688 case MODE_REQ:
672 mtu = lcp->fsm.bundle->cfg.mtu;
673 if (mru < MIN_MRU || (!lcp->want_mrru && mru < mtu)) {
689 phmtu = p ? physical_DeviceMTU(p) : 0;
690 if (phmtu && mru > phmtu) {
691 lcp->his_mru = lcp->cfg.mtu ? lcp->cfg.mtu : phmtu;
692 memcpy(dec->nakend, cp, 2);
693 ua_htons(&lcp->his_mru, dec->nakend + 2);
694 dec->nakend += 4;
695 } if (mru > lcp->cfg.max_mtu) {
696 lcp->his_mru = lcp->cfg.mtu ? lcp->cfg.mtu : lcp->cfg.max_mtu;
697 memcpy(dec->nakend, cp, 2);
698 ua_htons(&lcp->his_mru, dec->nakend + 2);
699 dec->nakend += 4;
700 } else if (mru < MIN_MRU || mru < lcp->cfg.mtu) {
674 /* Push him up to MTU or MIN_MRU */
701 /* Push him up to MTU or MIN_MRU */
675 lcp->his_mru = mru < mtu ? mtu : MIN_MRU;
702 lcp->his_mru = mru < lcp->cfg.mtu ? lcp->cfg.mtu : MIN_MRU;
676 memcpy(dec->nakend, cp, 2);
677 ua_htons(&lcp->his_mru, dec->nakend + 2);
678 dec->nakend += 4;
679 } else {
703 memcpy(dec->nakend, cp, 2);
704 ua_htons(&lcp->his_mru, dec->nakend + 2);
705 dec->nakend += 4;
706 } else {
680 lcp->his_mru = mtu ? mtu : mru;
707 lcp->his_mru = lcp->cfg.mtu ? lcp->cfg.mtu : mru;
681 memcpy(dec->ackend, cp, 4);
682 dec->ackend += 4;
683 }
684 break;
685 case MODE_NAK:
708 memcpy(dec->ackend, cp, 4);
709 dec->ackend += 4;
710 }
711 break;
712 case MODE_NAK:
686 if (mru > MAX_MRU)
687 lcp->want_mru = MAX_MRU;
688 else if (mru < MIN_MRU)
713 if (mru > lcp->cfg.max_mru) {
714 lcp->want_mru = lcp->cfg.max_mru;
715 if (p && lcp->want_mru > physical_DeviceMTU(p))
716 lcp->want_mru = physical_DeviceMTU(p);
717 } else if (mru < MIN_MRU)
689 lcp->want_mru = MIN_MRU;
690 else
691 lcp->want_mru = mru;
692 break;
693 case MODE_REJ:
694 lcp->his_reject |= (1 << type);
695 break;
696 }
697 break;
698
699 case TY_ACCMAP:
700 ua_ntohl(cp + 2, &accmap);
701 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
702
703 switch (mode_type) {
704 case MODE_REQ:
705 lcp->his_accmap = accmap;
706 memcpy(dec->ackend, cp, 6);
707 dec->ackend += 6;
708 break;
709 case MODE_NAK:
710 lcp->want_accmap = accmap;
711 break;
712 case MODE_REJ:
713 lcp->his_reject |= (1 << type);
714 break;
715 }
716 break;
717
718 case TY_AUTHPROTO:
719 ua_ntohs(cp + 2, &proto);
720 log_Printf(LogLCP, "%s 0x%04x (%s)\n", request, proto,
721 Auth2Nam(proto, length > 4 ? cp[4] : 0));
722
723 switch (mode_type) {
724 case MODE_REQ:
725 switch (proto) {
726 case PROTO_PAP:
727 if (length != 4) {
728 log_Printf(LogLCP, " Bad length!\n");
729 goto reqreject;
730 }
731 if (IsAccepted(lcp->cfg.pap)) {
732 lcp->his_auth = proto;
733 lcp->his_authtype = 0;
734 memcpy(dec->ackend, cp, length);
735 dec->ackend += length;
736 } else if (IsAccepted(lcp->cfg.chap05)) {
737 *dec->nakend++ = *cp;
738 *dec->nakend++ = 5;
739 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
740 *dec->nakend++ = (unsigned char) PROTO_CHAP;
741 *dec->nakend++ = 0x05;
742#ifdef HAVE_DES
743 } else if (IsAccepted(lcp->cfg.chap80nt) ||
744 IsAccepted(lcp->cfg.chap80lm)) {
745 *dec->nakend++ = *cp;
746 *dec->nakend++ = 5;
747 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
748 *dec->nakend++ = (unsigned char) PROTO_CHAP;
749 *dec->nakend++ = 0x80;
750 } else if (IsAccepted(lcp->cfg.chap81)) {
751 *dec->nakend++ = *cp;
752 *dec->nakend++ = 5;
753 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
754 *dec->nakend++ = (unsigned char) PROTO_CHAP;
755 *dec->nakend++ = 0x81;
756#endif
757 } else
758 goto reqreject;
759 break;
760
761 case PROTO_CHAP:
762 if (length != 5) {
763 log_Printf(LogLCP, " Bad length!\n");
764 goto reqreject;
765 }
766 if ((cp[4] == 0x05 && IsAccepted(lcp->cfg.chap05))
767#ifdef HAVE_DES
768 || (cp[4] == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
769 (IsAccepted(lcp->cfg.chap80lm))))
770 || (cp[4] == 0x81 && IsAccepted(lcp->cfg.chap81))
771#endif
772 ) {
773 lcp->his_auth = proto;
774 lcp->his_authtype = cp[4];
775 memcpy(dec->ackend, cp, length);
776 dec->ackend += length;
777 } else {
778#ifndef HAVE_DES
779 if (cp[4] == 0x80) {
780 log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
781 } else if (cp[4] == 0x81) {
782 log_Printf(LogWARN, "CHAP 0x81 not available without DES\n");
783 } else
784#endif
785 if (cp[4] != 0x05)
786 log_Printf(LogWARN, "%s not supported\n",
787 Auth2Nam(PROTO_CHAP, cp[4]));
788
789 if (IsAccepted(lcp->cfg.chap05)) {
790 *dec->nakend++ = *cp;
791 *dec->nakend++ = 5;
792 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
793 *dec->nakend++ = (unsigned char) PROTO_CHAP;
794 *dec->nakend++ = 0x05;
795#ifdef HAVE_DES
796 } else if (IsAccepted(lcp->cfg.chap80nt) ||
797 IsAccepted(lcp->cfg.chap80lm)) {
798 *dec->nakend++ = *cp;
799 *dec->nakend++ = 5;
800 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
801 *dec->nakend++ = (unsigned char) PROTO_CHAP;
802 *dec->nakend++ = 0x80;
803 } else if (IsAccepted(lcp->cfg.chap81)) {
804 *dec->nakend++ = *cp;
805 *dec->nakend++ = 5;
806 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
807 *dec->nakend++ = (unsigned char) PROTO_CHAP;
808 *dec->nakend++ = 0x81;
809#endif
810 } else if (IsAccepted(lcp->cfg.pap)) {
811 *dec->nakend++ = *cp;
812 *dec->nakend++ = 4;
813 *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
814 *dec->nakend++ = (unsigned char) PROTO_PAP;
815 } else
816 goto reqreject;
817 }
818 break;
819
820 default:
821 log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
822 request, proto);
823 memcpy(dec->nakend, cp, length);
824 dec->nakend += length;
825 break;
826 }
827 break;
828 case MODE_NAK:
829 switch (proto) {
830 case PROTO_PAP:
831 if (IsEnabled(lcp->cfg.pap)) {
832 lcp->want_auth = PROTO_PAP;
833 lcp->want_authtype = 0;
834 } else {
835 log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
836 lcp->his_reject |= (1 << type);
837 }
838 break;
839 case PROTO_CHAP:
840 if (cp[4] == 0x05 && IsEnabled(lcp->cfg.chap05)) {
841 lcp->want_auth = PROTO_CHAP;
842 lcp->want_authtype = 0x05;
843#ifdef HAVE_DES
844 } else if (cp[4] == 0x80 && (IsEnabled(lcp->cfg.chap80nt) ||
845 IsEnabled(lcp->cfg.chap80lm))) {
846 lcp->want_auth = PROTO_CHAP;
847 lcp->want_authtype = 0x80;
848 } else if (cp[4] == 0x81 && IsEnabled(lcp->cfg.chap81)) {
849 lcp->want_auth = PROTO_CHAP;
850 lcp->want_authtype = 0x81;
851#endif
852 } else {
853#ifndef HAVE_DES
854 if (cp[4] == 0x80) {
855 log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
856 " without DES)\n");
857 } else if (cp[4] == 0x81) {
858 log_Printf(LogLCP, "Peer will only send MSCHAPV2 (not available"
859 " without DES)\n");
860 } else
861#endif
862 log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
863 Auth2Nam(PROTO_CHAP, cp[4]),
864#ifdef HAVE_DES
865 (cp[4] == 0x80 || cp[4] == 0x81) ? "configured" :
866#endif
867 "supported");
868 lcp->his_reject |= (1 << type);
869 }
870 break;
871 default:
872 /* We've been NAK'd with something we don't understand :-( */
873 lcp->his_reject |= (1 << type);
874 break;
875 }
876 break;
877 case MODE_REJ:
878 lcp->his_reject |= (1 << type);
879 break;
880 }
881 break;
882
883 case TY_QUALPROTO:
884 req = (struct lqrreq *)cp;
885 log_Printf(LogLCP, "%s proto %x, interval %lums\n",
886 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
887 switch (mode_type) {
888 case MODE_REQ:
889 if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
890 goto reqreject;
891 else {
892 lcp->his_lqrperiod = ntohl(req->period);
893 if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
894 lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
895 req->period = htonl(lcp->his_lqrperiod);
896 memcpy(dec->ackend, cp, length);
897 dec->ackend += length;
898 }
899 break;
900 case MODE_NAK:
901 break;
902 case MODE_REJ:
903 lcp->his_reject |= (1 << type);
904 break;
905 }
906 break;
907
908 case TY_MAGICNUM:
909 ua_ntohl(cp + 2, &magic);
910 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
911
912 switch (mode_type) {
913 case MODE_REQ:
914 if (lcp->want_magic) {
915 /* Validate magic number */
916 if (magic == lcp->want_magic) {
917 log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
918 (u_long)magic, ++lcp->LcpFailedMagic);
919 lcp->want_magic = GenerateMagic();
920 memcpy(dec->nakend, cp, 6);
921 dec->nakend += 6;
922 ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
923 sigpause(0);
924 } else {
925 lcp->his_magic = magic;
926 memcpy(dec->ackend, cp, length);
927 dec->ackend += length;
928 lcp->LcpFailedMagic = 0;
929 }
930 } else {
931 goto reqreject;
932 }
933 break;
934 case MODE_NAK:
935 log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
936 lcp->want_magic = GenerateMagic();
937 break;
938 case MODE_REJ:
939 log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
940 lcp->want_magic = 0;
941 lcp->his_reject |= (1 << type);
942 break;
943 }
944 break;
945
946 case TY_PROTOCOMP:
947 log_Printf(LogLCP, "%s\n", request);
948
949 switch (mode_type) {
950 case MODE_REQ:
951 if (IsAccepted(lcp->cfg.protocomp)) {
952 lcp->his_protocomp = 1;
953 memcpy(dec->ackend, cp, 2);
954 dec->ackend += 2;
955 } else {
956#ifdef OLDMST
957 /* MorningStar before v1.3 needs NAK */
958 memcpy(dec->nakend, cp, 2);
959 dec->nakend += 2;
960#else
961 goto reqreject;
962#endif
963 }
964 break;
965 case MODE_NAK:
966 case MODE_REJ:
967 lcp->want_protocomp = 0;
968 lcp->his_reject |= (1 << type);
969 break;
970 }
971 break;
972
973 case TY_ACFCOMP:
974 log_Printf(LogLCP, "%s\n", request);
975 switch (mode_type) {
976 case MODE_REQ:
977 if (IsAccepted(lcp->cfg.acfcomp)) {
978 lcp->his_acfcomp = 1;
979 memcpy(dec->ackend, cp, 2);
980 dec->ackend += 2;
981 } else {
982#ifdef OLDMST
983 /* MorningStar before v1.3 needs NAK */
984 memcpy(dec->nakend, cp, 2);
985 dec->nakend += 2;
986#else
987 goto reqreject;
988#endif
989 }
990 break;
991 case MODE_NAK:
992 case MODE_REJ:
993 lcp->want_acfcomp = 0;
994 lcp->his_reject |= (1 << type);
995 break;
996 }
997 break;
998
999 case TY_SDP:
1000 log_Printf(LogLCP, "%s\n", request);
1001 switch (mode_type) {
1002 case MODE_REQ:
1003 case MODE_NAK:
1004 case MODE_REJ:
1005 break;
1006 }
1007 break;
1008
1009 case TY_CALLBACK:
1010 if (length == 2)
1011 op = CALLBACK_NONE;
1012 else
1013 op = (int)cp[2];
1014 sz = length - 3;
1015 switch (op) {
1016 case CALLBACK_AUTH:
1017 log_Printf(LogLCP, "%s Auth\n", request);
1018 break;
1019 case CALLBACK_DIALSTRING:
1020 log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3);
1021 break;
1022 case CALLBACK_LOCATION:
1023 log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3);
1024 break;
1025 case CALLBACK_E164:
1026 log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3);
1027 break;
1028 case CALLBACK_NAME:
1029 log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3);
1030 break;
1031 case CALLBACK_CBCP:
1032 log_Printf(LogLCP, "%s CBCP\n", request);
1033 break;
1034 default:
1035 log_Printf(LogLCP, "%s ???\n", request);
1036 break;
1037 }
1038
1039 switch (mode_type) {
1040 case MODE_REQ:
1041 callback_req = 1;
1042 if (p->type != PHYS_DIRECT)
1043 goto reqreject;
1044 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
1045 (op != CALLBACK_AUTH || p->link.lcp.auth_ineed) &&
1046 (op != CALLBACK_E164 ||
1047 E164ok(&p->dl->cfg.callback, cp + 3, sz))) {
1048 lcp->his_callback.opmask = CALLBACK_BIT(op);
1049 if (sz > sizeof lcp->his_callback.msg - 1) {
1050 sz = sizeof lcp->his_callback.msg - 1;
1051 log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz);
1052 }
1053 memcpy(lcp->his_callback.msg, cp + 3, sz);
1054 lcp->his_callback.msg[sz] = '\0';
1055 memcpy(dec->ackend, cp, sz + 3);
1056 dec->ackend += sz + 3;
1057 } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1058 p->link.lcp.auth_ineed) {
1059 *dec->nakend++ = *cp;
1060 *dec->nakend++ = 3;
1061 *dec->nakend++ = CALLBACK_AUTH;
1062 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
1063 *dec->nakend++ = *cp;
1064 *dec->nakend++ = 3;
1065 *dec->nakend++ = CALLBACK_CBCP;
1066 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
1067 *dec->nakend++ = *cp;
1068 *dec->nakend++ = 3;
1069 *dec->nakend++ = CALLBACK_E164;
1070 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
1071 log_Printf(LogWARN, "Cannot insist on auth callback without"
1072 " PAP or CHAP enabled !\n");
1073 *dec->nakend++ = *cp;
1074 *dec->nakend++ = 2;
1075 } else
1076 goto reqreject;
1077 break;
1078 case MODE_NAK:
1079 /* We don't do what he NAKs with, we do things in our preferred order */
1080 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
1081 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
1082 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1083 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
1084 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1085 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
1086 if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
1087 log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
1088 lcp->want_callback.opmask = 0;
1089 } else if (!lcp->want_callback.opmask) {
1090 log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
1091 fsm_Close(&lcp->fsm);
1092 }
1093 break;
1094 case MODE_REJ:
1095 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
1096 lcp->his_reject |= (1 << type);
1097 lcp->want_callback.opmask = 0;
1098 } else {
1099 log_Printf(LogPHASE, "Peer rejected *required* callback\n");
1100 fsm_Close(&lcp->fsm);
1101 }
1102 break;
1103 }
1104 break;
1105
1106 case TY_SHORTSEQ:
1107 mp = &lcp->fsm.bundle->ncp.mp;
1108 log_Printf(LogLCP, "%s\n", request);
1109
1110 switch (mode_type) {
1111 case MODE_REQ:
1112 if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
1113 lcp->his_shortseq = 1;
1114 memcpy(dec->ackend, cp, length);
1115 dec->ackend += length;
1116 } else
1117 goto reqreject;
1118 break;
1119 case MODE_NAK:
1120 /*
1121 * He's trying to get us to ask for short sequence numbers.
1122 * We ignore the NAK and honour our configuration file instead.
1123 */
1124 break;
1125 case MODE_REJ:
1126 lcp->his_reject |= (1 << type);
1127 lcp->want_shortseq = 0; /* For when we hit MP */
1128 break;
1129 }
1130 break;
1131
1132 case TY_ENDDISC:
1133 mp = &lcp->fsm.bundle->ncp.mp;
1134 log_Printf(LogLCP, "%s %s\n", request,
1135 mp_Enddisc(cp[2], cp + 3, length - 3));
1136 switch (mode_type) {
1137 case MODE_REQ:
1138 if (!p) {
1139 log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
1140 goto reqreject;
1141 } else if (!IsAccepted(mp->cfg.negenddisc))
1142 goto reqreject;
1143 else if (length-3 < sizeof p->dl->peer.enddisc.address &&
1144 cp[2] <= MAX_ENDDISC_CLASS) {
1145 p->dl->peer.enddisc.class = cp[2];
1146 p->dl->peer.enddisc.len = length-3;
1147 memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
1148 p->dl->peer.enddisc.address[length - 3] = '\0';
1149 /* XXX: If mp->active, compare and NAK with mp->peer ? */
1150 memcpy(dec->ackend, cp, length);
1151 dec->ackend += length;
1152 } else {
1153 if (cp[2] > MAX_ENDDISC_CLASS)
1154 log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
1155 cp[2]);
1156 else
1157 log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
1158 (long)(sizeof p->dl->peer.enddisc.address - 1));
1159 goto reqreject;
1160 }
1161 break;
1162
1163 case MODE_NAK: /* Treat this as a REJ, we don't vary our disc (yet) */
1164 case MODE_REJ:
1165 lcp->his_reject |= (1 << type);
1166 break;
1167 }
1168 break;
1169
1170 default:
1171 sz = (sizeof desc - 2) / 2;
1172 if (sz > length - 2)
1173 sz = length - 2;
1174 pos = 0;
1175 desc[0] = sz ? ' ' : '\0';
1176 for (pos = 0; sz--; pos++)
1177 sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
1178
1179 log_Printf(LogLCP, "%s%s\n", request, desc);
1180
1181 if (mode_type == MODE_REQ) {
1182reqreject:
1183 if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
1184 length = sizeof dec->rej - (dec->rejend - dec->rej);
1185 log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
1186 cp[1], length);
1187 }
1188 memcpy(dec->rejend, cp, length);
1189 dec->rejend += length;
1190 lcp->my_reject |= (1 << type);
1191 if (length != cp[1])
1192 length = 0; /* force our way out of the loop */
1193 }
1194 break;
1195 }
1196 plen -= length;
1197 cp += length;
1198 }
1199
1200 if (mode_type != MODE_NOP) {
1201 if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1202 p->dl->cfg.callback.opmask && !callback_req &&
1203 !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1204 /* We *REQUIRE* that the peer requests callback */
1205 *dec->nakend++ = TY_CALLBACK;
1206 *dec->nakend++ = 3;
1207 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1208 p->link.lcp.auth_ineed)
1209 *dec->nakend++ = CALLBACK_AUTH;
1210 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1211 *dec->nakend++ = CALLBACK_CBCP;
1212 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1213 *dec->nakend++ = CALLBACK_E164;
1214 else {
1215 log_Printf(LogWARN, "Cannot insist on auth callback without"
1216 " PAP or CHAP enabled !\n");
1217 dec->nakend[-1] = 2; /* XXX: Silly ! */
1218 }
1219 }
718 lcp->want_mru = MIN_MRU;
719 else
720 lcp->want_mru = mru;
721 break;
722 case MODE_REJ:
723 lcp->his_reject |= (1 << type);
724 break;
725 }
726 break;
727
728 case TY_ACCMAP:
729 ua_ntohl(cp + 2, &accmap);
730 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
731
732 switch (mode_type) {
733 case MODE_REQ:
734 lcp->his_accmap = accmap;
735 memcpy(dec->ackend, cp, 6);
736 dec->ackend += 6;
737 break;
738 case MODE_NAK:
739 lcp->want_accmap = accmap;
740 break;
741 case MODE_REJ:
742 lcp->his_reject |= (1 << type);
743 break;
744 }
745 break;
746
747 case TY_AUTHPROTO:
748 ua_ntohs(cp + 2, &proto);
749 log_Printf(LogLCP, "%s 0x%04x (%s)\n", request, proto,
750 Auth2Nam(proto, length > 4 ? cp[4] : 0));
751
752 switch (mode_type) {
753 case MODE_REQ:
754 switch (proto) {
755 case PROTO_PAP:
756 if (length != 4) {
757 log_Printf(LogLCP, " Bad length!\n");
758 goto reqreject;
759 }
760 if (IsAccepted(lcp->cfg.pap)) {
761 lcp->his_auth = proto;
762 lcp->his_authtype = 0;
763 memcpy(dec->ackend, cp, length);
764 dec->ackend += length;
765 } else if (IsAccepted(lcp->cfg.chap05)) {
766 *dec->nakend++ = *cp;
767 *dec->nakend++ = 5;
768 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
769 *dec->nakend++ = (unsigned char) PROTO_CHAP;
770 *dec->nakend++ = 0x05;
771#ifdef HAVE_DES
772 } else if (IsAccepted(lcp->cfg.chap80nt) ||
773 IsAccepted(lcp->cfg.chap80lm)) {
774 *dec->nakend++ = *cp;
775 *dec->nakend++ = 5;
776 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
777 *dec->nakend++ = (unsigned char) PROTO_CHAP;
778 *dec->nakend++ = 0x80;
779 } else if (IsAccepted(lcp->cfg.chap81)) {
780 *dec->nakend++ = *cp;
781 *dec->nakend++ = 5;
782 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
783 *dec->nakend++ = (unsigned char) PROTO_CHAP;
784 *dec->nakend++ = 0x81;
785#endif
786 } else
787 goto reqreject;
788 break;
789
790 case PROTO_CHAP:
791 if (length != 5) {
792 log_Printf(LogLCP, " Bad length!\n");
793 goto reqreject;
794 }
795 if ((cp[4] == 0x05 && IsAccepted(lcp->cfg.chap05))
796#ifdef HAVE_DES
797 || (cp[4] == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
798 (IsAccepted(lcp->cfg.chap80lm))))
799 || (cp[4] == 0x81 && IsAccepted(lcp->cfg.chap81))
800#endif
801 ) {
802 lcp->his_auth = proto;
803 lcp->his_authtype = cp[4];
804 memcpy(dec->ackend, cp, length);
805 dec->ackend += length;
806 } else {
807#ifndef HAVE_DES
808 if (cp[4] == 0x80) {
809 log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
810 } else if (cp[4] == 0x81) {
811 log_Printf(LogWARN, "CHAP 0x81 not available without DES\n");
812 } else
813#endif
814 if (cp[4] != 0x05)
815 log_Printf(LogWARN, "%s not supported\n",
816 Auth2Nam(PROTO_CHAP, cp[4]));
817
818 if (IsAccepted(lcp->cfg.chap05)) {
819 *dec->nakend++ = *cp;
820 *dec->nakend++ = 5;
821 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
822 *dec->nakend++ = (unsigned char) PROTO_CHAP;
823 *dec->nakend++ = 0x05;
824#ifdef HAVE_DES
825 } else if (IsAccepted(lcp->cfg.chap80nt) ||
826 IsAccepted(lcp->cfg.chap80lm)) {
827 *dec->nakend++ = *cp;
828 *dec->nakend++ = 5;
829 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
830 *dec->nakend++ = (unsigned char) PROTO_CHAP;
831 *dec->nakend++ = 0x80;
832 } else if (IsAccepted(lcp->cfg.chap81)) {
833 *dec->nakend++ = *cp;
834 *dec->nakend++ = 5;
835 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
836 *dec->nakend++ = (unsigned char) PROTO_CHAP;
837 *dec->nakend++ = 0x81;
838#endif
839 } else if (IsAccepted(lcp->cfg.pap)) {
840 *dec->nakend++ = *cp;
841 *dec->nakend++ = 4;
842 *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
843 *dec->nakend++ = (unsigned char) PROTO_PAP;
844 } else
845 goto reqreject;
846 }
847 break;
848
849 default:
850 log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
851 request, proto);
852 memcpy(dec->nakend, cp, length);
853 dec->nakend += length;
854 break;
855 }
856 break;
857 case MODE_NAK:
858 switch (proto) {
859 case PROTO_PAP:
860 if (IsEnabled(lcp->cfg.pap)) {
861 lcp->want_auth = PROTO_PAP;
862 lcp->want_authtype = 0;
863 } else {
864 log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
865 lcp->his_reject |= (1 << type);
866 }
867 break;
868 case PROTO_CHAP:
869 if (cp[4] == 0x05 && IsEnabled(lcp->cfg.chap05)) {
870 lcp->want_auth = PROTO_CHAP;
871 lcp->want_authtype = 0x05;
872#ifdef HAVE_DES
873 } else if (cp[4] == 0x80 && (IsEnabled(lcp->cfg.chap80nt) ||
874 IsEnabled(lcp->cfg.chap80lm))) {
875 lcp->want_auth = PROTO_CHAP;
876 lcp->want_authtype = 0x80;
877 } else if (cp[4] == 0x81 && IsEnabled(lcp->cfg.chap81)) {
878 lcp->want_auth = PROTO_CHAP;
879 lcp->want_authtype = 0x81;
880#endif
881 } else {
882#ifndef HAVE_DES
883 if (cp[4] == 0x80) {
884 log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
885 " without DES)\n");
886 } else if (cp[4] == 0x81) {
887 log_Printf(LogLCP, "Peer will only send MSCHAPV2 (not available"
888 " without DES)\n");
889 } else
890#endif
891 log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
892 Auth2Nam(PROTO_CHAP, cp[4]),
893#ifdef HAVE_DES
894 (cp[4] == 0x80 || cp[4] == 0x81) ? "configured" :
895#endif
896 "supported");
897 lcp->his_reject |= (1 << type);
898 }
899 break;
900 default:
901 /* We've been NAK'd with something we don't understand :-( */
902 lcp->his_reject |= (1 << type);
903 break;
904 }
905 break;
906 case MODE_REJ:
907 lcp->his_reject |= (1 << type);
908 break;
909 }
910 break;
911
912 case TY_QUALPROTO:
913 req = (struct lqrreq *)cp;
914 log_Printf(LogLCP, "%s proto %x, interval %lums\n",
915 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
916 switch (mode_type) {
917 case MODE_REQ:
918 if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
919 goto reqreject;
920 else {
921 lcp->his_lqrperiod = ntohl(req->period);
922 if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
923 lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
924 req->period = htonl(lcp->his_lqrperiod);
925 memcpy(dec->ackend, cp, length);
926 dec->ackend += length;
927 }
928 break;
929 case MODE_NAK:
930 break;
931 case MODE_REJ:
932 lcp->his_reject |= (1 << type);
933 break;
934 }
935 break;
936
937 case TY_MAGICNUM:
938 ua_ntohl(cp + 2, &magic);
939 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
940
941 switch (mode_type) {
942 case MODE_REQ:
943 if (lcp->want_magic) {
944 /* Validate magic number */
945 if (magic == lcp->want_magic) {
946 log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
947 (u_long)magic, ++lcp->LcpFailedMagic);
948 lcp->want_magic = GenerateMagic();
949 memcpy(dec->nakend, cp, 6);
950 dec->nakend += 6;
951 ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
952 sigpause(0);
953 } else {
954 lcp->his_magic = magic;
955 memcpy(dec->ackend, cp, length);
956 dec->ackend += length;
957 lcp->LcpFailedMagic = 0;
958 }
959 } else {
960 goto reqreject;
961 }
962 break;
963 case MODE_NAK:
964 log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
965 lcp->want_magic = GenerateMagic();
966 break;
967 case MODE_REJ:
968 log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
969 lcp->want_magic = 0;
970 lcp->his_reject |= (1 << type);
971 break;
972 }
973 break;
974
975 case TY_PROTOCOMP:
976 log_Printf(LogLCP, "%s\n", request);
977
978 switch (mode_type) {
979 case MODE_REQ:
980 if (IsAccepted(lcp->cfg.protocomp)) {
981 lcp->his_protocomp = 1;
982 memcpy(dec->ackend, cp, 2);
983 dec->ackend += 2;
984 } else {
985#ifdef OLDMST
986 /* MorningStar before v1.3 needs NAK */
987 memcpy(dec->nakend, cp, 2);
988 dec->nakend += 2;
989#else
990 goto reqreject;
991#endif
992 }
993 break;
994 case MODE_NAK:
995 case MODE_REJ:
996 lcp->want_protocomp = 0;
997 lcp->his_reject |= (1 << type);
998 break;
999 }
1000 break;
1001
1002 case TY_ACFCOMP:
1003 log_Printf(LogLCP, "%s\n", request);
1004 switch (mode_type) {
1005 case MODE_REQ:
1006 if (IsAccepted(lcp->cfg.acfcomp)) {
1007 lcp->his_acfcomp = 1;
1008 memcpy(dec->ackend, cp, 2);
1009 dec->ackend += 2;
1010 } else {
1011#ifdef OLDMST
1012 /* MorningStar before v1.3 needs NAK */
1013 memcpy(dec->nakend, cp, 2);
1014 dec->nakend += 2;
1015#else
1016 goto reqreject;
1017#endif
1018 }
1019 break;
1020 case MODE_NAK:
1021 case MODE_REJ:
1022 lcp->want_acfcomp = 0;
1023 lcp->his_reject |= (1 << type);
1024 break;
1025 }
1026 break;
1027
1028 case TY_SDP:
1029 log_Printf(LogLCP, "%s\n", request);
1030 switch (mode_type) {
1031 case MODE_REQ:
1032 case MODE_NAK:
1033 case MODE_REJ:
1034 break;
1035 }
1036 break;
1037
1038 case TY_CALLBACK:
1039 if (length == 2)
1040 op = CALLBACK_NONE;
1041 else
1042 op = (int)cp[2];
1043 sz = length - 3;
1044 switch (op) {
1045 case CALLBACK_AUTH:
1046 log_Printf(LogLCP, "%s Auth\n", request);
1047 break;
1048 case CALLBACK_DIALSTRING:
1049 log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3);
1050 break;
1051 case CALLBACK_LOCATION:
1052 log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3);
1053 break;
1054 case CALLBACK_E164:
1055 log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3);
1056 break;
1057 case CALLBACK_NAME:
1058 log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3);
1059 break;
1060 case CALLBACK_CBCP:
1061 log_Printf(LogLCP, "%s CBCP\n", request);
1062 break;
1063 default:
1064 log_Printf(LogLCP, "%s ???\n", request);
1065 break;
1066 }
1067
1068 switch (mode_type) {
1069 case MODE_REQ:
1070 callback_req = 1;
1071 if (p->type != PHYS_DIRECT)
1072 goto reqreject;
1073 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
1074 (op != CALLBACK_AUTH || p->link.lcp.auth_ineed) &&
1075 (op != CALLBACK_E164 ||
1076 E164ok(&p->dl->cfg.callback, cp + 3, sz))) {
1077 lcp->his_callback.opmask = CALLBACK_BIT(op);
1078 if (sz > sizeof lcp->his_callback.msg - 1) {
1079 sz = sizeof lcp->his_callback.msg - 1;
1080 log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz);
1081 }
1082 memcpy(lcp->his_callback.msg, cp + 3, sz);
1083 lcp->his_callback.msg[sz] = '\0';
1084 memcpy(dec->ackend, cp, sz + 3);
1085 dec->ackend += sz + 3;
1086 } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1087 p->link.lcp.auth_ineed) {
1088 *dec->nakend++ = *cp;
1089 *dec->nakend++ = 3;
1090 *dec->nakend++ = CALLBACK_AUTH;
1091 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
1092 *dec->nakend++ = *cp;
1093 *dec->nakend++ = 3;
1094 *dec->nakend++ = CALLBACK_CBCP;
1095 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
1096 *dec->nakend++ = *cp;
1097 *dec->nakend++ = 3;
1098 *dec->nakend++ = CALLBACK_E164;
1099 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
1100 log_Printf(LogWARN, "Cannot insist on auth callback without"
1101 " PAP or CHAP enabled !\n");
1102 *dec->nakend++ = *cp;
1103 *dec->nakend++ = 2;
1104 } else
1105 goto reqreject;
1106 break;
1107 case MODE_NAK:
1108 /* We don't do what he NAKs with, we do things in our preferred order */
1109 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
1110 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
1111 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1112 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
1113 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1114 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
1115 if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
1116 log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
1117 lcp->want_callback.opmask = 0;
1118 } else if (!lcp->want_callback.opmask) {
1119 log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
1120 fsm_Close(&lcp->fsm);
1121 }
1122 break;
1123 case MODE_REJ:
1124 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
1125 lcp->his_reject |= (1 << type);
1126 lcp->want_callback.opmask = 0;
1127 } else {
1128 log_Printf(LogPHASE, "Peer rejected *required* callback\n");
1129 fsm_Close(&lcp->fsm);
1130 }
1131 break;
1132 }
1133 break;
1134
1135 case TY_SHORTSEQ:
1136 mp = &lcp->fsm.bundle->ncp.mp;
1137 log_Printf(LogLCP, "%s\n", request);
1138
1139 switch (mode_type) {
1140 case MODE_REQ:
1141 if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
1142 lcp->his_shortseq = 1;
1143 memcpy(dec->ackend, cp, length);
1144 dec->ackend += length;
1145 } else
1146 goto reqreject;
1147 break;
1148 case MODE_NAK:
1149 /*
1150 * He's trying to get us to ask for short sequence numbers.
1151 * We ignore the NAK and honour our configuration file instead.
1152 */
1153 break;
1154 case MODE_REJ:
1155 lcp->his_reject |= (1 << type);
1156 lcp->want_shortseq = 0; /* For when we hit MP */
1157 break;
1158 }
1159 break;
1160
1161 case TY_ENDDISC:
1162 mp = &lcp->fsm.bundle->ncp.mp;
1163 log_Printf(LogLCP, "%s %s\n", request,
1164 mp_Enddisc(cp[2], cp + 3, length - 3));
1165 switch (mode_type) {
1166 case MODE_REQ:
1167 if (!p) {
1168 log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
1169 goto reqreject;
1170 } else if (!IsAccepted(mp->cfg.negenddisc))
1171 goto reqreject;
1172 else if (length-3 < sizeof p->dl->peer.enddisc.address &&
1173 cp[2] <= MAX_ENDDISC_CLASS) {
1174 p->dl->peer.enddisc.class = cp[2];
1175 p->dl->peer.enddisc.len = length-3;
1176 memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
1177 p->dl->peer.enddisc.address[length - 3] = '\0';
1178 /* XXX: If mp->active, compare and NAK with mp->peer ? */
1179 memcpy(dec->ackend, cp, length);
1180 dec->ackend += length;
1181 } else {
1182 if (cp[2] > MAX_ENDDISC_CLASS)
1183 log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
1184 cp[2]);
1185 else
1186 log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
1187 (long)(sizeof p->dl->peer.enddisc.address - 1));
1188 goto reqreject;
1189 }
1190 break;
1191
1192 case MODE_NAK: /* Treat this as a REJ, we don't vary our disc (yet) */
1193 case MODE_REJ:
1194 lcp->his_reject |= (1 << type);
1195 break;
1196 }
1197 break;
1198
1199 default:
1200 sz = (sizeof desc - 2) / 2;
1201 if (sz > length - 2)
1202 sz = length - 2;
1203 pos = 0;
1204 desc[0] = sz ? ' ' : '\0';
1205 for (pos = 0; sz--; pos++)
1206 sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
1207
1208 log_Printf(LogLCP, "%s%s\n", request, desc);
1209
1210 if (mode_type == MODE_REQ) {
1211reqreject:
1212 if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
1213 length = sizeof dec->rej - (dec->rejend - dec->rej);
1214 log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
1215 cp[1], length);
1216 }
1217 memcpy(dec->rejend, cp, length);
1218 dec->rejend += length;
1219 lcp->my_reject |= (1 << type);
1220 if (length != cp[1])
1221 length = 0; /* force our way out of the loop */
1222 }
1223 break;
1224 }
1225 plen -= length;
1226 cp += length;
1227 }
1228
1229 if (mode_type != MODE_NOP) {
1230 if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1231 p->dl->cfg.callback.opmask && !callback_req &&
1232 !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1233 /* We *REQUIRE* that the peer requests callback */
1234 *dec->nakend++ = TY_CALLBACK;
1235 *dec->nakend++ = 3;
1236 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1237 p->link.lcp.auth_ineed)
1238 *dec->nakend++ = CALLBACK_AUTH;
1239 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1240 *dec->nakend++ = CALLBACK_CBCP;
1241 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1242 *dec->nakend++ = CALLBACK_E164;
1243 else {
1244 log_Printf(LogWARN, "Cannot insist on auth callback without"
1245 " PAP or CHAP enabled !\n");
1246 dec->nakend[-1] = 2; /* XXX: Silly ! */
1247 }
1248 }
1249 if (mode_type == MODE_REQ && !mru_req) {
1250 mru = DEF_MRU;
1251 phmtu = p ? physical_DeviceMTU(p) : 0;
1252 if (phmtu && mru > phmtu)
1253 mru = phmtu;
1254 if (mru > lcp->cfg.max_mtu)
1255 mru = lcp->cfg.max_mtu;
1256 if (mru < DEF_MRU) {
1257 /* Don't let the peer use the default MRU */
1258 lcp->his_mru = lcp->cfg.mtu && lcp->cfg.mtu < mru ? lcp->cfg.mtu : mru;
1259 *dec->nakend++ = TY_MRU;
1260 *dec->nakend++ = 4;
1261 ua_htons(&lcp->his_mru, dec->nakend);
1262 dec->nakend += 2;
1263 }
1264 }
1220 if (dec->rejend != dec->rej) {
1221 /* rejects are preferred */
1222 dec->ackend = dec->ack;
1223 dec->nakend = dec->nak;
1224 } else if (dec->nakend != dec->nak)
1225 /* then NAKs */
1226 dec->ackend = dec->ack;
1227 }
1228}
1229
1230extern struct mbuf *
1231lcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1232{
1233 /* Got PROTO_LCP from link */
1234 m_settype(bp, MB_LCPIN);
1235 fsm_Input(&l->lcp.fsm, bp);
1236 return NULL;
1237}
1265 if (dec->rejend != dec->rej) {
1266 /* rejects are preferred */
1267 dec->ackend = dec->ack;
1268 dec->nakend = dec->nak;
1269 } else if (dec->nakend != dec->nak)
1270 /* then NAKs */
1271 dec->ackend = dec->ack;
1272 }
1273}
1274
1275extern struct mbuf *
1276lcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1277{
1278 /* Got PROTO_LCP from link */
1279 m_settype(bp, MB_LCPIN);
1280 fsm_Input(&l->lcp.fsm, bp);
1281 return NULL;
1282}