2 * lcp.c - PPP Link Control Protocol.
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
7 * Copyright (c) 1989 Carnegie Mellon University.
10 * Copyright (c) 2016 by Delphix. All rights reserved.
12 * Redistribution and use in source and binary forms are permitted
13 * provided that the above copyright notice and this paragraph are
14 * duplicated in all such forms and that any documentation,
15 * advertising materials, and other materials related to such
16 * distribution and use acknowledge that the software was developed
17 * by Carnegie Mellon University. The name of the
18 * University may not be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
22 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 #define RCSID "$Id: lcp.c,v 1.54 2000/04/27 03:51:18 masputra Exp $"
35 #if defined(CHAPMS) || defined(CHAPMSV2)
52 #include "patchlevel.h"
54 #if !defined(lint) && !defined(_lint)
55 static const char rcsid
[] = RCSID
;
59 * Special failure codes for logging link failure reasons.
61 bool peer_nak_auth
; /* Peer sent nak for our auth request */
62 u_short nak_auth_orig
; /* Auth proto peer naked */
63 u_short nak_auth_proto
; /* Auth proto peer suggested instead */
64 bool unsolicited_nak_auth
; /* Peer asked us to authenticate */
65 u_short unsolicit_auth_proto
; /* Auth proto peer wants */
66 bool peer_reject_auth
; /* Peer sent reject for auth */
67 u_short reject_auth_proto
; /* Protocol that peer rejected */
68 bool rejected_peers_auth
; /* We sent a reject to the peer */
69 u_short rejected_auth_proto
; /* Protocol that peer wanted to use */
70 bool naked_peers_auth
; /* We sent a nak to the peer */
71 u_short naked_auth_orig
; /* Protocol that we wanted to use */
72 u_short naked_auth_proto
; /* Protocol that peer wants us to use */
75 * LCP-related command-line options.
77 int lcp_echo_interval
= 0; /* Interval between LCP echo-requests */
78 int lcp_echo_fails
= 0; /* Tolerance to unanswered echo-requests */
79 bool lax_recv
= 0; /* accept control chars in asyncmap */
80 static int use_accm_test
= 2; /* use big echo-requests to check ACCM */
81 #define ACCM_TEST_FAILS 5
84 #define _tostr(x) _tostr2(x)
85 static char identstr
[256] = /* Identification string */
86 "ppp-" VERSION
"." _tostr(PATCHLEVEL
) IMPLEMENTATION
;
87 static int noident
= 0; /* 1 to disable; 2 to reject */
88 static int sentident
= 0; /* counts the # of ident codes sent */
90 /* set if we're allowed to send an unsolicited Configure-Nak for MRU. */
91 static bool unsolicit_mru
;
93 static int setescape
__P((char **, option_t
*));
95 static bool do_msft_workaround
= 1;
96 static int setasyncmap
__P((char **, option_t
*));
98 bool noendpoint
= 0; /* don't send/accept endpoint discriminator */
99 static int setendpoint
__P((char **, option_t
*));
101 static char *callback_strings
[] = {
102 "auth", "dialstring", "location", "E.164", "X.500", "", "CBCP", NULL
105 /* This is used in packet printing even if NEGOTIATE_FCS isn't enabled */
106 static char *fcsalt_strings
[] = {
107 "null", "crc16", "crc32", NULL
111 static int setfcsallow
__P((char **, option_t
*));
112 static int setfcswant
__P((char **, option_t
*));
115 /* Backward compatibility for Linux */
117 #define PPP_MTU 1500 /* Default MTU (size of Info field) */
118 #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN)
119 #define PPP_MINMTU 64
120 #define PPP_MAXMRU 65000 /* Largest MRU we allow */
121 #define PPP_MINMRU 128
124 static option_t lcp_option_list
[] = {
126 { "noaccomp", o_bool
, &lcp_wantoptions
[0].neg_accompression
,
127 "Disable address/control compression",
128 OPT_A2COPY
, &lcp_allowoptions
[0].neg_accompression
},
129 { "-ac", o_bool
, &lcp_wantoptions
[0].neg_accompression
,
130 "Disable address/control compression",
131 OPT_A2COPY
, &lcp_allowoptions
[0].neg_accompression
},
132 { "default-asyncmap", o_bool
, &lcp_wantoptions
[0].neg_asyncmap
,
133 "Disable asyncmap negotiation",
134 OPT_A2COPY
, &lcp_allowoptions
[0].neg_asyncmap
},
135 { "-am", o_bool
, &lcp_wantoptions
[0].neg_asyncmap
,
136 "Disable asyncmap negotiation",
137 OPT_A2COPY
, &lcp_allowoptions
[0].neg_asyncmap
},
138 { "asyncmap", o_special
, (void *)setasyncmap
,
139 "Set asyncmap (for received packets)" },
140 { "-as", o_special
, (void *)setasyncmap
,
141 "Set asyncmap (for received packets)" },
142 { "nomagic", o_bool
, &lcp_wantoptions
[0].neg_magicnumber
,
143 "Disable magic number option (looped-back line detect)",
144 OPT_A2COPY
, &lcp_allowoptions
[0].neg_magicnumber
},
145 { "-mn", o_bool
, &lcp_wantoptions
[0].neg_magicnumber
,
146 "Disable magic number option (looped-back line detect)",
147 OPT_A2COPY
, &lcp_allowoptions
[0].neg_magicnumber
},
148 { "default-mru", o_bool
, &lcp_wantoptions
[0].neg_mru
,
149 "Disable MRU negotiation (use default 1500)",
150 OPT_A2COPY
, &lcp_allowoptions
[0].neg_mru
},
151 { "-mru", o_bool
, &lcp_wantoptions
[0].neg_mru
,
152 "Disable MRU negotiation (use default 1500)",
153 OPT_A2COPY
, &lcp_allowoptions
[0].neg_mru
},
154 { "mru", o_int
, &lcp_wantoptions
[0].mru
,
155 "Set MRU (maximum received packet size) for negotiation",
156 OPT_LIMITS
, &lcp_wantoptions
[0].neg_mru
, PPP_MAXMRU
, PPP_MINMRU
},
157 { "mtu", o_int
, &lcp_allowoptions
[0].mru
,
158 "Set our MTU", OPT_LIMITS
|OPT_A2COPY
, &lcp_allowoptions
[0].mrru
,
159 PPP_MAXMTU
, PPP_MINMTU
},
160 { "nopcomp", o_bool
, &lcp_wantoptions
[0].neg_pcompression
,
161 "Disable protocol field compression",
162 OPT_A2COPY
, &lcp_allowoptions
[0].neg_pcompression
},
163 { "-pc", o_bool
, &lcp_wantoptions
[0].neg_pcompression
,
164 "Disable protocol field compression",
165 OPT_A2COPY
, &lcp_allowoptions
[0].neg_pcompression
},
166 { "-p", o_bool
, &lcp_wantoptions
[0].passive
,
167 "Set passive mode", 1 },
168 { "passive", o_bool
, &lcp_wantoptions
[0].passive
,
169 "Set passive mode", 1 },
170 { "silent", o_bool
, &lcp_wantoptions
[0].silent
,
171 "Set silent mode", 1 },
172 { "escape", o_special
, (void *)setescape
,
173 "List of character codes to escape on transmission" },
174 { "lcp-echo-failure", o_int
, &lcp_echo_fails
,
175 "Number of consecutive echo failures for link failure" },
176 { "lcp-echo-interval", o_int
, &lcp_echo_interval
,
177 "Set time in seconds between LCP echo requests" },
178 { "no-accm-test", o_int
, &use_accm_test
,
179 "Disable use of LCP Echo-Request asyncmap checking",
180 OPT_NOARG
|OPT_VAL(0) },
181 { "small-accm-test", o_int
, &use_accm_test
,
182 "Use only small Echo-Requests for asyncmap checking",
183 OPT_NOARG
|OPT_VAL(1) },
184 { "lcp-restart", o_int
, &lcp_fsm
[0].timeouttime
,
185 "Set time in seconds between LCP retransmissions" },
186 { "lcp-max-terminate", o_int
, &lcp_fsm
[0].maxtermtransmits
,
187 "Maximum number of LCP terminate-request transmissions" },
188 { "lcp-max-configure", o_int
, &lcp_fsm
[0].maxconfreqtransmits
,
189 "Maximum number of LCP configure-request transmissions" },
190 { "lcp-max-failure", o_int
, &lcp_fsm
[0].maxnakloops
,
191 "Set limit on number of LCP configure-naks" },
192 { "receive-all", o_bool
, &lax_recv
,
193 "Accept all received control characters", 1 },
194 #ifdef HAVE_MULTILINK
195 { "mrru", o_int
, &lcp_wantoptions
[0].mrru
,
196 "Maximum received packet size for multilink bundle",
197 OPT_LIMITS
, &lcp_wantoptions
[0].neg_mrru
, PPP_MAXMRU
, PPP_MINMRU
},
198 { "mpshortseq", o_bool
, &lcp_wantoptions
[0].neg_ssnhf
,
199 "Use short sequence numbers in multilink headers",
200 OPT_A2COPY
| 1, &lcp_allowoptions
[0].neg_ssnhf
},
201 { "nompshortseq", o_bool
, &lcp_wantoptions
[0].neg_ssnhf
,
202 "Don't use short sequence numbers in multilink headers",
203 OPT_A2COPY
, &lcp_allowoptions
[0].neg_ssnhf
},
204 #endif /* HAVE_MULTILINK */
205 { "endpoint", o_special
, (void *)setendpoint
,
206 "Endpoint discriminator for multilink", },
207 { "noendpoint", o_bool
, &noendpoint
,
208 "Don't send or accept multilink endpoint discriminator", 1 },
209 { "ident", o_string
, identstr
,
210 "LCP Identification string", OPT_STATIC
, NULL
, sizeof(identstr
) },
211 { "noident", o_int
, &noident
,
212 "Disable use of LCP Identification", OPT_INC
|OPT_NOARG
|1 },
214 { "default-fcs", o_bool
, &lcp_wantoptions
[0].neg_fcs
,
215 "Disable FCS Alternatives option (use default CRC-16)",
216 OPT_A2COPY
, &lcp_allowoptions
[0].neg_fcs
},
217 { "allow-fcs", o_special
, (void *)setfcsallow
,
218 "Set allowable FCS types; crc16, crc32, null, or number" },
219 { "fcs", o_special
, (void *)setfcswant
,
220 "Set FCS type(s) desired; crc16, crc32, null, or number" },
224 * if pppmux option is turned on, then the parameter to this
225 * is time value in microseconds
227 { "pppmux", o_int
, &lcp_wantoptions
[0].pppmux
,
228 "Set PPP Multiplexing option timer", OPT_LLIMIT
| OPT_A2COPY
,
229 &lcp_allowoptions
[0].pppmux
, 0, 0 },
235 fsm lcp_fsm
[NUM_PPP
]; /* LCP fsm structure (global)*/
236 lcp_options lcp_wantoptions
[NUM_PPP
]; /* Options that we want to request */
237 lcp_options lcp_gotoptions
[NUM_PPP
]; /* Options that peer ack'd */
238 lcp_options lcp_allowoptions
[NUM_PPP
]; /* Options we allow peer to request */
239 lcp_options lcp_hisoptions
[NUM_PPP
]; /* Options that we ack'd */
240 u_int32_t xmit_accm
[NUM_PPP
][8]; /* extended transmit ACCM */
243 * These variables allow a plugin to assert limits on the maximum
244 * MRU/MTU values that can be negotiated.
246 int absmax_mru
= PPP_MAXMRU
;
247 int absmax_mtu
= PPP_MAXMTU
;
249 static int lcp_echos_pending
= 0; /* Number of outstanding echo msgs */
250 static int lcp_echo_number
= 0; /* ID number of next echo frame */
251 static int lcp_echo_timer_running
= 0; /* set if a timer is running */
252 static bool lcp_echo_accm_test
= 0; /* flag if still testing ACCM */
253 static int lcp_echo_badreplies
= 0; /* number of bad replies from peer */
255 * The maximum number of bad replies we tolerate before bringing the
258 #define LCP_ECHO_MAX_BADREPLIES 10
261 * Callbacks for fsm code. (CI = Configuration Information)
263 static void lcp_resetci
__P((fsm
*)); /* Reset our CI */
264 static int lcp_cilen
__P((fsm
*)); /* Return length of our CI */
265 static void lcp_addci
__P((fsm
*, u_char
*, int *)); /* Add our CI to pkt */
266 static int lcp_ackci
__P((fsm
*, u_char
*, int)); /* Peer ack'd our CI */
267 static int lcp_nakci
__P((fsm
*, u_char
*, int)); /* Peer nak'd our CI */
268 static int lcp_rejci
__P((fsm
*, u_char
*, int)); /* Peer rej'd our CI */
269 static int lcp_reqci
__P((fsm
*, u_char
*, int *, int)); /* Rcv peer CI */
270 static void lcp_up
__P((fsm
*)); /* We're UP */
271 static void lcp_down
__P((fsm
*)); /* We're DOWN */
272 static void lcp_starting
__P((fsm
*)); /* We need lower layer up */
273 static void lcp_finished
__P((fsm
*)); /* We need lower layer down */
274 static int lcp_extcode
__P((fsm
*, int, int, u_char
*, int));
275 static void lcp_rprotrej
__P((fsm
*, u_char
*, int));
276 static int lcp_coderej
__P((fsm
*f
, int code
, int id
, u_char
*inp
, int len
));
279 * routines to send LCP echos to peer
282 static void lcp_echo_lowerup
__P((int));
283 static void lcp_echo_lowerdown
__P((int));
284 static void LcpEchoTimeout
__P((void *));
285 static int lcp_received_echo_reply
__P((fsm
*, int, u_char
*, int));
286 static void LcpSendEchoRequest
__P((fsm
*));
287 static void LcpLinkFailure
__P((fsm
*));
288 static void LcpEchoCheck
__P((fsm
*));
291 * routines to send and receive additional LCP packets described in
292 * section 1 of rfc1570.
294 static void LcpSendIdentification
__P((fsm
*));
295 static void lcp_received_identification
__P((fsm
*, int, u_char
*, int));
296 static void LcpSendTimeRemaining
__P((fsm
*, u_int32_t
));
297 static void lcp_timeremaining
__P((void *));
298 static void lcp_received_timeremain
__P((fsm
*, int, u_char
*, int));
301 static fsm_callbacks lcp_callbacks
= { /* LCP callback routines */
302 lcp_resetci
, /* Reset our Configuration Information */
303 lcp_cilen
, /* Length of our Configuration Information */
304 lcp_addci
, /* Add our Configuration Information */
305 lcp_ackci
, /* ACK our Configuration Information */
306 lcp_nakci
, /* NAK our Configuration Information */
307 lcp_rejci
, /* Reject our Configuration Information */
308 lcp_reqci
, /* Request peer's Configuration Information */
309 lcp_up
, /* Called when fsm reaches OPENED state */
310 lcp_down
, /* Called when fsm leaves OPENED state */
311 lcp_starting
, /* Called when we want the lower layer up */
312 lcp_finished
, /* Called when we want the lower layer down */
313 NULL
, /* Retransmission is necessary */
314 lcp_extcode
, /* Called to handle LCP-specific codes */
315 "LCP", /* String name of protocol */
316 lcp_coderej
, /* Peer rejected a code number */
320 * Protocol entry points.
321 * Some of these are called directly.
324 static void lcp_init
__P((int));
325 static void lcp_input
__P((int, u_char
*, int));
326 static void lcp_protrej
__P((int));
327 static int lcp_printpkt
__P((u_char
*, int,
328 void (*) __P((void *, const char *, ...)), void *));
331 struct protent lcp_protent
= {
332 PPP_LCP
, /* Protocol Number for LCP */
333 lcp_init
, /* Initializes LCP */
334 lcp_input
, /* Processes a received LCP packet */
335 lcp_protrej
, /* Process a received Protocol-reject */
336 lcp_lowerup
, /* Called after the serial device has been set up */
337 lcp_lowerdown
, /* Called when the link is brought down */
338 lcp_open
, /* Called after lcp_lowerup when bringing up the link */
339 lcp_close
, /* Called when the link goes down */
340 lcp_printpkt
, /* Print a packet in human readable form */
341 NULL
, /* Process a received data packet */
342 1, /* LCP is enabled by default */
343 "LCP", /* Name of the protocol */
344 NULL
, /* Name of the corresponding data protocol */
345 lcp_option_list
, /* List of LCP command-line options */
346 NULL
, /* Assigns default values for options */
347 NULL
, /* Configures demand-dial */
348 NULL
/* Bring up the link for this packet? */
351 int lcp_loopbackfail
= DEFLOOPBACKFAIL
;
354 * Length of each type of configuration option (in octets)
358 #define CILEN_SHORT 4 /* CILEN_VOID + 2 */
359 #define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */
360 #define CILEN_LONG 6 /* CILEN_VOID + 4 */
361 #define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */
366 * setescape - add chars to the set we escape on transmission.
380 n
= strtol(p
, &endp
, 16);
382 option_error("escape parameter contains invalid hex number '%s'",
387 if (n
< 0 || n
== 0x5E || n
> 0xFF) {
388 option_error("can't escape character 0x%x", n
);
391 xmit_accm
[0][n
>> 5] |= 1 << (n
& 0x1F);
392 while (*p
== ',' || *p
== ' ')
399 * setasyncmap - set async map negotiated
403 setasyncmap(argv
, opt
)
410 val
= strtoul(*argv
, &endp
, 16);
412 option_error("invalid numeric parameter '%s' for 'asyncmap' option",
416 lcp_wantoptions
[0].asyncmap
|= val
;
417 lcp_wantoptions
[0].neg_asyncmap
= (~lcp_wantoptions
[0].asyncmap
!= 0);
418 do_msft_workaround
= 0;
424 setendpoint(argv
, opt
)
428 if (str_to_epdisc(&lcp_wantoptions
[0].endpoint
, *argv
)) {
429 lcp_wantoptions
[0].neg_endpoint
= 1;
432 option_error("Can't parse '%s' as an endpoint discriminator", *argv
);
438 str_to_fcstype(opt
,arg
)
447 while (*arg
!= '\0') {
450 len
= strtol(arg
, &cp
, 0);
451 if (len
< 0 || len
> 255 || arg
== cp
||
452 (*cp
!= '\0' && *cp
!= ','))
457 for (cpp
= fcsalt_strings
; *cpp
!= NULL
; cpp
++) {
459 if (strncasecmp(arg
, *cpp
, len
) == 0 &&
460 (arg
[len
] == '\0' || arg
[len
] == ','))
465 val
|= 1<<(cpp
-fcsalt_strings
);
467 if (arg
[len
] == '\0') {
475 option_error("Can't parse '%s' as an FCS type", arg
);
481 setfcsallow(argv
, opt
)
485 return str_to_fcstype(&lcp_allowoptions
[0], *argv
);
490 setfcswant(argv
, opt
)
494 return str_to_fcstype(&lcp_wantoptions
[0], *argv
);
499 * lcp_init - Initialize LCP.
505 fsm
*f
= &lcp_fsm
[unit
];
506 lcp_options
*wo
= &lcp_wantoptions
[unit
];
507 lcp_options
*ao
= &lcp_allowoptions
[unit
];
510 f
->protocol
= PPP_LCP
;
511 f
->callbacks
= &lcp_callbacks
;
515 BZERO(wo
, sizeof(*wo
));
518 wo
->neg_asyncmap
= 1;
519 wo
->chap_mdtype
= CHAP_DIGEST_MD5
;
520 wo
->neg_magicnumber
= 1;
521 wo
->neg_pcompression
= 1;
522 wo
->neg_accompression
= 1;
525 * Leave allowed MRU (MTU) at zero; configuration option sets it
526 * non-zero if we should nak for something else.
528 BZERO(ao
, sizeof(*ao
));
530 ao
->neg_asyncmap
= 1;
532 #if defined(CHAPMS) || defined(CHAPMSV2)
534 /* Check if DES wasn't exported */
536 setkey("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
537 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
545 ao
->neg_mschapv2
= 1;
549 ao
->chap_mdtype
= CHAP_DIGEST_MD5
;
551 ao
->neg_magicnumber
= 1;
552 ao
->neg_pcompression
= 1;
553 ao
->neg_accompression
= 1;
557 ao
->neg_endpoint
= 1;
560 ao
->fcs_type
= FCSALT_NULL
|FCSALT_16
|FCSALT_32
;
563 BZERO(xmit_accm
[unit
], sizeof(xmit_accm
[0]));
564 xmit_accm
[unit
][3] = 0x60000000;
569 * lcp_open - LCP is allowed to come up.
575 fsm
*f
= &lcp_fsm
[unit
];
576 lcp_options
*wo
= &lcp_wantoptions
[unit
];
580 f
->flags
|= OPT_PASSIVE
;
582 f
->flags
|= OPT_SILENT
;
588 * lcp_close - Take LCP down.
591 lcp_close(unit
, reason
)
595 fsm
*f
= &lcp_fsm
[unit
];
597 if (phase
!= PHASE_DEAD
)
598 new_phase(PHASE_TERMINATE
);
599 if (f
->state
== STOPPED
&& (f
->flags
& (OPT_PASSIVE
|OPT_SILENT
))) {
601 * This action is not strictly according to the FSM in RFC1548,
602 * but it does mean that the program terminates if you do a
603 * lcp_close() in passive/silent mode when a connection hasn't
610 fsm_close(&lcp_fsm
[unit
], reason
);
615 * lcp_lowerup - The lower layer is up.
621 lcp_options
*wo
= &lcp_wantoptions
[unit
];
624 mru
= PPP_MRU
> absmax_mru
? absmax_mru
: PPP_MRU
;
625 mtu
= PPP_MTU
> absmax_mtu
? absmax_mtu
: PPP_MTU
;
628 * Don't use A/C or protocol compression on transmission,
629 * but accept A/C and protocol compressed packets
630 * if we are going to ask for A/C and protocol compression.
632 ppp_set_xaccm(unit
, xmit_accm
[unit
]);
633 ppp_send_config(unit
, mtu
, 0xffffffff, 0, 0);
634 ppp_recv_config(unit
, mru
, (lax_recv
? 0: 0xffffffff),
635 wo
->neg_pcompression
, wo
->neg_accompression
);
637 ppp_send_fcs(unit
, FCSALT_16
);
638 ppp_recv_fcs(unit
, FCSALT_16
);
641 fsm_setpeermru(unit
, mtu
);
642 lcp_allowoptions
[unit
].asyncmap
= xmit_accm
[unit
][0];
644 fsm_lowerup(&lcp_fsm
[unit
]);
649 * lcp_lowerdown - The lower layer is down.
655 fsm_lowerdown(&lcp_fsm
[unit
]);
660 * lcp_input - Input LCP packet.
663 lcp_input(unit
, p
, len
)
668 fsm
*f
= &lcp_fsm
[unit
];
670 fsm_input(f
, p
, len
);
675 * lcp_extcode - Handle a LCP-specific code.
678 lcp_extcode(f
, code
, id
, inp
, len
)
688 lcp_rprotrej(f
, inp
, len
);
692 if (f
->state
!= OPENED
)
695 PUTLONG(lcp_gotoptions
[f
->unit
].magicnumber
, magp
);
696 fsm_sdata(f
, CODE_ECHOREP
, id
, inp
, len
);
700 if (!lcp_received_echo_reply(f
, id
, inp
, len
)) {
701 lcp_echo_badreplies
++;
702 if (lcp_echo_badreplies
> LCP_ECHO_MAX_BADREPLIES
) {
704 lcp_echos_pending
= 0;
705 lcp_echo_badreplies
= 0;
714 /* More than one 'noident' tells us to reject the code number. */
717 lcp_received_identification(f
, id
, inp
, len
);
720 case CODE_TIMEREMAIN
:
721 lcp_received_timeremain(f
, id
, inp
, len
);
731 * lcp_rprotrej - Receive an Protocol-Reject.
733 * Figure out which protocol is rejected and inform it.
736 lcp_rprotrej(f
, inp
, len
)
742 struct protent
*protp
;
746 dbglog("lcp_rprotrej: Rcvd short Protocol-Reject packet!");
753 * Protocol-Reject packets received in any state other than the LCP
754 * OPENED state SHOULD be silently discarded.
756 if( f
->state
!= OPENED
){
757 dbglog("Protocol-Reject discarded: LCP in state %s",
758 fsm_state(f
->state
));
763 * Upcall the proper Protocol-Reject routine.
765 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
766 if (protp
->protocol
== prot
&& protp
->enabled_flag
) {
767 (*protp
->protrej
)(f
->unit
);
771 warn("Protocol-Reject for unsupported protocol 0x%x", prot
);
776 * lcp_protrej - A Protocol-Reject was received.
786 error("Received Protocol-Reject for LCP!");
790 * lcp_coderej - A Code-Reject was received.
794 lcp_coderej(f
, code
, id
, inp
, len
)
801 /* The peer cannot reject these code numbers. */
802 if (code
>= CODE_CONFREQ
&& code
<= CODE_PROTREJ
)
807 * If the peer rejects an Echo-Request, then stop doing that.
809 if (lcp_echo_timer_running
!= 0) {
810 UNTIMEOUT (LcpEchoTimeout
, f
);
811 lcp_echo_timer_running
= 0;
812 lcp_echo_interval
= 0;
820 * lcp_sprotrej - Send a Protocol-Reject for some protocol.
823 lcp_sprotrej(unit
, p
, len
)
829 * Send back the protocol and the information field of the
830 * rejected packet. We only get here if LCP is in the OPENED state.
835 fsm_sdata(&lcp_fsm
[unit
], CODE_PROTREJ
, ++lcp_fsm
[unit
].id
,
841 * lcp_resetci - Reset our CI.
847 lcp_options
*wo
= &lcp_wantoptions
[f
->unit
];
848 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
849 lcp_options
*ao
= &lcp_allowoptions
[f
->unit
];
851 wo
->magicnumber
= magic();
860 ao
->neg_endpoint
= 0;
861 if (go
->mru
> absmax_mru
)
862 go
->mru
= absmax_mru
;
863 if (ao
->mru
> absmax_mtu
)
864 ao
->mru
= absmax_mtu
;
866 fsm_setpeermru(f
->unit
, PPP_MTU
> absmax_mtu
? absmax_mtu
: PPP_MTU
);
872 * lcp_cilen - Return length of our CI.
878 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
880 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0)
881 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0)
882 #define LENCICHAR(neg) ((neg) ? CILEN_CHAR : 0)
883 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
884 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0)
885 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
886 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
888 * NB: we only ask for one of CHAP and UPAP, even if we will
891 return (LENCISHORT(go
->neg_mru
&& go
->mru
!= PPP_MRU
) +
892 LENCILONG(go
->neg_asyncmap
&& go
->asyncmap
!= 0xFFFFFFFF) +
893 LENCICHAP(go
->neg_chap
|| go
->neg_mschap
|| go
->neg_mschapv2
) +
894 LENCISHORT(!go
->neg_chap
&& go
->neg_upap
&& !go
->neg_mschap
&&
896 LENCILQR(go
->neg_lqr
) +
897 LENCICBCP(go
->neg_cbcp
) +
898 LENCILONG(go
->neg_magicnumber
) +
899 LENCIVOID(go
->neg_pcompression
) +
900 LENCIVOID(go
->neg_accompression
) +
901 LENCICHAR(go
->neg_fcs
) +
902 LENCISHORT(go
->neg_mrru
) +
903 LENCIVOID(go
->neg_ssnhf
) +
905 LENCIVOID(go
->pppmux
) +
907 (go
->neg_endpoint
? CILEN_CHAR
+ go
->endpoint
.length
: 0));
912 * lcp_addci - Add our desired CIs to a packet.
915 lcp_addci(f
, ucp
, lenp
)
920 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
921 lcp_options
*ho
= &lcp_hisoptions
[f
->unit
];
922 u_char
*start_ucp
= ucp
;
924 #define ADDCIVOID(opt, neg) \
927 PUTCHAR(CILEN_VOID, ucp); \
929 #define ADDCISHORT(opt, neg, val) \
932 PUTCHAR(CILEN_SHORT, ucp); \
933 PUTSHORT(val, ucp); \
935 #define ADDCICHAP(opt, neg, val, digest) \
938 PUTCHAR(CILEN_CHAP, ucp); \
939 PUTSHORT(val, ucp); \
940 PUTCHAR(digest, ucp); \
942 #define ADDCILONG(opt, neg, val) \
945 PUTCHAR(CILEN_LONG, ucp); \
948 #define ADDCILQR(opt, neg, val) \
951 PUTCHAR(CILEN_LQR, ucp); \
952 PUTSHORT(PPP_LQR, ucp); \
955 #define ADDCICHAR(opt, neg, val) \
958 PUTCHAR(CILEN_CHAR, ucp); \
961 #define ADDCIENDP(opt, neg, class, val, len) \
965 PUTCHAR(CILEN_CHAR + len, ucp); \
966 PUTCHAR(class, ucp); \
967 for (i = 0; i < len; ++i) \
968 PUTCHAR(val[i], ucp); \
971 ADDCISHORT(CI_MRU
, go
->neg_mru
&& go
->mru
!= PPP_MRU
, go
->mru
);
972 ADDCILONG(CI_ASYNCMAP
, go
->neg_asyncmap
&& go
->asyncmap
!= 0xFFFFFFFF,
974 /* go->chap_mdtype always points to a useful value */
975 ADDCICHAP(CI_AUTHTYPE
, go
->neg_chap
|| go
->neg_mschap
|| go
->neg_mschapv2
,
976 PPP_CHAP
, go
->chap_mdtype
);
977 ADDCISHORT(CI_AUTHTYPE
, !(go
->neg_chap
|| go
->neg_mschap
||
978 go
->neg_mschapv2
) && go
->neg_upap
, PPP_PAP
);
979 /* We can't both say zero for LQR period. */
980 if (f
->state
== ACKSENT
&& go
->neg_lqr
&& go
->lqr_period
== 0 &&
981 ho
->neg_lqr
&& ho
->lqr_period
== 0)
982 go
->lqr_period
= 500;
983 ADDCILQR(CI_QUALITY
, go
->neg_lqr
, go
->lqr_period
);
984 ADDCICHAR(CI_CALLBACK
, go
->neg_cbcp
, CBOP_CBCP
);
985 ADDCILONG(CI_MAGICNUMBER
, go
->neg_magicnumber
, go
->magicnumber
);
986 ADDCIVOID(CI_PCOMPRESSION
, go
->neg_pcompression
);
987 ADDCIVOID(CI_ACCOMPRESSION
, go
->neg_accompression
);
988 ADDCICHAR(CI_FCSALTERN
, (go
->neg_fcs
&& go
->fcs_type
!= 0), go
->fcs_type
);
989 ADDCIENDP(CI_EPDISC
, go
->neg_endpoint
, go
->endpoint
.class,
990 go
->endpoint
.value
, go
->endpoint
.length
);
992 ADDCIVOID(CI_MUXING
, go
->pppmux
);
994 ADDCISHORT(CI_MRRU
, go
->neg_mrru
, go
->mrru
);
995 ADDCIVOID(CI_SSNHF
, go
->neg_ssnhf
);
997 if (ucp
- start_ucp
!= *lenp
) {
998 /* this should never happen, because peer_mtu should be 1500 */
999 error("Bug in lcp_addci: wrong length");
1005 * lcp_ackci - Ack our CIs.
1006 * This should not modify any state if the Ack is bad.
1013 lcp_ackci(f
, p
, len
)
1018 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
1020 lcp_options
*ao
= &lcp_allowoptions
[f
->unit
];
1022 u_char cilen
, citype
, cichar
;
1027 * CIs must be in exactly the same order that we sent.
1028 * Check packet length and CI length at each step.
1029 * If we find any deviations, then this packet is bad.
1031 #define ACKCIVOID(opt, neg) \
1033 if ((len -= CILEN_VOID) < 0) \
1035 GETCHAR(citype, p); \
1036 GETCHAR(cilen, p); \
1037 if (cilen != CILEN_VOID || \
1041 #define ACKCISHORT(opt, neg, val) \
1043 if ((len -= CILEN_SHORT) < 0) \
1045 GETCHAR(citype, p); \
1046 GETCHAR(cilen, p); \
1047 if (cilen != CILEN_SHORT || \
1050 GETSHORT(cishort, p); \
1051 if (cishort != val) \
1054 #define ACKCIAUTH(opt, neg, val) \
1056 if ((len -= CILEN_SHORT) < 0) \
1058 GETCHAR(citype, p); \
1059 GETCHAR(cilen, p); \
1060 if (cilen != CILEN_SHORT || \
1063 GETSHORT(cishort, p); \
1064 if (cishort != val) \
1066 peer_nak_auth = 0; \
1067 peer_reject_auth = 0; \
1069 #define ACKCICHAR(opt, neg, val) \
1071 if ((len -= CILEN_CHAR) < 0) \
1073 GETCHAR(citype, p); \
1074 GETCHAR(cilen, p); \
1075 if (cilen != CILEN_CHAR || \
1078 GETCHAR(cichar, p); \
1079 if (cichar != val) \
1082 #define ACKCICHAP(opt, neg, val, digest) \
1084 if ((len -= CILEN_CHAP) < 0) \
1086 GETCHAR(citype, p); \
1087 GETCHAR(cilen, p); \
1088 if (cilen != CILEN_CHAP || \
1091 GETSHORT(cishort, p); \
1092 if (cishort != val) \
1094 GETCHAR(cichar, p); \
1095 if (cichar != digest) \
1097 peer_nak_auth = 0; \
1098 peer_reject_auth = 0; \
1100 #define ACKCILONG(opt, neg, val) \
1102 if ((len -= CILEN_LONG) < 0) \
1104 GETCHAR(citype, p); \
1105 GETCHAR(cilen, p); \
1106 if (cilen != CILEN_LONG || \
1109 GETLONG(cilong, p); \
1110 if (cilong != val) \
1113 #define ACKCILQR(opt, neg, val) \
1115 if ((len -= CILEN_LQR) < 0) \
1117 GETCHAR(citype, p); \
1118 GETCHAR(cilen, p); \
1119 if (cilen != CILEN_LQR || \
1122 GETSHORT(cishort, p); \
1123 if (cishort != PPP_LQR) \
1125 GETLONG(cilong, p); \
1126 if (cilong != val) \
1129 #define ACKCIENDP(opt, neg, class, val, vlen) \
1132 if ((len -= CILEN_CHAR + vlen) < 0) \
1134 GETCHAR(citype, p); \
1135 GETCHAR(cilen, p); \
1136 if (cilen != CILEN_CHAR + vlen || \
1139 GETCHAR(cichar, p); \
1140 if (cichar != class) \
1142 for (i = 0; i < vlen; ++i) { \
1143 GETCHAR(cichar, p); \
1144 if (cichar != val[i]) \
1149 ACKCISHORT(CI_MRU
, go
->neg_mru
&& go
->mru
!= PPP_MRU
, go
->mru
);
1150 ACKCILONG(CI_ASYNCMAP
, go
->neg_asyncmap
&& go
->asyncmap
!= 0xFFFFFFFF,
1152 /* go->chap_mdtype always points to a useful value */
1153 ACKCICHAP(CI_AUTHTYPE
, go
->neg_chap
|| go
->neg_mschap
|| go
->neg_mschapv2
,
1154 PPP_CHAP
, go
->chap_mdtype
);
1155 ACKCIAUTH(CI_AUTHTYPE
, !(go
->neg_chap
|| go
->neg_mschap
||
1156 go
->neg_mschapv2
) && go
->neg_upap
, PPP_PAP
);
1157 ACKCILQR(CI_QUALITY
, go
->neg_lqr
, go
->lqr_period
);
1158 ACKCICHAR(CI_CALLBACK
, go
->neg_cbcp
, CBOP_CBCP
);
1159 ACKCILONG(CI_MAGICNUMBER
, go
->neg_magicnumber
, go
->magicnumber
);
1160 ACKCIVOID(CI_PCOMPRESSION
, go
->neg_pcompression
);
1161 ACKCIVOID(CI_ACCOMPRESSION
, go
->neg_accompression
);
1162 ACKCICHAR(CI_FCSALTERN
, go
->neg_fcs
, go
->fcs_type
);
1163 ACKCIENDP(CI_EPDISC
, go
->neg_endpoint
, go
->endpoint
.class,
1164 go
->endpoint
.value
, go
->endpoint
.length
);
1166 ACKCIVOID(CI_MUXING
, go
->pppmux
);
1168 go
->pppmux
= ao
->pppmux
;
1170 ACKCISHORT(CI_MRRU
, go
->neg_mrru
, go
->mrru
);
1171 ACKCIVOID(CI_SSNHF
, go
->neg_ssnhf
);
1174 * If there are any remaining CIs, then this packet is bad.
1180 dbglog("lcp_acki: received bad Ack!");
1186 * lcp_nakci - Peer has sent a NAK for some of our CIs.
1187 * This should not modify any state if the Nak is bad
1188 * or if LCP is in the OPENED state.
1195 lcp_nakci(f
, p
, len
)
1200 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
1201 lcp_options
*wo
= &lcp_wantoptions
[f
->unit
];
1202 u_char citype
, cichar
, *next
;
1205 lcp_options no
; /* options we've seen Naks for */
1206 lcp_options
try; /* options to request next time */
1207 int looped_back
= 0;
1210 BZERO(&no
, sizeof(no
));
1214 * Any Nak'd CIs must be in exactly the same order that we sent.
1215 * Check packet length and CI length at each step.
1216 * If we find any deviations, then this packet is bad.
1218 #define NAKCIVOID(opt, neg) \
1220 len >= CILEN_VOID && \
1221 p[1] == CILEN_VOID && \
1223 len -= CILEN_VOID; \
1224 INCPTR(CILEN_VOID, p); \
1228 #define NAKCICHAR(opt, neg, code) \
1230 len >= CILEN_CHAR && \
1231 p[1] == CILEN_CHAR && \
1233 len -= CILEN_CHAR; \
1235 GETCHAR(cichar, p); \
1239 #define NAKCISHORT(opt, neg, code) \
1241 len >= CILEN_SHORT && \
1242 p[1] == CILEN_SHORT && \
1244 len -= CILEN_SHORT; \
1246 GETSHORT(cishort, p); \
1250 #define NAKCILONG(opt, neg, code) \
1252 len >= CILEN_LONG && \
1253 p[1] == CILEN_LONG && \
1255 len -= CILEN_LONG; \
1257 GETLONG(cilong, p); \
1261 #define NAKCILQR(opt, neg, code) \
1263 len >= CILEN_LQR && \
1264 p[1] == CILEN_LQR && \
1268 GETSHORT(cishort, p); \
1269 GETLONG(cilong, p); \
1273 #define NAKCIENDP(opt, neg) \
1275 len >= CILEN_CHAR && \
1277 p[1] >= CILEN_CHAR && \
1286 * We don't care if they want to send us smaller packets than
1287 * we want. Therefore, accept any MRU less than what we asked for,
1288 * but then ignore the new value when setting the MRU in the kernel.
1289 * If they send us a bigger MRU than what we asked, accept it, up to
1290 * the limit of the default MRU we'd get if we didn't negotiate.
1292 if (go
->neg_mru
&& go
->mru
!= PPP_MRU
) {
1293 NAKCISHORT(CI_MRU
, neg_mru
,
1294 if (cishort
<= wo
->mru
||
1295 (cishort
<= PPP_MRU
&& cishort
<= absmax_mru
))
1301 * Add any characters they want to our (receive-side) asyncmap.
1303 if (go
->neg_asyncmap
&& go
->asyncmap
!= 0xFFFFFFFF) {
1304 NAKCILONG(CI_ASYNCMAP
, neg_asyncmap
,
1305 try.asyncmap
= go
->asyncmap
| cilong
;
1310 * If they've nak'd our authentication-protocol, check whether
1311 * they are proposing a different protocol, or a different
1312 * hash algorithm for CHAP.
1314 if ((go
->neg_chap
|| go
->neg_mschap
|| go
->neg_mschapv2
|| go
->neg_upap
) &&
1315 len
>= CILEN_SHORT
&& p
[0] == CI_AUTHTYPE
&& p
[1] >= CILEN_SHORT
&&
1320 GETSHORT(cishort
, p
);
1322 nak_auth_orig
= (go
->neg_chap
|| go
->neg_mschap
|| go
->neg_mschapv2
) ?
1324 nak_auth_proto
= cishort
;
1325 if (cishort
== PPP_PAP
&& cilen
== CILEN_SHORT
) {
1326 no
.neg_upap
= go
->neg_upap
;
1328 * If we were asking for CHAP, they obviously don't want to do it.
1329 * If we weren't asking for CHAP, then we were asking for PAP,
1330 * in which case this Nak is bad.
1332 if (!go
->neg_chap
&& !go
->neg_mschap
&& !go
->neg_mschapv2
)
1336 try.neg_mschapv2
= 0;
1338 } else if (cishort
== PPP_CHAP
&& cilen
>= CILEN_CHAP
) {
1339 /* stop asking for that type */
1340 switch (go
->chap_mdtype
) {
1341 case CHAP_DIGEST_MD5
:
1342 no
.neg_chap
= go
->neg_chap
;
1345 case CHAP_MICROSOFT
:
1346 no
.neg_mschap
= go
->neg_mschap
;
1349 case CHAP_MICROSOFT_V2
:
1350 no
.neg_mschapv2
= go
->neg_mschapv2
;
1351 try.neg_mschapv2
= 0;
1355 /* Allow >= on length here for broken and silly peers. */
1356 p
+= cilen
- CILEN_CHAP
;
1358 if ((cichar
== CHAP_DIGEST_MD5
&& wo
->neg_chap
) ||
1359 (cichar
== CHAP_MICROSOFT
&& wo
->neg_mschap
) ||
1360 (cichar
== CHAP_MICROSOFT_V2
&& wo
->neg_mschapv2
)) {
1361 /* Try its requested algorithm. */
1362 try.chap_mdtype
= cichar
;
1369 * We don't recognize what they're suggesting.
1370 * Stop asking for what we were asking for.
1373 if (go
->neg_chap
|| go
->neg_mschap
|| go
->neg_mschapv2
) {
1374 switch (go
->chap_mdtype
) {
1375 case CHAP_DIGEST_MD5
:
1377 if (wo
->neg_mschap
) {
1378 try.chap_mdtype
= CHAP_MICROSOFT
;
1382 case CHAP_MICROSOFT
:
1384 if (wo
->neg_mschapv2
) {
1385 try.chap_mdtype
= CHAP_MICROSOFT_V2
;
1389 case CHAP_MICROSOFT_V2
:
1390 try.neg_mschapv2
= 0;
1395 p
+= cilen
- CILEN_SHORT
;
1400 * If they can't cope with our link quality protocol, we'll have
1401 * to stop asking for LQR. We haven't got any other protocol. If
1402 * they Nak the reporting period, then the following logic
1404 * If it suggests zero and go->neg_fcs is true and
1405 * ao->lqr_period isn't zero, then take its suggestion. If it
1406 * suggests zero otherwise, ignore it. If it suggests a nonzero
1407 * value and wo->lqr_period is zero, then take its suggestion. If
1408 * it suggests a nonzero value otherwise that's less than
1409 * wo->lqr_period, then ignore it.
1411 NAKCILQR(CI_QUALITY
, neg_lqr
,
1412 if (cishort
!= PPP_LQR
)
1414 else if (cilong
== 0 && go
->neg_fcs
&& wo
->lqr_period
!= 0)
1415 try.lqr_period
= cilong
;
1416 else if (cilong
!= 0 &&
1417 (wo
->lqr_period
== 0 || cilong
> wo
->lqr_period
))
1418 try.lqr_period
= cilong
;
1422 * Only implementing CBCP...not the rest of the callback options
1424 NAKCICHAR(CI_CALLBACK
, neg_cbcp
,
1429 * Check for a looped-back line.
1431 NAKCILONG(CI_MAGICNUMBER
, neg_magicnumber
,
1432 try.magicnumber
= magic();
1437 * Peer shouldn't send Nak for protocol compression or
1438 * address/control compression requests; they should send
1439 * a Reject instead. If they send a Nak, treat it as a Reject.
1441 NAKCIVOID(CI_PCOMPRESSION
, neg_pcompression
);
1442 NAKCIVOID(CI_ACCOMPRESSION
, neg_accompression
);
1445 * Remove any FCS types it doesn't like from our (receive-side)
1448 NAKCICHAR(CI_FCSALTERN
, neg_fcs
, try.fcs_type
= go
->fcs_type
& cichar
;);
1451 /* Nacked MUX option */
1452 NAKCIVOID(CI_MUXING
, pppmux
);
1456 * Nak of the endpoint discriminator option is not permitted,
1457 * treat it like a reject.
1459 NAKCIENDP(CI_EPDISC
, neg_endpoint
);
1462 * Nak for MRRU option - accept their value if it is smaller
1463 * than the one we want.
1466 NAKCISHORT(CI_MRRU
, neg_mrru
,
1467 if (cishort
<= wo
->mrru
)
1473 * Nak for short sequence numbers shouldn't be sent, treat it
1476 NAKCIVOID(CI_SSNHF
, neg_ssnhf
);
1479 * There may be remaining CIs, if the peer is requesting negotiation
1480 * on an option that we didn't include in our request packet.
1481 * If we see an option that we requested, or one we've already seen
1482 * in this packet, then this packet is bad.
1483 * If we wanted to respond by starting to negotiate on the requested
1484 * option(s), we could, but we don't, because except for the
1485 * authentication type and quality protocol, if we are not negotiating
1486 * an option, it is because we were told not to.
1487 * For the authentication type, the Nak from the peer means
1488 * `let me authenticate myself with you' which is a bit pointless.
1489 * For the quality protocol, the Nak means `ask me to send you quality
1490 * reports', but if we didn't ask for them, we don't want them.
1491 * An option we don't recognize represents the peer asking to
1492 * negotiate some option we don't support, so ignore it.
1494 while (len
> CILEN_VOID
) {
1497 if (cilen
< CILEN_VOID
|| (len
-= cilen
) < 0)
1499 next
= p
+ cilen
- 2;
1503 if ((go
->neg_mru
&& go
->mru
!= PPP_MRU
)
1504 || no
.neg_mru
|| cilen
!= CILEN_SHORT
)
1506 GETSHORT(cishort
, p
);
1507 if (cishort
< PPP_MRU
&& cishort
< absmax_mru
) {
1510 notice("Peer sent unsolicited Nak for MRU less than default.");
1514 if ((go
->neg_asyncmap
&& go
->asyncmap
!= 0xFFFFFFFF)
1515 || no
.neg_asyncmap
|| cilen
!= CILEN_LONG
)
1519 unsolicited_nak_auth
= 1;
1520 if (cilen
>= CILEN_SHORT
) {
1521 GETSHORT(unsolicit_auth_proto
, p
);
1523 unsolicit_auth_proto
= 0;
1525 if (go
->neg_chap
|| no
.neg_chap
||
1526 go
->neg_mschap
|| no
.neg_mschap
||
1527 go
->neg_mschapv2
|| no
.neg_mschapv2
||
1528 go
->neg_upap
|| no
.neg_upap
)
1531 case CI_MAGICNUMBER
:
1532 if (go
->neg_magicnumber
|| no
.neg_magicnumber
||
1533 cilen
!= CILEN_LONG
)
1536 case CI_PCOMPRESSION
:
1537 if (go
->neg_pcompression
|| no
.neg_pcompression
1538 || cilen
!= CILEN_VOID
)
1541 case CI_ACCOMPRESSION
:
1542 if (go
->neg_accompression
|| no
.neg_accompression
1543 || cilen
!= CILEN_VOID
)
1547 if (go
->neg_lqr
|| no
.neg_lqr
|| cilen
!= CILEN_LQR
)
1551 if (go
->neg_mrru
|| no
.neg_mrru
|| cilen
!= CILEN_SHORT
)
1555 if (go
->neg_ssnhf
|| no
.neg_ssnhf
|| cilen
!= CILEN_VOID
)
1560 if (go
->neg_endpoint
|| no
.neg_endpoint
|| cilen
< CILEN_CHAR
)
1564 if (go
->neg_fcs
|| no
.neg_fcs
|| cilen
< CILEN_CHAR
)
1569 if (go
->pppmux
|| no
.pppmux
|| cilen
< CILEN_VOID
)
1578 * OK, the Nak is good. Now we can update state.
1579 * If there are any options left we ignore them.
1581 if (f
->state
!= OPENED
) {
1583 * Note: the code once reset try.numloops to zero here if
1584 * looped_back wasn't set. This is wrong because a mixture of
1585 * looped-back and peer data (possible if half-duplex is used)
1586 * will allow the link to come up, and it shouldn't.
1589 if (++try.numloops
>= lcp_loopbackfail
) {
1590 notice("Serial line is looped back.");
1591 lcp_close(f
->unit
, "Loopback detected");
1592 status
= EXIT_LOOPBACK
;
1601 dbglog("lcp_nakci: received bad Nak!");
1607 * lcp_rejci - Peer has Rejected some of our CIs.
1608 * This should not modify any state if the Reject is bad
1609 * or if LCP is in the OPENED state.
1612 * 0 - Reject was bad.
1613 * 1 - Reject was good.
1616 lcp_rejci(f
, p
, len
)
1621 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
1625 lcp_options
try; /* options to request next time */
1630 * Any Rejected CIs must be in exactly the same order that we sent.
1631 * Check packet length and CI length at each step.
1632 * If we find any deviations, then this packet is bad.
1634 #define REJCIVOID(opt, neg) \
1636 len >= CILEN_VOID && \
1637 p[1] == CILEN_VOID && \
1639 len -= CILEN_VOID; \
1640 INCPTR(CILEN_VOID, p); \
1643 #define REJCICHAR(opt, neg, val) \
1645 len >= CILEN_CHAR && \
1646 p[1] == CILEN_CHAR && \
1648 len -= CILEN_CHAR; \
1650 GETCHAR(cichar, p); \
1651 /* Check rejected value. */ \
1652 if (cichar != val) \
1656 #define REJCISHORT(opt, neg, val) \
1658 len >= CILEN_SHORT && \
1659 p[1] == CILEN_SHORT && \
1661 len -= CILEN_SHORT; \
1663 GETSHORT(cishort, p); \
1664 /* Check rejected value. */ \
1665 if (cishort != val) \
1669 #define REJCIAUTH(opt, neg, val) \
1671 len >= CILEN_SHORT && \
1672 p[1] == CILEN_SHORT && \
1674 len -= CILEN_SHORT; \
1676 GETSHORT(cishort, p); \
1677 /* Check rejected value. */ \
1678 peer_reject_auth = 1; \
1679 reject_auth_proto = cishort; \
1680 if (cishort != val) \
1684 #define REJCILONG(opt, neg, val) \
1686 len >= CILEN_LONG && \
1687 p[1] == CILEN_LONG && \
1689 len -= CILEN_LONG; \
1691 GETLONG(cilong, p); \
1692 /* Check rejected value. */ \
1693 if (cilong != val) \
1697 #define REJCILQR(opt, neg, val) \
1699 len >= CILEN_LQR && \
1700 p[1] == CILEN_LQR && \
1704 GETSHORT(cishort, p); \
1705 GETLONG(cilong, p); \
1706 /* Check rejected value. */ \
1707 if (cishort != PPP_LQR || cilong != val) \
1711 #define REJCICBCP(opt, neg, val) \
1713 len >= CILEN_CBCP && \
1714 p[1] == CILEN_CBCP && \
1716 len -= CILEN_CBCP; \
1718 GETCHAR(cichar, p); \
1719 /* Check rejected value. */ \
1720 if (cichar != val) \
1724 #define REJCIENDP(opt, neg, class, val, vlen) \
1726 len >= CILEN_CHAR + vlen && \
1728 p[1] == CILEN_CHAR + vlen) { \
1730 len -= CILEN_CHAR + vlen; \
1732 GETCHAR(cichar, p); \
1733 if (cichar != class) \
1735 for (i = 0; i < vlen; ++i) { \
1736 GETCHAR(cichar, p); \
1737 if (cichar != val[i]) \
1743 /* Received a Configure-Reject, try to send Identification now. */
1744 if (!noident
&& sentident
< 3) {
1745 LcpSendIdentification(f
);
1749 REJCISHORT(CI_MRU
, neg_mru
, go
->mru
);
1750 REJCILONG(CI_ASYNCMAP
, neg_asyncmap
, go
->asyncmap
);
1753 * There are broken peers (such as unbundled Solaris PPP) that
1754 * send Configure-Reject for authentication when they really
1755 * intend Configure-Nak. This code works around this problem.
1757 if ((go
->neg_chap
|| go
->neg_mschap
|| go
->neg_mschapv2
) &&
1758 len
>= CILEN_CHAP
&& p
[1] == CILEN_CHAP
&& p
[0] == CI_AUTHTYPE
) {
1761 GETSHORT(cishort
, p
);
1763 peer_reject_auth
= 1;
1764 reject_auth_proto
= cishort
;
1765 /* Check rejected value. */
1766 if (cishort
!= PPP_CHAP
|| cichar
!= go
->chap_mdtype
)
1768 /* Disable the one that it rejected */
1770 case CHAP_DIGEST_MD5
:
1773 case CHAP_MICROSOFT
:
1776 case CHAP_MICROSOFT_V2
:
1777 try.neg_mschapv2
= 0;
1780 /* Try another, if we can. */
1782 try.chap_mdtype
= CHAP_DIGEST_MD5
;
1783 else if (try.neg_mschap
)
1784 try.chap_mdtype
= CHAP_MICROSOFT
;
1786 try.chap_mdtype
= CHAP_MICROSOFT_V2
;
1789 if (!go
->neg_chap
&& !go
->neg_mschap
&& !go
->neg_mschapv2
) {
1790 REJCIAUTH(CI_AUTHTYPE
, neg_upap
, PPP_PAP
);
1792 REJCILQR(CI_QUALITY
, neg_lqr
, go
->lqr_period
);
1793 REJCICBCP(CI_CALLBACK
, neg_cbcp
, CBOP_CBCP
);
1794 REJCILONG(CI_MAGICNUMBER
, neg_magicnumber
, go
->magicnumber
);
1795 REJCIVOID(CI_PCOMPRESSION
, neg_pcompression
);
1796 REJCIVOID(CI_ACCOMPRESSION
, neg_accompression
);
1797 REJCICHAR(CI_FCSALTERN
, neg_fcs
, go
->fcs_type
);
1799 REJCIVOID(CI_MUXING
,pppmux
);
1801 REJCIENDP(CI_EPDISC
, neg_endpoint
, go
->endpoint
.class,
1802 go
->endpoint
.value
, go
->endpoint
.length
);
1803 REJCISHORT(CI_MRRU
, neg_mrru
, go
->mrru
);
1804 REJCIVOID(CI_SSNHF
, neg_ssnhf
);
1807 * If there are any remaining CIs, then this packet is bad.
1812 * Now we can update state.
1814 if (f
->state
!= OPENED
)
1819 dbglog("lcp_rejci: received bad Reject!");
1825 * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1827 * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input
1828 * packet modified appropriately. If reject_if_disagree is non-zero,
1829 * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't
1830 * return CODE_CONFACK.
1833 lcp_reqci(f
, p
, lenp
, dont_nak
)
1835 u_char
*p
; /* Requested CIs */
1836 int *lenp
; /* Length of requested CIs */
1839 lcp_options
*wo
= &lcp_wantoptions
[f
->unit
];
1840 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
1841 lcp_options
*ho
= &lcp_hisoptions
[f
->unit
];
1842 lcp_options
*ao
= &lcp_allowoptions
[f
->unit
];
1843 int cilen
, citype
, cichar
; /* Parsed len, type, char value */
1844 u_short cishort
; /* Parsed short value */
1845 u_int32_t cilong
; /* Parse long value */
1847 u_char
*p0
, *nakp
, *rejp
, *prev
;
1851 * Loop through options once to find out if peer is offering
1852 * Multilink, and repair values as needed.
1856 for (len
= *lenp
; len
> 0; len
-= cilen
, p
= prev
+ cilen
) {
1857 if (len
< 2 || p
[1] > len
) {
1859 * RFC 1661 page 40 -- if the option extends beyond the
1860 * packet, then discard the entire packet.
1862 dbglog("discarding LCP Configure-Request due to truncated option");
1868 if (citype
== CI_MRRU
) {
1869 if (ao
->mrru
!= 0) {
1870 if (ao
->mrru
+6 > PPP_MTU
)
1873 ao
->mru
= ao
->mrru
+ 6;
1879 if (ao
->mru
> absmax_mtu
)
1880 ao
->mru
= absmax_mtu
;
1887 * Reset all its options.
1889 BZERO(ho
, sizeof(*ho
));
1892 * Process all its options.
1894 for (len
= *lenp
; len
> 0; len
-= cilen
, p
= prev
+ cilen
) {
1895 newret
= CODE_CONFACK
; /* Assume success */
1901 switch (citype
) { /* Check CI type */
1904 newret
= CODE_CONFREJ
;
1908 if (cilen
!= CILEN_SHORT
) { /* Check CI length */
1909 newret
= CODE_CONFNAK
;
1912 /* extract the MRU from the option */
1913 GETSHORT(cishort
, p
);
1916 * If the offered MRU is less than our desired MTU, we
1917 * should nak. This is especially helpful if we're
1918 * doing demand-dial, since those queued up packets
1919 * might be discarded otherwise.
1921 if (cishort
< ao
->mru
) {
1922 newret
= CODE_CONFNAK
;
1928 * If we're going to send a nak with something less than
1929 * or equal to the default PPP MTU, then just reject instead.
1931 if (newret
== CODE_CONFNAK
&& cishort
<= PPP_MTU
)
1932 newret
= CODE_CONFREJ
;
1934 if (newret
== CODE_CONFNAK
) {
1935 PUTCHAR(CI_MRU
, nakp
);
1936 PUTCHAR(CILEN_SHORT
, nakp
);
1937 PUTSHORT(cishort
, nakp
); /* Give it a hint */
1940 ho
->neg_mru
= 1; /* Remember that it sent MRU */
1941 ho
->mru
= cishort
; /* And remember value */
1945 if (!ao
->neg_asyncmap
) {
1946 newret
= CODE_CONFREJ
;
1950 if (cilen
!= CILEN_LONG
) {
1951 newret
= CODE_CONFNAK
;
1957 * Asyncmap must have set at least the bits
1958 * which are set in lcp_allowoptions[unit].asyncmap.
1960 if ((ao
->asyncmap
& ~cilong
) != 0)
1961 newret
= CODE_CONFNAK
;
1965 * Workaround for common broken Microsoft software -- if
1966 * the peer is sending us a nonzero ACCM, then it *needs*
1967 * us to send the same to it. Adjust our Configure-
1968 * Request message and restart LCP.
1970 if (do_msft_workaround
&& (cilong
& ~wo
->asyncmap
)) {
1971 dbglog("adjusted requested asyncmap from %X to %X",
1972 wo
->asyncmap
, wo
->asyncmap
| cilong
);
1973 do_msft_workaround
= 0;
1974 wo
->neg_asyncmap
= 1;
1975 wo
->asyncmap
|= cilong
;
1976 f
->flags
&= ~OPT_SILENT
;
1977 info("possibly broken peer detected; restarting LCP");
1983 if (newret
== CODE_CONFNAK
) {
1984 PUTCHAR(CI_ASYNCMAP
, nakp
);
1985 PUTCHAR(CILEN_LONG
, nakp
);
1986 PUTLONG(ao
->asyncmap
| cilong
, nakp
);
1988 ho
->neg_asyncmap
= 1;
1989 ho
->asyncmap
= cilong
;
1993 if (!(ao
->neg_upap
|| ao
->neg_chap
|| ao
->neg_mschap
||
1994 ao
->neg_mschapv2
)) {
1995 rejected_peers_auth
= 1;
1996 if (cilen
>= CILEN_SHORT
) {
1997 GETSHORT(rejected_auth_proto
, p
);
1999 rejected_auth_proto
= 0;
2002 * Reject the option if we're not willing to authenticate.
2004 newret
= CODE_CONFREJ
;
2007 rejected_peers_auth
= 0;
2008 naked_peers_auth
= 0;
2010 if (cilen
>= CILEN_SHORT
) {
2011 /* Extract the authentication protocol from the option */
2012 GETSHORT(cishort
, p
);
2014 if (ho
->neg_upap
|| ho
->neg_chap
|| ho
->neg_mschap
||
2016 dbglog("Rejecting extra authentication protocol option");
2017 newret
= CODE_CONFREJ
;
2022 * Authtype must be PAP or CHAP.
2024 * Note: if both ao->neg_upap and ao->neg_*chap* are
2025 * set, and the peer sends a Configure-Request with
2026 * two authenticate-protocol requests, one for CHAP
2027 * and one for UPAP, then we will reject the second
2028 * request. Whether we end up doing CHAP or UPAP
2029 * depends then on the ordering of the CIs in the
2030 * peer's Configure-Request.
2032 * We're supposed to list all of the protocols we can
2033 * possibly use in the returned Configure-Nak. This
2034 * part of RFC 1661 (section 5.3) is in conflict with
2035 * the section that says the options shouldn't be
2036 * reordered, so it's often ignored.
2039 if (cishort
== PPP_PAP
) {
2041 if (cilen
!= CILEN_SHORT
)
2042 goto try_pap_anyway
;
2046 } else if (cishort
== PPP_CHAP
) {
2047 /* Test >= here to allow for broken peers. */
2048 if (cilen
>= CILEN_CHAP
&&
2049 (ao
->neg_chap
|| ao
->neg_mschap
|| ao
->neg_mschapv2
)) {
2051 if (cichar
== CHAP_DIGEST_MD5
&& ao
->neg_chap
)
2053 else if (cichar
== CHAP_MICROSOFT
&& ao
->neg_mschap
)
2055 else if (cichar
== CHAP_MICROSOFT_V2
&&
2058 if (ho
->neg_chap
|| ho
->neg_mschap
||
2060 ho
->chap_mdtype
= cichar
; /* save md type */
2068 * We don't recognize the protocol they're asking for.
2069 * Nak it with something we're willing to do.
2070 * (At this point we know ao->neg_upap || ao->neg_chap.)
2072 PUTCHAR(CI_AUTHTYPE
, nakp
);
2073 if (ao
->neg_chap
|| ao
->neg_mschap
|| ao
->neg_mschapv2
) {
2074 PUTCHAR(CILEN_CHAP
, nakp
);
2075 PUTSHORT(PPP_CHAP
, nakp
);
2076 PUTCHAR(ao
->chap_mdtype
, nakp
);
2077 naked_auth_proto
= PPP_CHAP
;
2080 PUTCHAR(CILEN_SHORT
, nakp
);
2081 PUTSHORT(PPP_PAP
, nakp
);
2082 naked_auth_proto
= PPP_PAP
;
2084 naked_peers_auth
= 1;
2085 naked_auth_orig
= cishort
;
2086 newret
= CODE_CONFNAK
;
2091 newret
= CODE_CONFREJ
;
2095 if (cilen
!= CILEN_LQR
) {
2096 newret
= CODE_CONFNAK
;
2097 cilong
= ao
->lqr_period
;
2100 GETSHORT(cishort
, p
);
2103 /* Check the LQM protocol */
2104 if (cishort
!= PPP_LQR
) {
2105 newret
= CODE_CONFNAK
;
2108 /* Check the reporting period; we can't both send zero */
2109 if ((cilong
== 0 && go
->lqr_period
== 0) ||
2110 cilong
< ao
->lqr_period
) {
2111 newret
= CODE_CONFNAK
;
2112 if ((cilong
= ao
->lqr_period
) == 0)
2117 if (newret
== CODE_CONFNAK
) {
2118 PUTCHAR(CI_QUALITY
, nakp
);
2119 PUTCHAR(CILEN_LQR
, nakp
);
2120 PUTSHORT(PPP_LQR
, nakp
);
2121 PUTLONG(cilong
, nakp
);
2125 ho
->lqr_period
= cilong
;
2128 case CI_MAGICNUMBER
:
2129 if (!(ao
->neg_magicnumber
|| go
->neg_magicnumber
)) {
2130 newret
= CODE_CONFREJ
;
2134 ho
->neg_magicnumber
= 1;
2135 if (cilen
< CILEN_LONG
) {
2137 * If we send Magic-Number, then we must not reject it
2138 * when the peer sends it to us, even if its version
2139 * looks odd to us. Ack if the cilent is wrong in this
2140 * case. If we're not sending Magic-Number, then we don't
2141 * much care what its value is anyway.
2147 ho
->magicnumber
= cilong
;
2148 if (cilen
> CILEN_LONG
)
2152 * It must have a different magic number. Make sure we
2153 * give it a good one to use.
2155 while (go
->neg_magicnumber
&& cilong
== go
->magicnumber
) {
2156 newret
= CODE_CONFNAK
;
2160 if (newret
== CODE_CONFNAK
) {
2161 PUTCHAR(CI_MAGICNUMBER
, nakp
);
2162 PUTCHAR(CILEN_LONG
, nakp
);
2163 PUTLONG(cilong
, nakp
);
2165 * We don't need to bump the numloops counter here
2166 * since it's already done upon reception of a nak.
2171 case CI_PCOMPRESSION
:
2172 if (!ao
->neg_pcompression
) {
2173 newret
= CODE_CONFREJ
;
2176 if (cilen
!= CILEN_VOID
) {
2177 newret
= CODE_CONFNAK
;
2178 PUTCHAR(CI_PCOMPRESSION
, nakp
);
2179 PUTCHAR(CILEN_VOID
, nakp
);
2181 ho
->neg_pcompression
= 1;
2184 case CI_ACCOMPRESSION
:
2185 if (!ao
->neg_accompression
) {
2186 newret
= CODE_CONFREJ
;
2189 if (cilen
!= CILEN_VOID
) {
2190 newret
= CODE_CONFNAK
;
2191 PUTCHAR(CI_ACCOMPRESSION
, nakp
);
2192 PUTCHAR(CILEN_VOID
, nakp
);
2194 ho
->neg_accompression
= 1;
2199 newret
= CODE_CONFREJ
;
2203 if (cilen
!= CILEN_CHAR
) {
2204 newret
= CODE_CONFNAK
;
2205 cichar
= ao
->fcs_type
;
2209 /* If it has bits we don't like, tell it to stop. */
2210 if (cichar
& ~ao
->fcs_type
) {
2211 if ((cichar
&= ao
->fcs_type
) == 0) {
2212 newret
= CODE_CONFREJ
;
2215 newret
= CODE_CONFNAK
;
2218 if (newret
== CODE_CONFNAK
) {
2219 PUTCHAR(CI_FCSALTERN
, nakp
);
2220 PUTCHAR(CILEN_CHAR
, nakp
);
2221 PUTCHAR(cichar
, nakp
);
2224 ho
->fcs_type
= cichar
;
2228 if (!ao
->neg_mrru
|| !multilink
) {
2229 newret
= CODE_CONFREJ
;
2232 if (cilen
!= CILEN_SHORT
) {
2233 newret
= CODE_CONFNAK
;
2236 GETSHORT(cishort
, p
);
2237 if (cishort
< ao
->mrru
) {
2238 newret
= CODE_CONFNAK
;
2243 if (cishort
< PPP_MINMTU
) {
2244 newret
= CODE_CONFNAK
;
2245 cishort
= PPP_MINMTU
;
2248 if (newret
== CODE_CONFNAK
) {
2249 PUTCHAR(CI_MRRU
, nakp
);
2250 PUTCHAR(CILEN_SHORT
, nakp
);
2251 PUTSHORT(cishort
, nakp
);
2259 if (!ao
->neg_ssnhf
|| !multilink
) {
2260 newret
= CODE_CONFREJ
;
2263 if (cilen
!= CILEN_VOID
) {
2264 newret
= CODE_CONFNAK
;
2265 PUTCHAR(CI_SSNHF
, nakp
);
2266 PUTCHAR(CILEN_VOID
, nakp
);
2272 if (!ao
->neg_endpoint
) {
2273 newret
= CODE_CONFREJ
;
2276 if (cilen
< CILEN_CHAR
|| cilen
> CILEN_CHAR
+ MAX_ENDP_LEN
) {
2279 newret
= CODE_CONFNAK
;
2280 PUTCHAR(CI_EPDISC
, nakp
);
2281 PUTCHAR(CILEN_CHAR
+ ao
->endpoint
.length
, nakp
);
2282 PUTCHAR(ao
->endpoint
.class, nakp
);
2283 for (i
= 0; i
< ao
->endpoint
.length
; i
++)
2284 PUTCHAR(ao
->endpoint
.value
[i
], nakp
);
2288 ho
->neg_endpoint
= 1;
2289 ho
->endpoint
.class = cichar
;
2290 ho
->endpoint
.length
= cilen
- 3;
2291 BCOPY(p
, ho
->endpoint
.value
, cilen
- 3);
2296 if (ao
->pppmux
== 0 || cilen
!= CILEN_VOID
) {
2297 newret
= CODE_CONFREJ
;
2300 /* remember its option */
2301 ho
->pppmux
= ao
->pppmux
;
2306 dbglog("LCP: rejecting unknown option %d", citype
);
2307 newret
= CODE_CONFREJ
;
2311 /* Cope with confused peers. */
2316 * If this is an Ack'able CI, but we're sending back a Nak,
2317 * don't include this CI.
2319 if (newret
== CODE_CONFACK
&& ret
!= CODE_CONFACK
)
2322 if (newret
== CODE_CONFNAK
) {
2324 * Continue naking the Magic Number option until the cows come
2325 * home -- rejecting it is wrong.
2327 if (dont_nak
&& citype
!= CI_MAGICNUMBER
) {
2328 newret
= CODE_CONFREJ
;
2330 /* Ignore subsequent Nak'able things if rejecting. */
2331 if (ret
== CODE_CONFREJ
)
2337 if (newret
== CODE_CONFREJ
) {
2340 BCOPY(prev
, rejp
, cilen
);
2346 * If the peer hasn't negotiated its MRU, and we'd like an MTU
2347 * that's larger than the default, try sending an unsolicited
2348 * Nak for what we want.
2350 if (ret
!= CODE_CONFREJ
&& !ho
->neg_mru
&& ao
->mru
> PPP_MTU
&&
2351 !dont_nak
&& unsolicit_mru
) {
2352 unsolicit_mru
= 0; /* don't ask again */
2354 PUTCHAR(CI_MRU
, nakp
);
2355 PUTCHAR(CILEN_SHORT
, nakp
);
2356 PUTSHORT(ao
->mru
, nakp
);
2365 * Copy the Nak'd options from the nak_buffer to the caller's buffer.
2367 *lenp
= nakp
- nak_buffer
;
2368 BCOPY(nak_buffer
, p0
, *lenp
);
2373 /* We're about to send Configure-Reject; send Identification */
2374 if (!noident
&& sentident
< 3) {
2375 LcpSendIdentification(f
);
2381 LCPDEBUG(("lcp_reqci: returning %s.", code_name(ret
, 1)));
2382 return (ret
); /* Return final code */
2387 * lcp_up - LCP has come UP.
2393 lcp_options
*wo
= &lcp_wantoptions
[f
->unit
];
2394 lcp_options
*ho
= &lcp_hisoptions
[f
->unit
];
2395 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
2396 lcp_options
*ao
= &lcp_allowoptions
[f
->unit
];
2399 if (!go
->neg_magicnumber
)
2400 go
->magicnumber
= 0;
2401 if (!ho
->neg_magicnumber
)
2402 ho
->magicnumber
= 0;
2405 * Set our MTU to the smaller of the MTU we wanted and
2406 * the MRU our peer wanted. If we negotiated an MRU,
2407 * set our MRU to the larger of value we wanted and
2408 * the value we got in the negotiation.
2410 if (ao
->mru
!= 0 && ho
->mru
> ao
->mru
)
2412 mtu
= (ho
->neg_mru
? ho
->mru
: PPP_MRU
);
2413 if (mtu
> absmax_mtu
)
2415 ppp_send_config(f
->unit
, mtu
,
2416 (ho
->neg_asyncmap
? ho
->asyncmap
: 0xffffffff),
2417 ho
->neg_pcompression
, ho
->neg_accompression
);
2418 fsm_setpeermru(f
->unit
, mtu
);
2419 mru
= (go
->neg_mru
? MAX(wo
->mru
, go
->mru
): PPP_MRU
);
2420 if (mru
> absmax_mru
)
2422 ppp_recv_config(f
->unit
, mru
,
2423 (lax_recv
? 0: go
->neg_asyncmap
? go
->asyncmap
: 0xffffffff),
2424 go
->neg_pcompression
, go
->neg_accompression
);
2425 #ifdef NEGOTIATE_FCS
2426 ppp_send_fcs(f
->unit
, ho
->neg_fcs
? ho
->fcs_type
: FCSALT_16
);
2427 ppp_recv_fcs(f
->unit
, go
->neg_fcs
? go
->fcs_type
: FCSALT_16
);
2430 ppp_send_muxoption(f
->unit
, ho
->pppmux
);
2431 ppp_recv_muxoption(f
->unit
, go
->pppmux
);
2434 lcp_echo_lowerup(f
->unit
); /* Enable echo messages */
2436 /* LCP is Up; send Identification */
2438 LcpSendIdentification(f
);
2442 link_established(f
->unit
);
2447 * lcp_down - LCP has gone DOWN.
2449 * Alert other protocols.
2456 lcp_options
*go
= &lcp_gotoptions
[f
->unit
];
2458 lcp_echo_lowerdown(f
->unit
);
2462 mtu
= PPP_MTU
> absmax_mtu
? absmax_mtu
: PPP_MTU
;
2463 ppp_send_config(f
->unit
, mtu
, 0xffffffff, 0, 0);
2464 ppp_recv_config(f
->unit
, (PPP_MRU
> absmax_mru
? absmax_mru
: PPP_MRU
),
2465 (go
->neg_asyncmap
? go
->asyncmap
: 0xffffffff),
2466 go
->neg_pcompression
, go
->neg_accompression
);
2467 #ifdef NEGOTIATE_FCS
2468 ppp_send_fcs(f
->unit
, FCSALT_16
);
2469 ppp_recv_fcs(f
->unit
, FCSALT_16
);
2471 fsm_setpeermru(f
->unit
, mtu
);
2476 * lcp_starting - LCP needs the lower layer up.
2482 link_required(f
->unit
);
2487 * lcp_finished - LCP has finished with the lower layer.
2493 link_terminated(f
->unit
);
2498 * lcp_printpkt - print the contents of an LCP packet.
2502 lcp_printpkt(p
, plen
, printer
, arg
)
2505 void (*printer
) __P((void *, const char *, ...));
2508 int code
, id
, len
, olen
, i
;
2509 u_char
*pstart
, *optend
, cichar
;
2513 if (plen
< HEADERLEN
)
2519 if (len
< HEADERLEN
|| len
> plen
)
2522 printer(arg
, " %s id=0x%x", code_name(code
,1), id
);
2529 /* print option list */
2534 if (olen
< 2 || olen
> len
) {
2542 if (olen
>= CILEN_SHORT
) {
2544 GETSHORT(cishort
, p
);
2545 printer(arg
, "mru %d", cishort
);
2549 if (olen
>= CILEN_LONG
) {
2552 printer(arg
, "asyncmap 0x%x", cilong
);
2556 if (olen
>= CILEN_SHORT
) {
2558 printer(arg
, "auth ");
2559 GETSHORT(cishort
, p
);
2562 printer(arg
, "pap");
2565 printer(arg
, "chap");
2568 case CHAP_DIGEST_MD5
:
2569 printer(arg
, " MD5");
2572 case CHAP_MICROSOFT
:
2573 printer(arg
, " m$oft");
2576 case CHAP_MICROSOFT_V2
:
2577 printer(arg
, " m$oft-v2");
2585 printer(arg
, "eap");
2589 printer(arg
, "spap");
2592 printer(arg
, "old-spap");
2595 printer(arg
, "0x%x", cishort
);
2600 if (olen
>= CILEN_SHORT
) {
2602 printer(arg
, "quality ");
2603 GETSHORT(cishort
, p
);
2606 printer(arg
, "lqr");
2609 printer(arg
, "0x%x", cishort
);
2614 if (olen
>= CILEN_CHAR
) {
2616 printer(arg
, "callback ");
2619 *callback_strings
[(int)cichar
] != '\0') {
2620 printer(arg
, "%s", callback_strings
[(int)cichar
]);
2622 printer(arg
, "0x%x", cichar
);
2626 case CI_MAGICNUMBER
:
2627 if (olen
>= CILEN_LONG
) {
2630 printer(arg
, "magic 0x%x", cilong
);
2633 case CI_PCOMPRESSION
:
2634 if (olen
>= CILEN_VOID
) {
2636 printer(arg
, "pcomp");
2639 case CI_ACCOMPRESSION
:
2640 if (olen
>= CILEN_VOID
) {
2642 printer(arg
, "accomp");
2646 if (olen
>= CILEN_CHAR
) {
2652 for (cpp
= fcsalt_strings
; *cpp
!= NULL
; cpp
++)
2653 if (cichar
& 1<<(cpp
-fcsalt_strings
)) {
2654 cichar
&= ~(1<<(cpp
-fcsalt_strings
));
2655 printer(arg
, (needcomma
? ",%s" : "fcs %s"), *cpp
);
2658 if (cichar
!= 0 || !needcomma
)
2659 printer(arg
, (needcomma
? ",0x%x" : "fcs 0x%x"),
2664 if (olen
>= CILEN_SHORT
) {
2667 printer(arg
, "numb win %d", cichar
);
2669 printer(arg
, " addr %d", cichar
);
2673 if (olen
>= CILEN_SHORT
) {
2675 GETSHORT(cishort
, p
);
2676 printer(arg
, "mrru %d", cishort
);
2680 if (olen
>= CILEN_VOID
) {
2682 printer(arg
, "ssnhf");
2686 if (olen
>= CILEN_CHAR
) {
2689 GETCHAR(epd
.class, p
);
2690 epd
.length
= olen
- CILEN_CHAR
;
2691 if (epd
.length
> MAX_ENDP_LEN
)
2692 epd
.length
= MAX_ENDP_LEN
;
2693 if (epd
.length
> 0) {
2694 BCOPY(p
, epd
.value
, epd
.length
);
2697 printer(arg
, "endpoint [%s]", epdisc_to_str(&epd
));
2701 if (olen
>= CILEN_SHORT
) {
2703 GETSHORT(cishort
, p
);
2704 printer(arg
, "linkdisc %d", cishort
);
2708 if (olen
>= CILEN_CHAR
) {
2711 printer(arg
, "cobs 0x%x", cichar
);
2715 if (olen
>= CILEN_CHAR
) {
2717 printer(arg
, "pfx");
2721 if (olen
>= CILEN_SHORT
) {
2723 printer(arg
, "mphdr ");
2727 printer(arg
, "long");
2730 printer(arg
, "short");
2733 printer(arg
, "0x%x", cichar
);
2737 printer(arg
, " #cl %d", cichar
);
2741 if (olen
>= CILEN_LONG
) {
2744 printer(arg
, "i18n charset 0x%x", cilong
);
2745 if (olen
> CILEN_LONG
) {
2746 printer(arg
, " lang ");
2747 print_string((char *)p
, olen
-CILEN_LONG
, printer
, arg
);
2753 if (olen
>= CILEN_VOID
) {
2755 printer(arg
, "sdl");
2759 if (olen
>= CILEN_VOID
) {
2761 printer(arg
, "mux");
2765 while (p
< optend
) {
2767 printer(arg
, " %.2x", code
);
2775 if (len
> 0 && *p
>= ' ' && *p
< 0x7f) {
2777 print_string((char *)p
, len
, printer
, arg
);
2788 printer(arg
, " magic=0x%x", cilong
);
2796 printer(arg
, " magic=0x%x", cilong
);
2800 if (len
> 0 && (len
> 1 || *p
!= '\0')) {
2802 print_string((char *)p
, len
, printer
, arg
);
2808 case CODE_TIMEREMAIN
:
2811 printer(arg
, " magic=0x%x", cilong
);
2817 printer(arg
, " seconds=%d", cilong
);
2821 if (len
> 0 && (len
> 1 || *p
!= '\0')) {
2823 print_string((char *)p
, len
, printer
, arg
);
2830 /* print the rest of the bytes in the packet */
2831 for (i
= 0; i
< len
&& i
< 32; ++i
) {
2833 printer(arg
, " %.2x", code
);
2836 printer(arg
, " ...");
2844 * Time to shut down the link because there is nothing out there.
2851 char *close_message
;
2853 if (f
->state
== OPENED
) {
2854 if (lcp_echo_badreplies
> LCP_ECHO_MAX_BADREPLIES
) {
2855 info("Received %d bad echo-replies", lcp_echo_badreplies
);
2856 close_message
= "Receiving malformed Echo-Replies";
2857 } else if (lcp_echo_accm_test
) {
2859 * If this is an asynchronous line and we've missed all of
2860 * the initial echo requests, then this is probably due to
2863 notice("Peer not responding to initial Echo-Requests.");
2864 notice("Negotiated asyncmap may be incorrect for this link.");
2865 close_message
= "Peer not responding; perhaps bad asyncmap";
2867 info("No response to %d echo-requests", lcp_echos_pending
);
2868 notice("Serial link appears to be disconnected.");
2869 close_message
= "Peer not responding";
2872 lcp_close(f
->unit
, close_message
);
2873 status
= EXIT_PEER_DEAD
;
2878 * Timer expired for the LCP echo requests from this process.
2885 if (f
->state
!= OPENED
|| lcp_echo_interval
== 0)
2888 LcpSendEchoRequest (f
);
2891 * Start the timer for the next interval.
2893 if (lcp_echo_timer_running
)
2894 warn("assertion lcp_echo_timer_running==0 failed");
2895 TIMEOUT (LcpEchoTimeout
, f
, lcp_echo_interval
);
2896 lcp_echo_timer_running
= 1;
2900 * LcpEchoTimeout - Timer expired on the LCP echo
2904 LcpEchoTimeout (arg
)
2907 if (lcp_echo_timer_running
!= 0) {
2908 lcp_echo_timer_running
= 0;
2909 LcpEchoCheck ((fsm
*) arg
);
2914 * LcpEchoReply - LCP has received a reply to the echo
2918 lcp_received_echo_reply (f
, id
, inp
, len
)
2926 /* Check the magic number - don't count replies from ourselves. */
2928 dbglog("lcp: received short Echo-Reply, length %d", len
);
2931 GETLONG(magic
, inp
);
2932 if (lcp_gotoptions
[f
->unit
].neg_magicnumber
&&
2933 magic
== lcp_gotoptions
[f
->unit
].magicnumber
) {
2934 warn("appear to have received our own echo-reply!");
2938 /* Reset the number of outstanding echo frames */
2939 lcp_echos_pending
= 0;
2941 if (lcp_echo_accm_test
) {
2942 dbglog("lcp: validated asyncmap setting");
2943 lcp_echo_accm_test
= 0;
2944 if (lcp_echo_fails
== 0)
2945 lcp_echo_interval
= 0;
2951 * LcpSendEchoRequest - Send an echo request frame to the peer
2955 LcpSendEchoRequest (f
)
2958 u_int32_t lcp_magic
;
2959 u_char pkt
[4+256], *pktp
;
2963 * Detect the failure of the peer at this point. If we're not currently
2964 * performing the ACCM test, then we just check for the user's echo-failure
2965 * point. If we are performing the ACCM test, then use ACCM_TEST_FAILS if
2966 * the user hasn't specified a different failure point.
2970 i
= ACCM_TEST_FAILS
;
2971 if ((!lcp_echo_accm_test
&& lcp_echo_fails
!= 0 &&
2972 lcp_echos_pending
>= lcp_echo_fails
) ||
2973 (lcp_echo_accm_test
&& lcp_echos_pending
>= i
)) {
2975 lcp_echos_pending
= 0;
2976 lcp_echo_badreplies
= 0;
2980 * Make and send the echo request frame.
2982 if (f
->state
== OPENED
) {
2983 lcp_magic
= lcp_gotoptions
[f
->unit
].magicnumber
;
2985 PUTLONG(lcp_magic
, pktp
);
2986 /* Send some test packets so we can fail the link early. */
2987 if (lcp_echo_accm_test
) {
2988 switch (use_accm_test
) {
2990 /* Only the characters covered by negotiated ACCM */
2991 for (i
= 0; i
< 32; i
++)
2995 /* All characters */
2996 for (i
= 0; i
< 256; i
++)
3001 fsm_sdata(f
, CODE_ECHOREQ
, lcp_echo_number
++ & 0xFF, pkt
, pktp
- pkt
);
3002 ++lcp_echos_pending
;
3007 * lcp_echo_lowerup - Start the timer for the LCP frame
3011 lcp_echo_lowerup (unit
)
3014 fsm
*f
= &lcp_fsm
[unit
];
3016 /* Clear the parameters for generating echo frames */
3017 lcp_echos_pending
= 0;
3018 lcp_echo_number
= 0;
3019 lcp_echo_timer_running
= 0;
3020 lcp_echo_accm_test
= !sync_serial
&& use_accm_test
;
3022 /* If a timeout interval is specified then start the timer */
3027 * lcp_echo_lowerdown - Stop the timer for the LCP frame
3031 lcp_echo_lowerdown (unit
)
3034 fsm
*f
= &lcp_fsm
[unit
];
3036 if (lcp_echo_timer_running
!= 0) {
3037 UNTIMEOUT (LcpEchoTimeout
, f
);
3038 lcp_echo_timer_running
= 0;
3043 * LcpSendIdentification - Send LCP Identification string to peer.
3047 LcpSendIdentification (f
)
3050 u_int32_t lcp_magic
;
3051 u_char pkt
[4 + sizeof(identstr
)], *pktp
;
3055 * Make and send the Identification frame.
3057 if (f
->state
== OPENED
)
3058 lcp_magic
= lcp_gotoptions
[f
->unit
].magicnumber
;
3063 PUTLONG(lcp_magic
, pktp
);
3064 idlen
= strlen(identstr
);
3065 BCOPY(identstr
, pktp
, idlen
);
3066 INCPTR(idlen
, pktp
);
3067 fsm_sdata(f
, CODE_IDENT
, ++f
->id
, pkt
, pktp
- pkt
);
3072 lcp_received_identification (f
, id
, inp
, len
)
3080 /* Check the magic number - don't count replies from ourselves. */
3082 dbglog("%s: received short Identification; %d < 4", len
);
3085 GETLONG(magic
, inp
);
3087 if (lcp_gotoptions
[f
->unit
].neg_magicnumber
&& f
->state
== OPENED
&&
3088 magic
== lcp_gotoptions
[f
->unit
].magicnumber
) {
3089 warn("appear to have received our own Identification!");
3092 if (len
> 0 && (len
> 1 || *inp
!= '\0'))
3093 notice("Peer Identification: %0.*v", len
, inp
);
3097 * Send a Time-Remaining LCP packet. We don't include a message.
3100 LcpSendTimeRemaining(f
, time_remaining
)
3102 u_int32_t time_remaining
;
3104 u_int32_t lcp_magic
;
3108 if (f
->state
!= OPENED
)
3111 lcp_magic
= lcp_gotoptions
[f
->unit
].magicnumber
;
3113 PUTLONG(lcp_magic
, pktp
);
3114 PUTLONG(time_remaining
, pktp
);
3115 fsm_sdata(f
, CODE_TIMEREMAIN
, ++f
->id
, pkt
, pktp
- pkt
);
3120 lcp_received_timeremain(f
, id
, inp
, len
)
3127 u_int32_t time_remaining
;
3129 /* Check the magic number - don't count replies from ourselves. */
3131 dbglog("%s: received short Time-Remain; %d < 8", len
);
3134 GETLONG(magic
, inp
);
3135 if (lcp_gotoptions
[f
->unit
].neg_magicnumber
&& f
->state
== OPENED
&&
3136 magic
== lcp_gotoptions
[f
->unit
].magicnumber
) {
3137 warn("appear to have received our own Time-Remain!");
3140 GETLONG(time_remaining
, inp
);
3142 notice("%d seconds remain: \"%.*s\"", time_remaining
,
3145 notice("Time Remaining: %d seconds", time_remaining
);
3150 * lcp_timeremaining - timeout handler which sends LCP Time-Remaining
3154 lcp_timeremaining(arg
)
3157 struct lcp_timer
*lt
= (struct lcp_timer
*)arg
;
3158 u_int32_t time_remaining
;
3162 time_remaining
= lt
->tr
;
3163 LcpSendTimeRemaining(&lcp_fsm
[unit
], time_remaining
);
3168 * lcp_settimeremaining - set a timeout to send an LCP Time-Remaining
3169 * packet. The first argument, connecttime, is the time remaining
3170 * at the time this function is called. The second argument is the
3171 * desired time remaining when the packet should be sent out.
3174 lcp_settimeremaining(unit
, connecttime
, time_remaining
)
3176 u_int32_t connecttime
;
3177 u_int32_t time_remaining
;
3179 struct lcp_timer
*lt
;
3181 if (connecttime
== time_remaining
) {
3182 LcpSendTimeRemaining(&lcp_fsm
[unit
], time_remaining
);
3184 lt
= (struct lcp_timer
*)malloc(sizeof (struct lcp_timer
));
3186 lt
->tr
= time_remaining
;
3187 TIMEOUT(lcp_timeremaining
, (void *)lt
, connecttime
- time_remaining
);