1 | /* $NetBSD: if_spppsubr.c,v 1.157 2016/11/18 10:38:55 knakahara Exp $ */ |
2 | |
3 | /* |
4 | * Synchronous PPP/Cisco link level subroutines. |
5 | * Keepalive protocol implemented in both Cisco and PPP modes. |
6 | * |
7 | * Copyright (C) 1994-1996 Cronyx Engineering Ltd. |
8 | * Author: Serge Vakulenko, <vak@cronyx.ru> |
9 | * |
10 | * Heavily revamped to conform to RFC 1661. |
11 | * Copyright (C) 1997, Joerg Wunsch. |
12 | * |
13 | * RFC2472 IPv6CP support. |
14 | * Copyright (C) 2000, Jun-ichiro itojun Hagino <itojun@iijlab.net>. |
15 | * |
16 | * Redistribution and use in source and binary forms, with or without |
17 | * modification, are permitted provided that the following conditions are met: |
18 | * 1. Redistributions of source code must retain the above copyright notice, |
19 | * this list of conditions and the following disclaimer. |
20 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
21 | * this list of conditions and the following disclaimer in the documentation |
22 | * and/or other materials provided with the distribution. |
23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY |
25 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | * |
36 | * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 |
37 | * |
38 | * From: if_spppsubr.c,v 1.39 1998/04/04 13:26:03 phk Exp |
39 | * |
40 | * From: Id: if_spppsubr.c,v 1.23 1999/02/23 14:47:50 hm Exp |
41 | */ |
42 | |
43 | #include <sys/cdefs.h> |
44 | __KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.157 2016/11/18 10:38:55 knakahara Exp $" ); |
45 | |
46 | #if defined(_KERNEL_OPT) |
47 | #include "opt_inet.h" |
48 | #include "opt_modular.h" |
49 | #include "opt_compat_netbsd.h" |
50 | #include "opt_net_mpsafe.h" |
51 | #endif |
52 | |
53 | |
54 | #include <sys/param.h> |
55 | #include <sys/proc.h> |
56 | #include <sys/systm.h> |
57 | #include <sys/kernel.h> |
58 | #include <sys/sockio.h> |
59 | #include <sys/socket.h> |
60 | #include <sys/syslog.h> |
61 | #include <sys/malloc.h> |
62 | #include <sys/mbuf.h> |
63 | #include <sys/callout.h> |
64 | #include <sys/md5.h> |
65 | #include <sys/inttypes.h> |
66 | #include <sys/kauth.h> |
67 | #include <sys/cprng.h> |
68 | #include <sys/module.h> |
69 | |
70 | #include <net/if.h> |
71 | #include <net/netisr.h> |
72 | #include <net/if_types.h> |
73 | #include <net/route.h> |
74 | #include <net/ppp_defs.h> |
75 | |
76 | #include <netinet/in.h> |
77 | #include <netinet/in_systm.h> |
78 | #include <netinet/in_var.h> |
79 | #ifdef INET |
80 | #include <netinet/ip.h> |
81 | #include <netinet/tcp.h> |
82 | #endif |
83 | #include <net/ethertypes.h> |
84 | |
85 | #ifdef INET6 |
86 | #include <netinet6/scope6_var.h> |
87 | #endif |
88 | |
89 | #include <net/if_sppp.h> |
90 | #include <net/if_spppvar.h> |
91 | |
92 | #define LCP_KEEPALIVE_INTERVAL 10 /* seconds between checks */ |
93 | #define LOOPALIVECNT 3 /* loopback detection tries */ |
94 | #define DEFAULT_MAXALIVECNT 3 /* max. missed alive packets */ |
95 | #define DEFAULT_NORECV_TIME 15 /* before we get worried */ |
96 | #define DEFAULT_MAX_AUTH_FAILURES 5 /* max. auth. failures */ |
97 | |
98 | /* |
99 | * Interface flags that can be set in an ifconfig command. |
100 | * |
101 | * Setting link0 will make the link passive, i.e. it will be marked |
102 | * as being administrative openable, but won't be opened to begin |
103 | * with. Incoming calls will be answered, or subsequent calls with |
104 | * -link1 will cause the administrative open of the LCP layer. |
105 | * |
106 | * Setting link1 will cause the link to auto-dial only as packets |
107 | * arrive to be sent. |
108 | * |
109 | * Setting IFF_DEBUG will syslog the option negotiation and state |
110 | * transitions at level kern.debug. Note: all logs consistently look |
111 | * like |
112 | * |
113 | * <if-name><unit>: <proto-name> <additional info...> |
114 | * |
115 | * with <if-name><unit> being something like "bppp0", and <proto-name> |
116 | * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. |
117 | */ |
118 | |
119 | #define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ |
120 | #define IFF_AUTO IFF_LINK1 /* auto-dial on output */ |
121 | |
122 | #define CONF_REQ 1 /* PPP configure request */ |
123 | #define CONF_ACK 2 /* PPP configure acknowledge */ |
124 | #define CONF_NAK 3 /* PPP configure negative ack */ |
125 | #define CONF_REJ 4 /* PPP configure reject */ |
126 | #define TERM_REQ 5 /* PPP terminate request */ |
127 | #define TERM_ACK 6 /* PPP terminate acknowledge */ |
128 | #define CODE_REJ 7 /* PPP code reject */ |
129 | #define PROTO_REJ 8 /* PPP protocol reject */ |
130 | #define ECHO_REQ 9 /* PPP echo request */ |
131 | #define ECHO_REPLY 10 /* PPP echo reply */ |
132 | #define DISC_REQ 11 /* PPP discard request */ |
133 | |
134 | #define LCP_OPT_MRU 1 /* maximum receive unit */ |
135 | #define LCP_OPT_ASYNC_MAP 2 /* async control character map */ |
136 | #define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ |
137 | #define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ |
138 | #define LCP_OPT_MAGIC 5 /* magic number */ |
139 | #define LCP_OPT_RESERVED 6 /* reserved */ |
140 | #define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ |
141 | #define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ |
142 | |
143 | #define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ |
144 | #define IPCP_OPT_COMPRESSION 2 /* IP compression protocol */ |
145 | #define IPCP_OPT_ADDRESS 3 /* local IP address */ |
146 | #define IPCP_OPT_PRIMDNS 129 /* primary remote dns address */ |
147 | #define IPCP_OPT_SECDNS 131 /* secondary remote dns address */ |
148 | |
149 | #define IPV6CP_OPT_IFID 1 /* interface identifier */ |
150 | #define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ |
151 | |
152 | #define PAP_REQ 1 /* PAP name/password request */ |
153 | #define PAP_ACK 2 /* PAP acknowledge */ |
154 | #define PAP_NAK 3 /* PAP fail */ |
155 | |
156 | #define CHAP_CHALLENGE 1 /* CHAP challenge request */ |
157 | #define CHAP_RESPONSE 2 /* CHAP challenge response */ |
158 | #define CHAP_SUCCESS 3 /* CHAP response ok */ |
159 | #define CHAP_FAILURE 4 /* CHAP response failed */ |
160 | |
161 | #define CHAP_MD5 5 /* hash algorithm - MD5 */ |
162 | |
163 | #define CISCO_MULTICAST 0x8f /* Cisco multicast address */ |
164 | #define CISCO_UNICAST 0x0f /* Cisco unicast address */ |
165 | #define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ |
166 | #define CISCO_ADDR_REQ 0 /* Cisco address request */ |
167 | #define CISCO_ADDR_REPLY 1 /* Cisco address reply */ |
168 | #define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ |
169 | |
170 | /* states are named and numbered according to RFC 1661 */ |
171 | #define STATE_INITIAL 0 |
172 | #define STATE_STARTING 1 |
173 | #define STATE_CLOSED 2 |
174 | #define STATE_STOPPED 3 |
175 | #define STATE_CLOSING 4 |
176 | #define STATE_STOPPING 5 |
177 | #define STATE_REQ_SENT 6 |
178 | #define STATE_ACK_RCVD 7 |
179 | #define STATE_ACK_SENT 8 |
180 | #define STATE_OPENED 9 |
181 | |
182 | struct { |
183 | uint8_t ; |
184 | uint8_t ; |
185 | uint16_t ; |
186 | } __packed; |
187 | #define sizeof (struct ppp_header) |
188 | |
189 | struct { |
190 | uint8_t ; |
191 | uint8_t ; |
192 | uint16_t ; |
193 | } __packed; |
194 | #define sizeof (struct lcp_header) |
195 | |
196 | struct cisco_packet { |
197 | uint32_t type; |
198 | uint32_t par1; |
199 | uint32_t par2; |
200 | uint16_t rel; |
201 | uint16_t time0; |
202 | uint16_t time1; |
203 | } __packed; |
204 | #define CISCO_PACKET_LEN 18 |
205 | |
206 | /* |
207 | * We follow the spelling and capitalization of RFC 1661 here, to make |
208 | * it easier comparing with the standard. Please refer to this RFC in |
209 | * case you can't make sense out of these abbreviation; it will also |
210 | * explain the semantics related to the various events and actions. |
211 | */ |
212 | struct cp { |
213 | u_short proto; /* PPP control protocol number */ |
214 | u_char protoidx; /* index into state table in struct sppp */ |
215 | u_char flags; |
216 | #define CP_LCP 0x01 /* this is the LCP */ |
217 | #define CP_AUTH 0x02 /* this is an authentication protocol */ |
218 | #define CP_NCP 0x04 /* this is a NCP */ |
219 | #define CP_QUAL 0x08 /* this is a quality reporting protocol */ |
220 | const char *name; /* name of this control protocol */ |
221 | /* event handlers */ |
222 | void (*Up)(struct sppp *sp); |
223 | void (*Down)(struct sppp *sp); |
224 | void (*Open)(struct sppp *sp); |
225 | void (*Close)(struct sppp *sp); |
226 | void (*TO)(void *sp); |
227 | int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); |
228 | void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); |
229 | void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); |
230 | /* actions */ |
231 | void (*tlu)(struct sppp *sp); |
232 | void (*tld)(struct sppp *sp); |
233 | void (*tls)(struct sppp *sp); |
234 | void (*tlf)(struct sppp *sp); |
235 | void (*scr)(struct sppp *sp); |
236 | }; |
237 | |
238 | static struct sppp *spppq; |
239 | static callout_t keepalive_ch; |
240 | |
241 | #ifdef INET |
242 | /* |
243 | * The following disgusting hack gets around the problem that IP TOS |
244 | * can't be set yet. We want to put "interactive" traffic on a high |
245 | * priority queue. To decide if traffic is interactive, we check that |
246 | * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. |
247 | * |
248 | * XXX is this really still necessary? - joerg - |
249 | */ |
250 | static u_short interactive_ports[8] = { |
251 | 0, 513, 0, 0, |
252 | 0, 21, 0, 23, |
253 | }; |
254 | #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) |
255 | #endif |
256 | |
257 | /* almost every function needs these */ |
258 | #define STDDCL \ |
259 | struct ifnet *ifp = &sp->pp_if; \ |
260 | int debug = ifp->if_flags & IFF_DEBUG |
261 | |
262 | static int sppp_output(struct ifnet *ifp, struct mbuf *m, |
263 | const struct sockaddr *dst, const struct rtentry *rt); |
264 | |
265 | static void sppp_cisco_send(struct sppp *sp, int type, int32_t par1, int32_t par2); |
266 | static void sppp_cisco_input(struct sppp *sp, struct mbuf *m); |
267 | |
268 | static void sppp_cp_input(const struct cp *cp, struct sppp *sp, |
269 | struct mbuf *m); |
270 | static void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, |
271 | u_char ident, u_short len, void *data); |
272 | /* static void sppp_cp_timeout(void *arg); */ |
273 | static void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, |
274 | int newstate); |
275 | static void sppp_auth_send(const struct cp *cp, |
276 | struct sppp *sp, unsigned int type, unsigned int id, |
277 | ...); |
278 | |
279 | static void sppp_up_event(const struct cp *cp, struct sppp *sp); |
280 | static void sppp_down_event(const struct cp *cp, struct sppp *sp); |
281 | static void sppp_open_event(const struct cp *cp, struct sppp *sp); |
282 | static void sppp_close_event(const struct cp *cp, struct sppp *sp); |
283 | static void sppp_to_event(const struct cp *cp, struct sppp *sp); |
284 | |
285 | static void sppp_null(struct sppp *sp); |
286 | |
287 | static void sppp_lcp_init(struct sppp *sp); |
288 | static void sppp_lcp_up(struct sppp *sp); |
289 | static void sppp_lcp_down(struct sppp *sp); |
290 | static void sppp_lcp_open(struct sppp *sp); |
291 | static void sppp_lcp_close(struct sppp *sp); |
292 | static void sppp_lcp_TO(void *sp); |
293 | static int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); |
294 | static void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); |
295 | static void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); |
296 | static void sppp_lcp_tlu(struct sppp *sp); |
297 | static void sppp_lcp_tld(struct sppp *sp); |
298 | static void sppp_lcp_tls(struct sppp *sp); |
299 | static void sppp_lcp_tlf(struct sppp *sp); |
300 | static void sppp_lcp_scr(struct sppp *sp); |
301 | static void sppp_lcp_check_and_close(struct sppp *sp); |
302 | static int sppp_ncp_check(struct sppp *sp); |
303 | |
304 | static void sppp_ipcp_init(struct sppp *sp); |
305 | static void sppp_ipcp_up(struct sppp *sp); |
306 | static void sppp_ipcp_down(struct sppp *sp); |
307 | static void sppp_ipcp_open(struct sppp *sp); |
308 | static void sppp_ipcp_close(struct sppp *sp); |
309 | static void sppp_ipcp_TO(void *sp); |
310 | static int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); |
311 | static void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); |
312 | static void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); |
313 | static void sppp_ipcp_tlu(struct sppp *sp); |
314 | static void sppp_ipcp_tld(struct sppp *sp); |
315 | static void sppp_ipcp_tls(struct sppp *sp); |
316 | static void sppp_ipcp_tlf(struct sppp *sp); |
317 | static void sppp_ipcp_scr(struct sppp *sp); |
318 | |
319 | static void sppp_ipv6cp_init(struct sppp *sp); |
320 | static void sppp_ipv6cp_up(struct sppp *sp); |
321 | static void sppp_ipv6cp_down(struct sppp *sp); |
322 | static void sppp_ipv6cp_open(struct sppp *sp); |
323 | static void sppp_ipv6cp_close(struct sppp *sp); |
324 | static void sppp_ipv6cp_TO(void *sp); |
325 | static int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); |
326 | static void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); |
327 | static void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); |
328 | static void sppp_ipv6cp_tlu(struct sppp *sp); |
329 | static void sppp_ipv6cp_tld(struct sppp *sp); |
330 | static void sppp_ipv6cp_tls(struct sppp *sp); |
331 | static void sppp_ipv6cp_tlf(struct sppp *sp); |
332 | static void sppp_ipv6cp_scr(struct sppp *sp); |
333 | |
334 | static void sppp_pap_input(struct sppp *sp, struct mbuf *m); |
335 | static void sppp_pap_init(struct sppp *sp); |
336 | static void sppp_pap_open(struct sppp *sp); |
337 | static void sppp_pap_close(struct sppp *sp); |
338 | static void sppp_pap_TO(void *sp); |
339 | static void sppp_pap_my_TO(void *sp); |
340 | static void sppp_pap_tlu(struct sppp *sp); |
341 | static void sppp_pap_tld(struct sppp *sp); |
342 | static void sppp_pap_scr(struct sppp *sp); |
343 | |
344 | static void sppp_chap_input(struct sppp *sp, struct mbuf *m); |
345 | static void sppp_chap_init(struct sppp *sp); |
346 | static void sppp_chap_open(struct sppp *sp); |
347 | static void sppp_chap_close(struct sppp *sp); |
348 | static void sppp_chap_TO(void *sp); |
349 | static void sppp_chap_tlu(struct sppp *sp); |
350 | static void sppp_chap_tld(struct sppp *sp); |
351 | static void sppp_chap_scr(struct sppp *sp); |
352 | |
353 | static const char *sppp_auth_type_name(u_short proto, u_char type); |
354 | static const char *sppp_cp_type_name(u_char type); |
355 | static const char *sppp_dotted_quad(uint32_t addr); |
356 | static const char *sppp_ipcp_opt_name(u_char opt); |
357 | #ifdef INET6 |
358 | static const char *sppp_ipv6cp_opt_name(u_char opt); |
359 | #endif |
360 | static const char *sppp_lcp_opt_name(u_char opt); |
361 | static const char *sppp_phase_name(int phase); |
362 | static const char *sppp_proto_name(u_short proto); |
363 | static const char *sppp_state_name(int state); |
364 | static int sppp_params(struct sppp *sp, u_long cmd, void *data); |
365 | #ifdef INET |
366 | static void sppp_get_ip_addrs(struct sppp *sp, uint32_t *src, uint32_t *dst, |
367 | uint32_t *srcmask); |
368 | static void sppp_set_ip_addrs(struct sppp *sp, uint32_t myaddr, uint32_t hisaddr); |
369 | static void sppp_clear_ip_addrs(struct sppp *sp); |
370 | #endif |
371 | static void sppp_keepalive(void *dummy); |
372 | static void sppp_phase_network(struct sppp *sp); |
373 | static void sppp_print_bytes(const u_char *p, u_short len); |
374 | static void sppp_print_string(const char *p, u_short len); |
375 | #ifdef INET6 |
376 | static void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, |
377 | struct in6_addr *dst, struct in6_addr *srcmask); |
378 | #ifdef IPV6CP_MYIFID_DYN |
379 | static void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); |
380 | static void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); |
381 | #endif |
382 | static void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); |
383 | #endif |
384 | |
385 | /* our control protocol descriptors */ |
386 | static const struct cp lcp = { |
387 | PPP_LCP, IDX_LCP, CP_LCP, "lcp" , |
388 | sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, |
389 | sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, |
390 | sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, |
391 | sppp_lcp_scr |
392 | }; |
393 | |
394 | static const struct cp ipcp = { |
395 | PPP_IPCP, IDX_IPCP, |
396 | #ifdef INET |
397 | CP_NCP, /*don't run IPCP if there's no IPv4 support*/ |
398 | #else |
399 | 0, |
400 | #endif |
401 | "ipcp" , |
402 | sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, |
403 | sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, |
404 | sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, |
405 | sppp_ipcp_scr |
406 | }; |
407 | |
408 | static const struct cp ipv6cp = { |
409 | PPP_IPV6CP, IDX_IPV6CP, |
410 | #ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ |
411 | CP_NCP, |
412 | #else |
413 | 0, |
414 | #endif |
415 | "ipv6cp" , |
416 | sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, |
417 | sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, |
418 | sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, |
419 | sppp_ipv6cp_scr |
420 | }; |
421 | |
422 | static const struct cp pap = { |
423 | PPP_PAP, IDX_PAP, CP_AUTH, "pap" , |
424 | sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, |
425 | sppp_pap_TO, 0, 0, 0, |
426 | sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, |
427 | sppp_pap_scr |
428 | }; |
429 | |
430 | static const struct cp chap = { |
431 | PPP_CHAP, IDX_CHAP, CP_AUTH, "chap" , |
432 | sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, |
433 | sppp_chap_TO, 0, 0, 0, |
434 | sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, |
435 | sppp_chap_scr |
436 | }; |
437 | |
438 | static const struct cp *cps[IDX_COUNT] = { |
439 | &lcp, /* IDX_LCP */ |
440 | &ipcp, /* IDX_IPCP */ |
441 | &ipv6cp, /* IDX_IPV6CP */ |
442 | &pap, /* IDX_PAP */ |
443 | &chap, /* IDX_CHAP */ |
444 | }; |
445 | |
446 | static void |
447 | sppp_change_phase(struct sppp *sp, int phase) |
448 | { |
449 | STDDCL; |
450 | |
451 | if (sp->pp_phase == phase) |
452 | return; |
453 | |
454 | sp->pp_phase = phase; |
455 | |
456 | if (phase == SPPP_PHASE_NETWORK) |
457 | if_link_state_change(ifp, LINK_STATE_UP); |
458 | else |
459 | if_link_state_change(ifp, LINK_STATE_DOWN); |
460 | |
461 | if (debug) |
462 | { |
463 | log(LOG_INFO, "%s: phase %s\n" , ifp->if_xname, |
464 | sppp_phase_name(sp->pp_phase)); |
465 | } |
466 | } |
467 | |
468 | /* |
469 | * Exported functions, comprising our interface to the lower layer. |
470 | */ |
471 | |
472 | /* |
473 | * Process the received packet. |
474 | */ |
475 | void |
476 | sppp_input(struct ifnet *ifp, struct mbuf *m) |
477 | { |
478 | struct ppp_header *h = NULL; |
479 | pktqueue_t *pktq = NULL; |
480 | struct ifqueue *inq = NULL; |
481 | uint16_t protocol; |
482 | struct sppp *sp = (struct sppp *)ifp; |
483 | int debug = ifp->if_flags & IFF_DEBUG; |
484 | int isr = 0; |
485 | |
486 | if (ifp->if_flags & IFF_UP) { |
487 | /* Count received bytes, add hardware framing */ |
488 | ifp->if_ibytes += m->m_pkthdr.len + sp->pp_framebytes; |
489 | /* Note time of last receive */ |
490 | sp->pp_last_receive = time_uptime; |
491 | } |
492 | |
493 | if (m->m_pkthdr.len <= PPP_HEADER_LEN) { |
494 | /* Too small packet, drop it. */ |
495 | if (debug) |
496 | log(LOG_DEBUG, |
497 | "%s: input packet is too small, %d bytes\n" , |
498 | ifp->if_xname, m->m_pkthdr.len); |
499 | drop: |
500 | ++ifp->if_ierrors; |
501 | ++ifp->if_iqdrops; |
502 | m_freem(m); |
503 | return; |
504 | } |
505 | |
506 | if (sp->pp_flags & PP_NOFRAMING) { |
507 | memcpy(&protocol, mtod(m, void *), 2); |
508 | protocol = ntohs(protocol); |
509 | m_adj(m, 2); |
510 | } else { |
511 | |
512 | /* Get PPP header. */ |
513 | h = mtod(m, struct ppp_header *); |
514 | m_adj(m, PPP_HEADER_LEN); |
515 | |
516 | switch (h->address) { |
517 | case PPP_ALLSTATIONS: |
518 | if (h->control != PPP_UI) |
519 | goto invalid; |
520 | if (sp->pp_flags & PP_CISCO) { |
521 | if (debug) |
522 | log(LOG_DEBUG, |
523 | "%s: PPP packet in Cisco mode " |
524 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n" , |
525 | ifp->if_xname, |
526 | h->address, h->control, ntohs(h->protocol)); |
527 | goto drop; |
528 | } |
529 | break; |
530 | case CISCO_MULTICAST: |
531 | case CISCO_UNICAST: |
532 | /* Don't check the control field here (RFC 1547). */ |
533 | if (! (sp->pp_flags & PP_CISCO)) { |
534 | if (debug) |
535 | log(LOG_DEBUG, |
536 | "%s: Cisco packet in PPP mode " |
537 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n" , |
538 | ifp->if_xname, |
539 | h->address, h->control, ntohs(h->protocol)); |
540 | goto drop; |
541 | } |
542 | switch (ntohs(h->protocol)) { |
543 | default: |
544 | ++ifp->if_noproto; |
545 | goto invalid; |
546 | case CISCO_KEEPALIVE: |
547 | sppp_cisco_input((struct sppp *) ifp, m); |
548 | m_freem(m); |
549 | return; |
550 | #ifdef INET |
551 | case ETHERTYPE_IP: |
552 | pktq = ip_pktq; |
553 | break; |
554 | #endif |
555 | #ifdef INET6 |
556 | case ETHERTYPE_IPV6: |
557 | pktq = ip6_pktq; |
558 | break; |
559 | #endif |
560 | } |
561 | goto queue_pkt; |
562 | default: /* Invalid PPP packet. */ |
563 | invalid: |
564 | if (debug) |
565 | log(LOG_DEBUG, |
566 | "%s: invalid input packet " |
567 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n" , |
568 | ifp->if_xname, |
569 | h->address, h->control, ntohs(h->protocol)); |
570 | goto drop; |
571 | } |
572 | protocol = ntohs(h->protocol); |
573 | } |
574 | |
575 | switch (protocol) { |
576 | default: |
577 | if (sp->state[IDX_LCP] == STATE_OPENED) { |
578 | uint16_t prot = htons(protocol); |
579 | sppp_cp_send(sp, PPP_LCP, PROTO_REJ, |
580 | ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, |
581 | &prot); |
582 | } |
583 | if (debug) |
584 | log(LOG_DEBUG, |
585 | "%s: invalid input protocol " |
586 | "<proto=0x%x>\n" , ifp->if_xname, ntohs(protocol)); |
587 | ++ifp->if_noproto; |
588 | goto drop; |
589 | case PPP_LCP: |
590 | sppp_cp_input(&lcp, sp, m); |
591 | m_freem(m); |
592 | return; |
593 | case PPP_PAP: |
594 | if (sp->pp_phase >= SPPP_PHASE_AUTHENTICATE) |
595 | sppp_pap_input(sp, m); |
596 | m_freem(m); |
597 | return; |
598 | case PPP_CHAP: |
599 | if (sp->pp_phase >= SPPP_PHASE_AUTHENTICATE) |
600 | sppp_chap_input(sp, m); |
601 | m_freem(m); |
602 | return; |
603 | #ifdef INET |
604 | case PPP_IPCP: |
605 | if (sp->pp_phase == SPPP_PHASE_NETWORK) |
606 | sppp_cp_input(&ipcp, sp, m); |
607 | m_freem(m); |
608 | return; |
609 | case PPP_IP: |
610 | if (sp->state[IDX_IPCP] == STATE_OPENED) { |
611 | sp->pp_last_activity = time_uptime; |
612 | pktq = ip_pktq; |
613 | } |
614 | break; |
615 | #endif |
616 | #ifdef INET6 |
617 | case PPP_IPV6CP: |
618 | if (sp->pp_phase == SPPP_PHASE_NETWORK) |
619 | sppp_cp_input(&ipv6cp, sp, m); |
620 | m_freem(m); |
621 | return; |
622 | |
623 | case PPP_IPV6: |
624 | if (sp->state[IDX_IPV6CP] == STATE_OPENED) { |
625 | sp->pp_last_activity = time_uptime; |
626 | pktq = ip6_pktq; |
627 | } |
628 | break; |
629 | #endif |
630 | } |
631 | |
632 | queue_pkt: |
633 | if ((ifp->if_flags & IFF_UP) == 0 || (!inq && !pktq)) { |
634 | goto drop; |
635 | } |
636 | |
637 | /* Check queue. */ |
638 | if (__predict_true(pktq)) { |
639 | if (__predict_false(!pktq_enqueue(pktq, m, 0))) { |
640 | goto drop; |
641 | } |
642 | return; |
643 | } |
644 | |
645 | IFQ_LOCK(inq); |
646 | if (IF_QFULL(inq)) { |
647 | /* Queue overflow. */ |
648 | IF_DROP(inq); |
649 | IFQ_UNLOCK(inq); |
650 | if (debug) |
651 | log(LOG_DEBUG, "%s: protocol queue overflow\n" , |
652 | ifp->if_xname); |
653 | goto drop; |
654 | } |
655 | IF_ENQUEUE(inq, m); |
656 | IFQ_UNLOCK(inq); |
657 | schednetisr(isr); |
658 | } |
659 | |
660 | /* |
661 | * Enqueue transmit packet. |
662 | */ |
663 | static int |
664 | sppp_output(struct ifnet *ifp, struct mbuf *m, |
665 | const struct sockaddr *dst, const struct rtentry *rt) |
666 | { |
667 | struct sppp *sp = (struct sppp *) ifp; |
668 | struct ppp_header *h = NULL; |
669 | struct ifqueue *ifq = NULL; /* XXX */ |
670 | int s, error = 0; |
671 | uint16_t protocol; |
672 | |
673 | s = splnet(); |
674 | |
675 | sp->pp_last_activity = time_uptime; |
676 | |
677 | if ((ifp->if_flags & IFF_UP) == 0 || |
678 | (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { |
679 | m_freem(m); |
680 | splx(s); |
681 | return (ENETDOWN); |
682 | } |
683 | |
684 | if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { |
685 | /* |
686 | * Interface is not yet running, but auto-dial. Need |
687 | * to start LCP for it. |
688 | */ |
689 | ifp->if_flags |= IFF_RUNNING; |
690 | splx(s); |
691 | lcp.Open(sp); |
692 | s = splnet(); |
693 | } |
694 | |
695 | /* |
696 | * If the queueing discipline needs packet classification, |
697 | * do it before prepending link headers. |
698 | */ |
699 | IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); |
700 | |
701 | #ifdef INET |
702 | if (dst->sa_family == AF_INET) { |
703 | struct ip *ip = NULL; |
704 | struct tcphdr *th = NULL; |
705 | |
706 | if (m->m_len >= sizeof(struct ip)) { |
707 | ip = mtod(m, struct ip *); |
708 | if (ip->ip_p == IPPROTO_TCP && |
709 | m->m_len >= sizeof(struct ip) + (ip->ip_hl << 2) + |
710 | sizeof(struct tcphdr)) { |
711 | th = (struct tcphdr *) |
712 | ((char *)ip + (ip->ip_hl << 2)); |
713 | } |
714 | } else |
715 | ip = NULL; |
716 | |
717 | /* |
718 | * When using dynamic local IP address assignment by using |
719 | * 0.0.0.0 as a local address, the first TCP session will |
720 | * not connect because the local TCP checksum is computed |
721 | * using 0.0.0.0 which will later become our real IP address |
722 | * so the TCP checksum computed at the remote end will |
723 | * become invalid. So we |
724 | * - don't let packets with src ip addr 0 thru |
725 | * - we flag TCP packets with src ip 0 as an error |
726 | */ |
727 | if (ip && ip->ip_src.s_addr == INADDR_ANY) { |
728 | uint8_t proto = ip->ip_p; |
729 | |
730 | m_freem(m); |
731 | splx(s); |
732 | if (proto == IPPROTO_TCP) |
733 | return (EADDRNOTAVAIL); |
734 | else |
735 | return (0); |
736 | } |
737 | |
738 | /* |
739 | * Put low delay, telnet, rlogin and ftp control packets |
740 | * in front of the queue. |
741 | */ |
742 | |
743 | if (!IF_QFULL(&sp->pp_fastq) && |
744 | ((ip && (ip->ip_tos & IPTOS_LOWDELAY)) || |
745 | (th && (INTERACTIVE(ntohs(th->th_sport)) || |
746 | INTERACTIVE(ntohs(th->th_dport)))))) |
747 | ifq = &sp->pp_fastq; |
748 | } |
749 | #endif |
750 | |
751 | #ifdef INET6 |
752 | if (dst->sa_family == AF_INET6) { |
753 | /* XXX do something tricky here? */ |
754 | } |
755 | #endif |
756 | |
757 | if ((sp->pp_flags & PP_NOFRAMING) == 0) { |
758 | /* |
759 | * Prepend general data packet PPP header. For now, IP only. |
760 | */ |
761 | M_PREPEND(m, PPP_HEADER_LEN, M_DONTWAIT); |
762 | if (! m) { |
763 | if (ifp->if_flags & IFF_DEBUG) |
764 | log(LOG_DEBUG, "%s: no memory for transmit header\n" , |
765 | ifp->if_xname); |
766 | ++ifp->if_oerrors; |
767 | splx(s); |
768 | return (ENOBUFS); |
769 | } |
770 | /* |
771 | * May want to check size of packet |
772 | * (albeit due to the implementation it's always enough) |
773 | */ |
774 | h = mtod(m, struct ppp_header *); |
775 | if (sp->pp_flags & PP_CISCO) { |
776 | h->address = CISCO_UNICAST; /* unicast address */ |
777 | h->control = 0; |
778 | } else { |
779 | h->address = PPP_ALLSTATIONS; /* broadcast address */ |
780 | h->control = PPP_UI; /* Unnumbered Info */ |
781 | } |
782 | } |
783 | |
784 | switch (dst->sa_family) { |
785 | #ifdef INET |
786 | case AF_INET: /* Internet Protocol */ |
787 | if (sp->pp_flags & PP_CISCO) |
788 | protocol = htons(ETHERTYPE_IP); |
789 | else { |
790 | /* |
791 | * Don't choke with an ENETDOWN early. It's |
792 | * possible that we just started dialing out, |
793 | * so don't drop the packet immediately. If |
794 | * we notice that we run out of buffer space |
795 | * below, we will however remember that we are |
796 | * not ready to carry IP packets, and return |
797 | * ENETDOWN, as opposed to ENOBUFS. |
798 | */ |
799 | protocol = htons(PPP_IP); |
800 | if (sp->state[IDX_IPCP] != STATE_OPENED) |
801 | error = ENETDOWN; |
802 | } |
803 | break; |
804 | #endif |
805 | #ifdef INET6 |
806 | case AF_INET6: /* Internet Protocol version 6 */ |
807 | if (sp->pp_flags & PP_CISCO) |
808 | protocol = htons(ETHERTYPE_IPV6); |
809 | else { |
810 | /* |
811 | * Don't choke with an ENETDOWN early. It's |
812 | * possible that we just started dialing out, |
813 | * so don't drop the packet immediately. If |
814 | * we notice that we run out of buffer space |
815 | * below, we will however remember that we are |
816 | * not ready to carry IP packets, and return |
817 | * ENETDOWN, as opposed to ENOBUFS. |
818 | */ |
819 | protocol = htons(PPP_IPV6); |
820 | if (sp->state[IDX_IPV6CP] != STATE_OPENED) |
821 | error = ENETDOWN; |
822 | } |
823 | break; |
824 | #endif |
825 | default: |
826 | m_freem(m); |
827 | ++ifp->if_oerrors; |
828 | splx(s); |
829 | return (EAFNOSUPPORT); |
830 | } |
831 | |
832 | if (sp->pp_flags & PP_NOFRAMING) { |
833 | M_PREPEND(m, 2, M_DONTWAIT); |
834 | if (m == NULL) { |
835 | if (ifp->if_flags & IFF_DEBUG) |
836 | log(LOG_DEBUG, "%s: no memory for transmit header\n" , |
837 | ifp->if_xname); |
838 | ++ifp->if_oerrors; |
839 | splx(s); |
840 | return (ENOBUFS); |
841 | } |
842 | *mtod(m, uint16_t *) = protocol; |
843 | } else { |
844 | h->protocol = protocol; |
845 | } |
846 | |
847 | |
848 | error = ifq_enqueue2(ifp, ifq, m); |
849 | |
850 | if (error == 0) { |
851 | /* |
852 | * Count output packets and bytes. |
853 | * The packet length includes header + additional hardware |
854 | * framing according to RFC 1333. |
855 | */ |
856 | if (!(ifp->if_flags & IFF_OACTIVE)) |
857 | if_start_lock(ifp); |
858 | ifp->if_obytes += m->m_pkthdr.len + sp->pp_framebytes; |
859 | } |
860 | splx(s); |
861 | return error; |
862 | } |
863 | |
864 | static int |
865 | sppp_mediachange(struct ifnet *ifp) |
866 | { |
867 | |
868 | return (0); |
869 | } |
870 | |
871 | static void |
872 | sppp_mediastatus(struct ifnet *ifp, struct ifmediareq *imr) |
873 | { |
874 | |
875 | switch (ifp->if_link_state) { |
876 | case LINK_STATE_UP: |
877 | imr->ifm_status = IFM_AVALID | IFM_ACTIVE; |
878 | break; |
879 | case LINK_STATE_DOWN: |
880 | imr->ifm_status = IFM_AVALID; |
881 | break; |
882 | default: |
883 | /* Should be impossible as we set link state down in attach. */ |
884 | imr->ifm_status = 0; |
885 | break; |
886 | } |
887 | } |
888 | |
889 | void |
890 | sppp_attach(struct ifnet *ifp) |
891 | { |
892 | struct sppp *sp = (struct sppp *) ifp; |
893 | |
894 | /* Initialize keepalive handler. */ |
895 | if (! spppq) { |
896 | callout_init(&keepalive_ch, 0); |
897 | callout_reset(&keepalive_ch, hz * LCP_KEEPALIVE_INTERVAL, sppp_keepalive, NULL); |
898 | } |
899 | |
900 | /* Insert new entry into the keepalive list. */ |
901 | sp->pp_next = spppq; |
902 | spppq = sp; |
903 | |
904 | sp->pp_if.if_type = IFT_PPP; |
905 | sp->pp_if.if_output = sppp_output; |
906 | sp->pp_fastq.ifq_maxlen = 32; |
907 | sp->pp_cpq.ifq_maxlen = 20; |
908 | sp->pp_loopcnt = 0; |
909 | sp->pp_alivecnt = 0; |
910 | sp->pp_last_activity = 0; |
911 | sp->pp_last_receive = 0; |
912 | sp->pp_maxalive = DEFAULT_MAXALIVECNT; |
913 | sp->pp_max_noreceive = DEFAULT_NORECV_TIME; |
914 | sp->pp_idle_timeout = 0; |
915 | memset(&sp->pp_seq[0], 0, sizeof(sp->pp_seq)); |
916 | memset(&sp->pp_rseq[0], 0, sizeof(sp->pp_rseq)); |
917 | sp->pp_auth_failures = 0; |
918 | sp->pp_max_auth_fail = DEFAULT_MAX_AUTH_FAILURES; |
919 | sp->pp_phase = SPPP_PHASE_DEAD; |
920 | sp->pp_up = lcp.Up; |
921 | sp->pp_down = lcp.Down; |
922 | |
923 | if_alloc_sadl(ifp); |
924 | |
925 | /* Lets not beat about the bush, we know we're down. */ |
926 | ifp->if_link_state = LINK_STATE_DOWN; |
927 | /* There is no media for PPP, but it's needed to report link status. */ |
928 | ifmedia_init(&sp->pp_im, 0, sppp_mediachange, sppp_mediastatus); |
929 | |
930 | memset(&sp->myauth, 0, sizeof sp->myauth); |
931 | memset(&sp->hisauth, 0, sizeof sp->hisauth); |
932 | sppp_lcp_init(sp); |
933 | sppp_ipcp_init(sp); |
934 | sppp_ipv6cp_init(sp); |
935 | sppp_pap_init(sp); |
936 | sppp_chap_init(sp); |
937 | } |
938 | |
939 | void |
940 | sppp_detach(struct ifnet *ifp) |
941 | { |
942 | struct sppp **q, *p, *sp = (struct sppp *) ifp; |
943 | |
944 | /* Remove the entry from the keepalive list. */ |
945 | for (q = &spppq; (p = *q); q = &p->pp_next) |
946 | if (p == sp) { |
947 | *q = p->pp_next; |
948 | break; |
949 | } |
950 | |
951 | /* Stop keepalive handler. */ |
952 | if (! spppq) { |
953 | callout_stop(&keepalive_ch); |
954 | } |
955 | |
956 | callout_stop(&sp->ch[IDX_LCP]); |
957 | callout_stop(&sp->ch[IDX_IPCP]); |
958 | callout_stop(&sp->ch[IDX_PAP]); |
959 | callout_stop(&sp->ch[IDX_CHAP]); |
960 | #ifdef INET6 |
961 | callout_stop(&sp->ch[IDX_IPV6CP]); |
962 | #endif |
963 | callout_stop(&sp->pap_my_to_ch); |
964 | |
965 | /* free authentication info */ |
966 | if (sp->myauth.name) free(sp->myauth.name, M_DEVBUF); |
967 | if (sp->myauth.secret) free(sp->myauth.secret, M_DEVBUF); |
968 | if (sp->hisauth.name) free(sp->hisauth.name, M_DEVBUF); |
969 | if (sp->hisauth.secret) free(sp->hisauth.secret, M_DEVBUF); |
970 | |
971 | /* Safety - shouldn't be needed as there is no media to set. */ |
972 | ifmedia_delete_instance(&sp->pp_im, IFM_INST_ANY); |
973 | } |
974 | |
975 | /* |
976 | * Flush the interface output queue. |
977 | */ |
978 | void |
979 | sppp_flush(struct ifnet *ifp) |
980 | { |
981 | struct sppp *sp = (struct sppp *) ifp; |
982 | |
983 | IFQ_PURGE(&sp->pp_if.if_snd); |
984 | IF_PURGE(&sp->pp_fastq); |
985 | IF_PURGE(&sp->pp_cpq); |
986 | } |
987 | |
988 | /* |
989 | * Check if the output queue is empty. |
990 | */ |
991 | int |
992 | sppp_isempty(struct ifnet *ifp) |
993 | { |
994 | struct sppp *sp = (struct sppp *) ifp; |
995 | int empty, s; |
996 | |
997 | s = splnet(); |
998 | empty = IF_IS_EMPTY(&sp->pp_fastq) && IF_IS_EMPTY(&sp->pp_cpq) && |
999 | IFQ_IS_EMPTY(&sp->pp_if.if_snd); |
1000 | splx(s); |
1001 | return (empty); |
1002 | } |
1003 | |
1004 | /* |
1005 | * Get next packet to send. |
1006 | */ |
1007 | struct mbuf * |
1008 | sppp_dequeue(struct ifnet *ifp) |
1009 | { |
1010 | struct sppp *sp = (struct sppp *) ifp; |
1011 | struct mbuf *m; |
1012 | int s; |
1013 | |
1014 | s = splnet(); |
1015 | /* |
1016 | * Process only the control protocol queue until we have at |
1017 | * least one NCP open. |
1018 | * |
1019 | * Do always serve all three queues in Cisco mode. |
1020 | */ |
1021 | IF_DEQUEUE(&sp->pp_cpq, m); |
1022 | if (m == NULL && |
1023 | (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) { |
1024 | IF_DEQUEUE(&sp->pp_fastq, m); |
1025 | if (m == NULL) |
1026 | IFQ_DEQUEUE(&sp->pp_if.if_snd, m); |
1027 | } |
1028 | splx(s); |
1029 | return m; |
1030 | } |
1031 | |
1032 | /* |
1033 | * Process an ioctl request. Called on low priority level. |
1034 | */ |
1035 | int |
1036 | sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
1037 | { |
1038 | struct lwp *l = curlwp; /* XXX */ |
1039 | struct ifreq *ifr = (struct ifreq *) data; |
1040 | struct ifaddr *ifa = (struct ifaddr *) data; |
1041 | struct sppp *sp = (struct sppp *) ifp; |
1042 | int s, error=0, going_up, going_down, newmode; |
1043 | |
1044 | s = splnet(); |
1045 | switch (cmd) { |
1046 | case SIOCINITIFADDR: |
1047 | ifa->ifa_rtrequest = p2p_rtrequest; |
1048 | break; |
1049 | |
1050 | case SIOCSIFFLAGS: |
1051 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) |
1052 | break; |
1053 | going_up = ifp->if_flags & IFF_UP && |
1054 | (ifp->if_flags & IFF_RUNNING) == 0; |
1055 | going_down = (ifp->if_flags & IFF_UP) == 0 && |
1056 | ifp->if_flags & IFF_RUNNING; |
1057 | newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE); |
1058 | if (newmode == (IFF_AUTO | IFF_PASSIVE)) { |
1059 | /* sanity */ |
1060 | newmode = IFF_PASSIVE; |
1061 | ifp->if_flags &= ~IFF_AUTO; |
1062 | } |
1063 | |
1064 | if (going_up || going_down) |
1065 | lcp.Close(sp); |
1066 | if (going_up && newmode == 0) { |
1067 | /* neither auto-dial nor passive */ |
1068 | ifp->if_flags |= IFF_RUNNING; |
1069 | if (!(sp->pp_flags & PP_CISCO)) |
1070 | lcp.Open(sp); |
1071 | } else if (going_down) { |
1072 | sppp_flush(ifp); |
1073 | ifp->if_flags &= ~IFF_RUNNING; |
1074 | } |
1075 | |
1076 | break; |
1077 | |
1078 | case SIOCSIFMTU: |
1079 | if (ifr->ifr_mtu < PPP_MINMRU || |
1080 | ifr->ifr_mtu > sp->lcp.their_mru) { |
1081 | error = EINVAL; |
1082 | break; |
1083 | } |
1084 | /*FALLTHROUGH*/ |
1085 | case SIOCGIFMTU: |
1086 | if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) |
1087 | error = 0; |
1088 | break; |
1089 | case SIOCADDMULTI: |
1090 | case SIOCDELMULTI: |
1091 | break; |
1092 | |
1093 | case SPPPSETAUTHCFG: |
1094 | case SPPPSETLCPCFG: |
1095 | case SPPPSETIDLETO: |
1096 | case SPPPSETAUTHFAILURE: |
1097 | case SPPPSETDNSOPTS: |
1098 | case SPPPSETKEEPALIVE: |
1099 | #if defined(COMPAT_50) || defined(MODULAR) |
1100 | case __SPPPSETIDLETO50: |
1101 | case __SPPPSETKEEPALIVE50: |
1102 | #endif /* COMPAT_50 || MODULAR */ |
1103 | error = kauth_authorize_network(l->l_cred, |
1104 | KAUTH_NETWORK_INTERFACE, |
1105 | KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd, |
1106 | NULL); |
1107 | if (error) |
1108 | break; |
1109 | error = sppp_params(sp, cmd, data); |
1110 | break; |
1111 | |
1112 | case SPPPGETAUTHCFG: |
1113 | case SPPPGETLCPCFG: |
1114 | case SPPPGETAUTHFAILURES: |
1115 | error = kauth_authorize_network(l->l_cred, |
1116 | KAUTH_NETWORK_INTERFACE, |
1117 | KAUTH_REQ_NETWORK_INTERFACE_GETPRIV, ifp, (void *)cmd, |
1118 | NULL); |
1119 | if (error) |
1120 | break; |
1121 | error = sppp_params(sp, cmd, data); |
1122 | break; |
1123 | |
1124 | case SPPPGETSTATUS: |
1125 | case SPPPGETSTATUSNCP: |
1126 | case SPPPGETIDLETO: |
1127 | case SPPPGETDNSOPTS: |
1128 | case SPPPGETDNSADDRS: |
1129 | case SPPPGETKEEPALIVE: |
1130 | #if defined(COMPAT_50) || defined(MODULAR) |
1131 | case __SPPPGETIDLETO50: |
1132 | case __SPPPGETKEEPALIVE50: |
1133 | #endif /* COMPAT_50 || MODULAR */ |
1134 | error = sppp_params(sp, cmd, data); |
1135 | break; |
1136 | |
1137 | case SIOCGIFMEDIA: |
1138 | error = ifmedia_ioctl(ifp, ifr, &sp->pp_im, cmd); |
1139 | break; |
1140 | |
1141 | default: |
1142 | error = ifioctl_common(ifp, cmd, data); |
1143 | break; |
1144 | } |
1145 | splx(s); |
1146 | return (error); |
1147 | } |
1148 | |
1149 | |
1150 | /* |
1151 | * Cisco framing implementation. |
1152 | */ |
1153 | |
1154 | /* |
1155 | * Handle incoming Cisco keepalive protocol packets. |
1156 | */ |
1157 | static void |
1158 | sppp_cisco_input(struct sppp *sp, struct mbuf *m) |
1159 | { |
1160 | STDDCL; |
1161 | struct cisco_packet *h; |
1162 | #ifdef INET |
1163 | uint32_t me, mymask = 0; /* XXX: GCC */ |
1164 | #endif |
1165 | |
1166 | if (m->m_pkthdr.len < CISCO_PACKET_LEN) { |
1167 | if (debug) |
1168 | log(LOG_DEBUG, |
1169 | "%s: cisco invalid packet length: %d bytes\n" , |
1170 | ifp->if_xname, m->m_pkthdr.len); |
1171 | return; |
1172 | } |
1173 | h = mtod(m, struct cisco_packet *); |
1174 | if (debug) |
1175 | log(LOG_DEBUG, |
1176 | "%s: cisco input: %d bytes " |
1177 | "<0x%x 0x%x 0x%x 0x%x 0x%x-0x%x>\n" , |
1178 | ifp->if_xname, m->m_pkthdr.len, |
1179 | ntohl(h->type), h->par1, h->par2, (u_int)h->rel, |
1180 | (u_int)h->time0, (u_int)h->time1); |
1181 | switch (ntohl(h->type)) { |
1182 | default: |
1183 | if (debug) |
1184 | addlog("%s: cisco unknown packet type: 0x%x\n" , |
1185 | ifp->if_xname, ntohl(h->type)); |
1186 | break; |
1187 | case CISCO_ADDR_REPLY: |
1188 | /* Reply on address request, ignore */ |
1189 | break; |
1190 | case CISCO_KEEPALIVE_REQ: |
1191 | sp->pp_alivecnt = 0; |
1192 | sp->pp_rseq[IDX_LCP] = ntohl(h->par1); |
1193 | if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { |
1194 | /* Local and remote sequence numbers are equal. |
1195 | * Probably, the line is in loopback mode. */ |
1196 | if (sp->pp_loopcnt >= LOOPALIVECNT) { |
1197 | printf ("%s: loopback\n" , |
1198 | ifp->if_xname); |
1199 | sp->pp_loopcnt = 0; |
1200 | if (ifp->if_flags & IFF_UP) { |
1201 | if_down(ifp); |
1202 | IF_PURGE(&sp->pp_cpq); |
1203 | } |
1204 | } |
1205 | ++sp->pp_loopcnt; |
1206 | |
1207 | /* Generate new local sequence number */ |
1208 | sp->pp_seq[IDX_LCP] = cprng_fast32(); |
1209 | break; |
1210 | } |
1211 | sp->pp_loopcnt = 0; |
1212 | if (! (ifp->if_flags & IFF_UP) && |
1213 | (ifp->if_flags & IFF_RUNNING)) { |
1214 | if_up(ifp); |
1215 | } |
1216 | break; |
1217 | case CISCO_ADDR_REQ: |
1218 | #ifdef INET |
1219 | sppp_get_ip_addrs(sp, &me, 0, &mymask); |
1220 | if (me != 0L) |
1221 | sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); |
1222 | #endif |
1223 | break; |
1224 | } |
1225 | } |
1226 | |
1227 | /* |
1228 | * Send Cisco keepalive packet. |
1229 | */ |
1230 | static void |
1231 | sppp_cisco_send(struct sppp *sp, int type, int32_t par1, int32_t par2) |
1232 | { |
1233 | STDDCL; |
1234 | struct ppp_header *h; |
1235 | struct cisco_packet *ch; |
1236 | struct mbuf *m; |
1237 | uint32_t t; |
1238 | |
1239 | t = time_uptime * 1000; |
1240 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
1241 | if (! m) |
1242 | return; |
1243 | m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; |
1244 | m_reset_rcvif(m); |
1245 | |
1246 | h = mtod(m, struct ppp_header *); |
1247 | h->address = CISCO_MULTICAST; |
1248 | h->control = 0; |
1249 | h->protocol = htons(CISCO_KEEPALIVE); |
1250 | |
1251 | ch = (struct cisco_packet *)(h + 1); |
1252 | ch->type = htonl(type); |
1253 | ch->par1 = htonl(par1); |
1254 | ch->par2 = htonl(par2); |
1255 | ch->rel = -1; |
1256 | |
1257 | ch->time0 = htons((u_short)(t >> 16)); |
1258 | ch->time1 = htons((u_short) t); |
1259 | |
1260 | if (debug) |
1261 | log(LOG_DEBUG, |
1262 | "%s: cisco output: <0x%x 0x%x 0x%x 0x%x 0x%x-0x%x>\n" , |
1263 | ifp->if_xname, ntohl(ch->type), ch->par1, |
1264 | ch->par2, (u_int)ch->rel, (u_int)ch->time0, |
1265 | (u_int)ch->time1); |
1266 | |
1267 | if (IF_QFULL(&sp->pp_cpq)) { |
1268 | IF_DROP(&sp->pp_fastq); |
1269 | IF_DROP(&ifp->if_snd); |
1270 | m_freem(m); |
1271 | ++ifp->if_oerrors; |
1272 | return; |
1273 | } else |
1274 | IF_ENQUEUE(&sp->pp_cpq, m); |
1275 | if (! (ifp->if_flags & IFF_OACTIVE)) |
1276 | if_start_lock(ifp); |
1277 | ifp->if_obytes += m->m_pkthdr.len + sp->pp_framebytes; |
1278 | } |
1279 | |
1280 | /* |
1281 | * PPP protocol implementation. |
1282 | */ |
1283 | |
1284 | /* |
1285 | * Send PPP control protocol packet. |
1286 | */ |
1287 | static void |
1288 | sppp_cp_send(struct sppp *sp, u_short proto, u_char type, |
1289 | u_char ident, u_short len, void *data) |
1290 | { |
1291 | STDDCL; |
1292 | struct lcp_header *lh; |
1293 | struct mbuf *m; |
1294 | size_t pkthdrlen; |
1295 | |
1296 | pkthdrlen = (sp->pp_flags & PP_NOFRAMING) ? 2 : PPP_HEADER_LEN; |
1297 | |
1298 | if (len > MHLEN - pkthdrlen - LCP_HEADER_LEN) |
1299 | len = MHLEN - pkthdrlen - LCP_HEADER_LEN; |
1300 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
1301 | if (! m) |
1302 | return; |
1303 | m->m_pkthdr.len = m->m_len = pkthdrlen + LCP_HEADER_LEN + len; |
1304 | m_reset_rcvif(m); |
1305 | |
1306 | if (sp->pp_flags & PP_NOFRAMING) { |
1307 | *mtod(m, uint16_t *) = htons(proto); |
1308 | lh = (struct lcp_header *)(mtod(m, uint8_t *) + 2); |
1309 | } else { |
1310 | struct ppp_header *h; |
1311 | h = mtod(m, struct ppp_header *); |
1312 | h->address = PPP_ALLSTATIONS; /* broadcast address */ |
1313 | h->control = PPP_UI; /* Unnumbered Info */ |
1314 | h->protocol = htons(proto); /* Link Control Protocol */ |
1315 | lh = (struct lcp_header *)(h + 1); |
1316 | } |
1317 | lh->type = type; |
1318 | lh->ident = ident; |
1319 | lh->len = htons(LCP_HEADER_LEN + len); |
1320 | if (len) |
1321 | memcpy(lh + 1, data, len); |
1322 | |
1323 | if (debug) { |
1324 | log(LOG_DEBUG, "%s: %s output <%s id=0x%x len=%d" , |
1325 | ifp->if_xname, |
1326 | sppp_proto_name(proto), |
1327 | sppp_cp_type_name(lh->type), lh->ident, ntohs(lh->len)); |
1328 | if (len) |
1329 | sppp_print_bytes((u_char *)(lh + 1), len); |
1330 | addlog(">\n" ); |
1331 | } |
1332 | if (IF_QFULL(&sp->pp_cpq)) { |
1333 | IF_DROP(&sp->pp_fastq); |
1334 | IF_DROP(&ifp->if_snd); |
1335 | m_freem(m); |
1336 | ++ifp->if_oerrors; |
1337 | return; |
1338 | } else |
1339 | IF_ENQUEUE(&sp->pp_cpq, m); |
1340 | if (! (ifp->if_flags & IFF_OACTIVE)) |
1341 | if_start_lock(ifp); |
1342 | ifp->if_obytes += m->m_pkthdr.len + sp->pp_framebytes; |
1343 | } |
1344 | |
1345 | /* |
1346 | * Handle incoming PPP control protocol packets. |
1347 | */ |
1348 | static void |
1349 | sppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) |
1350 | { |
1351 | STDDCL; |
1352 | struct lcp_header *h; |
1353 | int printlen, len = m->m_pkthdr.len; |
1354 | int rv; |
1355 | u_char *p; |
1356 | uint32_t u32; |
1357 | |
1358 | if (len < 4) { |
1359 | if (debug) |
1360 | log(LOG_DEBUG, |
1361 | "%s: %s invalid packet length: %d bytes\n" , |
1362 | ifp->if_xname, cp->name, len); |
1363 | return; |
1364 | } |
1365 | h = mtod(m, struct lcp_header *); |
1366 | if (debug) { |
1367 | printlen = ntohs(h->len); |
1368 | log(LOG_DEBUG, |
1369 | "%s: %s input(%s): <%s id=0x%x len=%d" , |
1370 | ifp->if_xname, cp->name, |
1371 | sppp_state_name(sp->state[cp->protoidx]), |
1372 | sppp_cp_type_name(h->type), h->ident, printlen); |
1373 | if (len < printlen) |
1374 | printlen = len; |
1375 | if (printlen > 4) |
1376 | sppp_print_bytes((u_char *)(h + 1), printlen - 4); |
1377 | addlog(">\n" ); |
1378 | } |
1379 | if (len > ntohs(h->len)) |
1380 | len = ntohs(h->len); |
1381 | p = (u_char *)(h + 1); |
1382 | switch (h->type) { |
1383 | case CONF_REQ: |
1384 | if (len < 4) { |
1385 | if (debug) |
1386 | addlog("%s: %s invalid conf-req length %d\n" , |
1387 | ifp->if_xname, cp->name, |
1388 | len); |
1389 | ++ifp->if_ierrors; |
1390 | break; |
1391 | } |
1392 | /* handle states where RCR doesn't get a SCA/SCN */ |
1393 | switch (sp->state[cp->protoidx]) { |
1394 | case STATE_CLOSING: |
1395 | case STATE_STOPPING: |
1396 | return; |
1397 | case STATE_CLOSED: |
1398 | sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, |
1399 | 0, 0); |
1400 | return; |
1401 | } |
1402 | rv = (cp->RCR)(sp, h, len); |
1403 | if (rv < 0) { |
1404 | /* fatal error, shut down */ |
1405 | (cp->tld)(sp); |
1406 | sppp_lcp_tlf(sp); |
1407 | return; |
1408 | } |
1409 | switch (sp->state[cp->protoidx]) { |
1410 | case STATE_OPENED: |
1411 | (cp->tld)(sp); |
1412 | (cp->scr)(sp); |
1413 | /* fall through... */ |
1414 | case STATE_ACK_SENT: |
1415 | case STATE_REQ_SENT: |
1416 | sppp_cp_change_state(cp, sp, rv? |
1417 | STATE_ACK_SENT: STATE_REQ_SENT); |
1418 | break; |
1419 | case STATE_STOPPED: |
1420 | sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; |
1421 | (cp->scr)(sp); |
1422 | sppp_cp_change_state(cp, sp, rv? |
1423 | STATE_ACK_SENT: STATE_REQ_SENT); |
1424 | break; |
1425 | case STATE_ACK_RCVD: |
1426 | if (rv) { |
1427 | sppp_cp_change_state(cp, sp, STATE_OPENED); |
1428 | if (debug) |
1429 | log(LOG_DEBUG, "%s: %s tlu\n" , |
1430 | ifp->if_xname, |
1431 | cp->name); |
1432 | (cp->tlu)(sp); |
1433 | } else |
1434 | sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); |
1435 | break; |
1436 | default: |
1437 | printf("%s: %s illegal %s in state %s\n" , |
1438 | ifp->if_xname, cp->name, |
1439 | sppp_cp_type_name(h->type), |
1440 | sppp_state_name(sp->state[cp->protoidx])); |
1441 | ++ifp->if_ierrors; |
1442 | } |
1443 | break; |
1444 | case CONF_ACK: |
1445 | if (h->ident != sp->confid[cp->protoidx]) { |
1446 | if (debug) |
1447 | addlog("%s: %s id mismatch 0x%x != 0x%x\n" , |
1448 | ifp->if_xname, cp->name, |
1449 | h->ident, sp->confid[cp->protoidx]); |
1450 | ++ifp->if_ierrors; |
1451 | break; |
1452 | } |
1453 | switch (sp->state[cp->protoidx]) { |
1454 | case STATE_CLOSED: |
1455 | case STATE_STOPPED: |
1456 | sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); |
1457 | break; |
1458 | case STATE_CLOSING: |
1459 | case STATE_STOPPING: |
1460 | break; |
1461 | case STATE_REQ_SENT: |
1462 | sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; |
1463 | sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); |
1464 | break; |
1465 | case STATE_OPENED: |
1466 | (cp->tld)(sp); |
1467 | /* fall through */ |
1468 | case STATE_ACK_RCVD: |
1469 | (cp->scr)(sp); |
1470 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1471 | break; |
1472 | case STATE_ACK_SENT: |
1473 | sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; |
1474 | sppp_cp_change_state(cp, sp, STATE_OPENED); |
1475 | if (debug) |
1476 | log(LOG_DEBUG, "%s: %s tlu\n" , |
1477 | ifp->if_xname, cp->name); |
1478 | (cp->tlu)(sp); |
1479 | break; |
1480 | default: |
1481 | printf("%s: %s illegal %s in state %s\n" , |
1482 | ifp->if_xname, cp->name, |
1483 | sppp_cp_type_name(h->type), |
1484 | sppp_state_name(sp->state[cp->protoidx])); |
1485 | ++ifp->if_ierrors; |
1486 | } |
1487 | break; |
1488 | case CONF_NAK: |
1489 | case CONF_REJ: |
1490 | if (h->ident != sp->confid[cp->protoidx]) { |
1491 | if (debug) |
1492 | addlog("%s: %s id mismatch 0x%x != 0x%x\n" , |
1493 | ifp->if_xname, cp->name, |
1494 | h->ident, sp->confid[cp->protoidx]); |
1495 | ++ifp->if_ierrors; |
1496 | break; |
1497 | } |
1498 | if (h->type == CONF_NAK) |
1499 | (cp->RCN_nak)(sp, h, len); |
1500 | else /* CONF_REJ */ |
1501 | (cp->RCN_rej)(sp, h, len); |
1502 | |
1503 | switch (sp->state[cp->protoidx]) { |
1504 | case STATE_CLOSED: |
1505 | case STATE_STOPPED: |
1506 | sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); |
1507 | break; |
1508 | case STATE_REQ_SENT: |
1509 | case STATE_ACK_SENT: |
1510 | sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; |
1511 | (cp->scr)(sp); |
1512 | break; |
1513 | case STATE_OPENED: |
1514 | (cp->tld)(sp); |
1515 | /* fall through */ |
1516 | case STATE_ACK_RCVD: |
1517 | sppp_cp_change_state(cp, sp, STATE_ACK_SENT); |
1518 | (cp->scr)(sp); |
1519 | break; |
1520 | case STATE_CLOSING: |
1521 | case STATE_STOPPING: |
1522 | break; |
1523 | default: |
1524 | printf("%s: %s illegal %s in state %s\n" , |
1525 | ifp->if_xname, cp->name, |
1526 | sppp_cp_type_name(h->type), |
1527 | sppp_state_name(sp->state[cp->protoidx])); |
1528 | ++ifp->if_ierrors; |
1529 | } |
1530 | break; |
1531 | |
1532 | case TERM_REQ: |
1533 | switch (sp->state[cp->protoidx]) { |
1534 | case STATE_ACK_RCVD: |
1535 | case STATE_ACK_SENT: |
1536 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1537 | /* fall through */ |
1538 | case STATE_CLOSED: |
1539 | case STATE_STOPPED: |
1540 | case STATE_CLOSING: |
1541 | case STATE_STOPPING: |
1542 | case STATE_REQ_SENT: |
1543 | sta: |
1544 | /* Send Terminate-Ack packet. */ |
1545 | if (debug) |
1546 | log(LOG_DEBUG, "%s: %s send terminate-ack\n" , |
1547 | ifp->if_xname, cp->name); |
1548 | sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); |
1549 | break; |
1550 | case STATE_OPENED: |
1551 | (cp->tld)(sp); |
1552 | sp->rst_counter[cp->protoidx] = 0; |
1553 | sppp_cp_change_state(cp, sp, STATE_STOPPING); |
1554 | goto sta; |
1555 | default: |
1556 | printf("%s: %s illegal %s in state %s\n" , |
1557 | ifp->if_xname, cp->name, |
1558 | sppp_cp_type_name(h->type), |
1559 | sppp_state_name(sp->state[cp->protoidx])); |
1560 | ++ifp->if_ierrors; |
1561 | } |
1562 | break; |
1563 | case TERM_ACK: |
1564 | switch (sp->state[cp->protoidx]) { |
1565 | case STATE_CLOSED: |
1566 | case STATE_STOPPED: |
1567 | case STATE_REQ_SENT: |
1568 | case STATE_ACK_SENT: |
1569 | break; |
1570 | case STATE_CLOSING: |
1571 | (cp->tlf)(sp); |
1572 | sppp_cp_change_state(cp, sp, STATE_CLOSED); |
1573 | sppp_lcp_check_and_close(sp); |
1574 | break; |
1575 | case STATE_STOPPING: |
1576 | (cp->tlf)(sp); |
1577 | sppp_cp_change_state(cp, sp, STATE_STOPPED); |
1578 | sppp_lcp_check_and_close(sp); |
1579 | break; |
1580 | case STATE_ACK_RCVD: |
1581 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1582 | break; |
1583 | case STATE_OPENED: |
1584 | (cp->tld)(sp); |
1585 | (cp->scr)(sp); |
1586 | sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); |
1587 | break; |
1588 | default: |
1589 | printf("%s: %s illegal %s in state %s\n" , |
1590 | ifp->if_xname, cp->name, |
1591 | sppp_cp_type_name(h->type), |
1592 | sppp_state_name(sp->state[cp->protoidx])); |
1593 | ++ifp->if_ierrors; |
1594 | } |
1595 | break; |
1596 | case CODE_REJ: |
1597 | /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ |
1598 | log(LOG_INFO, |
1599 | "%s: %s: ignoring RXJ (%s) for code ?, " |
1600 | "danger will robinson\n" , |
1601 | ifp->if_xname, cp->name, |
1602 | sppp_cp_type_name(h->type)); |
1603 | switch (sp->state[cp->protoidx]) { |
1604 | case STATE_CLOSED: |
1605 | case STATE_STOPPED: |
1606 | case STATE_REQ_SENT: |
1607 | case STATE_ACK_SENT: |
1608 | case STATE_CLOSING: |
1609 | case STATE_STOPPING: |
1610 | case STATE_OPENED: |
1611 | break; |
1612 | case STATE_ACK_RCVD: |
1613 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1614 | break; |
1615 | default: |
1616 | printf("%s: %s illegal %s in state %s\n" , |
1617 | ifp->if_xname, cp->name, |
1618 | sppp_cp_type_name(h->type), |
1619 | sppp_state_name(sp->state[cp->protoidx])); |
1620 | ++ifp->if_ierrors; |
1621 | } |
1622 | break; |
1623 | case PROTO_REJ: |
1624 | { |
1625 | int catastrophic; |
1626 | const struct cp *upper; |
1627 | int i; |
1628 | uint16_t proto; |
1629 | |
1630 | catastrophic = 0; |
1631 | upper = NULL; |
1632 | proto = p[0] << 8 | p[1]; |
1633 | for (i = 0; i < IDX_COUNT; i++) { |
1634 | if (cps[i]->proto == proto) { |
1635 | upper = cps[i]; |
1636 | break; |
1637 | } |
1638 | } |
1639 | if (upper == NULL) |
1640 | catastrophic++; |
1641 | |
1642 | if (debug) |
1643 | log(LOG_INFO, |
1644 | "%s: %s: RXJ%c (%s) for proto 0x%x (%s/%s)\n" , |
1645 | ifp->if_xname, cp->name, catastrophic ? '-' : '+', |
1646 | sppp_cp_type_name(h->type), proto, |
1647 | upper ? upper->name : "unknown" , |
1648 | upper ? sppp_state_name(sp->state[upper->protoidx]) : "?" ); |
1649 | |
1650 | /* |
1651 | * if we got RXJ+ against conf-req, the peer does not implement |
1652 | * this particular protocol type. terminate the protocol. |
1653 | */ |
1654 | if (upper && !catastrophic) { |
1655 | if (sp->state[upper->protoidx] == STATE_REQ_SENT) { |
1656 | upper->Close(sp); |
1657 | break; |
1658 | } |
1659 | } |
1660 | |
1661 | /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ |
1662 | switch (sp->state[cp->protoidx]) { |
1663 | case STATE_CLOSED: |
1664 | case STATE_STOPPED: |
1665 | case STATE_REQ_SENT: |
1666 | case STATE_ACK_SENT: |
1667 | case STATE_CLOSING: |
1668 | case STATE_STOPPING: |
1669 | case STATE_OPENED: |
1670 | break; |
1671 | case STATE_ACK_RCVD: |
1672 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1673 | break; |
1674 | default: |
1675 | printf("%s: %s illegal %s in state %s\n" , |
1676 | ifp->if_xname, cp->name, |
1677 | sppp_cp_type_name(h->type), |
1678 | sppp_state_name(sp->state[cp->protoidx])); |
1679 | ++ifp->if_ierrors; |
1680 | } |
1681 | break; |
1682 | } |
1683 | case DISC_REQ: |
1684 | if (cp->proto != PPP_LCP) |
1685 | goto illegal; |
1686 | /* Discard the packet. */ |
1687 | break; |
1688 | case ECHO_REQ: |
1689 | if (cp->proto != PPP_LCP) |
1690 | goto illegal; |
1691 | if (sp->state[cp->protoidx] != STATE_OPENED) { |
1692 | if (debug) |
1693 | addlog("%s: lcp echo req but lcp closed\n" , |
1694 | ifp->if_xname); |
1695 | ++ifp->if_ierrors; |
1696 | break; |
1697 | } |
1698 | if (len < 8) { |
1699 | if (debug) |
1700 | addlog("%s: invalid lcp echo request " |
1701 | "packet length: %d bytes\n" , |
1702 | ifp->if_xname, len); |
1703 | break; |
1704 | } |
1705 | memcpy(&u32, h + 1, sizeof u32); |
1706 | if (ntohl(u32) == sp->lcp.magic) { |
1707 | /* Line loopback mode detected. */ |
1708 | printf("%s: loopback\n" , ifp->if_xname); |
1709 | if_down(ifp); |
1710 | IF_PURGE(&sp->pp_cpq); |
1711 | |
1712 | /* Shut down the PPP link. */ |
1713 | /* XXX */ |
1714 | lcp.Down(sp); |
1715 | lcp.Up(sp); |
1716 | break; |
1717 | } |
1718 | u32 = htonl(sp->lcp.magic); |
1719 | memcpy(h + 1, &u32, sizeof u32); |
1720 | if (debug) |
1721 | addlog("%s: got lcp echo req, sending echo rep\n" , |
1722 | ifp->if_xname); |
1723 | sppp_cp_send(sp, PPP_LCP, ECHO_REPLY, h->ident, len - 4, |
1724 | h + 1); |
1725 | break; |
1726 | case ECHO_REPLY: |
1727 | if (cp->proto != PPP_LCP) |
1728 | goto illegal; |
1729 | if (h->ident != sp->lcp.echoid) { |
1730 | ++ifp->if_ierrors; |
1731 | break; |
1732 | } |
1733 | if (len < 8) { |
1734 | if (debug) |
1735 | addlog("%s: lcp invalid echo reply " |
1736 | "packet length: %d bytes\n" , |
1737 | ifp->if_xname, len); |
1738 | break; |
1739 | } |
1740 | if (debug) |
1741 | addlog("%s: lcp got echo rep\n" , |
1742 | ifp->if_xname); |
1743 | memcpy(&u32, h + 1, sizeof u32); |
1744 | if (ntohl(u32) != sp->lcp.magic) |
1745 | sp->pp_alivecnt = 0; |
1746 | break; |
1747 | default: |
1748 | /* Unknown packet type -- send Code-Reject packet. */ |
1749 | illegal: |
1750 | if (debug) |
1751 | addlog("%s: %s send code-rej for 0x%x\n" , |
1752 | ifp->if_xname, cp->name, h->type); |
1753 | sppp_cp_send(sp, cp->proto, CODE_REJ, |
1754 | ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); |
1755 | ++ifp->if_ierrors; |
1756 | } |
1757 | } |
1758 | |
1759 | |
1760 | /* |
1761 | * The generic part of all Up/Down/Open/Close/TO event handlers. |
1762 | * Basically, the state transition handling in the automaton. |
1763 | */ |
1764 | static void |
1765 | sppp_up_event(const struct cp *cp, struct sppp *sp) |
1766 | { |
1767 | STDDCL; |
1768 | |
1769 | if (debug) |
1770 | log(LOG_DEBUG, "%s: %s up(%s)\n" , |
1771 | ifp->if_xname, cp->name, |
1772 | sppp_state_name(sp->state[cp->protoidx])); |
1773 | |
1774 | switch (sp->state[cp->protoidx]) { |
1775 | case STATE_INITIAL: |
1776 | sppp_cp_change_state(cp, sp, STATE_CLOSED); |
1777 | break; |
1778 | case STATE_STARTING: |
1779 | sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; |
1780 | (cp->scr)(sp); |
1781 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1782 | break; |
1783 | default: |
1784 | printf("%s: %s illegal up in state %s\n" , |
1785 | ifp->if_xname, cp->name, |
1786 | sppp_state_name(sp->state[cp->protoidx])); |
1787 | } |
1788 | } |
1789 | |
1790 | static void |
1791 | sppp_down_event(const struct cp *cp, struct sppp *sp) |
1792 | { |
1793 | STDDCL; |
1794 | |
1795 | if (debug) |
1796 | log(LOG_DEBUG, "%s: %s down(%s)\n" , |
1797 | ifp->if_xname, cp->name, |
1798 | sppp_state_name(sp->state[cp->protoidx])); |
1799 | |
1800 | switch (sp->state[cp->protoidx]) { |
1801 | case STATE_CLOSED: |
1802 | case STATE_CLOSING: |
1803 | sppp_cp_change_state(cp, sp, STATE_INITIAL); |
1804 | break; |
1805 | case STATE_STOPPED: |
1806 | (cp->tls)(sp); |
1807 | /* fall through */ |
1808 | case STATE_STOPPING: |
1809 | case STATE_REQ_SENT: |
1810 | case STATE_ACK_RCVD: |
1811 | case STATE_ACK_SENT: |
1812 | sppp_cp_change_state(cp, sp, STATE_STARTING); |
1813 | break; |
1814 | case STATE_OPENED: |
1815 | (cp->tld)(sp); |
1816 | sppp_cp_change_state(cp, sp, STATE_STARTING); |
1817 | break; |
1818 | default: |
1819 | printf("%s: %s illegal down in state %s\n" , |
1820 | ifp->if_xname, cp->name, |
1821 | sppp_state_name(sp->state[cp->protoidx])); |
1822 | } |
1823 | } |
1824 | |
1825 | |
1826 | static void |
1827 | sppp_open_event(const struct cp *cp, struct sppp *sp) |
1828 | { |
1829 | STDDCL; |
1830 | |
1831 | if (debug) |
1832 | log(LOG_DEBUG, "%s: %s open(%s)\n" , |
1833 | ifp->if_xname, cp->name, |
1834 | sppp_state_name(sp->state[cp->protoidx])); |
1835 | |
1836 | switch (sp->state[cp->protoidx]) { |
1837 | case STATE_INITIAL: |
1838 | sppp_cp_change_state(cp, sp, STATE_STARTING); |
1839 | (cp->tls)(sp); |
1840 | break; |
1841 | case STATE_STARTING: |
1842 | break; |
1843 | case STATE_CLOSED: |
1844 | sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; |
1845 | (cp->scr)(sp); |
1846 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1847 | break; |
1848 | case STATE_STOPPED: |
1849 | case STATE_STOPPING: |
1850 | case STATE_REQ_SENT: |
1851 | case STATE_ACK_RCVD: |
1852 | case STATE_ACK_SENT: |
1853 | case STATE_OPENED: |
1854 | break; |
1855 | case STATE_CLOSING: |
1856 | sppp_cp_change_state(cp, sp, STATE_STOPPING); |
1857 | break; |
1858 | } |
1859 | } |
1860 | |
1861 | |
1862 | static void |
1863 | sppp_close_event(const struct cp *cp, struct sppp *sp) |
1864 | { |
1865 | STDDCL; |
1866 | |
1867 | if (debug) |
1868 | log(LOG_DEBUG, "%s: %s close(%s)\n" , |
1869 | ifp->if_xname, cp->name, |
1870 | sppp_state_name(sp->state[cp->protoidx])); |
1871 | |
1872 | switch (sp->state[cp->protoidx]) { |
1873 | case STATE_INITIAL: |
1874 | case STATE_CLOSED: |
1875 | case STATE_CLOSING: |
1876 | break; |
1877 | case STATE_STARTING: |
1878 | sppp_cp_change_state(cp, sp, STATE_INITIAL); |
1879 | (cp->tlf)(sp); |
1880 | break; |
1881 | case STATE_STOPPED: |
1882 | sppp_cp_change_state(cp, sp, STATE_CLOSED); |
1883 | break; |
1884 | case STATE_STOPPING: |
1885 | sppp_cp_change_state(cp, sp, STATE_CLOSING); |
1886 | break; |
1887 | case STATE_OPENED: |
1888 | (cp->tld)(sp); |
1889 | /* fall through */ |
1890 | case STATE_REQ_SENT: |
1891 | case STATE_ACK_RCVD: |
1892 | case STATE_ACK_SENT: |
1893 | sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; |
1894 | sppp_cp_send(sp, cp->proto, TERM_REQ, |
1895 | ++sp->pp_seq[cp->protoidx], 0, 0); |
1896 | sppp_cp_change_state(cp, sp, STATE_CLOSING); |
1897 | break; |
1898 | } |
1899 | } |
1900 | |
1901 | static void |
1902 | sppp_to_event(const struct cp *cp, struct sppp *sp) |
1903 | { |
1904 | STDDCL; |
1905 | int s; |
1906 | |
1907 | s = splnet(); |
1908 | if (debug) |
1909 | log(LOG_DEBUG, "%s: %s TO(%s) rst_counter = %d\n" , |
1910 | ifp->if_xname, cp->name, |
1911 | sppp_state_name(sp->state[cp->protoidx]), |
1912 | sp->rst_counter[cp->protoidx]); |
1913 | |
1914 | if (--sp->rst_counter[cp->protoidx] < 0) |
1915 | /* TO- event */ |
1916 | switch (sp->state[cp->protoidx]) { |
1917 | case STATE_CLOSING: |
1918 | (cp->tlf)(sp); |
1919 | sppp_cp_change_state(cp, sp, STATE_CLOSED); |
1920 | sppp_lcp_check_and_close(sp); |
1921 | break; |
1922 | case STATE_STOPPING: |
1923 | (cp->tlf)(sp); |
1924 | sppp_cp_change_state(cp, sp, STATE_STOPPED); |
1925 | sppp_lcp_check_and_close(sp); |
1926 | break; |
1927 | case STATE_REQ_SENT: |
1928 | case STATE_ACK_RCVD: |
1929 | case STATE_ACK_SENT: |
1930 | (cp->tlf)(sp); |
1931 | sppp_cp_change_state(cp, sp, STATE_STOPPED); |
1932 | sppp_lcp_check_and_close(sp); |
1933 | break; |
1934 | } |
1935 | else |
1936 | /* TO+ event */ |
1937 | switch (sp->state[cp->protoidx]) { |
1938 | case STATE_CLOSING: |
1939 | case STATE_STOPPING: |
1940 | sppp_cp_send(sp, cp->proto, TERM_REQ, |
1941 | ++sp->pp_seq[cp->protoidx], 0, 0); |
1942 | callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, |
1943 | cp->TO, sp); |
1944 | break; |
1945 | case STATE_REQ_SENT: |
1946 | case STATE_ACK_RCVD: |
1947 | (cp->scr)(sp); |
1948 | /* sppp_cp_change_state() will restart the timer */ |
1949 | sppp_cp_change_state(cp, sp, STATE_REQ_SENT); |
1950 | break; |
1951 | case STATE_ACK_SENT: |
1952 | (cp->scr)(sp); |
1953 | callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, |
1954 | cp->TO, sp); |
1955 | break; |
1956 | } |
1957 | |
1958 | splx(s); |
1959 | } |
1960 | |
1961 | /* |
1962 | * Change the state of a control protocol in the state automaton. |
1963 | * Takes care of starting/stopping the restart timer. |
1964 | */ |
1965 | void |
1966 | sppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) |
1967 | { |
1968 | sp->state[cp->protoidx] = newstate; |
1969 | callout_stop(&sp->ch[cp->protoidx]); |
1970 | switch (newstate) { |
1971 | case STATE_INITIAL: |
1972 | case STATE_STARTING: |
1973 | case STATE_CLOSED: |
1974 | case STATE_STOPPED: |
1975 | case STATE_OPENED: |
1976 | break; |
1977 | case STATE_CLOSING: |
1978 | case STATE_STOPPING: |
1979 | case STATE_REQ_SENT: |
1980 | case STATE_ACK_RCVD: |
1981 | case STATE_ACK_SENT: |
1982 | callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, |
1983 | cp->TO, sp); |
1984 | break; |
1985 | } |
1986 | } |
1987 | |
1988 | /* |
1989 | *--------------------------------------------------------------------------* |
1990 | * * |
1991 | * The LCP implementation. * |
1992 | * * |
1993 | *--------------------------------------------------------------------------* |
1994 | */ |
1995 | static void |
1996 | sppp_lcp_init(struct sppp *sp) |
1997 | { |
1998 | sp->lcp.opts = (1 << LCP_OPT_MAGIC); |
1999 | sp->lcp.magic = 0; |
2000 | sp->state[IDX_LCP] = STATE_INITIAL; |
2001 | sp->fail_counter[IDX_LCP] = 0; |
2002 | sp->pp_seq[IDX_LCP] = 0; |
2003 | sp->pp_rseq[IDX_LCP] = 0; |
2004 | sp->lcp.protos = 0; |
2005 | |
2006 | /* |
2007 | * Initialize counters and timeout values. Note that we don't |
2008 | * use the 3 seconds suggested in RFC 1661 since we are likely |
2009 | * running on a fast link. XXX We should probably implement |
2010 | * the exponential backoff option. Note that these values are |
2011 | * relevant for all control protocols, not just LCP only. |
2012 | */ |
2013 | sp->lcp.timeout = 1 * hz; |
2014 | sp->lcp.max_terminate = 2; |
2015 | sp->lcp.max_configure = 10; |
2016 | sp->lcp.max_failure = 10; |
2017 | callout_init(&sp->ch[IDX_LCP], 0); |
2018 | } |
2019 | |
2020 | static void |
2021 | sppp_lcp_up(struct sppp *sp) |
2022 | { |
2023 | STDDCL; |
2024 | |
2025 | /* Initialize activity timestamp: opening a connection is an activity */ |
2026 | sp->pp_last_receive = sp->pp_last_activity = time_uptime; |
2027 | |
2028 | /* |
2029 | * If this interface is passive or dial-on-demand, and we are |
2030 | * still in Initial state, it means we've got an incoming |
2031 | * call. Activate the interface. |
2032 | */ |
2033 | if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { |
2034 | if (debug) |
2035 | log(LOG_DEBUG, |
2036 | "%s: Up event" , ifp->if_xname); |
2037 | ifp->if_flags |= IFF_RUNNING; |
2038 | if (sp->state[IDX_LCP] == STATE_INITIAL) { |
2039 | if (debug) |
2040 | addlog("(incoming call)\n" ); |
2041 | sp->pp_flags |= PP_CALLIN; |
2042 | lcp.Open(sp); |
2043 | } else if (debug) |
2044 | addlog("\n" ); |
2045 | } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && |
2046 | (sp->state[IDX_LCP] == STATE_INITIAL)) { |
2047 | ifp->if_flags |= IFF_RUNNING; |
2048 | lcp.Open(sp); |
2049 | } |
2050 | |
2051 | sppp_up_event(&lcp, sp); |
2052 | } |
2053 | |
2054 | static void |
2055 | sppp_lcp_down(struct sppp *sp) |
2056 | { |
2057 | STDDCL; |
2058 | |
2059 | sppp_down_event(&lcp, sp); |
2060 | |
2061 | /* |
2062 | * If this is neither a dial-on-demand nor a passive |
2063 | * interface, simulate an ``ifconfig down'' action, so the |
2064 | * administrator can force a redial by another ``ifconfig |
2065 | * up''. XXX For leased line operation, should we immediately |
2066 | * try to reopen the connection here? |
2067 | */ |
2068 | if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { |
2069 | if (debug) |
2070 | log(LOG_INFO, |
2071 | "%s: Down event (carrier loss), taking interface down.\n" , |
2072 | ifp->if_xname); |
2073 | if_down(ifp); |
2074 | } else { |
2075 | if (debug) |
2076 | log(LOG_DEBUG, |
2077 | "%s: Down event (carrier loss)\n" , |
2078 | ifp->if_xname); |
2079 | } |
2080 | sp->pp_flags &= ~PP_CALLIN; |
2081 | if (sp->state[IDX_LCP] != STATE_INITIAL) |
2082 | lcp.Close(sp); |
2083 | ifp->if_flags &= ~IFF_RUNNING; |
2084 | } |
2085 | |
2086 | static void |
2087 | sppp_lcp_open(struct sppp *sp) |
2088 | { |
2089 | if (sp->pp_if.if_mtu < PP_MTU) { |
2090 | sp->lcp.mru = sp->pp_if.if_mtu; |
2091 | sp->lcp.opts |= (1 << LCP_OPT_MRU); |
2092 | } else |
2093 | sp->lcp.mru = PP_MTU; |
2094 | sp->lcp.their_mru = PP_MTU; |
2095 | |
2096 | /* |
2097 | * If we are authenticator, negotiate LCP_AUTH |
2098 | */ |
2099 | if (sp->hisauth.proto != 0) |
2100 | sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); |
2101 | else |
2102 | sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); |
2103 | sp->pp_flags &= ~PP_NEEDAUTH; |
2104 | sppp_open_event(&lcp, sp); |
2105 | } |
2106 | |
2107 | static void |
2108 | sppp_lcp_close(struct sppp *sp) |
2109 | { |
2110 | sppp_close_event(&lcp, sp); |
2111 | } |
2112 | |
2113 | static void |
2114 | sppp_lcp_TO(void *cookie) |
2115 | { |
2116 | sppp_to_event(&lcp, (struct sppp *)cookie); |
2117 | } |
2118 | |
2119 | /* |
2120 | * Analyze a configure request. Return true if it was agreeable, and |
2121 | * caused action sca, false if it has been rejected or nak'ed, and |
2122 | * caused action scn. (The return value is used to make the state |
2123 | * transition decision in the state automaton.) |
2124 | */ |
2125 | static int |
2126 | sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) |
2127 | { |
2128 | STDDCL; |
2129 | u_char *buf, *r, *p, l, blen; |
2130 | int origlen, rlen; |
2131 | uint32_t nmagic; |
2132 | u_short authproto; |
2133 | |
2134 | len -= 4; |
2135 | origlen = len; |
2136 | buf = r = malloc (blen = len, M_TEMP, M_NOWAIT); |
2137 | if (! buf) |
2138 | return (0); |
2139 | |
2140 | if (debug) |
2141 | log(LOG_DEBUG, "%s: lcp parse opts:" , |
2142 | ifp->if_xname); |
2143 | |
2144 | /* pass 1: check for things that need to be rejected */ |
2145 | p = (void *)(h + 1); |
2146 | for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
2147 | /* Sanity check option length */ |
2148 | if (l > len) { |
2149 | /* |
2150 | * Malicious option - drop immediately. |
2151 | * XXX Maybe we should just RXJ it? |
2152 | */ |
2153 | addlog("%s: received malicious LCP option 0x%02x, " |
2154 | "length 0x%02x, (len: 0x%02x) dropping.\n" , ifp->if_xname, |
2155 | p[0], l, len); |
2156 | goto drop; |
2157 | } |
2158 | if (debug) |
2159 | addlog(" %s" , sppp_lcp_opt_name(*p)); |
2160 | switch (*p) { |
2161 | case LCP_OPT_MAGIC: |
2162 | /* Magic number. */ |
2163 | /* fall through, both are same length */ |
2164 | case LCP_OPT_ASYNC_MAP: |
2165 | /* Async control character map. */ |
2166 | if (len >= 6 || l == 6) |
2167 | continue; |
2168 | if (debug) |
2169 | addlog(" [invalid]" ); |
2170 | break; |
2171 | case LCP_OPT_MRU: |
2172 | /* Maximum receive unit. */ |
2173 | if (len >= 4 && l == 4) |
2174 | continue; |
2175 | if (debug) |
2176 | addlog(" [invalid]" ); |
2177 | break; |
2178 | case LCP_OPT_AUTH_PROTO: |
2179 | if (len < 4) { |
2180 | if (debug) |
2181 | addlog(" [invalid]" ); |
2182 | break; |
2183 | } |
2184 | authproto = (p[2] << 8) + p[3]; |
2185 | if (authproto == PPP_CHAP && l != 5) { |
2186 | if (debug) |
2187 | addlog(" [invalid chap len]" ); |
2188 | break; |
2189 | } |
2190 | if (sp->myauth.proto == 0) { |
2191 | /* we are not configured to do auth */ |
2192 | if (debug) |
2193 | addlog(" [not configured]" ); |
2194 | break; |
2195 | } |
2196 | /* |
2197 | * Remote want us to authenticate, remember this, |
2198 | * so we stay in SPPP_PHASE_AUTHENTICATE after LCP got |
2199 | * up. |
2200 | */ |
2201 | sp->pp_flags |= PP_NEEDAUTH; |
2202 | continue; |
2203 | default: |
2204 | /* Others not supported. */ |
2205 | if (debug) |
2206 | addlog(" [rej]" ); |
2207 | break; |
2208 | } |
2209 | if (rlen + l > blen) { |
2210 | if (debug) |
2211 | addlog(" [overflow]" ); |
2212 | continue; |
2213 | } |
2214 | /* Add the option to rejected list. */ |
2215 | memcpy(r, p, l); |
2216 | r += l; |
2217 | rlen += l; |
2218 | } |
2219 | if (rlen) { |
2220 | if (debug) |
2221 | addlog(" send conf-rej\n" ); |
2222 | sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); |
2223 | goto end; |
2224 | } else if (debug) |
2225 | addlog("\n" ); |
2226 | |
2227 | /* |
2228 | * pass 2: check for option values that are unacceptable and |
2229 | * thus require to be nak'ed. |
2230 | */ |
2231 | if (debug) |
2232 | log(LOG_DEBUG, "%s: lcp parse opt values: " , |
2233 | ifp->if_xname); |
2234 | |
2235 | p = (void *)(h + 1); |
2236 | len = origlen; |
2237 | for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
2238 | if (debug) |
2239 | addlog(" %s" , sppp_lcp_opt_name(*p)); |
2240 | switch (*p) { |
2241 | case LCP_OPT_MAGIC: |
2242 | /* Magic number -- extract. */ |
2243 | nmagic = (uint32_t)p[2] << 24 | |
2244 | (uint32_t)p[3] << 16 | p[4] << 8 | p[5]; |
2245 | if (nmagic != sp->lcp.magic) { |
2246 | if (debug) |
2247 | addlog(" 0x%x" , nmagic); |
2248 | continue; |
2249 | } |
2250 | /* |
2251 | * Local and remote magics equal -- loopback? |
2252 | */ |
2253 | if (sp->pp_loopcnt >= LOOPALIVECNT*5) { |
2254 | printf ("%s: loopback\n" , |
2255 | ifp->if_xname); |
2256 | sp->pp_loopcnt = 0; |
2257 | if (ifp->if_flags & IFF_UP) { |
2258 | if_down(ifp); |
2259 | IF_PURGE(&sp->pp_cpq); |
2260 | /* XXX ? */ |
2261 | lcp.Down(sp); |
2262 | lcp.Up(sp); |
2263 | } |
2264 | } else if (debug) |
2265 | addlog(" [glitch]" ); |
2266 | ++sp->pp_loopcnt; |
2267 | /* |
2268 | * We negate our magic here, and NAK it. If |
2269 | * we see it later in an NAK packet, we |
2270 | * suggest a new one. |
2271 | */ |
2272 | nmagic = ~sp->lcp.magic; |
2273 | /* Gonna NAK it. */ |
2274 | p[2] = nmagic >> 24; |
2275 | p[3] = nmagic >> 16; |
2276 | p[4] = nmagic >> 8; |
2277 | p[5] = nmagic; |
2278 | break; |
2279 | |
2280 | case LCP_OPT_ASYNC_MAP: |
2281 | /* |
2282 | * Async control character map -- just ignore it. |
2283 | * |
2284 | * Quote from RFC 1662, chapter 6: |
2285 | * To enable this functionality, synchronous PPP |
2286 | * implementations MUST always respond to the |
2287 | * Async-Control-Character-Map Configuration |
2288 | * Option with the LCP Configure-Ack. However, |
2289 | * acceptance of the Configuration Option does |
2290 | * not imply that the synchronous implementation |
2291 | * will do any ACCM mapping. Instead, all such |
2292 | * octet mapping will be performed by the |
2293 | * asynchronous-to-synchronous converter. |
2294 | */ |
2295 | continue; |
2296 | |
2297 | case LCP_OPT_MRU: |
2298 | /* |
2299 | * Maximum receive unit. Always agreeable, |
2300 | * but ignored by now. |
2301 | */ |
2302 | sp->lcp.their_mru = p[2] * 256 + p[3]; |
2303 | if (debug) |
2304 | addlog(" %ld" , sp->lcp.their_mru); |
2305 | continue; |
2306 | |
2307 | case LCP_OPT_AUTH_PROTO: |
2308 | authproto = (p[2] << 8) + p[3]; |
2309 | if (sp->myauth.proto != authproto) { |
2310 | /* not agreed, nak */ |
2311 | if (debug) |
2312 | addlog(" [mine %s != his %s]" , |
2313 | sppp_proto_name(sp->myauth.proto), |
2314 | sppp_proto_name(authproto)); |
2315 | p[2] = sp->myauth.proto >> 8; |
2316 | p[3] = sp->myauth.proto; |
2317 | break; |
2318 | } |
2319 | if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { |
2320 | if (debug) |
2321 | addlog(" [chap not MD5]" ); |
2322 | p[4] = CHAP_MD5; |
2323 | break; |
2324 | } |
2325 | continue; |
2326 | } |
2327 | if (rlen + l > blen) { |
2328 | if (debug) |
2329 | addlog(" [overflow]" ); |
2330 | continue; |
2331 | } |
2332 | /* Add the option to nak'ed list. */ |
2333 | memcpy(r, p, l); |
2334 | r += l; |
2335 | rlen += l; |
2336 | } |
2337 | if (rlen) { |
2338 | if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { |
2339 | if (debug) |
2340 | addlog(" max_failure (%d) exceeded, " |
2341 | "send conf-rej\n" , |
2342 | sp->lcp.max_failure); |
2343 | sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); |
2344 | } else { |
2345 | if (debug) |
2346 | addlog(" send conf-nak\n" ); |
2347 | sppp_cp_send(sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); |
2348 | } |
2349 | goto end; |
2350 | } else { |
2351 | if (debug) |
2352 | addlog(" send conf-ack\n" ); |
2353 | sp->fail_counter[IDX_LCP] = 0; |
2354 | sp->pp_loopcnt = 0; |
2355 | sppp_cp_send(sp, PPP_LCP, CONF_ACK, h->ident, origlen, h + 1); |
2356 | } |
2357 | |
2358 | end: |
2359 | free(buf, M_TEMP); |
2360 | return (rlen == 0); |
2361 | |
2362 | drop: |
2363 | free(buf, M_TEMP); |
2364 | return -1; |
2365 | } |
2366 | |
2367 | /* |
2368 | * Analyze the LCP Configure-Reject option list, and adjust our |
2369 | * negotiation. |
2370 | */ |
2371 | static void |
2372 | sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) |
2373 | { |
2374 | STDDCL; |
2375 | u_char *buf, *p, l; |
2376 | |
2377 | len -= 4; |
2378 | buf = malloc (len, M_TEMP, M_NOWAIT); |
2379 | if (!buf) |
2380 | return; |
2381 | |
2382 | if (debug) |
2383 | log(LOG_DEBUG, "%s: lcp rej opts:" , |
2384 | ifp->if_xname); |
2385 | |
2386 | p = (void *)(h + 1); |
2387 | for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
2388 | /* Sanity check option length */ |
2389 | if (l > len) { |
2390 | /* |
2391 | * Malicious option - drop immediately. |
2392 | * XXX Maybe we should just RXJ it? |
2393 | */ |
2394 | addlog("%s: received malicious LCP option, " |
2395 | "dropping.\n" , ifp->if_xname); |
2396 | goto drop; |
2397 | } |
2398 | if (debug) |
2399 | addlog(" %s" , sppp_lcp_opt_name(*p)); |
2400 | switch (*p) { |
2401 | case LCP_OPT_MAGIC: |
2402 | /* Magic number -- can't use it, use 0 */ |
2403 | sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); |
2404 | sp->lcp.magic = 0; |
2405 | break; |
2406 | case LCP_OPT_MRU: |
2407 | /* |
2408 | * We try to negotiate a lower MRU if the underlying |
2409 | * link's MTU is less than PP_MTU (e.g. PPPoE). If the |
2410 | * peer rejects this lower rate, fallback to the |
2411 | * default. |
2412 | */ |
2413 | if (debug) { |
2414 | addlog("%s: warning: peer rejected our MRU of " |
2415 | "%ld bytes. Defaulting to %d bytes\n" , |
2416 | ifp->if_xname, sp->lcp.mru, PP_MTU); |
2417 | } |
2418 | sp->lcp.opts &= ~(1 << LCP_OPT_MRU); |
2419 | sp->lcp.mru = PP_MTU; |
2420 | break; |
2421 | case LCP_OPT_AUTH_PROTO: |
2422 | /* |
2423 | * Peer doesn't want to authenticate himself, |
2424 | * deny unless this is a dialout call, and |
2425 | * SPPP_AUTHFLAG_NOCALLOUT is set. |
2426 | */ |
2427 | if ((sp->pp_flags & PP_CALLIN) == 0 && |
2428 | (sp->hisauth.flags & SPPP_AUTHFLAG_NOCALLOUT) != 0) { |
2429 | if (debug) |
2430 | addlog(" [don't insist on auth " |
2431 | "for callout]" ); |
2432 | sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); |
2433 | break; |
2434 | } |
2435 | if (debug) |
2436 | addlog("[access denied]\n" ); |
2437 | lcp.Close(sp); |
2438 | break; |
2439 | } |
2440 | } |
2441 | if (debug) |
2442 | addlog("\n" ); |
2443 | drop: |
2444 | free(buf, M_TEMP); |
2445 | return; |
2446 | } |
2447 | |
2448 | /* |
2449 | * Analyze the LCP Configure-NAK option list, and adjust our |
2450 | * negotiation. |
2451 | */ |
2452 | static void |
2453 | sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) |
2454 | { |
2455 | STDDCL; |
2456 | u_char *buf, *p, l, blen; |
2457 | uint32_t magic; |
2458 | |
2459 | len -= 4; |
2460 | buf = malloc (blen = len, M_TEMP, M_NOWAIT); |
2461 | if (!buf) |
2462 | return; |
2463 | |
2464 | if (debug) |
2465 | log(LOG_DEBUG, "%s: lcp nak opts:" , |
2466 | ifp->if_xname); |
2467 | |
2468 | p = (void *)(h + 1); |
2469 | for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
2470 | /* Sanity check option length */ |
2471 | if (l > len) { |
2472 | /* |
2473 | * Malicious option - drop immediately. |
2474 | * XXX Maybe we should just RXJ it? |
2475 | */ |
2476 | addlog("%s: received malicious LCP option, " |
2477 | "dropping.\n" , ifp->if_xname); |
2478 | goto drop; |
2479 | } |
2480 | if (debug) |
2481 | addlog(" %s" , sppp_lcp_opt_name(*p)); |
2482 | switch (*p) { |
2483 | case LCP_OPT_MAGIC: |
2484 | /* Magic number -- renegotiate */ |
2485 | if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && |
2486 | len >= 6 && l == 6) { |
2487 | magic = (uint32_t)p[2] << 24 | |
2488 | (uint32_t)p[3] << 16 | p[4] << 8 | p[5]; |
2489 | /* |
2490 | * If the remote magic is our negated one, |
2491 | * this looks like a loopback problem. |
2492 | * Suggest a new magic to make sure. |
2493 | */ |
2494 | if (magic == ~sp->lcp.magic) { |
2495 | if (debug) |
2496 | addlog(" magic glitch" ); |
2497 | sp->lcp.magic = cprng_fast32(); |
2498 | } else { |
2499 | sp->lcp.magic = magic; |
2500 | if (debug) |
2501 | addlog(" %d" , magic); |
2502 | } |
2503 | } |
2504 | break; |
2505 | case LCP_OPT_MRU: |
2506 | /* |
2507 | * Peer wants to advise us to negotiate an MRU. |
2508 | * Agree on it if it's reasonable, or use |
2509 | * default otherwise. |
2510 | */ |
2511 | if (len >= 4 && l == 4) { |
2512 | u_int mru = p[2] * 256 + p[3]; |
2513 | if (debug) |
2514 | addlog(" %d" , mru); |
2515 | if (mru < PPP_MINMRU || mru > sp->pp_if.if_mtu) |
2516 | mru = sp->pp_if.if_mtu; |
2517 | sp->lcp.mru = mru; |
2518 | sp->lcp.opts |= (1 << LCP_OPT_MRU); |
2519 | } |
2520 | break; |
2521 | case LCP_OPT_AUTH_PROTO: |
2522 | /* |
2523 | * Peer doesn't like our authentication method, |
2524 | * deny. |
2525 | */ |
2526 | if (debug) |
2527 | addlog("[access denied]\n" ); |
2528 | lcp.Close(sp); |
2529 | break; |
2530 | } |
2531 | } |
2532 | if (debug) |
2533 | addlog("\n" ); |
2534 | drop: |
2535 | free(buf, M_TEMP); |
2536 | return; |
2537 | } |
2538 | |
2539 | static void |
2540 | sppp_lcp_tlu(struct sppp *sp) |
2541 | { |
2542 | struct ifnet *ifp = &sp->pp_if; |
2543 | int i; |
2544 | uint32_t mask; |
2545 | |
2546 | /* XXX ? */ |
2547 | if (! (ifp->if_flags & IFF_UP) && |
2548 | (ifp->if_flags & IFF_RUNNING)) { |
2549 | /* Coming out of loopback mode. */ |
2550 | if_up(ifp); |
2551 | } |
2552 | |
2553 | for (i = 0; i < IDX_COUNT; i++) |
2554 | if ((cps[i])->flags & CP_QUAL) |
2555 | (cps[i])->Open(sp); |
2556 | |
2557 | if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || |
2558 | (sp->pp_flags & PP_NEEDAUTH) != 0) |
2559 | sppp_change_phase(sp, SPPP_PHASE_AUTHENTICATE); |
2560 | else |
2561 | sppp_change_phase(sp, SPPP_PHASE_NETWORK); |
2562 | |
2563 | /* |
2564 | * Open all authentication protocols. This is even required |
2565 | * if we already proceeded to network phase, since it might be |
2566 | * that remote wants us to authenticate, so we might have to |
2567 | * send a PAP request. Undesired authentication protocols |
2568 | * don't do anything when they get an Open event. |
2569 | */ |
2570 | for (i = 0; i < IDX_COUNT; i++) |
2571 | if ((cps[i])->flags & CP_AUTH) |
2572 | (cps[i])->Open(sp); |
2573 | |
2574 | if (sp->pp_phase == SPPP_PHASE_NETWORK) { |
2575 | /* Notify all NCPs. */ |
2576 | for (i = 0; i < IDX_COUNT; i++) |
2577 | if ((cps[i])->flags & CP_NCP) |
2578 | (cps[i])->Open(sp); |
2579 | } |
2580 | |
2581 | /* Send Up events to all started protos. */ |
2582 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) |
2583 | if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) |
2584 | (cps[i])->Up(sp); |
2585 | |
2586 | /* notify low-level driver of state change */ |
2587 | if (sp->pp_chg) |
2588 | sp->pp_chg(sp, (int)sp->pp_phase); |
2589 | |
2590 | if (sp->pp_phase == SPPP_PHASE_NETWORK) |
2591 | /* if no NCP is starting, close down */ |
2592 | sppp_lcp_check_and_close(sp); |
2593 | } |
2594 | |
2595 | static void |
2596 | sppp_lcp_tld(struct sppp *sp) |
2597 | { |
2598 | int i; |
2599 | uint32_t mask; |
2600 | |
2601 | sppp_change_phase(sp, SPPP_PHASE_TERMINATE); |
2602 | |
2603 | /* |
2604 | * Take upper layers down. We send the Down event first and |
2605 | * the Close second to prevent the upper layers from sending |
2606 | * ``a flurry of terminate-request packets'', as the RFC |
2607 | * describes it. |
2608 | */ |
2609 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) |
2610 | if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { |
2611 | (cps[i])->Down(sp); |
2612 | (cps[i])->Close(sp); |
2613 | } |
2614 | } |
2615 | |
2616 | static void |
2617 | sppp_lcp_tls(struct sppp *sp) |
2618 | { |
2619 | |
2620 | if (sp->pp_max_auth_fail != 0 && sp->pp_auth_failures >= sp->pp_max_auth_fail) { |
2621 | printf("%s: authentication failed %d times, not retrying again\n" , |
2622 | sp->pp_if.if_xname, sp->pp_auth_failures); |
2623 | if_down(&sp->pp_if); |
2624 | return; |
2625 | } |
2626 | |
2627 | sppp_change_phase(sp, SPPP_PHASE_ESTABLISH); |
2628 | |
2629 | /* Notify lower layer if desired. */ |
2630 | if (sp->pp_tls) |
2631 | (sp->pp_tls)(sp); |
2632 | } |
2633 | |
2634 | static void |
2635 | sppp_lcp_tlf(struct sppp *sp) |
2636 | { |
2637 | |
2638 | sppp_change_phase(sp, SPPP_PHASE_DEAD); |
2639 | |
2640 | /* Notify lower layer if desired. */ |
2641 | if (sp->pp_tlf) |
2642 | (sp->pp_tlf)(sp); |
2643 | } |
2644 | |
2645 | static void |
2646 | sppp_lcp_scr(struct sppp *sp) |
2647 | { |
2648 | char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; |
2649 | int i = 0; |
2650 | u_short authproto; |
2651 | |
2652 | if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { |
2653 | if (! sp->lcp.magic) |
2654 | sp->lcp.magic = cprng_fast32(); |
2655 | opt[i++] = LCP_OPT_MAGIC; |
2656 | opt[i++] = 6; |
2657 | opt[i++] = sp->lcp.magic >> 24; |
2658 | opt[i++] = sp->lcp.magic >> 16; |
2659 | opt[i++] = sp->lcp.magic >> 8; |
2660 | opt[i++] = sp->lcp.magic; |
2661 | } |
2662 | |
2663 | if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { |
2664 | opt[i++] = LCP_OPT_MRU; |
2665 | opt[i++] = 4; |
2666 | opt[i++] = sp->lcp.mru >> 8; |
2667 | opt[i++] = sp->lcp.mru; |
2668 | } |
2669 | |
2670 | if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { |
2671 | authproto = sp->hisauth.proto; |
2672 | opt[i++] = LCP_OPT_AUTH_PROTO; |
2673 | opt[i++] = authproto == PPP_CHAP? 5: 4; |
2674 | opt[i++] = authproto >> 8; |
2675 | opt[i++] = authproto; |
2676 | if (authproto == PPP_CHAP) |
2677 | opt[i++] = CHAP_MD5; |
2678 | } |
2679 | |
2680 | sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; |
2681 | sppp_cp_send(sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); |
2682 | } |
2683 | |
2684 | /* |
2685 | * Check the open NCPs, return true if at least one NCP is open. |
2686 | */ |
2687 | static int |
2688 | sppp_ncp_check(struct sppp *sp) |
2689 | { |
2690 | int i, mask; |
2691 | |
2692 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) |
2693 | if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) |
2694 | return 1; |
2695 | return 0; |
2696 | } |
2697 | |
2698 | /* |
2699 | * Re-check the open NCPs and see if we should terminate the link. |
2700 | * Called by the NCPs during their tlf action handling. |
2701 | */ |
2702 | static void |
2703 | sppp_lcp_check_and_close(struct sppp *sp) |
2704 | { |
2705 | |
2706 | if (sp->pp_phase < SPPP_PHASE_NETWORK) |
2707 | /* don't bother, we are already going down */ |
2708 | return; |
2709 | |
2710 | if (sppp_ncp_check(sp)) |
2711 | return; |
2712 | |
2713 | lcp.Close(sp); |
2714 | } |
2715 | |
2716 | |
2717 | /* |
2718 | *--------------------------------------------------------------------------* |
2719 | * * |
2720 | * The IPCP implementation. * |
2721 | * * |
2722 | *--------------------------------------------------------------------------* |
2723 | */ |
2724 | |
2725 | static void |
2726 | sppp_ipcp_init(struct sppp *sp) |
2727 | { |
2728 | sp->ipcp.opts = 0; |
2729 | sp->ipcp.flags = 0; |
2730 | sp->state[IDX_IPCP] = STATE_INITIAL; |
2731 | sp->fail_counter[IDX_IPCP] = 0; |
2732 | sp->pp_seq[IDX_IPCP] = 0; |
2733 | sp->pp_rseq[IDX_IPCP] = 0; |
2734 | callout_init(&sp->ch[IDX_IPCP], 0); |
2735 | } |
2736 | |
2737 | static void |
2738 | sppp_ipcp_up(struct sppp *sp) |
2739 | { |
2740 | sppp_up_event(&ipcp, sp); |
2741 | } |
2742 | |
2743 | static void |
2744 | sppp_ipcp_down(struct sppp *sp) |
2745 | { |
2746 | sppp_down_event(&ipcp, sp); |
2747 | } |
2748 | |
2749 | static void |
2750 | sppp_ipcp_open(struct sppp *sp) |
2751 | { |
2752 | STDDCL; |
2753 | uint32_t myaddr, hisaddr; |
2754 | |
2755 | sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN|IPCP_HISADDR_DYN); |
2756 | sp->ipcp.req_myaddr = 0; |
2757 | sp->ipcp.req_hisaddr = 0; |
2758 | memset(&sp->dns_addrs, 0, sizeof sp->dns_addrs); |
2759 | |
2760 | #ifdef INET |
2761 | sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); |
2762 | #else |
2763 | myaddr = hisaddr = 0; |
2764 | #endif |
2765 | /* |
2766 | * If we don't have his address, this probably means our |
2767 | * interface doesn't want to talk IP at all. (This could |
2768 | * be the case if somebody wants to speak only IPX, for |
2769 | * example.) Don't open IPCP in this case. |
2770 | */ |
2771 | if (hisaddr == 0) { |
2772 | /* XXX this message should go away */ |
2773 | if (debug) |
2774 | log(LOG_DEBUG, "%s: ipcp_open(): no IP interface\n" , |
2775 | ifp->if_xname); |
2776 | return; |
2777 | } |
2778 | |
2779 | if (myaddr == 0) { |
2780 | /* |
2781 | * I don't have an assigned address, so i need to |
2782 | * negotiate my address. |
2783 | */ |
2784 | sp->ipcp.flags |= IPCP_MYADDR_DYN; |
2785 | sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); |
2786 | } |
2787 | if (hisaddr == 1) { |
2788 | /* |
2789 | * XXX - remove this hack! |
2790 | * remote has no valid address, we need to get one assigned. |
2791 | */ |
2792 | sp->ipcp.flags |= IPCP_HISADDR_DYN; |
2793 | } |
2794 | sppp_open_event(&ipcp, sp); |
2795 | } |
2796 | |
2797 | static void |
2798 | sppp_ipcp_close(struct sppp *sp) |
2799 | { |
2800 | STDDCL; |
2801 | |
2802 | sppp_close_event(&ipcp, sp); |
2803 | #ifdef INET |
2804 | if (sp->ipcp.flags & (IPCP_MYADDR_DYN|IPCP_HISADDR_DYN)) |
2805 | /* |
2806 | * Some address was dynamic, clear it again. |
2807 | */ |
2808 | sppp_clear_ip_addrs(sp); |
2809 | #endif |
2810 | |
2811 | if (sp->pp_saved_mtu > 0) { |
2812 | ifp->if_mtu = sp->pp_saved_mtu; |
2813 | sp->pp_saved_mtu = 0; |
2814 | if (debug) |
2815 | log(LOG_DEBUG, |
2816 | "%s: resetting MTU to %" PRIu64 " bytes\n" , |
2817 | ifp->if_xname, ifp->if_mtu); |
2818 | } |
2819 | } |
2820 | |
2821 | static void |
2822 | sppp_ipcp_TO(void *cookie) |
2823 | { |
2824 | sppp_to_event(&ipcp, (struct sppp *)cookie); |
2825 | } |
2826 | |
2827 | /* |
2828 | * Analyze a configure request. Return true if it was agreeable, and |
2829 | * caused action sca, false if it has been rejected or nak'ed, and |
2830 | * caused action scn. (The return value is used to make the state |
2831 | * transition decision in the state automaton.) |
2832 | */ |
2833 | static int |
2834 | sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) |
2835 | { |
2836 | u_char *buf, *r, *p, l, blen; |
2837 | struct ifnet *ifp = &sp->pp_if; |
2838 | int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; |
2839 | uint32_t hisaddr, desiredaddr; |
2840 | |
2841 | len -= 4; |
2842 | origlen = len; |
2843 | /* |
2844 | * Make sure to allocate a buf that can at least hold a |
2845 | * conf-nak with an `address' option. We might need it below. |
2846 | */ |
2847 | blen = len < 6 ? 6 : len; |
2848 | buf = r = malloc (blen, M_TEMP, M_NOWAIT); |
2849 | if (! buf) |
2850 | return (0); |
2851 | |
2852 | /* pass 1: see if we can recognize them */ |
2853 | if (debug) |
2854 | log(LOG_DEBUG, "%s: ipcp parse opts:" , |
2855 | ifp->if_xname); |
2856 | p = (void *)(h + 1); |
2857 | for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
2858 | /* Sanity check option length */ |
2859 | if (l > len) { |
2860 | /* XXX should we just RXJ? */ |
2861 | addlog("%s: malicious IPCP option received, dropping\n" , |
2862 | ifp->if_xname); |
2863 | goto drop; |
2864 | } |
2865 | if (debug) |
2866 | addlog(" %s" , sppp_ipcp_opt_name(*p)); |
2867 | switch (*p) { |
2868 | #ifdef notyet |
2869 | case IPCP_OPT_COMPRESSION: |
2870 | if (len >= 6 && l >= 6) { |
2871 | /* correctly formed compress option */ |
2872 | continue; |
2873 | } |
2874 | if (debug) |
2875 | addlog(" [invalid]" ); |
2876 | break; |
2877 | #endif |
2878 | case IPCP_OPT_ADDRESS: |
2879 | if (len >= 6 && l == 6) { |
2880 | /* correctly formed address option */ |
2881 | continue; |
2882 | } |
2883 | if (debug) |
2884 | addlog(" [invalid]" ); |
2885 | break; |
2886 | default: |
2887 | /* Others not supported. */ |
2888 | if (debug) |
2889 | addlog(" [rej]" ); |
2890 | break; |
2891 | } |
2892 | /* Add the option to rejected list. */ |
2893 | if (rlen + l > blen) { |
2894 | if (debug) |
2895 | addlog(" [overflow]" ); |
2896 | continue; |
2897 | } |
2898 | memcpy(r, p, l); |
2899 | r += l; |
2900 | rlen += l; |
2901 | } |
2902 | if (rlen) { |
2903 | if (debug) |
2904 | addlog(" send conf-rej\n" ); |
2905 | sppp_cp_send(sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); |
2906 | goto end; |
2907 | } else if (debug) |
2908 | addlog("\n" ); |
2909 | |
2910 | /* pass 2: parse option values */ |
2911 | if (sp->ipcp.flags & IPCP_HISADDR_SEEN) |
2912 | hisaddr = sp->ipcp.req_hisaddr; /* we already aggreed on that */ |
2913 | else |
2914 | #ifdef INET |
2915 | sppp_get_ip_addrs(sp, 0, &hisaddr, 0); /* user configuration */ |
2916 | #else |
2917 | hisaddr = 0; |
2918 | #endif |
2919 | if (debug) |
2920 | log(LOG_DEBUG, "%s: ipcp parse opt values: " , |
2921 | ifp->if_xname); |
2922 | p = (void *)(h + 1); |
2923 | len = origlen; |
2924 | for (rlen=0; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
2925 | if (debug) |
2926 | addlog(" %s" , sppp_ipcp_opt_name(*p)); |
2927 | switch (*p) { |
2928 | #ifdef notyet |
2929 | case IPCP_OPT_COMPRESSION: |
2930 | continue; |
2931 | #endif |
2932 | case IPCP_OPT_ADDRESS: |
2933 | desiredaddr = p[2] << 24 | p[3] << 16 | |
2934 | p[4] << 8 | p[5]; |
2935 | if (desiredaddr == hisaddr || |
2936 | ((sp->ipcp.flags & IPCP_HISADDR_DYN) && desiredaddr != 0)) { |
2937 | /* |
2938 | * Peer's address is same as our value, |
2939 | * this is agreeable. Gonna conf-ack |
2940 | * it. |
2941 | */ |
2942 | if (debug) |
2943 | addlog(" %s [ack]" , |
2944 | sppp_dotted_quad(hisaddr)); |
2945 | /* record that we've seen it already */ |
2946 | sp->ipcp.flags |= IPCP_HISADDR_SEEN; |
2947 | sp->ipcp.req_hisaddr = desiredaddr; |
2948 | hisaddr = desiredaddr; |
2949 | continue; |
2950 | } |
2951 | /* |
2952 | * The address wasn't agreeable. This is either |
2953 | * he sent us 0.0.0.0, asking to assign him an |
2954 | * address, or he send us another address not |
2955 | * matching our value. Either case, we gonna |
2956 | * conf-nak it with our value. |
2957 | */ |
2958 | if (debug) { |
2959 | if (desiredaddr == 0) |
2960 | addlog(" [addr requested]" ); |
2961 | else |
2962 | addlog(" %s [not agreed]" , |
2963 | sppp_dotted_quad(desiredaddr)); |
2964 | } |
2965 | |
2966 | p[2] = hisaddr >> 24; |
2967 | p[3] = hisaddr >> 16; |
2968 | p[4] = hisaddr >> 8; |
2969 | p[5] = hisaddr; |
2970 | break; |
2971 | } |
2972 | if (rlen + l > blen) { |
2973 | if (debug) |
2974 | addlog(" [overflow]" ); |
2975 | continue; |
2976 | } |
2977 | /* Add the option to nak'ed list. */ |
2978 | memcpy(r, p, l); |
2979 | r += l; |
2980 | rlen += l; |
2981 | } |
2982 | |
2983 | /* |
2984 | * If we are about to conf-ack the request, but haven't seen |
2985 | * his address so far, gonna conf-nak it instead, with the |
2986 | * `address' option present and our idea of his address being |
2987 | * filled in there, to request negotiation of both addresses. |
2988 | * |
2989 | * XXX This can result in an endless req - nak loop if peer |
2990 | * doesn't want to send us his address. Q: What should we do |
2991 | * about it? XXX A: implement the max-failure counter. |
2992 | */ |
2993 | if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { |
2994 | buf[0] = IPCP_OPT_ADDRESS; |
2995 | buf[1] = 6; |
2996 | buf[2] = hisaddr >> 24; |
2997 | buf[3] = hisaddr >> 16; |
2998 | buf[4] = hisaddr >> 8; |
2999 | buf[5] = hisaddr; |
3000 | rlen = 6; |
3001 | if (debug) |
3002 | addlog(" still need hisaddr" ); |
3003 | } |
3004 | |
3005 | if (rlen) { |
3006 | if (debug) |
3007 | addlog(" send conf-nak\n" ); |
3008 | sppp_cp_send(sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); |
3009 | } else { |
3010 | if (debug) |
3011 | addlog(" send conf-ack\n" ); |
3012 | sppp_cp_send(sp, PPP_IPCP, CONF_ACK, h->ident, origlen, h + 1); |
3013 | } |
3014 | |
3015 | end: |
3016 | free(buf, M_TEMP); |
3017 | return (rlen == 0); |
3018 | |
3019 | drop: |
3020 | free(buf, M_TEMP); |
3021 | return -1; |
3022 | } |
3023 | |
3024 | /* |
3025 | * Analyze the IPCP Configure-Reject option list, and adjust our |
3026 | * negotiation. |
3027 | */ |
3028 | static void |
3029 | sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) |
3030 | { |
3031 | u_char *buf, *p, l, blen; |
3032 | struct ifnet *ifp = &sp->pp_if; |
3033 | int debug = ifp->if_flags & IFF_DEBUG; |
3034 | |
3035 | len -= 4; |
3036 | buf = malloc (blen = len, M_TEMP, M_NOWAIT); |
3037 | if (!buf) |
3038 | return; |
3039 | |
3040 | if (debug) |
3041 | log(LOG_DEBUG, "%s: ipcp rej opts:" , |
3042 | ifp->if_xname); |
3043 | |
3044 | p = (void *)(h + 1); |
3045 | for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
3046 | /* Sanity check option length */ |
3047 | if (l > len) { |
3048 | /* XXX should we just RXJ? */ |
3049 | addlog("%s: malicious IPCP option received, dropping\n" , |
3050 | ifp->if_xname); |
3051 | goto drop; |
3052 | } |
3053 | if (debug) |
3054 | addlog(" %s" , sppp_ipcp_opt_name(*p)); |
3055 | switch (*p) { |
3056 | case IPCP_OPT_ADDRESS: |
3057 | /* |
3058 | * Peer doesn't grok address option. This is |
3059 | * bad. XXX Should we better give up here? |
3060 | */ |
3061 | sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); |
3062 | break; |
3063 | #ifdef notyet |
3064 | case IPCP_OPT_COMPRESS: |
3065 | sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); |
3066 | break; |
3067 | #endif |
3068 | } |
3069 | } |
3070 | if (debug) |
3071 | addlog("\n" ); |
3072 | drop: |
3073 | free(buf, M_TEMP); |
3074 | return; |
3075 | } |
3076 | |
3077 | /* |
3078 | * Analyze the IPCP Configure-NAK option list, and adjust our |
3079 | * negotiation. |
3080 | */ |
3081 | static void |
3082 | sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) |
3083 | { |
3084 | u_char *p, l; |
3085 | struct ifnet *ifp = &sp->pp_if; |
3086 | int debug = ifp->if_flags & IFF_DEBUG; |
3087 | uint32_t wantaddr; |
3088 | |
3089 | len -= 4; |
3090 | |
3091 | if (debug) |
3092 | log(LOG_DEBUG, "%s: ipcp nak opts:" , |
3093 | ifp->if_xname); |
3094 | |
3095 | p = (void *)(h + 1); |
3096 | for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
3097 | /* Sanity check option length */ |
3098 | if (l > len) { |
3099 | /* XXX should we just RXJ? */ |
3100 | addlog("%s: malicious IPCP option received, dropping\n" , |
3101 | ifp->if_xname); |
3102 | return; |
3103 | } |
3104 | if (debug) |
3105 | addlog(" %s" , sppp_ipcp_opt_name(*p)); |
3106 | switch (*p) { |
3107 | case IPCP_OPT_ADDRESS: |
3108 | /* |
3109 | * Peer doesn't like our local IP address. See |
3110 | * if we can do something for him. We'll drop |
3111 | * him our address then. |
3112 | */ |
3113 | if (len >= 6 && l == 6) { |
3114 | wantaddr = p[2] << 24 | p[3] << 16 | |
3115 | p[4] << 8 | p[5]; |
3116 | sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); |
3117 | if (debug) |
3118 | addlog(" [wantaddr %s]" , |
3119 | sppp_dotted_quad(wantaddr)); |
3120 | /* |
3121 | * When doing dynamic address assignment, |
3122 | * we accept his offer. Otherwise, we |
3123 | * ignore it and thus continue to negotiate |
3124 | * our already existing value. |
3125 | */ |
3126 | if (sp->ipcp.flags & IPCP_MYADDR_DYN) { |
3127 | if (debug) |
3128 | addlog(" [agree]" ); |
3129 | sp->ipcp.flags |= IPCP_MYADDR_SEEN; |
3130 | sp->ipcp.req_myaddr = wantaddr; |
3131 | } |
3132 | } |
3133 | break; |
3134 | |
3135 | case IPCP_OPT_PRIMDNS: |
3136 | if (len >= 6 && l == 6) { |
3137 | sp->dns_addrs[0] = p[2] << 24 | p[3] << 16 | |
3138 | p[4] << 8 | p[5]; |
3139 | } |
3140 | break; |
3141 | |
3142 | case IPCP_OPT_SECDNS: |
3143 | if (len >= 6 && l == 6) { |
3144 | sp->dns_addrs[1] = p[2] << 24 | p[3] << 16 | |
3145 | p[4] << 8 | p[5]; |
3146 | } |
3147 | break; |
3148 | #ifdef notyet |
3149 | case IPCP_OPT_COMPRESS: |
3150 | /* |
3151 | * Peer wants different compression parameters. |
3152 | */ |
3153 | break; |
3154 | #endif |
3155 | } |
3156 | } |
3157 | if (debug) |
3158 | addlog("\n" ); |
3159 | } |
3160 | |
3161 | static void |
3162 | sppp_ipcp_tlu(struct sppp *sp) |
3163 | { |
3164 | #ifdef INET |
3165 | /* we are up. Set addresses and notify anyone interested */ |
3166 | STDDCL; |
3167 | uint32_t myaddr, hisaddr; |
3168 | |
3169 | sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); |
3170 | if ((sp->ipcp.flags & IPCP_MYADDR_DYN) && (sp->ipcp.flags & IPCP_MYADDR_SEEN)) |
3171 | myaddr = sp->ipcp.req_myaddr; |
3172 | if ((sp->ipcp.flags & IPCP_HISADDR_DYN) && (sp->ipcp.flags & IPCP_HISADDR_SEEN)) |
3173 | hisaddr = sp->ipcp.req_hisaddr; |
3174 | sppp_set_ip_addrs(sp, myaddr, hisaddr); |
3175 | |
3176 | if (ifp->if_mtu > sp->lcp.their_mru) { |
3177 | sp->pp_saved_mtu = ifp->if_mtu; |
3178 | ifp->if_mtu = sp->lcp.their_mru; |
3179 | if (debug) |
3180 | log(LOG_DEBUG, |
3181 | "%s: setting MTU to %" PRIu64 " bytes\n" , |
3182 | ifp->if_xname, ifp->if_mtu); |
3183 | } |
3184 | |
3185 | if (sp->pp_con) |
3186 | sp->pp_con(sp); |
3187 | #endif |
3188 | } |
3189 | |
3190 | static void |
3191 | sppp_ipcp_tld(struct sppp *sp) |
3192 | { |
3193 | } |
3194 | |
3195 | static void |
3196 | sppp_ipcp_tls(struct sppp *sp) |
3197 | { |
3198 | /* indicate to LCP that it must stay alive */ |
3199 | sp->lcp.protos |= (1 << IDX_IPCP); |
3200 | } |
3201 | |
3202 | static void |
3203 | sppp_ipcp_tlf(struct sppp *sp) |
3204 | { |
3205 | /* we no longer need LCP */ |
3206 | sp->lcp.protos &= ~(1 << IDX_IPCP); |
3207 | } |
3208 | |
3209 | static void |
3210 | sppp_ipcp_scr(struct sppp *sp) |
3211 | { |
3212 | uint8_t opt[6 /* compression */ + 6 /* address */ + 12 /* dns addresses */]; |
3213 | #ifdef INET |
3214 | uint32_t ouraddr; |
3215 | #endif |
3216 | int i = 0; |
3217 | |
3218 | #ifdef notyet |
3219 | if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { |
3220 | opt[i++] = IPCP_OPT_COMPRESSION; |
3221 | opt[i++] = 6; |
3222 | opt[i++] = 0; /* VJ header compression */ |
3223 | opt[i++] = 0x2d; /* VJ header compression */ |
3224 | opt[i++] = max_slot_id; |
3225 | opt[i++] = comp_slot_id; |
3226 | } |
3227 | #endif |
3228 | |
3229 | #ifdef INET |
3230 | if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { |
3231 | if (sp->ipcp.flags & IPCP_MYADDR_SEEN) |
3232 | ouraddr = sp->ipcp.req_myaddr; /* not sure if this can ever happen */ |
3233 | else |
3234 | sppp_get_ip_addrs(sp, &ouraddr, 0, 0); |
3235 | opt[i++] = IPCP_OPT_ADDRESS; |
3236 | opt[i++] = 6; |
3237 | opt[i++] = ouraddr >> 24; |
3238 | opt[i++] = ouraddr >> 16; |
3239 | opt[i++] = ouraddr >> 8; |
3240 | opt[i++] = ouraddr; |
3241 | } |
3242 | #endif |
3243 | |
3244 | if (sp->query_dns & 1) { |
3245 | opt[i++] = IPCP_OPT_PRIMDNS; |
3246 | opt[i++] = 6; |
3247 | opt[i++] = sp->dns_addrs[0] >> 24; |
3248 | opt[i++] = sp->dns_addrs[0] >> 16; |
3249 | opt[i++] = sp->dns_addrs[0] >> 8; |
3250 | opt[i++] = sp->dns_addrs[0]; |
3251 | } |
3252 | if (sp->query_dns & 2) { |
3253 | opt[i++] = IPCP_OPT_SECDNS; |
3254 | opt[i++] = 6; |
3255 | opt[i++] = sp->dns_addrs[1] >> 24; |
3256 | opt[i++] = sp->dns_addrs[1] >> 16; |
3257 | opt[i++] = sp->dns_addrs[1] >> 8; |
3258 | opt[i++] = sp->dns_addrs[1]; |
3259 | } |
3260 | |
3261 | sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; |
3262 | sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); |
3263 | } |
3264 | |
3265 | |
3266 | /* |
3267 | *--------------------------------------------------------------------------* |
3268 | * * |
3269 | * The IPv6CP implementation. * |
3270 | * * |
3271 | *--------------------------------------------------------------------------* |
3272 | */ |
3273 | |
3274 | #ifdef INET6 |
3275 | static void |
3276 | sppp_ipv6cp_init(struct sppp *sp) |
3277 | { |
3278 | sp->ipv6cp.opts = 0; |
3279 | sp->ipv6cp.flags = 0; |
3280 | sp->state[IDX_IPV6CP] = STATE_INITIAL; |
3281 | sp->fail_counter[IDX_IPV6CP] = 0; |
3282 | sp->pp_seq[IDX_IPV6CP] = 0; |
3283 | sp->pp_rseq[IDX_IPV6CP] = 0; |
3284 | callout_init(&sp->ch[IDX_IPV6CP], 0); |
3285 | } |
3286 | |
3287 | static void |
3288 | sppp_ipv6cp_up(struct sppp *sp) |
3289 | { |
3290 | sppp_up_event(&ipv6cp, sp); |
3291 | } |
3292 | |
3293 | static void |
3294 | sppp_ipv6cp_down(struct sppp *sp) |
3295 | { |
3296 | sppp_down_event(&ipv6cp, sp); |
3297 | } |
3298 | |
3299 | static void |
3300 | sppp_ipv6cp_open(struct sppp *sp) |
3301 | { |
3302 | STDDCL; |
3303 | struct in6_addr myaddr, hisaddr; |
3304 | |
3305 | #ifdef IPV6CP_MYIFID_DYN |
3306 | sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); |
3307 | #else |
3308 | sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; |
3309 | #endif |
3310 | |
3311 | sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); |
3312 | /* |
3313 | * If we don't have our address, this probably means our |
3314 | * interface doesn't want to talk IPv6 at all. (This could |
3315 | * be the case if somebody wants to speak only IPX, for |
3316 | * example.) Don't open IPv6CP in this case. |
3317 | */ |
3318 | if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { |
3319 | /* XXX this message should go away */ |
3320 | if (debug) |
3321 | log(LOG_DEBUG, "%s: ipv6cp_open(): no IPv6 interface\n" , |
3322 | ifp->if_xname); |
3323 | return; |
3324 | } |
3325 | |
3326 | sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; |
3327 | sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); |
3328 | sppp_open_event(&ipv6cp, sp); |
3329 | } |
3330 | |
3331 | static void |
3332 | sppp_ipv6cp_close(struct sppp *sp) |
3333 | { |
3334 | sppp_close_event(&ipv6cp, sp); |
3335 | } |
3336 | |
3337 | static void |
3338 | sppp_ipv6cp_TO(void *cookie) |
3339 | { |
3340 | sppp_to_event(&ipv6cp, (struct sppp *)cookie); |
3341 | } |
3342 | |
3343 | /* |
3344 | * Analyze a configure request. Return true if it was agreeable, and |
3345 | * caused action sca, false if it has been rejected or nak'ed, and |
3346 | * caused action scn. (The return value is used to make the state |
3347 | * transition decision in the state automaton.) |
3348 | */ |
3349 | static int |
3350 | sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) |
3351 | { |
3352 | u_char *buf, *r, *p, l, blen; |
3353 | struct ifnet *ifp = &sp->pp_if; |
3354 | int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; |
3355 | struct in6_addr myaddr, desiredaddr, suggestaddr; |
3356 | int ifidcount; |
3357 | int type; |
3358 | int collision, nohisaddr; |
3359 | |
3360 | len -= 4; |
3361 | origlen = len; |
3362 | /* |
3363 | * Make sure to allocate a buf that can at least hold a |
3364 | * conf-nak with an `address' option. We might need it below. |
3365 | */ |
3366 | blen = len < 6 ? 6 : len; |
3367 | buf = r = malloc (blen, M_TEMP, M_NOWAIT); |
3368 | if (! buf) |
3369 | return (0); |
3370 | |
3371 | /* pass 1: see if we can recognize them */ |
3372 | if (debug) |
3373 | log(LOG_DEBUG, "%s: ipv6cp parse opts:" , |
3374 | ifp->if_xname); |
3375 | p = (void *)(h + 1); |
3376 | ifidcount = 0; |
3377 | for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
3378 | /* Sanity check option length */ |
3379 | if (l > len) { |
3380 | /* XXX just RXJ? */ |
3381 | addlog("%s: received malicious IPCPv6 option, " |
3382 | "dropping\n" , ifp->if_xname); |
3383 | goto drop; |
3384 | } |
3385 | if (debug) |
3386 | addlog(" %s" , sppp_ipv6cp_opt_name(*p)); |
3387 | switch (*p) { |
3388 | case IPV6CP_OPT_IFID: |
3389 | if (len >= 10 && l == 10 && ifidcount == 0) { |
3390 | /* correctly formed address option */ |
3391 | ifidcount++; |
3392 | continue; |
3393 | } |
3394 | if (debug) |
3395 | addlog(" [invalid]" ); |
3396 | break; |
3397 | #ifdef notyet |
3398 | case IPV6CP_OPT_COMPRESSION: |
3399 | if (len >= 4 && l >= 4) { |
3400 | /* correctly formed compress option */ |
3401 | continue; |
3402 | } |
3403 | if (debug) |
3404 | addlog(" [invalid]" ); |
3405 | break; |
3406 | #endif |
3407 | default: |
3408 | /* Others not supported. */ |
3409 | if (debug) |
3410 | addlog(" [rej]" ); |
3411 | break; |
3412 | } |
3413 | if (rlen + l > blen) { |
3414 | if (debug) |
3415 | addlog(" [overflow]" ); |
3416 | continue; |
3417 | } |
3418 | /* Add the option to rejected list. */ |
3419 | memcpy(r, p, l); |
3420 | r += l; |
3421 | rlen += l; |
3422 | } |
3423 | if (rlen) { |
3424 | if (debug) |
3425 | addlog(" send conf-rej\n" ); |
3426 | sppp_cp_send(sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); |
3427 | goto end; |
3428 | } else if (debug) |
3429 | addlog("\n" ); |
3430 | |
3431 | /* pass 2: parse option values */ |
3432 | sppp_get_ip6_addrs(sp, &myaddr, 0, 0); |
3433 | if (debug) |
3434 | log(LOG_DEBUG, "%s: ipv6cp parse opt values: " , |
3435 | ifp->if_xname); |
3436 | p = (void *)(h + 1); |
3437 | len = origlen; |
3438 | type = CONF_ACK; |
3439 | for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
3440 | if (debug) |
3441 | addlog(" %s" , sppp_ipv6cp_opt_name(*p)); |
3442 | switch (*p) { |
3443 | #ifdef notyet |
3444 | case IPV6CP_OPT_COMPRESSION: |
3445 | continue; |
3446 | #endif |
3447 | case IPV6CP_OPT_IFID: |
3448 | memset(&desiredaddr, 0, sizeof(desiredaddr)); |
3449 | memcpy(&desiredaddr.s6_addr[8], &p[2], 8); |
3450 | collision = (memcmp(&desiredaddr.s6_addr[8], |
3451 | &myaddr.s6_addr[8], 8) == 0); |
3452 | nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); |
3453 | |
3454 | desiredaddr.s6_addr16[0] = htons(0xfe80); |
3455 | (void)in6_setscope(&desiredaddr, &sp->pp_if, NULL); |
3456 | |
3457 | if (!collision && !nohisaddr) { |
3458 | /* no collision, hisaddr known - Conf-Ack */ |
3459 | type = CONF_ACK; |
3460 | |
3461 | if (debug) { |
3462 | addlog(" %s [%s]" , |
3463 | ip6_sprintf(&desiredaddr), |
3464 | sppp_cp_type_name(type)); |
3465 | } |
3466 | continue; |
3467 | } |
3468 | |
3469 | memset(&suggestaddr, 0, sizeof(suggestaddr)); |
3470 | if (collision && nohisaddr) { |
3471 | /* collision, hisaddr unknown - Conf-Rej */ |
3472 | type = CONF_REJ; |
3473 | memset(&p[2], 0, 8); |
3474 | } else { |
3475 | /* |
3476 | * - no collision, hisaddr unknown, or |
3477 | * - collision, hisaddr known |
3478 | * Conf-Nak, suggest hisaddr |
3479 | */ |
3480 | type = CONF_NAK; |
3481 | sppp_suggest_ip6_addr(sp, &suggestaddr); |
3482 | memcpy(&p[2], &suggestaddr.s6_addr[8], 8); |
3483 | } |
3484 | if (debug) |
3485 | addlog(" %s [%s]" , ip6_sprintf(&desiredaddr), |
3486 | sppp_cp_type_name(type)); |
3487 | break; |
3488 | } |
3489 | if (rlen + l > blen) { |
3490 | if (debug) |
3491 | addlog(" [overflow]" ); |
3492 | continue; |
3493 | } |
3494 | /* Add the option to nak'ed list. */ |
3495 | memcpy(r, p, l); |
3496 | r += l; |
3497 | rlen += l; |
3498 | } |
3499 | |
3500 | if (rlen == 0 && type == CONF_ACK) { |
3501 | if (debug) |
3502 | addlog(" send %s\n" , sppp_cp_type_name(type)); |
3503 | sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, origlen, h + 1); |
3504 | } else { |
3505 | #ifdef notdef |
3506 | if (type == CONF_ACK) |
3507 | panic("IPv6CP RCR: CONF_ACK with non-zero rlen" ); |
3508 | #endif |
3509 | |
3510 | if (debug) { |
3511 | addlog(" send %s suggest %s\n" , |
3512 | sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); |
3513 | } |
3514 | sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, rlen, buf); |
3515 | } |
3516 | |
3517 | end: |
3518 | free(buf, M_TEMP); |
3519 | return (rlen == 0); |
3520 | |
3521 | drop: |
3522 | free(buf, M_TEMP); |
3523 | return -1; |
3524 | } |
3525 | |
3526 | /* |
3527 | * Analyze the IPv6CP Configure-Reject option list, and adjust our |
3528 | * negotiation. |
3529 | */ |
3530 | static void |
3531 | sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) |
3532 | { |
3533 | u_char *buf, *p, l, blen; |
3534 | struct ifnet *ifp = &sp->pp_if; |
3535 | int debug = ifp->if_flags & IFF_DEBUG; |
3536 | |
3537 | len -= 4; |
3538 | buf = malloc (blen = len, M_TEMP, M_NOWAIT); |
3539 | if (!buf) |
3540 | return; |
3541 | |
3542 | if (debug) |
3543 | log(LOG_DEBUG, "%s: ipv6cp rej opts:" , |
3544 | ifp->if_xname); |
3545 | |
3546 | p = (void *)(h + 1); |
3547 | for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
3548 | if (l > len) { |
3549 | /* XXX just RXJ? */ |
3550 | addlog("%s: received malicious IPCPv6 option, " |
3551 | "dropping\n" , ifp->if_xname); |
3552 | goto drop; |
3553 | } |
3554 | if (debug) |
3555 | addlog(" %s" , sppp_ipv6cp_opt_name(*p)); |
3556 | switch (*p) { |
3557 | case IPV6CP_OPT_IFID: |
3558 | /* |
3559 | * Peer doesn't grok address option. This is |
3560 | * bad. XXX Should we better give up here? |
3561 | */ |
3562 | sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); |
3563 | break; |
3564 | #ifdef notyet |
3565 | case IPV6CP_OPT_COMPRESS: |
3566 | sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); |
3567 | break; |
3568 | #endif |
3569 | } |
3570 | } |
3571 | if (debug) |
3572 | addlog("\n" ); |
3573 | drop: |
3574 | free(buf, M_TEMP); |
3575 | return; |
3576 | } |
3577 | |
3578 | /* |
3579 | * Analyze the IPv6CP Configure-NAK option list, and adjust our |
3580 | * negotiation. |
3581 | */ |
3582 | static void |
3583 | sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) |
3584 | { |
3585 | u_char *buf, *p, l, blen; |
3586 | struct ifnet *ifp = &sp->pp_if; |
3587 | int debug = ifp->if_flags & IFF_DEBUG; |
3588 | struct in6_addr suggestaddr; |
3589 | |
3590 | len -= 4; |
3591 | buf = malloc (blen = len, M_TEMP, M_NOWAIT); |
3592 | if (!buf) |
3593 | return; |
3594 | |
3595 | if (debug) |
3596 | log(LOG_DEBUG, "%s: ipv6cp nak opts:" , |
3597 | ifp->if_xname); |
3598 | |
3599 | p = (void *)(h + 1); |
3600 | for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) { |
3601 | if (l > len) { |
3602 | /* XXX just RXJ? */ |
3603 | addlog("%s: received malicious IPCPv6 option, " |
3604 | "dropping\n" , ifp->if_xname); |
3605 | goto drop; |
3606 | } |
3607 | if (debug) |
3608 | addlog(" %s" , sppp_ipv6cp_opt_name(*p)); |
3609 | switch (*p) { |
3610 | case IPV6CP_OPT_IFID: |
3611 | /* |
3612 | * Peer doesn't like our local ifid. See |
3613 | * if we can do something for him. We'll drop |
3614 | * him our address then. |
3615 | */ |
3616 | if (len < 10 || l != 10) |
3617 | break; |
3618 | memset(&suggestaddr, 0, sizeof(suggestaddr)); |
3619 | suggestaddr.s6_addr16[0] = htons(0xfe80); |
3620 | (void)in6_setscope(&suggestaddr, &sp->pp_if, NULL); |
3621 | memcpy(&suggestaddr.s6_addr[8], &p[2], 8); |
3622 | |
3623 | sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); |
3624 | if (debug) |
3625 | addlog(" [suggestaddr %s]" , |
3626 | ip6_sprintf(&suggestaddr)); |
3627 | #ifdef IPV6CP_MYIFID_DYN |
3628 | /* |
3629 | * When doing dynamic address assignment, |
3630 | * we accept his offer. |
3631 | */ |
3632 | if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { |
3633 | struct in6_addr lastsuggest; |
3634 | /* |
3635 | * If <suggested myaddr from peer> equals to |
3636 | * <hisaddr we have suggested last time>, |
3637 | * we have a collision. generate new random |
3638 | * ifid. |
3639 | */ |
3640 | sppp_suggest_ip6_addr(&lastsuggest); |
3641 | if (IN6_ARE_ADDR_EQUAL(&suggestaddr, |
3642 | lastsuggest)) { |
3643 | if (debug) |
3644 | addlog(" [random]" ); |
3645 | sppp_gen_ip6_addr(sp, &suggestaddr); |
3646 | } |
3647 | sppp_set_ip6_addr(sp, &suggestaddr, 0); |
3648 | if (debug) |
3649 | addlog(" [agree]" ); |
3650 | sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; |
3651 | } |
3652 | #else |
3653 | /* |
3654 | * Since we do not do dynamic address assignment, |
3655 | * we ignore it and thus continue to negotiate |
3656 | * our already existing value. This can possibly |
3657 | * go into infinite request-reject loop. |
3658 | * |
3659 | * This is not likely because we normally use |
3660 | * ifid based on MAC-address. |
3661 | * If you have no ethernet card on the node, too bad. |
3662 | * XXX should we use fail_counter? |
3663 | */ |
3664 | #endif |
3665 | break; |
3666 | #ifdef notyet |
3667 | case IPV6CP_OPT_COMPRESS: |
3668 | /* |
3669 | * Peer wants different compression parameters. |
3670 | */ |
3671 | break; |
3672 | #endif |
3673 | } |
3674 | } |
3675 | if (debug) |
3676 | addlog("\n" ); |
3677 | drop: |
3678 | free(buf, M_TEMP); |
3679 | return; |
3680 | } |
3681 | |
3682 | static void |
3683 | sppp_ipv6cp_tlu(struct sppp *sp) |
3684 | { |
3685 | /* we are up - notify isdn daemon */ |
3686 | if (sp->pp_con) |
3687 | sp->pp_con(sp); |
3688 | } |
3689 | |
3690 | static void |
3691 | sppp_ipv6cp_tld(struct sppp *sp) |
3692 | { |
3693 | } |
3694 | |
3695 | static void |
3696 | sppp_ipv6cp_tls(struct sppp *sp) |
3697 | { |
3698 | /* indicate to LCP that it must stay alive */ |
3699 | sp->lcp.protos |= (1 << IDX_IPV6CP); |
3700 | } |
3701 | |
3702 | static void |
3703 | sppp_ipv6cp_tlf(struct sppp *sp) |
3704 | { |
3705 | /* we no longer need LCP */ |
3706 | sp->lcp.protos &= ~(1 << IDX_IPV6CP); |
3707 | } |
3708 | |
3709 | static void |
3710 | sppp_ipv6cp_scr(struct sppp *sp) |
3711 | { |
3712 | char opt[10 /* ifid */ + 4 /* compression, minimum */]; |
3713 | struct in6_addr ouraddr; |
3714 | int i = 0; |
3715 | |
3716 | if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { |
3717 | sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); |
3718 | opt[i++] = IPV6CP_OPT_IFID; |
3719 | opt[i++] = 10; |
3720 | memcpy(&opt[i], &ouraddr.s6_addr[8], 8); |
3721 | i += 8; |
3722 | } |
3723 | |
3724 | #ifdef notyet |
3725 | if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { |
3726 | opt[i++] = IPV6CP_OPT_COMPRESSION; |
3727 | opt[i++] = 4; |
3728 | opt[i++] = 0; /* TBD */ |
3729 | opt[i++] = 0; /* TBD */ |
3730 | /* variable length data may follow */ |
3731 | } |
3732 | #endif |
3733 | |
3734 | sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; |
3735 | sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); |
3736 | } |
3737 | #else /*INET6*/ |
3738 | static void |
3739 | sppp_ipv6cp_init(struct sppp *sp) |
3740 | { |
3741 | } |
3742 | |
3743 | static void |
3744 | sppp_ipv6cp_up(struct sppp *sp) |
3745 | { |
3746 | } |
3747 | |
3748 | static void |
3749 | sppp_ipv6cp_down(struct sppp *sp) |
3750 | { |
3751 | } |
3752 | |
3753 | static void |
3754 | sppp_ipv6cp_open(struct sppp *sp) |
3755 | { |
3756 | } |
3757 | |
3758 | static void |
3759 | sppp_ipv6cp_close(struct sppp *sp) |
3760 | { |
3761 | } |
3762 | |
3763 | static void |
3764 | sppp_ipv6cp_TO(void *sp) |
3765 | { |
3766 | } |
3767 | |
3768 | static int |
3769 | sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, |
3770 | int len) |
3771 | { |
3772 | return 0; |
3773 | } |
3774 | |
3775 | static void |
3776 | sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, |
3777 | int len) |
3778 | { |
3779 | } |
3780 | |
3781 | static void |
3782 | sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, |
3783 | int len) |
3784 | { |
3785 | } |
3786 | |
3787 | static void |
3788 | sppp_ipv6cp_tlu(struct sppp *sp) |
3789 | { |
3790 | } |
3791 | |
3792 | static void |
3793 | sppp_ipv6cp_tld(struct sppp *sp) |
3794 | { |
3795 | } |
3796 | |
3797 | static void |
3798 | sppp_ipv6cp_tls(struct sppp *sp) |
3799 | { |
3800 | } |
3801 | |
3802 | static void |
3803 | sppp_ipv6cp_tlf(struct sppp *sp) |
3804 | { |
3805 | } |
3806 | |
3807 | static void |
3808 | sppp_ipv6cp_scr(struct sppp *sp) |
3809 | { |
3810 | } |
3811 | #endif /*INET6*/ |
3812 | |
3813 | |
3814 | /* |
3815 | *--------------------------------------------------------------------------* |
3816 | * * |
3817 | * The CHAP implementation. * |
3818 | * * |
3819 | *--------------------------------------------------------------------------* |
3820 | */ |
3821 | |
3822 | /* |
3823 | * The authentication protocols don't employ a full-fledged state machine as |
3824 | * the control protocols do, since they do have Open and Close events, but |
3825 | * not Up and Down, nor are they explicitly terminated. Also, use of the |
3826 | * authentication protocols may be different in both directions (this makes |
3827 | * sense, think of a machine that never accepts incoming calls but only |
3828 | * calls out, it doesn't require the called party to authenticate itself). |
3829 | * |
3830 | * Our state machine for the local authentication protocol (we are requesting |
3831 | * the peer to authenticate) looks like: |
3832 | * |
3833 | * RCA- |
3834 | * +--------------------------------------------+ |
3835 | * V scn,tld| |
3836 | * +--------+ Close +---------+ RCA+ |
3837 | * | |<----------------------------------| |------+ |
3838 | * +--->| Closed | TO* | Opened | sca | |
3839 | * | | |-----+ +-------| |<-----+ |
3840 | * | +--------+ irc | | +---------+ |
3841 | * | ^ | | ^ |
3842 | * | | | | | |
3843 | * | | | | | |
3844 | * | TO-| | | | |
3845 | * | |tld TO+ V | | |
3846 | * | | +------->+ | | |
3847 | * | | | | | | |
3848 | * | +--------+ V | | |
3849 | * | | |<----+<--------------------+ | |
3850 | * | | Req- | scr | |
3851 | * | | Sent | | |
3852 | * | | | | |
3853 | * | +--------+ | |
3854 | * | RCA- | | RCA+ | |
3855 | * +------+ +------------------------------------------+ |
3856 | * scn,tld sca,irc,ict,tlu |
3857 | * |
3858 | * |
3859 | * with: |
3860 | * |
3861 | * Open: LCP reached authentication phase |
3862 | * Close: LCP reached terminate phase |
3863 | * |
3864 | * RCA+: received reply (pap-req, chap-response), acceptable |
3865 | * RCN: received reply (pap-req, chap-response), not acceptable |
3866 | * TO+: timeout with restart counter >= 0 |
3867 | * TO-: timeout with restart counter < 0 |
3868 | * TO*: reschedule timeout for CHAP |
3869 | * |
3870 | * scr: send request packet (none for PAP, chap-challenge) |
3871 | * sca: send ack packet (pap-ack, chap-success) |
3872 | * scn: send nak packet (pap-nak, chap-failure) |
3873 | * ict: initialize re-challenge timer (CHAP only) |
3874 | * |
3875 | * tlu: this-layer-up, LCP reaches network phase |
3876 | * tld: this-layer-down, LCP enters terminate phase |
3877 | * |
3878 | * Note that in CHAP mode, after sending a new challenge, while the state |
3879 | * automaton falls back into Req-Sent state, it doesn't signal a tld |
3880 | * event to LCP, so LCP remains in network phase. Only after not getting |
3881 | * any response (or after getting an unacceptable response), CHAP closes, |
3882 | * causing LCP to enter terminate phase. |
3883 | * |
3884 | * With PAP, there is no initial request that can be sent. The peer is |
3885 | * expected to send one based on the successful negotiation of PAP as |
3886 | * the authentication protocol during the LCP option negotiation. |
3887 | * |
3888 | * Incoming authentication protocol requests (remote requests |
3889 | * authentication, we are peer) don't employ a state machine at all, |
3890 | * they are simply answered. Some peers [Ascend P50 firmware rev |
3891 | * 4.50] react allergically when sending IPCP/IPv6CP requests while they are |
3892 | * still in authentication phase (thereby violating the standard that |
3893 | * demands that these NCP packets are to be discarded), so we keep |
3894 | * track of the peer demanding us to authenticate, and only proceed to |
3895 | * phase network once we've seen a positive acknowledge for the |
3896 | * authentication. |
3897 | */ |
3898 | |
3899 | /* |
3900 | * Handle incoming CHAP packets. |
3901 | */ |
3902 | void |
3903 | sppp_chap_input(struct sppp *sp, struct mbuf *m) |
3904 | { |
3905 | STDDCL; |
3906 | struct lcp_header *h; |
3907 | int len, x; |
3908 | u_char *value, *name, digest[sizeof(sp->myauth.challenge)], dsize; |
3909 | int value_len, name_len; |
3910 | MD5_CTX ctx; |
3911 | |
3912 | len = m->m_pkthdr.len; |
3913 | if (len < 4) { |
3914 | if (debug) |
3915 | log(LOG_DEBUG, |
3916 | "%s: chap invalid packet length: %d bytes\n" , |
3917 | ifp->if_xname, len); |
3918 | return; |
3919 | } |
3920 | h = mtod(m, struct lcp_header *); |
3921 | if (len > ntohs(h->len)) |
3922 | len = ntohs(h->len); |
3923 | |
3924 | switch (h->type) { |
3925 | /* challenge, failure and success are his authproto */ |
3926 | case CHAP_CHALLENGE: |
3927 | if (sp->myauth.secret == NULL || sp->myauth.name == NULL) { |
3928 | /* can't do anything useful */ |
3929 | sp->pp_auth_failures++; |
3930 | printf("%s: chap input without my name and my secret being set\n" , |
3931 | ifp->if_xname); |
3932 | break; |
3933 | } |
3934 | value = 1 + (u_char *)(h + 1); |
3935 | value_len = value[-1]; |
3936 | name = value + value_len; |
3937 | name_len = len - value_len - 5; |
3938 | if (name_len < 0) { |
3939 | if (debug) { |
3940 | log(LOG_DEBUG, |
3941 | "%s: chap corrupted challenge " |
3942 | "<%s id=0x%x len=%d" , |
3943 | ifp->if_xname, |
3944 | sppp_auth_type_name(PPP_CHAP, h->type), |
3945 | h->ident, ntohs(h->len)); |
3946 | if (len > 4) |
3947 | sppp_print_bytes((u_char *)(h + 1), |
3948 | len - 4); |
3949 | addlog(">\n" ); |
3950 | } |
3951 | break; |
3952 | } |
3953 | |
3954 | if (debug) { |
3955 | log(LOG_DEBUG, |
3956 | "%s: chap input <%s id=0x%x len=%d name=" , |
3957 | ifp->if_xname, |
3958 | sppp_auth_type_name(PPP_CHAP, h->type), h->ident, |
3959 | ntohs(h->len)); |
3960 | sppp_print_string((char *) name, name_len); |
3961 | addlog(" value-size=%d value=" , value_len); |
3962 | sppp_print_bytes(value, value_len); |
3963 | addlog(">\n" ); |
3964 | } |
3965 | |
3966 | /* Compute reply value. */ |
3967 | MD5Init(&ctx); |
3968 | MD5Update(&ctx, &h->ident, 1); |
3969 | MD5Update(&ctx, sp->myauth.secret, sp->myauth.secret_len); |
3970 | MD5Update(&ctx, value, value_len); |
3971 | MD5Final(digest, &ctx); |
3972 | dsize = sizeof digest; |
3973 | |
3974 | sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, |
3975 | sizeof dsize, (const char *)&dsize, |
3976 | sizeof digest, digest, |
3977 | sp->myauth.name_len, |
3978 | sp->myauth.name, |
3979 | 0); |
3980 | break; |
3981 | |
3982 | case CHAP_SUCCESS: |
3983 | if (debug) { |
3984 | log(LOG_DEBUG, "%s: chap success" , |
3985 | ifp->if_xname); |
3986 | if (len > 4) { |
3987 | addlog(": " ); |
3988 | sppp_print_string((char *)(h + 1), len - 4); |
3989 | } |
3990 | addlog("\n" ); |
3991 | } |
3992 | x = splnet(); |
3993 | sp->pp_auth_failures = 0; |
3994 | sp->pp_flags &= ~PP_NEEDAUTH; |
3995 | if (sp->myauth.proto == PPP_CHAP && |
3996 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && |
3997 | (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { |
3998 | /* |
3999 | * We are authenticator for CHAP but didn't |
4000 | * complete yet. Leave it to tlu to proceed |
4001 | * to network phase. |
4002 | */ |
4003 | splx(x); |
4004 | break; |
4005 | } |
4006 | splx(x); |
4007 | sppp_phase_network(sp); |
4008 | break; |
4009 | |
4010 | case CHAP_FAILURE: |
4011 | x = splnet(); |
4012 | sp->pp_auth_failures++; |
4013 | splx(x); |
4014 | if (debug) { |
4015 | log(LOG_INFO, "%s: chap failure" , |
4016 | ifp->if_xname); |
4017 | if (len > 4) { |
4018 | addlog(": " ); |
4019 | sppp_print_string((char *)(h + 1), len - 4); |
4020 | } |
4021 | addlog("\n" ); |
4022 | } else |
4023 | log(LOG_INFO, "%s: chap failure\n" , |
4024 | ifp->if_xname); |
4025 | /* await LCP shutdown by authenticator */ |
4026 | break; |
4027 | |
4028 | /* response is my authproto */ |
4029 | case CHAP_RESPONSE: |
4030 | if (sp->hisauth.secret == NULL) { |
4031 | /* can't do anything useful */ |
4032 | printf("%s: chap input without his secret being set\n" , |
4033 | ifp->if_xname); |
4034 | break; |
4035 | } |
4036 | value = 1 + (u_char *)(h + 1); |
4037 | value_len = value[-1]; |
4038 | name = value + value_len; |
4039 | name_len = len - value_len - 5; |
4040 | if (name_len < 0) { |
4041 | if (debug) { |
4042 | log(LOG_DEBUG, |
4043 | "%s: chap corrupted response " |
4044 | "<%s id=0x%x len=%d" , |
4045 | ifp->if_xname, |
4046 | sppp_auth_type_name(PPP_CHAP, h->type), |
4047 | h->ident, ntohs(h->len)); |
4048 | if (len > 4) |
4049 | sppp_print_bytes((u_char *)(h + 1), |
4050 | len - 4); |
4051 | addlog(">\n" ); |
4052 | } |
4053 | break; |
4054 | } |
4055 | if (h->ident != sp->confid[IDX_CHAP]) { |
4056 | if (debug) |
4057 | log(LOG_DEBUG, |
4058 | "%s: chap dropping response for old ID " |
4059 | "(got %d, expected %d)\n" , |
4060 | ifp->if_xname, |
4061 | h->ident, sp->confid[IDX_CHAP]); |
4062 | break; |
4063 | } |
4064 | if (sp->hisauth.name != NULL && |
4065 | (name_len != sp->hisauth.name_len |
4066 | || memcmp(name, sp->hisauth.name, name_len) != 0)) { |
4067 | log(LOG_INFO, "%s: chap response, his name " , |
4068 | ifp->if_xname); |
4069 | sppp_print_string(name, name_len); |
4070 | addlog(" != expected " ); |
4071 | sppp_print_string(sp->hisauth.name, |
4072 | sp->hisauth.name_len); |
4073 | addlog("\n" ); |
4074 | goto chap_failure; |
4075 | } |
4076 | if (debug) { |
4077 | log(LOG_DEBUG, "%s: chap input(%s) " |
4078 | "<%s id=0x%x len=%d name=" , |
4079 | ifp->if_xname, |
4080 | sppp_state_name(sp->state[IDX_CHAP]), |
4081 | sppp_auth_type_name(PPP_CHAP, h->type), |
4082 | h->ident, ntohs(h->len)); |
4083 | sppp_print_string((char *)name, name_len); |
4084 | addlog(" value-size=%d value=" , value_len); |
4085 | sppp_print_bytes(value, value_len); |
4086 | addlog(">\n" ); |
4087 | } |
4088 | if (value_len != sizeof(sp->hisauth.challenge)) { |
4089 | if (debug) |
4090 | log(LOG_DEBUG, |
4091 | "%s: chap bad hash value length: " |
4092 | "%d bytes, should be %zu\n" , |
4093 | ifp->if_xname, value_len, |
4094 | sizeof(sp->hisauth.challenge)); |
4095 | goto chap_failure; |
4096 | } |
4097 | |
4098 | MD5Init(&ctx); |
4099 | MD5Update(&ctx, &h->ident, 1); |
4100 | MD5Update(&ctx, sp->hisauth.secret, sp->hisauth.secret_len); |
4101 | MD5Update(&ctx, sp->hisauth.challenge, sizeof(sp->hisauth.challenge)); |
4102 | MD5Final(digest, &ctx); |
4103 | |
4104 | #define FAILMSG "Failed..." |
4105 | #define SUCCMSG "Welcome!" |
4106 | |
4107 | if (value_len != sizeof digest || |
4108 | memcmp(digest, value, value_len) != 0) { |
4109 | chap_failure: |
4110 | /* action scn, tld */ |
4111 | x = splnet(); |
4112 | sp->pp_auth_failures++; |
4113 | splx(x); |
4114 | sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, |
4115 | sizeof(FAILMSG) - 1, (const u_char *)FAILMSG, |
4116 | 0); |
4117 | chap.tld(sp); |
4118 | break; |
4119 | } |
4120 | sp->pp_auth_failures = 0; |
4121 | /* action sca, perhaps tlu */ |
4122 | if (sp->state[IDX_CHAP] == STATE_REQ_SENT || |
4123 | sp->state[IDX_CHAP] == STATE_OPENED) |
4124 | sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, |
4125 | sizeof(SUCCMSG) - 1, (const u_char *)SUCCMSG, |
4126 | 0); |
4127 | if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { |
4128 | sppp_cp_change_state(&chap, sp, STATE_OPENED); |
4129 | chap.tlu(sp); |
4130 | } |
4131 | break; |
4132 | |
4133 | default: |
4134 | /* Unknown CHAP packet type -- ignore. */ |
4135 | if (debug) { |
4136 | log(LOG_DEBUG, "%s: chap unknown input(%s) " |
4137 | "<0x%x id=0x%xh len=%d" , |
4138 | ifp->if_xname, |
4139 | sppp_state_name(sp->state[IDX_CHAP]), |
4140 | h->type, h->ident, ntohs(h->len)); |
4141 | if (len > 4) |
4142 | sppp_print_bytes((u_char *)(h + 1), len - 4); |
4143 | addlog(">\n" ); |
4144 | } |
4145 | break; |
4146 | |
4147 | } |
4148 | } |
4149 | |
4150 | static void |
4151 | sppp_chap_init(struct sppp *sp) |
4152 | { |
4153 | /* Chap doesn't have STATE_INITIAL at all. */ |
4154 | sp->state[IDX_CHAP] = STATE_CLOSED; |
4155 | sp->fail_counter[IDX_CHAP] = 0; |
4156 | sp->pp_seq[IDX_CHAP] = 0; |
4157 | sp->pp_rseq[IDX_CHAP] = 0; |
4158 | callout_init(&sp->ch[IDX_CHAP], 0); |
4159 | } |
4160 | |
4161 | static void |
4162 | sppp_chap_open(struct sppp *sp) |
4163 | { |
4164 | if (sp->hisauth.proto == PPP_CHAP && |
4165 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { |
4166 | /* we are authenticator for CHAP, start it */ |
4167 | chap.scr(sp); |
4168 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; |
4169 | sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); |
4170 | } |
4171 | /* nothing to be done if we are peer, await a challenge */ |
4172 | } |
4173 | |
4174 | static void |
4175 | sppp_chap_close(struct sppp *sp) |
4176 | { |
4177 | if (sp->state[IDX_CHAP] != STATE_CLOSED) |
4178 | sppp_cp_change_state(&chap, sp, STATE_CLOSED); |
4179 | } |
4180 | |
4181 | static void |
4182 | sppp_chap_TO(void *cookie) |
4183 | { |
4184 | struct sppp *sp = (struct sppp *)cookie; |
4185 | STDDCL; |
4186 | int s; |
4187 | |
4188 | s = splnet(); |
4189 | if (debug) |
4190 | log(LOG_DEBUG, "%s: chap TO(%s) rst_counter = %d\n" , |
4191 | ifp->if_xname, |
4192 | sppp_state_name(sp->state[IDX_CHAP]), |
4193 | sp->rst_counter[IDX_CHAP]); |
4194 | |
4195 | if (--sp->rst_counter[IDX_CHAP] < 0) |
4196 | /* TO- event */ |
4197 | switch (sp->state[IDX_CHAP]) { |
4198 | case STATE_REQ_SENT: |
4199 | chap.tld(sp); |
4200 | sppp_cp_change_state(&chap, sp, STATE_CLOSED); |
4201 | break; |
4202 | } |
4203 | else |
4204 | /* TO+ (or TO*) event */ |
4205 | switch (sp->state[IDX_CHAP]) { |
4206 | case STATE_OPENED: |
4207 | /* TO* event */ |
4208 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; |
4209 | /* fall through */ |
4210 | case STATE_REQ_SENT: |
4211 | chap.scr(sp); |
4212 | /* sppp_cp_change_state() will restart the timer */ |
4213 | sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); |
4214 | break; |
4215 | } |
4216 | |
4217 | splx(s); |
4218 | } |
4219 | |
4220 | static void |
4221 | sppp_chap_tlu(struct sppp *sp) |
4222 | { |
4223 | STDDCL; |
4224 | int i, x; |
4225 | |
4226 | i = 0; |
4227 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; |
4228 | |
4229 | /* |
4230 | * Some broken CHAP implementations (Conware CoNet, firmware |
4231 | * 4.0.?) don't want to re-authenticate their CHAP once the |
4232 | * initial challenge-response exchange has taken place. |
4233 | * Provide for an option to avoid rechallenges. |
4234 | */ |
4235 | if ((sp->hisauth.flags & SPPP_AUTHFLAG_NORECHALLENGE) == 0) { |
4236 | /* |
4237 | * Compute the re-challenge timeout. This will yield |
4238 | * a number between 300 and 810 seconds. |
4239 | */ |
4240 | i = 300 + ((unsigned)(cprng_fast32() & 0xff00) >> 7); |
4241 | |
4242 | callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, sp); |
4243 | } |
4244 | |
4245 | if (debug) { |
4246 | log(LOG_DEBUG, |
4247 | "%s: chap %s, " , |
4248 | ifp->if_xname, |
4249 | sp->pp_phase == SPPP_PHASE_NETWORK? "reconfirmed" : "tlu" ); |
4250 | if ((sp->hisauth.flags & SPPP_AUTHFLAG_NORECHALLENGE) == 0) |
4251 | addlog("next re-challenge in %d seconds\n" , i); |
4252 | else |
4253 | addlog("re-challenging supressed\n" ); |
4254 | } |
4255 | |
4256 | x = splnet(); |
4257 | sp->pp_auth_failures = 0; |
4258 | /* indicate to LCP that we need to be closed down */ |
4259 | sp->lcp.protos |= (1 << IDX_CHAP); |
4260 | |
4261 | if (sp->pp_flags & PP_NEEDAUTH) { |
4262 | /* |
4263 | * Remote is authenticator, but his auth proto didn't |
4264 | * complete yet. Defer the transition to network |
4265 | * phase. |
4266 | */ |
4267 | splx(x); |
4268 | return; |
4269 | } |
4270 | splx(x); |
4271 | |
4272 | /* |
4273 | * If we are already in phase network, we are done here. This |
4274 | * is the case if this is a dummy tlu event after a re-challenge. |
4275 | */ |
4276 | if (sp->pp_phase != SPPP_PHASE_NETWORK) |
4277 | sppp_phase_network(sp); |
4278 | } |
4279 | |
4280 | static void |
4281 | sppp_chap_tld(struct sppp *sp) |
4282 | { |
4283 | STDDCL; |
4284 | |
4285 | if (debug) |
4286 | log(LOG_DEBUG, "%s: chap tld\n" , ifp->if_xname); |
4287 | callout_stop(&sp->ch[IDX_CHAP]); |
4288 | sp->lcp.protos &= ~(1 << IDX_CHAP); |
4289 | |
4290 | lcp.Close(sp); |
4291 | } |
4292 | |
4293 | static void |
4294 | sppp_chap_scr(struct sppp *sp) |
4295 | { |
4296 | uint32_t *ch; |
4297 | u_char clen = 4 * sizeof(uint32_t); |
4298 | |
4299 | if (sp->hisauth.name == NULL) { |
4300 | /* can't do anything useful */ |
4301 | printf("%s: chap starting without his name being set\n" , |
4302 | sp->pp_if.if_xname); |
4303 | return; |
4304 | } |
4305 | |
4306 | /* Compute random challenge. */ |
4307 | ch = (uint32_t *)sp->hisauth.challenge; |
4308 | cprng_strong(kern_cprng, ch, clen, 0); |
4309 | |
4310 | sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; |
4311 | |
4312 | sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], |
4313 | sizeof clen, (const char *)&clen, |
4314 | sizeof(sp->hisauth.challenge), sp->hisauth.challenge, |
4315 | 0); |
4316 | } |
4317 | |
4318 | /* |
4319 | *--------------------------------------------------------------------------* |
4320 | * * |
4321 | * The PAP implementation. * |
4322 | * * |
4323 | *--------------------------------------------------------------------------* |
4324 | */ |
4325 | /* |
4326 | * For PAP, we need to keep a little state also if we are the peer, not the |
4327 | * authenticator. This is since we don't get a request to authenticate, but |
4328 | * have to repeatedly authenticate ourself until we got a response (or the |
4329 | * retry counter is expired). |
4330 | */ |
4331 | |
4332 | /* |
4333 | * Handle incoming PAP packets. */ |
4334 | static void |
4335 | sppp_pap_input(struct sppp *sp, struct mbuf *m) |
4336 | { |
4337 | STDDCL; |
4338 | struct lcp_header *h; |
4339 | int len, x; |
4340 | u_char mlen; |
4341 | char *name, *secret; |
4342 | int name_len, secret_len; |
4343 | |
4344 | /* |
4345 | * Malicious input might leave this uninitialized, so |
4346 | * init to an impossible value. |
4347 | */ |
4348 | secret_len = -1; |
4349 | |
4350 | len = m->m_pkthdr.len; |
4351 | if (len < 5) { |
4352 | if (debug) |
4353 | log(LOG_DEBUG, |
4354 | "%s: pap invalid packet length: %d bytes\n" , |
4355 | ifp->if_xname, len); |
4356 | return; |
4357 | } |
4358 | h = mtod(m, struct lcp_header *); |
4359 | if (len > ntohs(h->len)) |
4360 | len = ntohs(h->len); |
4361 | switch (h->type) { |
4362 | /* PAP request is my authproto */ |
4363 | case PAP_REQ: |
4364 | if (sp->hisauth.name == NULL || sp->hisauth.secret == NULL) { |
4365 | /* can't do anything useful */ |
4366 | printf("%s: pap request without his name and his secret being set\n" , |
4367 | ifp->if_xname); |
4368 | break; |
4369 | } |
4370 | name = 1 + (u_char *)(h + 1); |
4371 | name_len = name[-1]; |
4372 | secret = name + name_len + 1; |
4373 | if (name_len > len - 6 || |
4374 | (secret_len = secret[-1]) > len - 6 - name_len) { |
4375 | if (debug) { |
4376 | log(LOG_DEBUG, "%s: pap corrupted input " |
4377 | "<%s id=0x%x len=%d" , |
4378 | ifp->if_xname, |
4379 | sppp_auth_type_name(PPP_PAP, h->type), |
4380 | h->ident, ntohs(h->len)); |
4381 | if (len > 4) |
4382 | sppp_print_bytes((u_char *)(h + 1), |
4383 | len - 4); |
4384 | addlog(">\n" ); |
4385 | } |
4386 | break; |
4387 | } |
4388 | if (debug) { |
4389 | log(LOG_DEBUG, "%s: pap input(%s) " |
4390 | "<%s id=0x%x len=%d name=" , |
4391 | ifp->if_xname, |
4392 | sppp_state_name(sp->state[IDX_PAP]), |
4393 | sppp_auth_type_name(PPP_PAP, h->type), |
4394 | h->ident, ntohs(h->len)); |
4395 | sppp_print_string((char *)name, name_len); |
4396 | addlog(" secret=" ); |
4397 | sppp_print_string((char *)secret, secret_len); |
4398 | addlog(">\n" ); |
4399 | } |
4400 | if (name_len != sp->hisauth.name_len || |
4401 | secret_len != sp->hisauth.secret_len || |
4402 | memcmp(name, sp->hisauth.name, name_len) != 0 || |
4403 | memcmp(secret, sp->hisauth.secret, secret_len) != 0) { |
4404 | /* action scn, tld */ |
4405 | sp->pp_auth_failures++; |
4406 | mlen = sizeof(FAILMSG) - 1; |
4407 | sppp_auth_send(&pap, sp, PAP_NAK, h->ident, |
4408 | sizeof mlen, (const char *)&mlen, |
4409 | sizeof(FAILMSG) - 1, (const u_char *)FAILMSG, |
4410 | 0); |
4411 | pap.tld(sp); |
4412 | break; |
4413 | } |
4414 | /* action sca, perhaps tlu */ |
4415 | if (sp->state[IDX_PAP] == STATE_REQ_SENT || |
4416 | sp->state[IDX_PAP] == STATE_OPENED) { |
4417 | mlen = sizeof(SUCCMSG) - 1; |
4418 | sppp_auth_send(&pap, sp, PAP_ACK, h->ident, |
4419 | sizeof mlen, (const char *)&mlen, |
4420 | sizeof(SUCCMSG) - 1, (const u_char *)SUCCMSG, |
4421 | 0); |
4422 | } |
4423 | if (sp->state[IDX_PAP] == STATE_REQ_SENT) { |
4424 | sppp_cp_change_state(&pap, sp, STATE_OPENED); |
4425 | pap.tlu(sp); |
4426 | } |
4427 | break; |
4428 | |
4429 | /* ack and nak are his authproto */ |
4430 | case PAP_ACK: |
4431 | callout_stop(&sp->pap_my_to_ch); |
4432 | if (debug) { |
4433 | log(LOG_DEBUG, "%s: pap success" , |
4434 | ifp->if_xname); |
4435 | name = 1 + (u_char *)(h + 1); |
4436 | name_len = name[-1]; |
4437 | if (len > 5 && name_len < len+4) { |
4438 | addlog(": " ); |
4439 | sppp_print_string(name, name_len); |
4440 | } |
4441 | addlog("\n" ); |
4442 | } |
4443 | x = splnet(); |
4444 | sp->pp_auth_failures = 0; |
4445 | sp->pp_flags &= ~PP_NEEDAUTH; |
4446 | if (sp->myauth.proto == PPP_PAP && |
4447 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && |
4448 | (sp->lcp.protos & (1 << IDX_PAP)) == 0) { |
4449 | /* |
4450 | * We are authenticator for PAP but didn't |
4451 | * complete yet. Leave it to tlu to proceed |
4452 | * to network phase. |
4453 | */ |
4454 | splx(x); |
4455 | break; |
4456 | } |
4457 | splx(x); |
4458 | sppp_phase_network(sp); |
4459 | break; |
4460 | |
4461 | case PAP_NAK: |
4462 | callout_stop(&sp->pap_my_to_ch); |
4463 | sp->pp_auth_failures++; |
4464 | if (debug) { |
4465 | log(LOG_INFO, "%s: pap failure" , |
4466 | ifp->if_xname); |
4467 | name = 1 + (u_char *)(h + 1); |
4468 | name_len = name[-1]; |
4469 | if (len > 5 && name_len < len+4) { |
4470 | addlog(": " ); |
4471 | sppp_print_string(name, name_len); |
4472 | } |
4473 | addlog("\n" ); |
4474 | } else |
4475 | log(LOG_INFO, "%s: pap failure\n" , |
4476 | ifp->if_xname); |
4477 | /* await LCP shutdown by authenticator */ |
4478 | break; |
4479 | |
4480 | default: |
4481 | /* Unknown PAP packet type -- ignore. */ |
4482 | if (debug) { |
4483 | log(LOG_DEBUG, "%s: pap corrupted input " |
4484 | "<0x%x id=0x%x len=%d" , |
4485 | ifp->if_xname, |
4486 | h->type, h->ident, ntohs(h->len)); |
4487 | if (len > 4) |
4488 | sppp_print_bytes((u_char *)(h + 1), len - 4); |
4489 | addlog(">\n" ); |
4490 | } |
4491 | break; |
4492 | |
4493 | } |
4494 | } |
4495 | |
4496 | static void |
4497 | sppp_pap_init(struct sppp *sp) |
4498 | { |
4499 | /* PAP doesn't have STATE_INITIAL at all. */ |
4500 | sp->state[IDX_PAP] = STATE_CLOSED; |
4501 | sp->fail_counter[IDX_PAP] = 0; |
4502 | sp->pp_seq[IDX_PAP] = 0; |
4503 | sp->pp_rseq[IDX_PAP] = 0; |
4504 | callout_init(&sp->ch[IDX_PAP], 0); |
4505 | callout_init(&sp->pap_my_to_ch, 0); |
4506 | } |
4507 | |
4508 | static void |
4509 | sppp_pap_open(struct sppp *sp) |
4510 | { |
4511 | if (sp->hisauth.proto == PPP_PAP && |
4512 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { |
4513 | /* we are authenticator for PAP, start our timer */ |
4514 | sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; |
4515 | sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); |
4516 | } |
4517 | if (sp->myauth.proto == PPP_PAP) { |
4518 | /* we are peer, send a request, and start a timer */ |
4519 | pap.scr(sp); |
4520 | callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout, |
4521 | sppp_pap_my_TO, sp); |
4522 | } |
4523 | } |
4524 | |
4525 | static void |
4526 | sppp_pap_close(struct sppp *sp) |
4527 | { |
4528 | if (sp->state[IDX_PAP] != STATE_CLOSED) |
4529 | sppp_cp_change_state(&pap, sp, STATE_CLOSED); |
4530 | } |
4531 | |
4532 | /* |
4533 | * That's the timeout routine if we are authenticator. Since the |
4534 | * authenticator is basically passive in PAP, we can't do much here. |
4535 | */ |
4536 | static void |
4537 | sppp_pap_TO(void *cookie) |
4538 | { |
4539 | struct sppp *sp = (struct sppp *)cookie; |
4540 | STDDCL; |
4541 | int s; |
4542 | |
4543 | s = splnet(); |
4544 | if (debug) |
4545 | log(LOG_DEBUG, "%s: pap TO(%s) rst_counter = %d\n" , |
4546 | ifp->if_xname, |
4547 | sppp_state_name(sp->state[IDX_PAP]), |
4548 | sp->rst_counter[IDX_PAP]); |
4549 | |
4550 | if (--sp->rst_counter[IDX_PAP] < 0) |
4551 | /* TO- event */ |
4552 | switch (sp->state[IDX_PAP]) { |
4553 | case STATE_REQ_SENT: |
4554 | pap.tld(sp); |
4555 | sppp_cp_change_state(&pap, sp, STATE_CLOSED); |
4556 | break; |
4557 | } |
4558 | else |
4559 | /* TO+ event, not very much we could do */ |
4560 | switch (sp->state[IDX_PAP]) { |
4561 | case STATE_REQ_SENT: |
4562 | /* sppp_cp_change_state() will restart the timer */ |
4563 | sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); |
4564 | break; |
4565 | } |
4566 | |
4567 | splx(s); |
4568 | } |
4569 | |
4570 | /* |
4571 | * That's the timeout handler if we are peer. Since the peer is active, |
4572 | * we need to retransmit our PAP request since it is apparently lost. |
4573 | * XXX We should impose a max counter. |
4574 | */ |
4575 | static void |
4576 | sppp_pap_my_TO(void *cookie) |
4577 | { |
4578 | struct sppp *sp = (struct sppp *)cookie; |
4579 | STDDCL; |
4580 | |
4581 | if (debug) |
4582 | log(LOG_DEBUG, "%s: pap peer TO\n" , |
4583 | ifp->if_xname); |
4584 | |
4585 | pap.scr(sp); |
4586 | } |
4587 | |
4588 | static void |
4589 | sppp_pap_tlu(struct sppp *sp) |
4590 | { |
4591 | STDDCL; |
4592 | int x; |
4593 | |
4594 | sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; |
4595 | |
4596 | if (debug) |
4597 | log(LOG_DEBUG, "%s: %s tlu\n" , |
4598 | ifp->if_xname, pap.name); |
4599 | |
4600 | x = splnet(); |
4601 | sp->pp_auth_failures = 0; |
4602 | /* indicate to LCP that we need to be closed down */ |
4603 | sp->lcp.protos |= (1 << IDX_PAP); |
4604 | |
4605 | if (sp->pp_flags & PP_NEEDAUTH) { |
4606 | /* |
4607 | * Remote is authenticator, but his auth proto didn't |
4608 | * complete yet. Defer the transition to network |
4609 | * phase. |
4610 | */ |
4611 | splx(x); |
4612 | return; |
4613 | } |
4614 | splx(x); |
4615 | sppp_phase_network(sp); |
4616 | } |
4617 | |
4618 | static void |
4619 | sppp_pap_tld(struct sppp *sp) |
4620 | { |
4621 | STDDCL; |
4622 | |
4623 | if (debug) |
4624 | log(LOG_DEBUG, "%s: pap tld\n" , ifp->if_xname); |
4625 | callout_stop(&sp->ch[IDX_PAP]); |
4626 | callout_stop(&sp->pap_my_to_ch); |
4627 | sp->lcp.protos &= ~(1 << IDX_PAP); |
4628 | |
4629 | lcp.Close(sp); |
4630 | } |
4631 | |
4632 | static void |
4633 | sppp_pap_scr(struct sppp *sp) |
4634 | { |
4635 | u_char idlen, pwdlen; |
4636 | |
4637 | if (sp->myauth.secret == NULL || sp->myauth.name == NULL) { |
4638 | /* can't do anything useful */ |
4639 | printf("%s: pap starting without my name and secret being set\n" , |
4640 | sp->pp_if.if_xname); |
4641 | return; |
4642 | } |
4643 | |
4644 | sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; |
4645 | pwdlen = sp->myauth.secret_len; |
4646 | idlen = sp->myauth.name_len; |
4647 | |
4648 | sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], |
4649 | sizeof idlen, (const char *)&idlen, |
4650 | idlen, sp->myauth.name, |
4651 | sizeof pwdlen, (const char *)&pwdlen, |
4652 | pwdlen, sp->myauth.secret, |
4653 | 0); |
4654 | } |
4655 | |
4656 | /* |
4657 | * Random miscellaneous functions. |
4658 | */ |
4659 | |
4660 | /* |
4661 | * Send a PAP or CHAP proto packet. |
4662 | * |
4663 | * Varadic function, each of the elements for the ellipsis is of type |
4664 | * ``size_t mlen, const u_char *msg''. Processing will stop iff |
4665 | * mlen == 0. |
4666 | * NOTE: never declare variadic functions with types subject to type |
4667 | * promotion (i.e. u_char). This is asking for big trouble depending |
4668 | * on the architecture you are on... |
4669 | */ |
4670 | |
4671 | static void |
4672 | sppp_auth_send(const struct cp *cp, struct sppp *sp, |
4673 | unsigned int type, unsigned int id, |
4674 | ...) |
4675 | { |
4676 | STDDCL; |
4677 | struct lcp_header *lh; |
4678 | struct mbuf *m; |
4679 | u_char *p; |
4680 | int len; |
4681 | size_t pkthdrlen; |
4682 | unsigned int mlen; |
4683 | const char *msg; |
4684 | va_list ap; |
4685 | |
4686 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
4687 | if (! m) |
4688 | return; |
4689 | m_reset_rcvif(m); |
4690 | |
4691 | if (sp->pp_flags & PP_NOFRAMING) { |
4692 | *mtod(m, uint16_t *) = htons(cp->proto); |
4693 | pkthdrlen = 2; |
4694 | lh = (struct lcp_header *)(mtod(m, uint8_t *)+2); |
4695 | } else { |
4696 | struct ppp_header *h; |
4697 | h = mtod(m, struct ppp_header *); |
4698 | h->address = PPP_ALLSTATIONS; /* broadcast address */ |
4699 | h->control = PPP_UI; /* Unnumbered Info */ |
4700 | h->protocol = htons(cp->proto); |
4701 | pkthdrlen = PPP_HEADER_LEN; |
4702 | |
4703 | lh = (struct lcp_header *)(h + 1); |
4704 | } |
4705 | |
4706 | lh->type = type; |
4707 | lh->ident = id; |
4708 | p = (u_char *)(lh + 1); |
4709 | |
4710 | va_start(ap, id); |
4711 | len = 0; |
4712 | |
4713 | while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { |
4714 | msg = va_arg(ap, const char *); |
4715 | len += mlen; |
4716 | if (len > MHLEN - pkthdrlen - LCP_HEADER_LEN) { |
4717 | va_end(ap); |
4718 | m_freem(m); |
4719 | return; |
4720 | } |
4721 | |
4722 | memcpy(p, msg, mlen); |
4723 | p += mlen; |
4724 | } |
4725 | va_end(ap); |
4726 | |
4727 | m->m_pkthdr.len = m->m_len = pkthdrlen + LCP_HEADER_LEN + len; |
4728 | lh->len = htons(LCP_HEADER_LEN + len); |
4729 | |
4730 | if (debug) { |
4731 | log(LOG_DEBUG, "%s: %s output <%s id=0x%x len=%d" , |
4732 | ifp->if_xname, cp->name, |
4733 | sppp_auth_type_name(cp->proto, lh->type), |
4734 | lh->ident, ntohs(lh->len)); |
4735 | if (len) |
4736 | sppp_print_bytes((u_char *)(lh + 1), len); |
4737 | addlog(">\n" ); |
4738 | } |
4739 | if (IF_QFULL(&sp->pp_cpq)) { |
4740 | IF_DROP(&sp->pp_fastq); |
4741 | IF_DROP(&ifp->if_snd); |
4742 | m_freem(m); |
4743 | ++ifp->if_oerrors; |
4744 | return; |
4745 | } else |
4746 | IF_ENQUEUE(&sp->pp_cpq, m); |
4747 | if (! (ifp->if_flags & IFF_OACTIVE)) |
4748 | if_start_lock(ifp); |
4749 | ifp->if_obytes += m->m_pkthdr.len + 3; |
4750 | } |
4751 | |
4752 | /* |
4753 | * Send keepalive packets, every 10 seconds. |
4754 | */ |
4755 | static void |
4756 | sppp_keepalive(void *dummy) |
4757 | { |
4758 | struct sppp *sp; |
4759 | int s; |
4760 | time_t now; |
4761 | |
4762 | s = splnet(); |
4763 | now = time_uptime; |
4764 | for (sp=spppq; sp; sp=sp->pp_next) { |
4765 | struct ifnet *ifp = &sp->pp_if; |
4766 | |
4767 | /* check idle timeout */ |
4768 | if ((sp->pp_idle_timeout != 0) && (ifp->if_flags & IFF_RUNNING) |
4769 | && (sp->pp_phase == SPPP_PHASE_NETWORK)) { |
4770 | /* idle timeout is enabled for this interface */ |
4771 | if ((now-sp->pp_last_activity) >= sp->pp_idle_timeout) { |
4772 | if (ifp->if_flags & IFF_DEBUG) |
4773 | printf("%s: no activity for %lu seconds\n" , |
4774 | sp->pp_if.if_xname, |
4775 | (unsigned long)(now-sp->pp_last_activity)); |
4776 | lcp.Close(sp); |
4777 | continue; |
4778 | } |
4779 | } |
4780 | |
4781 | /* Keepalive mode disabled or channel down? */ |
4782 | if (! (sp->pp_flags & PP_KEEPALIVE) || |
4783 | ! (ifp->if_flags & IFF_RUNNING)) |
4784 | continue; |
4785 | |
4786 | /* No keepalive in PPP mode if LCP not opened yet. */ |
4787 | if (! (sp->pp_flags & PP_CISCO) && |
4788 | sp->pp_phase < SPPP_PHASE_AUTHENTICATE) |
4789 | continue; |
4790 | |
4791 | /* No echo reply, but maybe user data passed through? */ |
4792 | if ((now - sp->pp_last_receive) < sp->pp_max_noreceive) { |
4793 | sp->pp_alivecnt = 0; |
4794 | continue; |
4795 | } |
4796 | |
4797 | if (sp->pp_alivecnt >= sp->pp_maxalive) { |
4798 | /* No keepalive packets got. Stop the interface. */ |
4799 | if_down (ifp); |
4800 | IF_PURGE(&sp->pp_cpq); |
4801 | if (! (sp->pp_flags & PP_CISCO)) { |
4802 | printf("%s: LCP keepalive timed out, going to restart the connection\n" , |
4803 | ifp->if_xname); |
4804 | sp->pp_alivecnt = 0; |
4805 | |
4806 | /* we are down, close all open protocols */ |
4807 | lcp.Close(sp); |
4808 | |
4809 | /* And now prepare LCP to reestablish the link, if configured to do so. */ |
4810 | sppp_cp_change_state(&lcp, sp, STATE_STOPPED); |
4811 | |
4812 | /* Close connection immediately, completition of this |
4813 | * will summon the magic needed to reestablish it. */ |
4814 | if (sp->pp_tlf) |
4815 | sp->pp_tlf(sp); |
4816 | continue; |
4817 | } |
4818 | } |
4819 | if (sp->pp_alivecnt < sp->pp_maxalive) |
4820 | ++sp->pp_alivecnt; |
4821 | if (sp->pp_flags & PP_CISCO) |
4822 | sppp_cisco_send(sp, CISCO_KEEPALIVE_REQ, |
4823 | ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); |
4824 | else if (sp->pp_phase >= SPPP_PHASE_AUTHENTICATE) { |
4825 | int32_t nmagic = htonl(sp->lcp.magic); |
4826 | sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; |
4827 | sppp_cp_send(sp, PPP_LCP, ECHO_REQ, |
4828 | sp->lcp.echoid, 4, &nmagic); |
4829 | } |
4830 | } |
4831 | splx(s); |
4832 | callout_reset(&keepalive_ch, hz * LCP_KEEPALIVE_INTERVAL, sppp_keepalive, NULL); |
4833 | } |
4834 | |
4835 | #ifdef INET |
4836 | /* |
4837 | * Get both IP addresses. |
4838 | */ |
4839 | static void |
4840 | sppp_get_ip_addrs(struct sppp *sp, uint32_t *src, uint32_t *dst, uint32_t *srcmask) |
4841 | { |
4842 | struct ifnet *ifp = &sp->pp_if; |
4843 | struct ifaddr *ifa; |
4844 | struct sockaddr_in *si, *sm; |
4845 | uint32_t ssrc, ddst; |
4846 | |
4847 | sm = NULL; |
4848 | ssrc = ddst = 0; |
4849 | /* |
4850 | * Pick the first AF_INET address from the list, |
4851 | * aliases don't make any sense on a p2p link anyway. |
4852 | */ |
4853 | si = 0; |
4854 | IFADDR_READER_FOREACH(ifa, ifp) { |
4855 | if (ifa->ifa_addr->sa_family == AF_INET) { |
4856 | si = (struct sockaddr_in *)ifa->ifa_addr; |
4857 | sm = (struct sockaddr_in *)ifa->ifa_netmask; |
4858 | if (si) |
4859 | break; |
4860 | } |
4861 | } |
4862 | if (ifa) { |
4863 | if (si && si->sin_addr.s_addr) { |
4864 | ssrc = si->sin_addr.s_addr; |
4865 | if (srcmask) |
4866 | *srcmask = ntohl(sm->sin_addr.s_addr); |
4867 | } |
4868 | |
4869 | si = (struct sockaddr_in *)ifa->ifa_dstaddr; |
4870 | if (si && si->sin_addr.s_addr) |
4871 | ddst = si->sin_addr.s_addr; |
4872 | } |
4873 | |
4874 | if (dst) *dst = ntohl(ddst); |
4875 | if (src) *src = ntohl(ssrc); |
4876 | } |
4877 | |
4878 | /* |
4879 | * Set IP addresses. Must be called at splnet. |
4880 | * If an address is 0, leave it the way it is. |
4881 | */ |
4882 | static void |
4883 | sppp_set_ip_addrs(struct sppp *sp, uint32_t myaddr, uint32_t hisaddr) |
4884 | { |
4885 | STDDCL; |
4886 | struct ifaddr *ifa; |
4887 | struct sockaddr_in *si, *dest; |
4888 | |
4889 | /* |
4890 | * Pick the first AF_INET address from the list, |
4891 | * aliases don't make any sense on a p2p link anyway. |
4892 | */ |
4893 | |
4894 | IFADDR_READER_FOREACH(ifa, ifp) { |
4895 | if (ifa->ifa_addr->sa_family == AF_INET) { |
4896 | si = (struct sockaddr_in *)ifa->ifa_addr; |
4897 | dest = (struct sockaddr_in *)ifa->ifa_dstaddr; |
4898 | goto found; |
4899 | } |
4900 | } |
4901 | return; |
4902 | |
4903 | found: |
4904 | { |
4905 | int error; |
4906 | struct sockaddr_in new_sin = *si; |
4907 | struct sockaddr_in new_dst = *dest; |
4908 | |
4909 | if (myaddr != 0) |
4910 | new_sin.sin_addr.s_addr = htonl(myaddr); |
4911 | if (hisaddr != 0) { |
4912 | new_dst.sin_addr.s_addr = htonl(hisaddr); |
4913 | if (new_dst.sin_addr.s_addr != dest->sin_addr.s_addr) |
4914 | sp->ipcp.saved_hisaddr = dest->sin_addr.s_addr; |
4915 | } |
4916 | |
4917 | LIST_REMOVE(ifatoia(ifa), ia_hash); |
4918 | IN_ADDRHASH_WRITER_REMOVE(ifatoia(ifa)); |
4919 | #ifdef NET_MPSAFE |
4920 | pserialize_perform(in_ifaddrhash_psz); |
4921 | #endif |
4922 | IN_ADDRHASH_ENTRY_DESTROY(ifatoia(ifa)); |
4923 | |
4924 | error = in_ifinit(ifp, ifatoia(ifa), &new_sin, &new_dst, 0); |
4925 | |
4926 | IN_ADDRHASH_ENTRY_INIT(ifatoia(ifa)); |
4927 | LIST_INSERT_HEAD(&IN_IFADDR_HASH(ifatoia(ifa)->ia_addr.sin_addr.s_addr), |
4928 | ifatoia(ifa), ia_hash); |
4929 | IN_ADDRHASH_WRITER_INSERT_HEAD(ifatoia(ifa)); |
4930 | |
4931 | if (debug && error) |
4932 | { |
4933 | log(LOG_DEBUG, "%s: %s: in_ifinit failed, error=%d\n" , |
4934 | ifp->if_xname, __func__, error); |
4935 | } |
4936 | if (!error) { |
4937 | (void)pfil_run_hooks(if_pfil, |
4938 | (struct mbuf **)SIOCAIFADDR, ifp, PFIL_IFADDR); |
4939 | } |
4940 | } |
4941 | } |
4942 | |
4943 | /* |
4944 | * Clear IP addresses. Must be called at splnet. |
4945 | */ |
4946 | static void |
4947 | sppp_clear_ip_addrs(struct sppp *sp) |
4948 | { |
4949 | STDDCL; |
4950 | struct ifaddr *ifa; |
4951 | struct sockaddr_in *si, *dest; |
4952 | |
4953 | uint32_t remote; |
4954 | if (sp->ipcp.flags & IPCP_HISADDR_DYN) |
4955 | remote = sp->ipcp.saved_hisaddr; |
4956 | else |
4957 | sppp_get_ip_addrs(sp, 0, &remote, 0); |
4958 | |
4959 | /* |
4960 | * Pick the first AF_INET address from the list, |
4961 | * aliases don't make any sense on a p2p link anyway. |
4962 | */ |
4963 | |
4964 | IFADDR_READER_FOREACH(ifa, ifp) { |
4965 | if (ifa->ifa_addr->sa_family == AF_INET) { |
4966 | si = (struct sockaddr_in *)ifa->ifa_addr; |
4967 | dest = (struct sockaddr_in *)ifa->ifa_dstaddr; |
4968 | goto found; |
4969 | } |
4970 | } |
4971 | return; |
4972 | |
4973 | found: |
4974 | { |
4975 | struct sockaddr_in new_sin = *si; |
4976 | struct sockaddr_in new_dst = *dest; |
4977 | int error; |
4978 | |
4979 | if (sp->ipcp.flags & IPCP_MYADDR_DYN) |
4980 | new_sin.sin_addr.s_addr = 0; |
4981 | if (sp->ipcp.flags & IPCP_HISADDR_DYN) |
4982 | new_dst.sin_addr.s_addr = sp->ipcp.saved_hisaddr; |
4983 | |
4984 | LIST_REMOVE(ifatoia(ifa), ia_hash); |
4985 | IN_ADDRHASH_WRITER_REMOVE(ifatoia(ifa)); |
4986 | #ifdef NET_MPSAFE |
4987 | pserialize_perform(in_ifaddrhash_psz); |
4988 | #endif |
4989 | IN_ADDRHASH_ENTRY_DESTROY(ifatoia(ifa)); |
4990 | |
4991 | error = in_ifinit(ifp, ifatoia(ifa), &new_sin, &new_dst, 0); |
4992 | |
4993 | IN_ADDRHASH_ENTRY_INIT(ifatoia(ifa)); |
4994 | LIST_INSERT_HEAD(&IN_IFADDR_HASH(ifatoia(ifa)->ia_addr.sin_addr.s_addr), |
4995 | ifatoia(ifa), ia_hash); |
4996 | IN_ADDRHASH_WRITER_INSERT_HEAD(ifatoia(ifa)); |
4997 | |
4998 | if (debug && error) |
4999 | { |
5000 | log(LOG_DEBUG, "%s: %s: in_ifinit failed, error=%d\n" , |
5001 | ifp->if_xname, __func__, error); |
5002 | } |
5003 | if (!error) { |
5004 | (void)pfil_run_hooks(if_pfil, |
5005 | (struct mbuf **)SIOCAIFADDR, ifp, PFIL_IFADDR); |
5006 | } |
5007 | } |
5008 | } |
5009 | #endif |
5010 | |
5011 | #ifdef INET6 |
5012 | /* |
5013 | * Get both IPv6 addresses. |
5014 | */ |
5015 | static void |
5016 | sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, |
5017 | struct in6_addr *srcmask) |
5018 | { |
5019 | struct ifnet *ifp = &sp->pp_if; |
5020 | struct ifaddr *ifa; |
5021 | struct sockaddr_in6 *si, *sm; |
5022 | struct in6_addr ssrc, ddst; |
5023 | |
5024 | sm = NULL; |
5025 | memset(&ssrc, 0, sizeof(ssrc)); |
5026 | memset(&ddst, 0, sizeof(ddst)); |
5027 | /* |
5028 | * Pick the first link-local AF_INET6 address from the list, |
5029 | * aliases don't make any sense on a p2p link anyway. |
5030 | */ |
5031 | si = 0; |
5032 | IFADDR_READER_FOREACH(ifa, ifp) |
5033 | if (ifa->ifa_addr->sa_family == AF_INET6) { |
5034 | si = (struct sockaddr_in6 *)ifa->ifa_addr; |
5035 | sm = (struct sockaddr_in6 *)ifa->ifa_netmask; |
5036 | if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) |
5037 | break; |
5038 | } |
5039 | if (ifa) { |
5040 | if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { |
5041 | memcpy(&ssrc, &si->sin6_addr, sizeof(ssrc)); |
5042 | if (srcmask) { |
5043 | memcpy(srcmask, &sm->sin6_addr, |
5044 | sizeof(*srcmask)); |
5045 | } |
5046 | } |
5047 | |
5048 | si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; |
5049 | if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) |
5050 | memcpy(&ddst, &si->sin6_addr, sizeof(ddst)); |
5051 | } |
5052 | |
5053 | if (dst) |
5054 | memcpy(dst, &ddst, sizeof(*dst)); |
5055 | if (src) |
5056 | memcpy(src, &ssrc, sizeof(*src)); |
5057 | } |
5058 | |
5059 | #ifdef IPV6CP_MYIFID_DYN |
5060 | /* |
5061 | * Generate random ifid. |
5062 | */ |
5063 | static void |
5064 | sppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) |
5065 | { |
5066 | /* TBD */ |
5067 | } |
5068 | |
5069 | /* |
5070 | * Set my IPv6 address. Must be called at splnet. |
5071 | */ |
5072 | static void |
5073 | sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) |
5074 | { |
5075 | STDDCL; |
5076 | struct ifaddr *ifa; |
5077 | struct sockaddr_in6 *sin6; |
5078 | |
5079 | /* |
5080 | * Pick the first link-local AF_INET6 address from the list, |
5081 | * aliases don't make any sense on a p2p link anyway. |
5082 | */ |
5083 | |
5084 | sin6 = NULL; |
5085 | IFADDR_READER_FOREACH(ifa, ifp) |
5086 | { |
5087 | if (ifa->ifa_addr->sa_family == AF_INET6) |
5088 | { |
5089 | sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; |
5090 | if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) |
5091 | break; |
5092 | } |
5093 | } |
5094 | |
5095 | if (ifa && sin6) |
5096 | { |
5097 | int error; |
5098 | struct sockaddr_in6 new_sin6 = *sin6; |
5099 | |
5100 | memcpy(&new_sin6.sin6_addr, src, sizeof(new_sin6.sin6_addr)); |
5101 | error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); |
5102 | if (debug && error) |
5103 | { |
5104 | log(LOG_DEBUG, "%s: %s: in6_ifinit failed, error=%d\n" , |
5105 | ifp->if_xname, __func__, error); |
5106 | } |
5107 | if (!error) { |
5108 | (void)pfil_run_hooks(if_pfil, |
5109 | (struct mbuf **)SIOCAIFADDR_IN6, ifp, PFIL_IFADDR); |
5110 | } |
5111 | } |
5112 | } |
5113 | #endif |
5114 | |
5115 | /* |
5116 | * Suggest a candidate address to be used by peer. |
5117 | */ |
5118 | static void |
5119 | sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) |
5120 | { |
5121 | struct in6_addr myaddr; |
5122 | struct timeval tv; |
5123 | |
5124 | sppp_get_ip6_addrs(sp, &myaddr, 0, 0); |
5125 | |
5126 | myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ |
5127 | microtime(&tv); |
5128 | if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { |
5129 | myaddr.s6_addr[14] ^= 0xff; |
5130 | myaddr.s6_addr[15] ^= 0xff; |
5131 | } else { |
5132 | myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); |
5133 | myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); |
5134 | } |
5135 | if (suggest) |
5136 | memcpy(suggest, &myaddr, sizeof(myaddr)); |
5137 | } |
5138 | #endif /*INET6*/ |
5139 | |
5140 | /* |
5141 | * Process ioctl requests specific to the PPP interface. |
5142 | * Permissions have already been checked. |
5143 | */ |
5144 | static int |
5145 | sppp_params(struct sppp *sp, u_long cmd, void *data) |
5146 | { |
5147 | switch (cmd) { |
5148 | case SPPPGETAUTHCFG: |
5149 | { |
5150 | struct spppauthcfg *cfg = (struct spppauthcfg *)data; |
5151 | int error; |
5152 | size_t len; |
5153 | |
5154 | cfg->myauthflags = sp->myauth.flags; |
5155 | cfg->hisauthflags = sp->hisauth.flags; |
5156 | strlcpy(cfg->ifname, sp->pp_if.if_xname, sizeof(cfg->ifname)); |
5157 | cfg->hisauth = 0; |
5158 | if (sp->hisauth.proto) |
5159 | cfg->hisauth = (sp->hisauth.proto == PPP_PAP) ? SPPP_AUTHPROTO_PAP : SPPP_AUTHPROTO_CHAP; |
5160 | cfg->myauth = 0; |
5161 | if (sp->myauth.proto) |
5162 | cfg->myauth = (sp->myauth.proto == PPP_PAP) ? SPPP_AUTHPROTO_PAP : SPPP_AUTHPROTO_CHAP; |
5163 | if (cfg->myname_length == 0) { |
5164 | if (sp->myauth.name != NULL) |
5165 | cfg->myname_length = sp->myauth.name_len + 1; |
5166 | } else { |
5167 | if (sp->myauth.name == NULL) { |
5168 | cfg->myname_length = 0; |
5169 | } else { |
5170 | len = sp->myauth.name_len + 1; |
5171 | if (cfg->myname_length < len) |
5172 | return (ENAMETOOLONG); |
5173 | error = copyout(sp->myauth.name, cfg->myname, len); |
5174 | if (error) return error; |
5175 | } |
5176 | } |
5177 | if (cfg->hisname_length == 0) { |
5178 | if (sp->hisauth.name != NULL) |
5179 | cfg->hisname_length = sp->hisauth.name_len + 1; |
5180 | } else { |
5181 | if (sp->hisauth.name == NULL) { |
5182 | cfg->hisname_length = 0; |
5183 | } else { |
5184 | len = sp->hisauth.name_len + 1; |
5185 | if (cfg->hisname_length < len) |
5186 | return (ENAMETOOLONG); |
5187 | error = copyout(sp->hisauth.name, cfg->hisname, len); |
5188 | if (error) return error; |
5189 | } |
5190 | } |
5191 | } |
5192 | break; |
5193 | case SPPPSETAUTHCFG: |
5194 | { |
5195 | struct spppauthcfg *cfg = (struct spppauthcfg *)data; |
5196 | int error; |
5197 | |
5198 | if (sp->myauth.name) { |
5199 | free(sp->myauth.name, M_DEVBUF); |
5200 | sp->myauth.name = NULL; |
5201 | } |
5202 | if (sp->myauth.secret) { |
5203 | free(sp->myauth.secret, M_DEVBUF); |
5204 | sp->myauth.secret = NULL; |
5205 | } |
5206 | if (sp->hisauth.name) { |
5207 | free(sp->hisauth.name, M_DEVBUF); |
5208 | sp->hisauth.name = NULL; |
5209 | } |
5210 | if (sp->hisauth.secret) { |
5211 | free(sp->hisauth.secret, M_DEVBUF); |
5212 | sp->hisauth.secret = NULL; |
5213 | } |
5214 | |
5215 | if (cfg->hisname != NULL && cfg->hisname_length > 0) { |
5216 | if (cfg->hisname_length >= MCLBYTES) |
5217 | return (ENAMETOOLONG); |
5218 | sp->hisauth.name = malloc(cfg->hisname_length, M_DEVBUF, M_WAITOK); |
5219 | error = copyin(cfg->hisname, sp->hisauth.name, cfg->hisname_length); |
5220 | if (error) { |
5221 | free(sp->hisauth.name, M_DEVBUF); |
5222 | sp->hisauth.name = NULL; |
5223 | return error; |
5224 | } |
5225 | sp->hisauth.name_len = cfg->hisname_length - 1; |
5226 | sp->hisauth.name[sp->hisauth.name_len] = 0; |
5227 | } |
5228 | if (cfg->hissecret != NULL && cfg->hissecret_length > 0) { |
5229 | if (cfg->hissecret_length >= MCLBYTES) |
5230 | return (ENAMETOOLONG); |
5231 | sp->hisauth.secret = malloc(cfg->hissecret_length, M_DEVBUF, M_WAITOK); |
5232 | error = copyin(cfg->hissecret, sp->hisauth.secret, cfg->hissecret_length); |
5233 | if (error) { |
5234 | free(sp->hisauth.secret, M_DEVBUF); |
5235 | sp->hisauth.secret = NULL; |
5236 | return error; |
5237 | } |
5238 | sp->hisauth.secret_len = cfg->hissecret_length - 1; |
5239 | sp->hisauth.secret[sp->hisauth.secret_len] = 0; |
5240 | } |
5241 | if (cfg->myname != NULL && cfg->myname_length > 0) { |
5242 | if (cfg->myname_length >= MCLBYTES) |
5243 | return (ENAMETOOLONG); |
5244 | sp->myauth.name = malloc(cfg->myname_length, M_DEVBUF, M_WAITOK); |
5245 | error = copyin(cfg->myname, sp->myauth.name, cfg->myname_length); |
5246 | if (error) { |
5247 | free(sp->myauth.name, M_DEVBUF); |
5248 | sp->myauth.name = NULL; |
5249 | return error; |
5250 | } |
5251 | sp->myauth.name_len = cfg->myname_length - 1; |
5252 | sp->myauth.name[sp->myauth.name_len] = 0; |
5253 | } |
5254 | if (cfg->mysecret != NULL && cfg->mysecret_length > 0) { |
5255 | if (cfg->mysecret_length >= MCLBYTES) |
5256 | return (ENAMETOOLONG); |
5257 | sp->myauth.secret = malloc(cfg->mysecret_length, M_DEVBUF, M_WAITOK); |
5258 | error = copyin(cfg->mysecret, sp->myauth.secret, cfg->mysecret_length); |
5259 | if (error) { |
5260 | free(sp->myauth.secret, M_DEVBUF); |
5261 | sp->myauth.secret = NULL; |
5262 | return error; |
5263 | } |
5264 | sp->myauth.secret_len = cfg->mysecret_length - 1; |
5265 | sp->myauth.secret[sp->myauth.secret_len] = 0; |
5266 | } |
5267 | sp->myauth.flags = cfg->myauthflags; |
5268 | if (cfg->myauth) |
5269 | sp->myauth.proto = (cfg->myauth == SPPP_AUTHPROTO_PAP) ? PPP_PAP : PPP_CHAP; |
5270 | sp->hisauth.flags = cfg->hisauthflags; |
5271 | if (cfg->hisauth) |
5272 | sp->hisauth.proto = (cfg->hisauth == SPPP_AUTHPROTO_PAP) ? PPP_PAP : PPP_CHAP; |
5273 | sp->pp_auth_failures = 0; |
5274 | if (sp->hisauth.proto != 0) |
5275 | sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); |
5276 | else |
5277 | sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); |
5278 | } |
5279 | break; |
5280 | case SPPPGETLCPCFG: |
5281 | { |
5282 | struct sppplcpcfg *lcpp = (struct sppplcpcfg *)data; |
5283 | lcpp->lcp_timeout = sp->lcp.timeout; |
5284 | } |
5285 | break; |
5286 | case SPPPSETLCPCFG: |
5287 | { |
5288 | struct sppplcpcfg *lcpp = (struct sppplcpcfg *)data; |
5289 | sp->lcp.timeout = lcpp->lcp_timeout; |
5290 | } |
5291 | break; |
5292 | case SPPPGETSTATUS: |
5293 | { |
5294 | struct spppstatus *status = (struct spppstatus *)data; |
5295 | status->phase = sp->pp_phase; |
5296 | } |
5297 | break; |
5298 | case SPPPGETSTATUSNCP: |
5299 | { |
5300 | struct spppstatusncp *status = (struct spppstatusncp *)data; |
5301 | status->phase = sp->pp_phase; |
5302 | status->ncpup = sppp_ncp_check(sp); |
5303 | } |
5304 | break; |
5305 | case SPPPGETIDLETO: |
5306 | { |
5307 | struct spppidletimeout *to = (struct spppidletimeout *)data; |
5308 | to->idle_seconds = sp->pp_idle_timeout; |
5309 | } |
5310 | break; |
5311 | case SPPPSETIDLETO: |
5312 | { |
5313 | struct spppidletimeout *to = (struct spppidletimeout *)data; |
5314 | sp->pp_idle_timeout = to->idle_seconds; |
5315 | } |
5316 | break; |
5317 | case SPPPSETAUTHFAILURE: |
5318 | { |
5319 | struct spppauthfailuresettings *afsettings = (struct spppauthfailuresettings *)data; |
5320 | sp->pp_max_auth_fail = afsettings->max_failures; |
5321 | sp->pp_auth_failures = 0; |
5322 | } |
5323 | break; |
5324 | case SPPPGETAUTHFAILURES: |
5325 | { |
5326 | struct spppauthfailurestats *stats = (struct spppauthfailurestats *)data; |
5327 | stats->auth_failures = sp->pp_auth_failures; |
5328 | stats->max_failures = sp->pp_max_auth_fail; |
5329 | } |
5330 | break; |
5331 | case SPPPSETDNSOPTS: |
5332 | { |
5333 | struct spppdnssettings *req = (struct spppdnssettings *)data; |
5334 | sp->query_dns = req->query_dns & 3; |
5335 | } |
5336 | break; |
5337 | case SPPPGETDNSOPTS: |
5338 | { |
5339 | struct spppdnssettings *req = (struct spppdnssettings *)data; |
5340 | req->query_dns = sp->query_dns; |
5341 | } |
5342 | break; |
5343 | case SPPPGETDNSADDRS: |
5344 | { |
5345 | struct spppdnsaddrs *addrs = (struct spppdnsaddrs *)data; |
5346 | memcpy(&addrs->dns, &sp->dns_addrs, sizeof addrs->dns); |
5347 | } |
5348 | break; |
5349 | case SPPPGETKEEPALIVE: |
5350 | { |
5351 | struct spppkeepalivesettings *settings = |
5352 | (struct spppkeepalivesettings*)data; |
5353 | settings->maxalive = sp->pp_maxalive; |
5354 | settings->max_noreceive = sp->pp_max_noreceive; |
5355 | } |
5356 | break; |
5357 | case SPPPSETKEEPALIVE: |
5358 | { |
5359 | struct spppkeepalivesettings *settings = |
5360 | (struct spppkeepalivesettings*)data; |
5361 | sp->pp_maxalive = settings->maxalive; |
5362 | sp->pp_max_noreceive = settings->max_noreceive; |
5363 | } |
5364 | break; |
5365 | #if defined(COMPAT_50) || defined(MODULAR) |
5366 | case __SPPPGETIDLETO50: |
5367 | { |
5368 | struct spppidletimeout50 *to = (struct spppidletimeout50 *)data; |
5369 | to->idle_seconds = (uint32_t)sp->pp_idle_timeout; |
5370 | } |
5371 | break; |
5372 | case __SPPPSETIDLETO50: |
5373 | { |
5374 | struct spppidletimeout50 *to = (struct spppidletimeout50 *)data; |
5375 | sp->pp_idle_timeout = (time_t)to->idle_seconds; |
5376 | } |
5377 | break; |
5378 | case __SPPPGETKEEPALIVE50: |
5379 | { |
5380 | struct spppkeepalivesettings50 *settings = |
5381 | (struct spppkeepalivesettings50*)data; |
5382 | settings->maxalive = sp->pp_maxalive; |
5383 | settings->max_noreceive = (uint32_t)sp->pp_max_noreceive; |
5384 | } |
5385 | break; |
5386 | case __SPPPSETKEEPALIVE50: |
5387 | { |
5388 | struct spppkeepalivesettings50 *settings = |
5389 | (struct spppkeepalivesettings50*)data; |
5390 | sp->pp_maxalive = settings->maxalive; |
5391 | sp->pp_max_noreceive = (time_t)settings->max_noreceive; |
5392 | } |
5393 | break; |
5394 | #endif /* COMPAT_50 || MODULAR */ |
5395 | default: |
5396 | return (EINVAL); |
5397 | } |
5398 | |
5399 | return (0); |
5400 | } |
5401 | |
5402 | static void |
5403 | sppp_phase_network(struct sppp *sp) |
5404 | { |
5405 | int i; |
5406 | uint32_t mask; |
5407 | |
5408 | sppp_change_phase(sp, SPPP_PHASE_NETWORK); |
5409 | |
5410 | /* Notify NCPs now. */ |
5411 | for (i = 0; i < IDX_COUNT; i++) |
5412 | if ((cps[i])->flags & CP_NCP) |
5413 | (cps[i])->Open(sp); |
5414 | |
5415 | /* Send Up events to all NCPs. */ |
5416 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) |
5417 | if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) |
5418 | (cps[i])->Up(sp); |
5419 | |
5420 | /* if no NCP is starting, all this was in vain, close down */ |
5421 | sppp_lcp_check_and_close(sp); |
5422 | } |
5423 | |
5424 | |
5425 | static const char * |
5426 | sppp_cp_type_name(u_char type) |
5427 | { |
5428 | static char buf[12]; |
5429 | switch (type) { |
5430 | case CONF_REQ: return "conf-req" ; |
5431 | case CONF_ACK: return "conf-ack" ; |
5432 | case CONF_NAK: return "conf-nak" ; |
5433 | case CONF_REJ: return "conf-rej" ; |
5434 | case TERM_REQ: return "term-req" ; |
5435 | case TERM_ACK: return "term-ack" ; |
5436 | case CODE_REJ: return "code-rej" ; |
5437 | case PROTO_REJ: return "proto-rej" ; |
5438 | case ECHO_REQ: return "echo-req" ; |
5439 | case ECHO_REPLY: return "echo-reply" ; |
5440 | case DISC_REQ: return "discard-req" ; |
5441 | } |
5442 | snprintf(buf, sizeof(buf), "0x%x" , type); |
5443 | return buf; |
5444 | } |
5445 | |
5446 | static const char * |
5447 | sppp_auth_type_name(u_short proto, u_char type) |
5448 | { |
5449 | static char buf[32]; |
5450 | const char *name; |
5451 | |
5452 | switch (proto) { |
5453 | case PPP_CHAP: |
5454 | switch (type) { |
5455 | case CHAP_CHALLENGE: return "challenge" ; |
5456 | case CHAP_RESPONSE: return "response" ; |
5457 | case CHAP_SUCCESS: return "success" ; |
5458 | case CHAP_FAILURE: return "failure" ; |
5459 | default: name = "chap" ; break; |
5460 | } |
5461 | break; |
5462 | |
5463 | case PPP_PAP: |
5464 | switch (type) { |
5465 | case PAP_REQ: return "req" ; |
5466 | case PAP_ACK: return "ack" ; |
5467 | case PAP_NAK: return "nak" ; |
5468 | default: name = "pap" ; break; |
5469 | } |
5470 | break; |
5471 | |
5472 | default: |
5473 | name = "bad" ; |
5474 | break; |
5475 | } |
5476 | |
5477 | snprintf(buf, sizeof(buf), "%s(%#x) %#x" , name, proto, type); |
5478 | return buf; |
5479 | } |
5480 | |
5481 | static const char * |
5482 | sppp_lcp_opt_name(u_char opt) |
5483 | { |
5484 | static char buf[12]; |
5485 | switch (opt) { |
5486 | case LCP_OPT_MRU: return "mru" ; |
5487 | case LCP_OPT_ASYNC_MAP: return "async-map" ; |
5488 | case LCP_OPT_AUTH_PROTO: return "auth-proto" ; |
5489 | case LCP_OPT_QUAL_PROTO: return "qual-proto" ; |
5490 | case LCP_OPT_MAGIC: return "magic" ; |
5491 | case LCP_OPT_PROTO_COMP: return "proto-comp" ; |
5492 | case LCP_OPT_ADDR_COMP: return "addr-comp" ; |
5493 | } |
5494 | snprintf(buf, sizeof(buf), "0x%x" , opt); |
5495 | return buf; |
5496 | } |
5497 | |
5498 | static const char * |
5499 | sppp_ipcp_opt_name(u_char opt) |
5500 | { |
5501 | static char buf[12]; |
5502 | switch (opt) { |
5503 | case IPCP_OPT_ADDRESSES: return "addresses" ; |
5504 | case IPCP_OPT_COMPRESSION: return "compression" ; |
5505 | case IPCP_OPT_ADDRESS: return "address" ; |
5506 | } |
5507 | snprintf(buf, sizeof(buf), "0x%x" , opt); |
5508 | return buf; |
5509 | } |
5510 | |
5511 | #ifdef INET6 |
5512 | static const char * |
5513 | sppp_ipv6cp_opt_name(u_char opt) |
5514 | { |
5515 | static char buf[12]; |
5516 | switch (opt) { |
5517 | case IPV6CP_OPT_IFID: return "ifid" ; |
5518 | case IPV6CP_OPT_COMPRESSION: return "compression" ; |
5519 | } |
5520 | snprintf(buf, sizeof(buf), "0x%x" , opt); |
5521 | return buf; |
5522 | } |
5523 | #endif |
5524 | |
5525 | static const char * |
5526 | sppp_state_name(int state) |
5527 | { |
5528 | switch (state) { |
5529 | case STATE_INITIAL: return "initial" ; |
5530 | case STATE_STARTING: return "starting" ; |
5531 | case STATE_CLOSED: return "closed" ; |
5532 | case STATE_STOPPED: return "stopped" ; |
5533 | case STATE_CLOSING: return "closing" ; |
5534 | case STATE_STOPPING: return "stopping" ; |
5535 | case STATE_REQ_SENT: return "req-sent" ; |
5536 | case STATE_ACK_RCVD: return "ack-rcvd" ; |
5537 | case STATE_ACK_SENT: return "ack-sent" ; |
5538 | case STATE_OPENED: return "opened" ; |
5539 | } |
5540 | return "illegal" ; |
5541 | } |
5542 | |
5543 | static const char * |
5544 | sppp_phase_name(int phase) |
5545 | { |
5546 | switch (phase) { |
5547 | case SPPP_PHASE_DEAD: return "dead" ; |
5548 | case SPPP_PHASE_ESTABLISH: return "establish" ; |
5549 | case SPPP_PHASE_TERMINATE: return "terminate" ; |
5550 | case SPPP_PHASE_AUTHENTICATE: return "authenticate" ; |
5551 | case SPPP_PHASE_NETWORK: return "network" ; |
5552 | } |
5553 | return "illegal" ; |
5554 | } |
5555 | |
5556 | static const char * |
5557 | sppp_proto_name(u_short proto) |
5558 | { |
5559 | static char buf[12]; |
5560 | switch (proto) { |
5561 | case PPP_LCP: return "lcp" ; |
5562 | case PPP_IPCP: return "ipcp" ; |
5563 | case PPP_PAP: return "pap" ; |
5564 | case PPP_CHAP: return "chap" ; |
5565 | case PPP_IPV6CP: return "ipv6cp" ; |
5566 | } |
5567 | snprintf(buf, sizeof(buf), "0x%x" , (unsigned)proto); |
5568 | return buf; |
5569 | } |
5570 | |
5571 | static void |
5572 | sppp_print_bytes(const u_char *p, u_short len) |
5573 | { |
5574 | addlog(" %02x" , *p++); |
5575 | while (--len > 0) |
5576 | addlog("-%02x" , *p++); |
5577 | } |
5578 | |
5579 | static void |
5580 | sppp_print_string(const char *p, u_short len) |
5581 | { |
5582 | u_char c; |
5583 | |
5584 | while (len-- > 0) { |
5585 | c = *p++; |
5586 | /* |
5587 | * Print only ASCII chars directly. RFC 1994 recommends |
5588 | * using only them, but we don't rely on it. */ |
5589 | if (c < ' ' || c > '~') |
5590 | addlog("\\x%x" , c); |
5591 | else |
5592 | addlog("%c" , c); |
5593 | } |
5594 | } |
5595 | |
5596 | static const char * |
5597 | sppp_dotted_quad(uint32_t addr) |
5598 | { |
5599 | static char s[16]; |
5600 | snprintf(s, sizeof(s), "%d.%d.%d.%d" , |
5601 | (int)((addr >> 24) & 0xff), |
5602 | (int)((addr >> 16) & 0xff), |
5603 | (int)((addr >> 8) & 0xff), |
5604 | (int)(addr & 0xff)); |
5605 | return s; |
5606 | } |
5607 | |
5608 | /* a dummy, used to drop uninteresting events */ |
5609 | static void |
5610 | sppp_null(struct sppp *unused) |
5611 | { |
5612 | /* do just nothing */ |
5613 | } |
5614 | /* |
5615 | * This file is large. Tell emacs to highlight it nevertheless. |
5616 | * |
5617 | * Local Variables: |
5618 | * hilit-auto-highlight-maxout: 120000 |
5619 | * End: |
5620 | */ |
5621 | |
5622 | /* |
5623 | * Module glue |
5624 | */ |
5625 | MODULE(MODULE_CLASS_MISC, sppp_subr, NULL); |
5626 | |
5627 | static int |
5628 | sppp_subr_modcmd(modcmd_t cmd, void *arg) |
5629 | { |
5630 | switch (cmd) { |
5631 | case MODULE_CMD_INIT: |
5632 | case MODULE_CMD_FINI: |
5633 | return 0; |
5634 | case MODULE_CMD_STAT: |
5635 | case MODULE_CMD_AUTOUNLOAD: |
5636 | default: |
5637 | return ENOTTY; |
5638 | } |
5639 | } |
5640 | |
5641 | |