| @@ -1,1043 +1,1043 @@ | | | @@ -1,1043 +1,1043 @@ |
1 | /* $NetBSD: if_spppsubr.c,v 1.113 2008/08/22 12:13:18 martin Exp $ */ | | 1 | /* $NetBSD: if_spppsubr.c,v 1.114 2008/10/03 18:33:06 pooka Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Synchronous PPP/Cisco link level subroutines. | | 4 | * Synchronous PPP/Cisco link level subroutines. |
5 | * Keepalive protocol implemented in both Cisco and PPP modes. | | 5 | * Keepalive protocol implemented in both Cisco and PPP modes. |
6 | * | | 6 | * |
7 | * Copyright (C) 1994-1996 Cronyx Engineering Ltd. | | 7 | * Copyright (C) 1994-1996 Cronyx Engineering Ltd. |
8 | * Author: Serge Vakulenko, <vak@cronyx.ru> | | 8 | * Author: Serge Vakulenko, <vak@cronyx.ru> |
9 | * | | 9 | * |
10 | * Heavily revamped to conform to RFC 1661. | | 10 | * Heavily revamped to conform to RFC 1661. |
11 | * Copyright (C) 1997, Joerg Wunsch. | | 11 | * Copyright (C) 1997, Joerg Wunsch. |
12 | * | | 12 | * |
13 | * RFC2472 IPv6CP support. | | 13 | * RFC2472 IPv6CP support. |
14 | * Copyright (C) 2000, Jun-ichiro itojun Hagino <itojun@iijlab.net>. | | 14 | * Copyright (C) 2000, Jun-ichiro itojun Hagino <itojun@iijlab.net>. |
15 | * | | 15 | * |
16 | * Redistribution and use in source and binary forms, with or without | | 16 | * Redistribution and use in source and binary forms, with or without |
17 | * modification, are permitted provided that the following conditions are met: | | 17 | * modification, are permitted provided that the following conditions are met: |
18 | * 1. Redistributions of source code must retain the above copyright notice, | | 18 | * 1. Redistributions of source code must retain the above copyright notice, |
19 | * this list of conditions and the following disclaimer. | | 19 | * this list of conditions and the following disclaimer. |
20 | * 2. Redistributions in binary form must reproduce the above copyright notice, | | 20 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
21 | * this list of conditions and the following disclaimer in the documentation | | 21 | * this list of conditions and the following disclaimer in the documentation |
22 | * and/or other materials provided with the distribution. | | 22 | * and/or other materials provided with the distribution. |
23 | * | | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY | | 24 | * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY |
25 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 25 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE | | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 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 | | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. | | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | * | | 35 | * |
36 | * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 | | 36 | * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 |
37 | * | | 37 | * |
38 | * From: if_spppsubr.c,v 1.39 1998/04/04 13:26:03 phk Exp | | 38 | * From: if_spppsubr.c,v 1.39 1998/04/04 13:26:03 phk Exp |
39 | * | | 39 | * |
40 | * From: Id: if_spppsubr.c,v 1.23 1999/02/23 14:47:50 hm Exp | | 40 | * From: Id: if_spppsubr.c,v 1.23 1999/02/23 14:47:50 hm Exp |
41 | */ | | 41 | */ |
42 | | | 42 | |
43 | #include <sys/cdefs.h> | | 43 | #include <sys/cdefs.h> |
44 | __KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.113 2008/08/22 12:13:18 martin Exp $"); | | 44 | __KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.114 2008/10/03 18:33:06 pooka Exp $"); |
45 | | | 45 | |
46 | #include "opt_inet.h" | | 46 | #include "opt_inet.h" |
47 | #include "opt_ipx.h" | | 47 | #include "opt_ipx.h" |
48 | #include "opt_iso.h" | | 48 | #include "opt_iso.h" |
49 | #include "opt_pfil_hooks.h" | | 49 | #include "opt_pfil_hooks.h" |
50 | | | 50 | |
51 | #include <sys/param.h> | | 51 | #include <sys/param.h> |
52 | #include <sys/proc.h> | | 52 | #include <sys/proc.h> |
53 | #include <sys/systm.h> | | 53 | #include <sys/systm.h> |
54 | #include <sys/kernel.h> | | 54 | #include <sys/kernel.h> |
55 | #include <sys/sockio.h> | | 55 | #include <sys/sockio.h> |
56 | #include <sys/socket.h> | | 56 | #include <sys/socket.h> |
57 | #include <sys/syslog.h> | | 57 | #include <sys/syslog.h> |
58 | #include <sys/malloc.h> | | 58 | #include <sys/malloc.h> |
59 | #include <sys/mbuf.h> | | 59 | #include <sys/mbuf.h> |
60 | #include <sys/callout.h> | | 60 | #include <sys/callout.h> |
61 | #include <sys/md5.h> | | 61 | #include <sys/md5.h> |
62 | #include <sys/inttypes.h> | | 62 | #include <sys/inttypes.h> |
63 | #include <sys/kauth.h> | | 63 | #include <sys/kauth.h> |
64 | | | 64 | |
65 | #include <net/if.h> | | 65 | #include <net/if.h> |
66 | #include <net/netisr.h> | | 66 | #include <net/netisr.h> |
67 | #include <net/if_types.h> | | 67 | #include <net/if_types.h> |
68 | #include <net/route.h> | | 68 | #include <net/route.h> |
69 | #include <net/ppp_defs.h> | | 69 | #include <net/ppp_defs.h> |
70 | | | 70 | |
71 | #include <machine/stdarg.h> | | 71 | #include <machine/stdarg.h> |
72 | | | 72 | |
73 | #include <netinet/in.h> | | 73 | #include <netinet/in.h> |
74 | #include <netinet/in_systm.h> | | 74 | #include <netinet/in_systm.h> |
75 | #include <netinet/in_var.h> | | 75 | #include <netinet/in_var.h> |
76 | #ifdef INET | | 76 | #ifdef INET |
77 | #include <netinet/ip.h> | | 77 | #include <netinet/ip.h> |
78 | #include <netinet/tcp.h> | | 78 | #include <netinet/tcp.h> |
79 | #endif | | 79 | #endif |
80 | #include <net/ethertypes.h> | | 80 | #include <net/ethertypes.h> |
81 | | | 81 | |
82 | #ifdef INET6 | | 82 | #ifdef INET6 |
83 | #include <netinet6/scope6_var.h> | | 83 | #include <netinet6/scope6_var.h> |
84 | #endif | | 84 | #endif |
85 | | | 85 | |
86 | #ifdef IPX | | 86 | #ifdef IPX |
87 | #include <netipx/ipx.h> | | 87 | #include <netipx/ipx.h> |
88 | #include <netipx/ipx_if.h> | | 88 | #include <netipx/ipx_if.h> |
89 | #endif | | 89 | #endif |
90 | | | 90 | |
91 | | | 91 | |
92 | #ifdef ISO | | 92 | #ifdef ISO |
93 | #include <netiso/argo_debug.h> | | 93 | #include <netiso/argo_debug.h> |
94 | #include <netiso/iso.h> | | 94 | #include <netiso/iso.h> |
95 | #include <netiso/iso_var.h> | | 95 | #include <netiso/iso_var.h> |
96 | #include <netiso/iso_snpac.h> | | 96 | #include <netiso/iso_snpac.h> |
97 | #endif | | 97 | #endif |
98 | | | 98 | |
99 | #include <net/if_sppp.h> | | 99 | #include <net/if_sppp.h> |
100 | #include <net/if_spppvar.h> | | 100 | #include <net/if_spppvar.h> |
101 | | | 101 | |
102 | #define LCP_KEEPALIVE_INTERVAL 10 /* seconds between checks */ | | 102 | #define LCP_KEEPALIVE_INTERVAL 10 /* seconds between checks */ |
103 | #define LOOPALIVECNT 3 /* loopback detection tries */ | | 103 | #define LOOPALIVECNT 3 /* loopback detection tries */ |
104 | #define DEFAULT_MAXALIVECNT 3 /* max. missed alive packets */ | | 104 | #define DEFAULT_MAXALIVECNT 3 /* max. missed alive packets */ |
105 | #define DEFAULT_NORECV_TIME 15 /* before we get worried */ | | 105 | #define DEFAULT_NORECV_TIME 15 /* before we get worried */ |
106 | #define DEFAULT_MAX_AUTH_FAILURES 5 /* max. auth. failures */ | | 106 | #define DEFAULT_MAX_AUTH_FAILURES 5 /* max. auth. failures */ |
107 | | | 107 | |
108 | /* | | 108 | /* |
109 | * Interface flags that can be set in an ifconfig command. | | 109 | * Interface flags that can be set in an ifconfig command. |
110 | * | | 110 | * |
111 | * Setting link0 will make the link passive, i.e. it will be marked | | 111 | * Setting link0 will make the link passive, i.e. it will be marked |
112 | * as being administrative openable, but won't be opened to begin | | 112 | * as being administrative openable, but won't be opened to begin |
113 | * with. Incoming calls will be answered, or subsequent calls with | | 113 | * with. Incoming calls will be answered, or subsequent calls with |
114 | * -link1 will cause the administrative open of the LCP layer. | | 114 | * -link1 will cause the administrative open of the LCP layer. |
115 | * | | 115 | * |
116 | * Setting link1 will cause the link to auto-dial only as packets | | 116 | * Setting link1 will cause the link to auto-dial only as packets |
117 | * arrive to be sent. | | 117 | * arrive to be sent. |
118 | * | | 118 | * |
119 | * Setting IFF_DEBUG will syslog the option negotiation and state | | 119 | * Setting IFF_DEBUG will syslog the option negotiation and state |
120 | * transitions at level kern.debug. Note: all logs consistently look | | 120 | * transitions at level kern.debug. Note: all logs consistently look |
121 | * like | | 121 | * like |
122 | * | | 122 | * |
123 | * <if-name><unit>: <proto-name> <additional info...> | | 123 | * <if-name><unit>: <proto-name> <additional info...> |
124 | * | | 124 | * |
125 | * with <if-name><unit> being something like "bppp0", and <proto-name> | | 125 | * with <if-name><unit> being something like "bppp0", and <proto-name> |
126 | * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. | | 126 | * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. |
127 | */ | | 127 | */ |
128 | | | 128 | |
129 | #define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ | | 129 | #define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ |
130 | #define IFF_AUTO IFF_LINK1 /* auto-dial on output */ | | 130 | #define IFF_AUTO IFF_LINK1 /* auto-dial on output */ |
131 | | | 131 | |
132 | #define CONF_REQ 1 /* PPP configure request */ | | 132 | #define CONF_REQ 1 /* PPP configure request */ |
133 | #define CONF_ACK 2 /* PPP configure acknowledge */ | | 133 | #define CONF_ACK 2 /* PPP configure acknowledge */ |
134 | #define CONF_NAK 3 /* PPP configure negative ack */ | | 134 | #define CONF_NAK 3 /* PPP configure negative ack */ |
135 | #define CONF_REJ 4 /* PPP configure reject */ | | 135 | #define CONF_REJ 4 /* PPP configure reject */ |
136 | #define TERM_REQ 5 /* PPP terminate request */ | | 136 | #define TERM_REQ 5 /* PPP terminate request */ |
137 | #define TERM_ACK 6 /* PPP terminate acknowledge */ | | 137 | #define TERM_ACK 6 /* PPP terminate acknowledge */ |
138 | #define CODE_REJ 7 /* PPP code reject */ | | 138 | #define CODE_REJ 7 /* PPP code reject */ |
139 | #define PROTO_REJ 8 /* PPP protocol reject */ | | 139 | #define PROTO_REJ 8 /* PPP protocol reject */ |
140 | #define ECHO_REQ 9 /* PPP echo request */ | | 140 | #define ECHO_REQ 9 /* PPP echo request */ |
141 | #define ECHO_REPLY 10 /* PPP echo reply */ | | 141 | #define ECHO_REPLY 10 /* PPP echo reply */ |
142 | #define DISC_REQ 11 /* PPP discard request */ | | 142 | #define DISC_REQ 11 /* PPP discard request */ |
143 | | | 143 | |
144 | #define LCP_OPT_MRU 1 /* maximum receive unit */ | | 144 | #define LCP_OPT_MRU 1 /* maximum receive unit */ |
145 | #define LCP_OPT_ASYNC_MAP 2 /* async control character map */ | | 145 | #define LCP_OPT_ASYNC_MAP 2 /* async control character map */ |
146 | #define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ | | 146 | #define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ |
147 | #define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ | | 147 | #define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ |
148 | #define LCP_OPT_MAGIC 5 /* magic number */ | | 148 | #define LCP_OPT_MAGIC 5 /* magic number */ |
149 | #define LCP_OPT_RESERVED 6 /* reserved */ | | 149 | #define LCP_OPT_RESERVED 6 /* reserved */ |
150 | #define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ | | 150 | #define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ |
151 | #define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ | | 151 | #define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ |
152 | | | 152 | |
153 | #define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ | | 153 | #define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ |
154 | #define IPCP_OPT_COMPRESSION 2 /* IP compression protocol */ | | 154 | #define IPCP_OPT_COMPRESSION 2 /* IP compression protocol */ |
155 | #define IPCP_OPT_ADDRESS 3 /* local IP address */ | | 155 | #define IPCP_OPT_ADDRESS 3 /* local IP address */ |
156 | #define IPCP_OPT_PRIMDNS 129 /* primary remote dns address */ | | 156 | #define IPCP_OPT_PRIMDNS 129 /* primary remote dns address */ |
157 | #define IPCP_OPT_SECDNS 131 /* secondary remote dns address */ | | 157 | #define IPCP_OPT_SECDNS 131 /* secondary remote dns address */ |
158 | | | 158 | |
159 | #define IPV6CP_OPT_IFID 1 /* interface identifier */ | | 159 | #define IPV6CP_OPT_IFID 1 /* interface identifier */ |
160 | #define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ | | 160 | #define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ |
161 | | | 161 | |
162 | #define PAP_REQ 1 /* PAP name/password request */ | | 162 | #define PAP_REQ 1 /* PAP name/password request */ |
163 | #define PAP_ACK 2 /* PAP acknowledge */ | | 163 | #define PAP_ACK 2 /* PAP acknowledge */ |
164 | #define PAP_NAK 3 /* PAP fail */ | | 164 | #define PAP_NAK 3 /* PAP fail */ |
165 | | | 165 | |
166 | #define CHAP_CHALLENGE 1 /* CHAP challenge request */ | | 166 | #define CHAP_CHALLENGE 1 /* CHAP challenge request */ |
167 | #define CHAP_RESPONSE 2 /* CHAP challenge response */ | | 167 | #define CHAP_RESPONSE 2 /* CHAP challenge response */ |
168 | #define CHAP_SUCCESS 3 /* CHAP response ok */ | | 168 | #define CHAP_SUCCESS 3 /* CHAP response ok */ |
169 | #define CHAP_FAILURE 4 /* CHAP response failed */ | | 169 | #define CHAP_FAILURE 4 /* CHAP response failed */ |
170 | | | 170 | |
171 | #define CHAP_MD5 5 /* hash algorithm - MD5 */ | | 171 | #define CHAP_MD5 5 /* hash algorithm - MD5 */ |
172 | | | 172 | |
173 | #define CISCO_MULTICAST 0x8f /* Cisco multicast address */ | | 173 | #define CISCO_MULTICAST 0x8f /* Cisco multicast address */ |
174 | #define CISCO_UNICAST 0x0f /* Cisco unicast address */ | | 174 | #define CISCO_UNICAST 0x0f /* Cisco unicast address */ |
175 | #define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ | | 175 | #define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ |
176 | #define CISCO_ADDR_REQ 0 /* Cisco address request */ | | 176 | #define CISCO_ADDR_REQ 0 /* Cisco address request */ |
177 | #define CISCO_ADDR_REPLY 1 /* Cisco address reply */ | | 177 | #define CISCO_ADDR_REPLY 1 /* Cisco address reply */ |
178 | #define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ | | 178 | #define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ |
179 | | | 179 | |
180 | /* states are named and numbered according to RFC 1661 */ | | 180 | /* states are named and numbered according to RFC 1661 */ |
181 | #define STATE_INITIAL 0 | | 181 | #define STATE_INITIAL 0 |
182 | #define STATE_STARTING 1 | | 182 | #define STATE_STARTING 1 |
183 | #define STATE_CLOSED 2 | | 183 | #define STATE_CLOSED 2 |
184 | #define STATE_STOPPED 3 | | 184 | #define STATE_STOPPED 3 |
185 | #define STATE_CLOSING 4 | | 185 | #define STATE_CLOSING 4 |
186 | #define STATE_STOPPING 5 | | 186 | #define STATE_STOPPING 5 |
187 | #define STATE_REQ_SENT 6 | | 187 | #define STATE_REQ_SENT 6 |
188 | #define STATE_ACK_RCVD 7 | | 188 | #define STATE_ACK_RCVD 7 |
189 | #define STATE_ACK_SENT 8 | | 189 | #define STATE_ACK_SENT 8 |
190 | #define STATE_OPENED 9 | | 190 | #define STATE_OPENED 9 |
191 | | | 191 | |
192 | struct ppp_header { | | 192 | struct ppp_header { |
193 | uint8_t address; | | 193 | uint8_t address; |
194 | uint8_t control; | | 194 | uint8_t control; |
195 | uint16_t protocol; | | 195 | uint16_t protocol; |
196 | } __packed; | | 196 | } __packed; |
197 | #define PPP_HEADER_LEN sizeof (struct ppp_header) | | 197 | #define PPP_HEADER_LEN sizeof (struct ppp_header) |
198 | | | 198 | |
199 | struct lcp_header { | | 199 | struct lcp_header { |
200 | uint8_t type; | | 200 | uint8_t type; |
201 | uint8_t ident; | | 201 | uint8_t ident; |
202 | uint16_t len; | | 202 | uint16_t len; |
203 | } __packed; | | 203 | } __packed; |
204 | #define LCP_HEADER_LEN sizeof (struct lcp_header) | | 204 | #define LCP_HEADER_LEN sizeof (struct lcp_header) |
205 | | | 205 | |
206 | struct cisco_packet { | | 206 | struct cisco_packet { |
207 | uint32_t type; | | 207 | uint32_t type; |
208 | uint32_t par1; | | 208 | uint32_t par1; |
209 | uint32_t par2; | | 209 | uint32_t par2; |
210 | uint16_t rel; | | 210 | uint16_t rel; |
211 | uint16_t time0; | | 211 | uint16_t time0; |
212 | uint16_t time1; | | 212 | uint16_t time1; |
213 | } __packed; | | 213 | } __packed; |
214 | #define CISCO_PACKET_LEN 18 | | 214 | #define CISCO_PACKET_LEN 18 |
215 | | | 215 | |
216 | /* | | 216 | /* |
217 | * We follow the spelling and capitalization of RFC 1661 here, to make | | 217 | * We follow the spelling and capitalization of RFC 1661 here, to make |
218 | * it easier comparing with the standard. Please refer to this RFC in | | 218 | * it easier comparing with the standard. Please refer to this RFC in |
219 | * case you can't make sense out of these abbreviation; it will also | | 219 | * case you can't make sense out of these abbreviation; it will also |
220 | * explain the semantics related to the various events and actions. | | 220 | * explain the semantics related to the various events and actions. |
221 | */ | | 221 | */ |
222 | struct cp { | | 222 | struct cp { |
223 | u_short proto; /* PPP control protocol number */ | | 223 | u_short proto; /* PPP control protocol number */ |
224 | u_char protoidx; /* index into state table in struct sppp */ | | 224 | u_char protoidx; /* index into state table in struct sppp */ |
225 | u_char flags; | | 225 | u_char flags; |
226 | #define CP_LCP 0x01 /* this is the LCP */ | | 226 | #define CP_LCP 0x01 /* this is the LCP */ |
227 | #define CP_AUTH 0x02 /* this is an authentication protocol */ | | 227 | #define CP_AUTH 0x02 /* this is an authentication protocol */ |
228 | #define CP_NCP 0x04 /* this is a NCP */ | | 228 | #define CP_NCP 0x04 /* this is a NCP */ |
229 | #define CP_QUAL 0x08 /* this is a quality reporting protocol */ | | 229 | #define CP_QUAL 0x08 /* this is a quality reporting protocol */ |
230 | const char *name; /* name of this control protocol */ | | 230 | const char *name; /* name of this control protocol */ |
231 | /* event handlers */ | | 231 | /* event handlers */ |
232 | void (*Up)(struct sppp *sp); | | 232 | void (*Up)(struct sppp *sp); |
233 | void (*Down)(struct sppp *sp); | | 233 | void (*Down)(struct sppp *sp); |
234 | void (*Open)(struct sppp *sp); | | 234 | void (*Open)(struct sppp *sp); |
235 | void (*Close)(struct sppp *sp); | | 235 | void (*Close)(struct sppp *sp); |
236 | void (*TO)(void *sp); | | 236 | void (*TO)(void *sp); |
237 | int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); | | 237 | int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); |
238 | void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); | | 238 | void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); |
239 | void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); | | 239 | void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); |
240 | /* actions */ | | 240 | /* actions */ |
241 | void (*tlu)(struct sppp *sp); | | 241 | void (*tlu)(struct sppp *sp); |
242 | void (*tld)(struct sppp *sp); | | 242 | void (*tld)(struct sppp *sp); |
243 | void (*tls)(struct sppp *sp); | | 243 | void (*tls)(struct sppp *sp); |
244 | void (*tlf)(struct sppp *sp); | | 244 | void (*tlf)(struct sppp *sp); |
245 | void (*scr)(struct sppp *sp); | | 245 | void (*scr)(struct sppp *sp); |
246 | }; | | 246 | }; |
247 | | | 247 | |
248 | static struct sppp *spppq; | | 248 | static struct sppp *spppq; |
249 | static callout_t keepalive_ch; | | 249 | static callout_t keepalive_ch; |
250 | | | 250 | |
251 | #ifdef INET | | 251 | #ifdef INET |
252 | /* | | 252 | /* |
253 | * The following disgusting hack gets around the problem that IP TOS | | 253 | * The following disgusting hack gets around the problem that IP TOS |
254 | * can't be set yet. We want to put "interactive" traffic on a high | | 254 | * can't be set yet. We want to put "interactive" traffic on a high |
255 | * priority queue. To decide if traffic is interactive, we check that | | 255 | * priority queue. To decide if traffic is interactive, we check that |
256 | * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. | | 256 | * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. |
257 | * | | 257 | * |
258 | * XXX is this really still necessary? - joerg - | | 258 | * XXX is this really still necessary? - joerg - |
259 | */ | | 259 | */ |
260 | static u_short interactive_ports[8] = { | | 260 | static u_short interactive_ports[8] = { |
261 | 0, 513, 0, 0, | | 261 | 0, 513, 0, 0, |
262 | 0, 21, 0, 23, | | 262 | 0, 21, 0, 23, |
263 | }; | | 263 | }; |
264 | #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) | | 264 | #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) |
265 | #endif | | 265 | #endif |
266 | | | 266 | |
267 | /* almost every function needs these */ | | 267 | /* almost every function needs these */ |
268 | #define STDDCL \ | | 268 | #define STDDCL \ |
269 | struct ifnet *ifp = &sp->pp_if; \ | | 269 | struct ifnet *ifp = &sp->pp_if; \ |
270 | int debug = ifp->if_flags & IFF_DEBUG | | 270 | int debug = ifp->if_flags & IFF_DEBUG |
271 | | | 271 | |
272 | static int sppp_output(struct ifnet *ifp, struct mbuf *m, | | 272 | static int sppp_output(struct ifnet *ifp, struct mbuf *m, |
273 | const struct sockaddr *dst, struct rtentry *rt); | | 273 | const struct sockaddr *dst, struct rtentry *rt); |
274 | | | 274 | |
275 | static void sppp_cisco_send(struct sppp *sp, int type, int32_t par1, int32_t par2); | | 275 | static void sppp_cisco_send(struct sppp *sp, int type, int32_t par1, int32_t par2); |
276 | static void sppp_cisco_input(struct sppp *sp, struct mbuf *m); | | 276 | static void sppp_cisco_input(struct sppp *sp, struct mbuf *m); |
277 | | | 277 | |
278 | static void sppp_cp_input(const struct cp *cp, struct sppp *sp, | | 278 | static void sppp_cp_input(const struct cp *cp, struct sppp *sp, |
279 | struct mbuf *m); | | 279 | struct mbuf *m); |
280 | static void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, | | 280 | static void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, |
281 | u_char ident, u_short len, void *data); | | 281 | u_char ident, u_short len, void *data); |
282 | /* static void sppp_cp_timeout(void *arg); */ | | 282 | /* static void sppp_cp_timeout(void *arg); */ |
283 | static void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, | | 283 | static void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, |
284 | int newstate); | | 284 | int newstate); |
285 | static void sppp_auth_send(const struct cp *cp, | | 285 | static void sppp_auth_send(const struct cp *cp, |
286 | struct sppp *sp, unsigned int type, unsigned int id, | | 286 | struct sppp *sp, unsigned int type, unsigned int id, |
287 | ...); | | 287 | ...); |
288 | | | 288 | |
289 | static void sppp_up_event(const struct cp *cp, struct sppp *sp); | | 289 | static void sppp_up_event(const struct cp *cp, struct sppp *sp); |
290 | static void sppp_down_event(const struct cp *cp, struct sppp *sp); | | 290 | static void sppp_down_event(const struct cp *cp, struct sppp *sp); |
291 | static void sppp_open_event(const struct cp *cp, struct sppp *sp); | | 291 | static void sppp_open_event(const struct cp *cp, struct sppp *sp); |
292 | static void sppp_close_event(const struct cp *cp, struct sppp *sp); | | 292 | static void sppp_close_event(const struct cp *cp, struct sppp *sp); |
293 | static void sppp_to_event(const struct cp *cp, struct sppp *sp); | | 293 | static void sppp_to_event(const struct cp *cp, struct sppp *sp); |
294 | | | 294 | |
295 | static void sppp_null(struct sppp *sp); | | 295 | static void sppp_null(struct sppp *sp); |
296 | | | 296 | |
297 | static void sppp_lcp_init(struct sppp *sp); | | 297 | static void sppp_lcp_init(struct sppp *sp); |
298 | static void sppp_lcp_up(struct sppp *sp); | | 298 | static void sppp_lcp_up(struct sppp *sp); |
299 | static void sppp_lcp_down(struct sppp *sp); | | 299 | static void sppp_lcp_down(struct sppp *sp); |
300 | static void sppp_lcp_open(struct sppp *sp); | | 300 | static void sppp_lcp_open(struct sppp *sp); |
301 | static void sppp_lcp_close(struct sppp *sp); | | 301 | static void sppp_lcp_close(struct sppp *sp); |
302 | static void sppp_lcp_TO(void *sp); | | 302 | static void sppp_lcp_TO(void *sp); |
303 | static int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); | | 303 | static int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); |
304 | static void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); | | 304 | static void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); |
305 | static void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); | | 305 | static void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); |
306 | static void sppp_lcp_tlu(struct sppp *sp); | | 306 | static void sppp_lcp_tlu(struct sppp *sp); |
307 | static void sppp_lcp_tld(struct sppp *sp); | | 307 | static void sppp_lcp_tld(struct sppp *sp); |
308 | static void sppp_lcp_tls(struct sppp *sp); | | 308 | static void sppp_lcp_tls(struct sppp *sp); |
309 | static void sppp_lcp_tlf(struct sppp *sp); | | 309 | static void sppp_lcp_tlf(struct sppp *sp); |
310 | static void sppp_lcp_scr(struct sppp *sp); | | 310 | static void sppp_lcp_scr(struct sppp *sp); |
311 | static void sppp_lcp_check_and_close(struct sppp *sp); | | 311 | static void sppp_lcp_check_and_close(struct sppp *sp); |
312 | static int sppp_ncp_check(struct sppp *sp); | | 312 | static int sppp_ncp_check(struct sppp *sp); |
313 | | | 313 | |
314 | static void sppp_ipcp_init(struct sppp *sp); | | 314 | static void sppp_ipcp_init(struct sppp *sp); |
315 | static void sppp_ipcp_up(struct sppp *sp); | | 315 | static void sppp_ipcp_up(struct sppp *sp); |
316 | static void sppp_ipcp_down(struct sppp *sp); | | 316 | static void sppp_ipcp_down(struct sppp *sp); |
317 | static void sppp_ipcp_open(struct sppp *sp); | | 317 | static void sppp_ipcp_open(struct sppp *sp); |
318 | static void sppp_ipcp_close(struct sppp *sp); | | 318 | static void sppp_ipcp_close(struct sppp *sp); |
319 | static void sppp_ipcp_TO(void *sp); | | 319 | static void sppp_ipcp_TO(void *sp); |
320 | static int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); | | 320 | static int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); |
321 | static void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); | | 321 | static void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); |
322 | static void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); | | 322 | static void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); |
323 | static void sppp_ipcp_tlu(struct sppp *sp); | | 323 | static void sppp_ipcp_tlu(struct sppp *sp); |
324 | static void sppp_ipcp_tld(struct sppp *sp); | | 324 | static void sppp_ipcp_tld(struct sppp *sp); |
325 | static void sppp_ipcp_tls(struct sppp *sp); | | 325 | static void sppp_ipcp_tls(struct sppp *sp); |
326 | static void sppp_ipcp_tlf(struct sppp *sp); | | 326 | static void sppp_ipcp_tlf(struct sppp *sp); |
327 | static void sppp_ipcp_scr(struct sppp *sp); | | 327 | static void sppp_ipcp_scr(struct sppp *sp); |
328 | | | 328 | |
329 | static void sppp_ipv6cp_init(struct sppp *sp); | | 329 | static void sppp_ipv6cp_init(struct sppp *sp); |
330 | static void sppp_ipv6cp_up(struct sppp *sp); | | 330 | static void sppp_ipv6cp_up(struct sppp *sp); |
331 | static void sppp_ipv6cp_down(struct sppp *sp); | | 331 | static void sppp_ipv6cp_down(struct sppp *sp); |
332 | static void sppp_ipv6cp_open(struct sppp *sp); | | 332 | static void sppp_ipv6cp_open(struct sppp *sp); |
333 | static void sppp_ipv6cp_close(struct sppp *sp); | | 333 | static void sppp_ipv6cp_close(struct sppp *sp); |
334 | static void sppp_ipv6cp_TO(void *sp); | | 334 | static void sppp_ipv6cp_TO(void *sp); |
335 | static int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); | | 335 | static int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); |
336 | static void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); | | 336 | static void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); |
337 | static void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); | | 337 | static void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); |
338 | static void sppp_ipv6cp_tlu(struct sppp *sp); | | 338 | static void sppp_ipv6cp_tlu(struct sppp *sp); |
339 | static void sppp_ipv6cp_tld(struct sppp *sp); | | 339 | static void sppp_ipv6cp_tld(struct sppp *sp); |
340 | static void sppp_ipv6cp_tls(struct sppp *sp); | | 340 | static void sppp_ipv6cp_tls(struct sppp *sp); |
341 | static void sppp_ipv6cp_tlf(struct sppp *sp); | | 341 | static void sppp_ipv6cp_tlf(struct sppp *sp); |
342 | static void sppp_ipv6cp_scr(struct sppp *sp); | | 342 | static void sppp_ipv6cp_scr(struct sppp *sp); |
343 | | | 343 | |
344 | static void sppp_pap_input(struct sppp *sp, struct mbuf *m); | | 344 | static void sppp_pap_input(struct sppp *sp, struct mbuf *m); |
345 | static void sppp_pap_init(struct sppp *sp); | | 345 | static void sppp_pap_init(struct sppp *sp); |
346 | static void sppp_pap_open(struct sppp *sp); | | 346 | static void sppp_pap_open(struct sppp *sp); |
347 | static void sppp_pap_close(struct sppp *sp); | | 347 | static void sppp_pap_close(struct sppp *sp); |
348 | static void sppp_pap_TO(void *sp); | | 348 | static void sppp_pap_TO(void *sp); |
349 | static void sppp_pap_my_TO(void *sp); | | 349 | static void sppp_pap_my_TO(void *sp); |
350 | static void sppp_pap_tlu(struct sppp *sp); | | 350 | static void sppp_pap_tlu(struct sppp *sp); |
351 | static void sppp_pap_tld(struct sppp *sp); | | 351 | static void sppp_pap_tld(struct sppp *sp); |
352 | static void sppp_pap_scr(struct sppp *sp); | | 352 | static void sppp_pap_scr(struct sppp *sp); |
353 | | | 353 | |
354 | static void sppp_chap_input(struct sppp *sp, struct mbuf *m); | | 354 | static void sppp_chap_input(struct sppp *sp, struct mbuf *m); |
355 | static void sppp_chap_init(struct sppp *sp); | | 355 | static void sppp_chap_init(struct sppp *sp); |
356 | static void sppp_chap_open(struct sppp *sp); | | 356 | static void sppp_chap_open(struct sppp *sp); |
357 | static void sppp_chap_close(struct sppp *sp); | | 357 | static void sppp_chap_close(struct sppp *sp); |
358 | static void sppp_chap_TO(void *sp); | | 358 | static void sppp_chap_TO(void *sp); |
359 | static void sppp_chap_tlu(struct sppp *sp); | | 359 | static void sppp_chap_tlu(struct sppp *sp); |
360 | static void sppp_chap_tld(struct sppp *sp); | | 360 | static void sppp_chap_tld(struct sppp *sp); |
361 | static void sppp_chap_scr(struct sppp *sp); | | 361 | static void sppp_chap_scr(struct sppp *sp); |
362 | | | 362 | |
363 | static const char *sppp_auth_type_name(u_short proto, u_char type); | | 363 | static const char *sppp_auth_type_name(u_short proto, u_char type); |
364 | static const char *sppp_cp_type_name(u_char type); | | 364 | static const char *sppp_cp_type_name(u_char type); |
365 | static const char *sppp_dotted_quad(uint32_t addr); | | 365 | static const char *sppp_dotted_quad(uint32_t addr); |
366 | static const char *sppp_ipcp_opt_name(u_char opt); | | 366 | static const char *sppp_ipcp_opt_name(u_char opt); |
367 | #ifdef INET6 | | 367 | #ifdef INET6 |
368 | static const char *sppp_ipv6cp_opt_name(u_char opt); | | 368 | static const char *sppp_ipv6cp_opt_name(u_char opt); |
369 | #endif | | 369 | #endif |
370 | static const char *sppp_lcp_opt_name(u_char opt); | | 370 | static const char *sppp_lcp_opt_name(u_char opt); |
371 | static const char *sppp_phase_name(int phase); | | 371 | static const char *sppp_phase_name(int phase); |
372 | static const char *sppp_proto_name(u_short proto); | | 372 | static const char *sppp_proto_name(u_short proto); |
373 | static const char *sppp_state_name(int state); | | 373 | static const char *sppp_state_name(int state); |
374 | static int sppp_params(struct sppp *sp, u_long cmd, void *data); | | 374 | static int sppp_params(struct sppp *sp, u_long cmd, void *data); |
375 | #ifdef INET | | 375 | #ifdef INET |
376 | static void sppp_get_ip_addrs(struct sppp *sp, uint32_t *src, uint32_t *dst, | | 376 | static void sppp_get_ip_addrs(struct sppp *sp, uint32_t *src, uint32_t *dst, |
377 | uint32_t *srcmask); | | 377 | uint32_t *srcmask); |
378 | static void sppp_set_ip_addrs(struct sppp *sp, uint32_t myaddr, uint32_t hisaddr); | | 378 | static void sppp_set_ip_addrs(struct sppp *sp, uint32_t myaddr, uint32_t hisaddr); |
379 | static void sppp_clear_ip_addrs(struct sppp *sp); | | 379 | static void sppp_clear_ip_addrs(struct sppp *sp); |
380 | #endif | | 380 | #endif |
381 | static void sppp_keepalive(void *dummy); | | 381 | static void sppp_keepalive(void *dummy); |
382 | static void sppp_phase_network(struct sppp *sp); | | 382 | static void sppp_phase_network(struct sppp *sp); |
383 | static void sppp_print_bytes(const u_char *p, u_short len); | | 383 | static void sppp_print_bytes(const u_char *p, u_short len); |
384 | static void sppp_print_string(const char *p, u_short len); | | 384 | static void sppp_print_string(const char *p, u_short len); |
385 | #ifdef INET6 | | 385 | #ifdef INET6 |
386 | static void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, | | 386 | static void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, |
387 | struct in6_addr *dst, struct in6_addr *srcmask); | | 387 | struct in6_addr *dst, struct in6_addr *srcmask); |
388 | #ifdef IPV6CP_MYIFID_DYN | | 388 | #ifdef IPV6CP_MYIFID_DYN |
389 | static void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); | | 389 | static void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); |
390 | static void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); | | 390 | static void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); |
391 | #endif | | 391 | #endif |
392 | static void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); | | 392 | static void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); |
393 | #endif | | 393 | #endif |
394 | | | 394 | |
395 | /* our control protocol descriptors */ | | 395 | /* our control protocol descriptors */ |
396 | static const struct cp lcp = { | | 396 | static const struct cp lcp = { |
397 | PPP_LCP, IDX_LCP, CP_LCP, "lcp", | | 397 | PPP_LCP, IDX_LCP, CP_LCP, "lcp", |
398 | sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, | | 398 | sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, |
399 | sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, | | 399 | sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, |
400 | sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, | | 400 | sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, |
401 | sppp_lcp_scr | | 401 | sppp_lcp_scr |
402 | }; | | 402 | }; |
403 | | | 403 | |
404 | static const struct cp ipcp = { | | 404 | static const struct cp ipcp = { |
405 | PPP_IPCP, IDX_IPCP, | | 405 | PPP_IPCP, IDX_IPCP, |
406 | #ifdef INET | | 406 | #ifdef INET |
407 | CP_NCP, /*don't run IPCP if there's no IPv4 support*/ | | 407 | CP_NCP, /*don't run IPCP if there's no IPv4 support*/ |
408 | #else | | 408 | #else |
409 | 0, | | 409 | 0, |
410 | #endif | | 410 | #endif |
411 | "ipcp", | | 411 | "ipcp", |
412 | sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, | | 412 | sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, |
413 | sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, | | 413 | sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, |
414 | sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, | | 414 | sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, |
415 | sppp_ipcp_scr | | 415 | sppp_ipcp_scr |
416 | }; | | 416 | }; |
417 | | | 417 | |
418 | static const struct cp ipv6cp = { | | 418 | static const struct cp ipv6cp = { |
419 | PPP_IPV6CP, IDX_IPV6CP, | | 419 | PPP_IPV6CP, IDX_IPV6CP, |
420 | #ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ | | 420 | #ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ |
421 | CP_NCP, | | 421 | CP_NCP, |
422 | #else | | 422 | #else |
423 | 0, | | 423 | 0, |
424 | #endif | | 424 | #endif |
425 | "ipv6cp", | | 425 | "ipv6cp", |
426 | sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, | | 426 | sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, |
427 | sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, | | 427 | sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, |
428 | sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, | | 428 | sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, |
429 | sppp_ipv6cp_scr | | 429 | sppp_ipv6cp_scr |
430 | }; | | 430 | }; |
431 | | | 431 | |
432 | static const struct cp pap = { | | 432 | static const struct cp pap = { |
433 | PPP_PAP, IDX_PAP, CP_AUTH, "pap", | | 433 | PPP_PAP, IDX_PAP, CP_AUTH, "pap", |
434 | sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, | | 434 | sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, |
435 | sppp_pap_TO, 0, 0, 0, | | 435 | sppp_pap_TO, 0, 0, 0, |
436 | sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, | | 436 | sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, |
437 | sppp_pap_scr | | 437 | sppp_pap_scr |
438 | }; | | 438 | }; |
439 | | | 439 | |
440 | static const struct cp chap = { | | 440 | static const struct cp chap = { |
441 | PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", | | 441 | PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", |
442 | sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, | | 442 | sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, |
443 | sppp_chap_TO, 0, 0, 0, | | 443 | sppp_chap_TO, 0, 0, 0, |
444 | sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, | | 444 | sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, |
445 | sppp_chap_scr | | 445 | sppp_chap_scr |
446 | }; | | 446 | }; |
447 | | | 447 | |
448 | static const struct cp *cps[IDX_COUNT] = { | | 448 | static const struct cp *cps[IDX_COUNT] = { |
449 | &lcp, /* IDX_LCP */ | | 449 | &lcp, /* IDX_LCP */ |
450 | &ipcp, /* IDX_IPCP */ | | 450 | &ipcp, /* IDX_IPCP */ |
451 | &ipv6cp, /* IDX_IPV6CP */ | | 451 | &ipv6cp, /* IDX_IPV6CP */ |
452 | &pap, /* IDX_PAP */ | | 452 | &pap, /* IDX_PAP */ |
453 | &chap, /* IDX_CHAP */ | | 453 | &chap, /* IDX_CHAP */ |
454 | }; | | 454 | }; |
455 | | | 455 | |
456 | | | 456 | |
457 | void spppattach(int); | | 457 | void spppattach(int); |
458 | void | | 458 | void |
459 | /*ARGSUSED*/ | | 459 | /*ARGSUSED*/ |
460 | spppattach(int count) | | 460 | spppattach(int count) |
461 | { | | 461 | { |
462 | } | | 462 | } |
463 | | | 463 | |
464 | /* | | 464 | /* |
465 | * Exported functions, comprising our interface to the lower layer. | | 465 | * Exported functions, comprising our interface to the lower layer. |
466 | */ | | 466 | */ |
467 | | | 467 | |
468 | /* | | 468 | /* |
469 | * Process the received packet. | | 469 | * Process the received packet. |
470 | */ | | 470 | */ |
471 | void | | 471 | void |
472 | sppp_input(struct ifnet *ifp, struct mbuf *m) | | 472 | sppp_input(struct ifnet *ifp, struct mbuf *m) |
473 | { | | 473 | { |
474 | struct ppp_header *h = NULL; | | 474 | struct ppp_header *h = NULL; |
475 | struct ifqueue *inq = 0; | | 475 | struct ifqueue *inq = 0; |
476 | uint16_t protocol; | | 476 | uint16_t protocol; |
477 | int s; | | 477 | int s; |
478 | struct sppp *sp = (struct sppp *)ifp; | | 478 | struct sppp *sp = (struct sppp *)ifp; |
479 | int debug = ifp->if_flags & IFF_DEBUG; | | 479 | int debug = ifp->if_flags & IFF_DEBUG; |
480 | | | 480 | |
481 | if (ifp->if_flags & IFF_UP) { | | 481 | if (ifp->if_flags & IFF_UP) { |
482 | /* Count received bytes, add hardware framing */ | | 482 | /* Count received bytes, add hardware framing */ |
483 | ifp->if_ibytes += m->m_pkthdr.len + sp->pp_framebytes; | | 483 | ifp->if_ibytes += m->m_pkthdr.len + sp->pp_framebytes; |
484 | /* Note time of last receive */ | | 484 | /* Note time of last receive */ |
485 | sp->pp_last_receive = time_uptime; | | 485 | sp->pp_last_receive = time_uptime; |
486 | } | | 486 | } |
487 | | | 487 | |
488 | if (m->m_pkthdr.len <= PPP_HEADER_LEN) { | | 488 | if (m->m_pkthdr.len <= PPP_HEADER_LEN) { |
489 | /* Too small packet, drop it. */ | | 489 | /* Too small packet, drop it. */ |
490 | if (debug) | | 490 | if (debug) |
491 | log(LOG_DEBUG, | | 491 | log(LOG_DEBUG, |
492 | "%s: input packet is too small, %d bytes\n", | | 492 | "%s: input packet is too small, %d bytes\n", |
493 | ifp->if_xname, m->m_pkthdr.len); | | 493 | ifp->if_xname, m->m_pkthdr.len); |
494 | drop: | | 494 | drop: |
495 | ++ifp->if_ierrors; | | 495 | ++ifp->if_ierrors; |
496 | ++ifp->if_iqdrops; | | 496 | ++ifp->if_iqdrops; |
497 | m_freem(m); | | 497 | m_freem(m); |
498 | return; | | 498 | return; |
499 | } | | 499 | } |
500 | | | 500 | |
501 | if (sp->pp_flags & PP_NOFRAMING) { | | 501 | if (sp->pp_flags & PP_NOFRAMING) { |
502 | memcpy(&protocol, mtod(m, void *), 2); | | 502 | memcpy(&protocol, mtod(m, void *), 2); |
503 | protocol = ntohs(protocol); | | 503 | protocol = ntohs(protocol); |
504 | m_adj(m, 2); | | 504 | m_adj(m, 2); |
505 | } else { | | 505 | } else { |
506 | | | 506 | |
507 | /* Get PPP header. */ | | 507 | /* Get PPP header. */ |
508 | h = mtod(m, struct ppp_header *); | | 508 | h = mtod(m, struct ppp_header *); |
509 | m_adj(m, PPP_HEADER_LEN); | | 509 | m_adj(m, PPP_HEADER_LEN); |
510 | | | 510 | |
511 | switch (h->address) { | | 511 | switch (h->address) { |
512 | case PPP_ALLSTATIONS: | | 512 | case PPP_ALLSTATIONS: |
513 | if (h->control != PPP_UI) | | 513 | if (h->control != PPP_UI) |
514 | goto invalid; | | 514 | goto invalid; |
515 | if (sp->pp_flags & PP_CISCO) { | | 515 | if (sp->pp_flags & PP_CISCO) { |
516 | if (debug) | | 516 | if (debug) |
517 | log(LOG_DEBUG, | | 517 | log(LOG_DEBUG, |
518 | "%s: PPP packet in Cisco mode " | | 518 | "%s: PPP packet in Cisco mode " |
519 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n", | | 519 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n", |
520 | ifp->if_xname, | | 520 | ifp->if_xname, |
521 | h->address, h->control, ntohs(h->protocol)); | | 521 | h->address, h->control, ntohs(h->protocol)); |
522 | goto drop; | | 522 | goto drop; |
523 | } | | 523 | } |
524 | break; | | 524 | break; |
525 | case CISCO_MULTICAST: | | 525 | case CISCO_MULTICAST: |
526 | case CISCO_UNICAST: | | 526 | case CISCO_UNICAST: |
527 | /* Don't check the control field here (RFC 1547). */ | | 527 | /* Don't check the control field here (RFC 1547). */ |
528 | if (! (sp->pp_flags & PP_CISCO)) { | | 528 | if (! (sp->pp_flags & PP_CISCO)) { |
529 | if (debug) | | 529 | if (debug) |
530 | log(LOG_DEBUG, | | 530 | log(LOG_DEBUG, |
531 | "%s: Cisco packet in PPP mode " | | 531 | "%s: Cisco packet in PPP mode " |
532 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n", | | 532 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n", |
533 | ifp->if_xname, | | 533 | ifp->if_xname, |
534 | h->address, h->control, ntohs(h->protocol)); | | 534 | h->address, h->control, ntohs(h->protocol)); |
535 | goto drop; | | 535 | goto drop; |
536 | } | | 536 | } |
537 | switch (ntohs(h->protocol)) { | | 537 | switch (ntohs(h->protocol)) { |
538 | default: | | 538 | default: |
539 | ++ifp->if_noproto; | | 539 | ++ifp->if_noproto; |
540 | goto invalid; | | 540 | goto invalid; |
541 | case CISCO_KEEPALIVE: | | 541 | case CISCO_KEEPALIVE: |
542 | sppp_cisco_input((struct sppp *) ifp, m); | | 542 | sppp_cisco_input((struct sppp *) ifp, m); |
543 | m_freem(m); | | 543 | m_freem(m); |
544 | return; | | 544 | return; |
545 | #ifdef INET | | 545 | #ifdef INET |
546 | case ETHERTYPE_IP: | | 546 | case ETHERTYPE_IP: |
547 | schednetisr(NETISR_IP); | | 547 | schednetisr(NETISR_IP); |
548 | inq = &ipintrq; | | 548 | inq = &ipintrq; |
549 | break; | | 549 | break; |
550 | #endif | | 550 | #endif |
551 | #ifdef INET6 | | 551 | #ifdef INET6 |
552 | case ETHERTYPE_IPV6: | | 552 | case ETHERTYPE_IPV6: |
553 | schednetisr(NETISR_IPV6); | | 553 | schednetisr(NETISR_IPV6); |
554 | inq = &ip6intrq; | | 554 | inq = &ip6intrq; |
555 | break; | | 555 | break; |
556 | #endif | | 556 | #endif |
557 | #ifdef IPX | | 557 | #ifdef IPX |
558 | case ETHERTYPE_IPX: | | 558 | case ETHERTYPE_IPX: |
559 | schednetisr(NETISR_IPX); | | 559 | schednetisr(NETISR_IPX); |
560 | inq = &ipxintrq; | | 560 | inq = &ipxintrq; |
561 | break; | | 561 | break; |
562 | #endif | | 562 | #endif |
563 | } | | 563 | } |
564 | goto queue_pkt; | | 564 | goto queue_pkt; |
565 | default: /* Invalid PPP packet. */ | | 565 | default: /* Invalid PPP packet. */ |
566 | invalid: | | 566 | invalid: |
567 | if (debug) | | 567 | if (debug) |
568 | log(LOG_DEBUG, | | 568 | log(LOG_DEBUG, |
569 | "%s: invalid input packet " | | 569 | "%s: invalid input packet " |
570 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n", | | 570 | "<addr=0x%x ctrl=0x%x proto=0x%x>\n", |
571 | ifp->if_xname, | | 571 | ifp->if_xname, |
572 | h->address, h->control, ntohs(h->protocol)); | | 572 | h->address, h->control, ntohs(h->protocol)); |
573 | goto drop; | | 573 | goto drop; |
574 | } | | 574 | } |
575 | protocol = ntohs(h->protocol); | | 575 | protocol = ntohs(h->protocol); |
576 | } | | 576 | } |
577 | | | 577 | |
578 | switch (protocol) { | | 578 | switch (protocol) { |
579 | default: | | 579 | default: |
580 | if (sp->state[IDX_LCP] == STATE_OPENED) { | | 580 | if (sp->state[IDX_LCP] == STATE_OPENED) { |
581 | uint16_t prot = htons(protocol); | | 581 | uint16_t prot = htons(protocol); |
582 | sppp_cp_send(sp, PPP_LCP, PROTO_REJ, | | 582 | sppp_cp_send(sp, PPP_LCP, PROTO_REJ, |
583 | ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, | | 583 | ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, |
584 | &prot); | | 584 | &prot); |
585 | } | | 585 | } |
586 | if (debug) | | 586 | if (debug) |
587 | log(LOG_DEBUG, | | 587 | log(LOG_DEBUG, |
588 | "%s: invalid input protocol " | | 588 | "%s: invalid input protocol " |
589 | "<proto=0x%x>\n", ifp->if_xname, ntohs(protocol)); | | 589 | "<proto=0x%x>\n", ifp->if_xname, ntohs(protocol)); |
590 | ++ifp->if_noproto; | | 590 | ++ifp->if_noproto; |
591 | goto drop; | | 591 | goto drop; |
592 | case PPP_LCP: | | 592 | case PPP_LCP: |
593 | sppp_cp_input(&lcp, sp, m); | | 593 | sppp_cp_input(&lcp, sp, m); |
594 | m_freem(m); | | 594 | m_freem(m); |
595 | return; | | 595 | return; |
596 | case PPP_PAP: | | 596 | case PPP_PAP: |
597 | if (sp->pp_phase >= SPPP_PHASE_AUTHENTICATE) | | 597 | if (sp->pp_phase >= SPPP_PHASE_AUTHENTICATE) |
598 | sppp_pap_input(sp, m); | | 598 | sppp_pap_input(sp, m); |
599 | m_freem(m); | | 599 | m_freem(m); |
600 | return; | | 600 | return; |
601 | case PPP_CHAP: | | 601 | case PPP_CHAP: |
602 | if (sp->pp_phase >= SPPP_PHASE_AUTHENTICATE) | | 602 | if (sp->pp_phase >= SPPP_PHASE_AUTHENTICATE) |
603 | sppp_chap_input(sp, m); | | 603 | sppp_chap_input(sp, m); |
604 | m_freem(m); | | 604 | m_freem(m); |
605 | return; | | 605 | return; |
606 | #ifdef INET | | 606 | #ifdef INET |
607 | case PPP_IPCP: | | 607 | case PPP_IPCP: |
608 | if (sp->pp_phase == SPPP_PHASE_NETWORK) | | 608 | if (sp->pp_phase == SPPP_PHASE_NETWORK) |
609 | sppp_cp_input(&ipcp, sp, m); | | 609 | sppp_cp_input(&ipcp, sp, m); |
610 | m_freem(m); | | 610 | m_freem(m); |
611 | return; | | 611 | return; |
612 | case PPP_IP: | | 612 | case PPP_IP: |
613 | if (sp->state[IDX_IPCP] == STATE_OPENED) { | | 613 | if (sp->state[IDX_IPCP] == STATE_OPENED) { |
614 | schednetisr(NETISR_IP); | | 614 | schednetisr(NETISR_IP); |
615 | inq = &ipintrq; | | 615 | inq = &ipintrq; |
616 | sp->pp_last_activity = time_uptime; | | 616 | sp->pp_last_activity = time_uptime; |
617 | } | | 617 | } |
618 | break; | | 618 | break; |
619 | #endif | | 619 | #endif |
620 | #ifdef INET6 | | 620 | #ifdef INET6 |
621 | case PPP_IPV6CP: | | 621 | case PPP_IPV6CP: |
622 | if (sp->pp_phase == SPPP_PHASE_NETWORK) | | 622 | if (sp->pp_phase == SPPP_PHASE_NETWORK) |
623 | sppp_cp_input(&ipv6cp, sp, m); | | 623 | sppp_cp_input(&ipv6cp, sp, m); |
624 | m_freem(m); | | 624 | m_freem(m); |
625 | return; | | 625 | return; |
626 | | | 626 | |
627 | case PPP_IPV6: | | 627 | case PPP_IPV6: |
628 | if (sp->state[IDX_IPV6CP] == STATE_OPENED) { | | 628 | if (sp->state[IDX_IPV6CP] == STATE_OPENED) { |
629 | schednetisr(NETISR_IPV6); | | 629 | schednetisr(NETISR_IPV6); |
630 | inq = &ip6intrq; | | 630 | inq = &ip6intrq; |
631 | sp->pp_last_activity = time_uptime; | | 631 | sp->pp_last_activity = time_uptime; |
632 | } | | 632 | } |
633 | break; | | 633 | break; |
634 | #endif | | 634 | #endif |
635 | #ifdef IPX | | 635 | #ifdef IPX |
636 | case PPP_IPX: | | 636 | case PPP_IPX: |
637 | /* IPX IPXCP not implemented yet */ | | 637 | /* IPX IPXCP not implemented yet */ |
638 | if (sp->pp_phase == SPPP_PHASE_NETWORK) { | | 638 | if (sp->pp_phase == SPPP_PHASE_NETWORK) { |
639 | schednetisr(NETISR_IPX); | | 639 | schednetisr(NETISR_IPX); |
640 | inq = &ipxintrq; | | 640 | inq = &ipxintrq; |
641 | } | | 641 | } |
642 | break; | | 642 | break; |
643 | #endif | | 643 | #endif |
644 | #ifdef ISO | | 644 | #ifdef ISO |
645 | case PPP_ISO: | | 645 | case PPP_ISO: |
646 | /* OSI NLCP not implemented yet */ | | 646 | /* OSI NLCP not implemented yet */ |
647 | if (sp->pp_phase == SPPP_PHASE_NETWORK) { | | 647 | if (sp->pp_phase == SPPP_PHASE_NETWORK) { |
648 | schednetisr(NETISR_ISO); | | 648 | schednetisr(NETISR_ISO); |
649 | inq = &clnlintrq; | | 649 | inq = &clnlintrq; |
650 | } | | 650 | } |
651 | break; | | 651 | break; |
652 | #endif | | 652 | #endif |
653 | } | | 653 | } |
654 | | | 654 | |
655 | queue_pkt: | | 655 | queue_pkt: |
656 | if (! (ifp->if_flags & IFF_UP) || ! inq) | | 656 | if (! (ifp->if_flags & IFF_UP) || ! inq) |
657 | goto drop; | | 657 | goto drop; |
658 | | | 658 | |
659 | /* Check queue. */ | | 659 | /* Check queue. */ |
660 | s = splnet(); | | 660 | s = splnet(); |
661 | if (IF_QFULL(inq)) { | | 661 | if (IF_QFULL(inq)) { |
662 | /* Queue overflow. */ | | 662 | /* Queue overflow. */ |
663 | IF_DROP(inq); | | 663 | IF_DROP(inq); |
664 | splx(s); | | 664 | splx(s); |
665 | if (debug) | | 665 | if (debug) |
666 | log(LOG_DEBUG, "%s: protocol queue overflow\n", | | 666 | log(LOG_DEBUG, "%s: protocol queue overflow\n", |
667 | ifp->if_xname); | | 667 | ifp->if_xname); |
668 | goto drop; | | 668 | goto drop; |
669 | } | | 669 | } |
670 | IF_ENQUEUE(inq, m); | | 670 | IF_ENQUEUE(inq, m); |
671 | splx(s); | | 671 | splx(s); |
672 | } | | 672 | } |
673 | | | 673 | |
674 | /* | | 674 | /* |
675 | * Enqueue transmit packet. | | 675 | * Enqueue transmit packet. |
676 | */ | | 676 | */ |
677 | static int | | 677 | static int |
678 | sppp_output(struct ifnet *ifp, struct mbuf *m, | | 678 | sppp_output(struct ifnet *ifp, struct mbuf *m, |
679 | const struct sockaddr *dst, struct rtentry *rt) | | 679 | const struct sockaddr *dst, struct rtentry *rt) |
680 | { | | 680 | { |
681 | struct sppp *sp = (struct sppp *) ifp; | | 681 | struct sppp *sp = (struct sppp *) ifp; |
682 | struct ppp_header *h = NULL; | | 682 | struct ppp_header *h = NULL; |
683 | struct ifqueue *ifq = NULL; /* XXX */ | | 683 | struct ifqueue *ifq = NULL; /* XXX */ |
684 | int s, error = 0; | | 684 | int s, error = 0; |
685 | uint16_t protocol; | | 685 | uint16_t protocol; |
686 | ALTQ_DECL(struct altq_pktattr pktattr;) | | 686 | ALTQ_DECL(struct altq_pktattr pktattr;) |
687 | | | 687 | |
688 | s = splnet(); | | 688 | s = splnet(); |
689 | | | 689 | |
690 | sp->pp_last_activity = time_uptime; | | 690 | sp->pp_last_activity = time_uptime; |
691 | | | 691 | |
692 | if ((ifp->if_flags & IFF_UP) == 0 || | | 692 | if ((ifp->if_flags & IFF_UP) == 0 || |
693 | (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { | | 693 | (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { |
694 | m_freem(m); | | 694 | m_freem(m); |
695 | splx(s); | | 695 | splx(s); |
696 | return (ENETDOWN); | | 696 | return (ENETDOWN); |
697 | } | | 697 | } |
698 | | | 698 | |
699 | if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { | | 699 | if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { |
700 | /* | | 700 | /* |
701 | * Interface is not yet running, but auto-dial. Need | | 701 | * Interface is not yet running, but auto-dial. Need |
702 | * to start LCP for it. | | 702 | * to start LCP for it. |
703 | */ | | 703 | */ |
704 | ifp->if_flags |= IFF_RUNNING; | | 704 | ifp->if_flags |= IFF_RUNNING; |
705 | splx(s); | | 705 | splx(s); |
706 | lcp.Open(sp); | | 706 | lcp.Open(sp); |
707 | s = splnet(); | | 707 | s = splnet(); |
708 | } | | 708 | } |
709 | | | 709 | |
710 | /* | | 710 | /* |
711 | * If the queueing discipline needs packet classification, | | 711 | * If the queueing discipline needs packet classification, |
712 | * do it before prepending link headers. | | 712 | * do it before prepending link headers. |
713 | */ | | 713 | */ |
714 | IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); | | 714 | IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); |
715 | | | 715 | |
716 | #ifdef INET | | 716 | #ifdef INET |
717 | if (dst->sa_family == AF_INET) { | | 717 | if (dst->sa_family == AF_INET) { |
718 | struct ip *ip = NULL; | | 718 | struct ip *ip = NULL; |
719 | struct tcphdr *th = NULL; | | 719 | struct tcphdr *th = NULL; |
720 | | | 720 | |
721 | if (m->m_len >= sizeof(struct ip)) { | | 721 | if (m->m_len >= sizeof(struct ip)) { |
722 | ip = mtod(m, struct ip *); | | 722 | ip = mtod(m, struct ip *); |
723 | if (ip->ip_p == IPPROTO_TCP && | | 723 | if (ip->ip_p == IPPROTO_TCP && |
724 | m->m_len >= sizeof(struct ip) + (ip->ip_hl << 2) + | | 724 | m->m_len >= sizeof(struct ip) + (ip->ip_hl << 2) + |
725 | sizeof(struct tcphdr)) { | | 725 | sizeof(struct tcphdr)) { |
726 | th = (struct tcphdr *) | | 726 | th = (struct tcphdr *) |
727 | ((char *)ip + (ip->ip_hl << 2)); | | 727 | ((char *)ip + (ip->ip_hl << 2)); |
728 | } | | 728 | } |
729 | } else | | 729 | } else |
730 | ip = NULL; | | 730 | ip = NULL; |
731 | | | 731 | |
732 | /* | | 732 | /* |
733 | * When using dynamic local IP address assignment by using | | 733 | * When using dynamic local IP address assignment by using |
734 | * 0.0.0.0 as a local address, the first TCP session will | | 734 | * 0.0.0.0 as a local address, the first TCP session will |
735 | * not connect because the local TCP checksum is computed | | 735 | * not connect because the local TCP checksum is computed |
736 | * using 0.0.0.0 which will later become our real IP address | | 736 | * using 0.0.0.0 which will later become our real IP address |
737 | * so the TCP checksum computed at the remote end will | | 737 | * so the TCP checksum computed at the remote end will |
738 | * become invalid. So we | | 738 | * become invalid. So we |
739 | * - don't let packets with src ip addr 0 thru | | 739 | * - don't let packets with src ip addr 0 thru |
740 | * - we flag TCP packets with src ip 0 as an error | | 740 | * - we flag TCP packets with src ip 0 as an error |
741 | */ | | 741 | */ |
742 | if (ip && ip->ip_src.s_addr == INADDR_ANY) { | | 742 | if (ip && ip->ip_src.s_addr == INADDR_ANY) { |
743 | uint8_t proto = ip->ip_p; | | 743 | uint8_t proto = ip->ip_p; |
744 | | | 744 | |
745 | m_freem(m); | | 745 | m_freem(m); |
746 | splx(s); | | 746 | splx(s); |
747 | if (proto == IPPROTO_TCP) | | 747 | if (proto == IPPROTO_TCP) |
748 | return (EADDRNOTAVAIL); | | 748 | return (EADDRNOTAVAIL); |
749 | else | | 749 | else |
750 | return (0); | | 750 | return (0); |
751 | } | | 751 | } |
752 | | | 752 | |
753 | /* | | 753 | /* |
754 | * Put low delay, telnet, rlogin and ftp control packets | | 754 | * Put low delay, telnet, rlogin and ftp control packets |
755 | * in front of the queue. | | 755 | * in front of the queue. |
756 | */ | | 756 | */ |
757 | | | 757 | |
758 | if (!IF_QFULL(&sp->pp_fastq) && | | 758 | if (!IF_QFULL(&sp->pp_fastq) && |
759 | ((ip && (ip->ip_tos & IPTOS_LOWDELAY)) || | | 759 | ((ip && (ip->ip_tos & IPTOS_LOWDELAY)) || |
760 | (th && (INTERACTIVE(ntohs(th->th_sport)) || | | 760 | (th && (INTERACTIVE(ntohs(th->th_sport)) || |
761 | INTERACTIVE(ntohs(th->th_dport)))))) | | 761 | INTERACTIVE(ntohs(th->th_dport)))))) |
762 | ifq = &sp->pp_fastq; | | 762 | ifq = &sp->pp_fastq; |
763 | } | | 763 | } |
764 | #endif | | 764 | #endif |
765 | | | 765 | |
766 | #ifdef INET6 | | 766 | #ifdef INET6 |
767 | if (dst->sa_family == AF_INET6) { | | 767 | if (dst->sa_family == AF_INET6) { |
768 | /* XXX do something tricky here? */ | | 768 | /* XXX do something tricky here? */ |
769 | } | | 769 | } |
770 | #endif | | 770 | #endif |
771 | | | 771 | |
772 | if ((sp->pp_flags & PP_NOFRAMING) == 0) { | | 772 | if ((sp->pp_flags & PP_NOFRAMING) == 0) { |
773 | /* | | 773 | /* |
774 | * Prepend general data packet PPP header. For now, IP only. | | 774 | * Prepend general data packet PPP header. For now, IP only. |
775 | */ | | 775 | */ |
776 | M_PREPEND(m, PPP_HEADER_LEN, M_DONTWAIT); | | 776 | M_PREPEND(m, PPP_HEADER_LEN, M_DONTWAIT); |
777 | if (! m) { | | 777 | if (! m) { |
778 | if (ifp->if_flags & IFF_DEBUG) | | 778 | if (ifp->if_flags & IFF_DEBUG) |
779 | log(LOG_DEBUG, "%s: no memory for transmit header\n", | | 779 | log(LOG_DEBUG, "%s: no memory for transmit header\n", |
780 | ifp->if_xname); | | 780 | ifp->if_xname); |
781 | ++ifp->if_oerrors; | | 781 | ++ifp->if_oerrors; |
782 | splx(s); | | 782 | splx(s); |
783 | return (ENOBUFS); | | 783 | return (ENOBUFS); |
784 | } | | 784 | } |
785 | /* | | 785 | /* |
786 | * May want to check size of packet | | 786 | * May want to check size of packet |
787 | * (albeit due to the implementation it's always enough) | | 787 | * (albeit due to the implementation it's always enough) |
788 | */ | | 788 | */ |
789 | h = mtod(m, struct ppp_header *); | | 789 | h = mtod(m, struct ppp_header *); |
790 | if (sp->pp_flags & PP_CISCO) { | | 790 | if (sp->pp_flags & PP_CISCO) { |
791 | h->address = CISCO_UNICAST; /* unicast address */ | | 791 | h->address = CISCO_UNICAST; /* unicast address */ |
792 | h->control = 0; | | 792 | h->control = 0; |
793 | } else { | | 793 | } else { |
794 | h->address = PPP_ALLSTATIONS; /* broadcast address */ | | 794 | h->address = PPP_ALLSTATIONS; /* broadcast address */ |
795 | h->control = PPP_UI; /* Unnumbered Info */ | | 795 | h->control = PPP_UI; /* Unnumbered Info */ |
796 | } | | 796 | } |
797 | } | | 797 | } |
798 | | | 798 | |
799 | switch (dst->sa_family) { | | 799 | switch (dst->sa_family) { |
800 | #ifdef INET | | 800 | #ifdef INET |
801 | case AF_INET: /* Internet Protocol */ | | 801 | case AF_INET: /* Internet Protocol */ |
802 | if (sp->pp_flags & PP_CISCO) | | 802 | if (sp->pp_flags & PP_CISCO) |
803 | protocol = htons(ETHERTYPE_IP); | | 803 | protocol = htons(ETHERTYPE_IP); |
804 | else { | | 804 | else { |
805 | /* | | 805 | /* |
806 | * Don't choke with an ENETDOWN early. It's | | 806 | * Don't choke with an ENETDOWN early. It's |
807 | * possible that we just started dialing out, | | 807 | * possible that we just started dialing out, |
808 | * so don't drop the packet immediately. If | | 808 | * so don't drop the packet immediately. If |
809 | * we notice that we run out of buffer space | | 809 | * we notice that we run out of buffer space |
810 | * below, we will however remember that we are | | 810 | * below, we will however remember that we are |
811 | * not ready to carry IP packets, and return | | 811 | * not ready to carry IP packets, and return |
812 | * ENETDOWN, as opposed to ENOBUFS. | | 812 | * ENETDOWN, as opposed to ENOBUFS. |
813 | */ | | 813 | */ |
814 | protocol = htons(PPP_IP); | | 814 | protocol = htons(PPP_IP); |
815 | if (sp->state[IDX_IPCP] != STATE_OPENED) | | 815 | if (sp->state[IDX_IPCP] != STATE_OPENED) |
816 | error = ENETDOWN; | | 816 | error = ENETDOWN; |
817 | } | | 817 | } |
818 | break; | | 818 | break; |
819 | #endif | | 819 | #endif |
820 | #ifdef INET6 | | 820 | #ifdef INET6 |
821 | case AF_INET6: /* Internet Protocol version 6 */ | | 821 | case AF_INET6: /* Internet Protocol version 6 */ |
822 | if (sp->pp_flags & PP_CISCO) | | 822 | if (sp->pp_flags & PP_CISCO) |
823 | protocol = htons(ETHERTYPE_IPV6); | | 823 | protocol = htons(ETHERTYPE_IPV6); |
824 | else { | | 824 | else { |
825 | /* | | 825 | /* |
826 | * Don't choke with an ENETDOWN early. It's | | 826 | * Don't choke with an ENETDOWN early. It's |
827 | * possible that we just started dialing out, | | 827 | * possible that we just started dialing out, |
828 | * so don't drop the packet immediately. If | | 828 | * so don't drop the packet immediately. If |
829 | * we notice that we run out of buffer space | | 829 | * we notice that we run out of buffer space |
830 | * below, we will however remember that we are | | 830 | * below, we will however remember that we are |
831 | * not ready to carry IP packets, and return | | 831 | * not ready to carry IP packets, and return |
832 | * ENETDOWN, as opposed to ENOBUFS. | | 832 | * ENETDOWN, as opposed to ENOBUFS. |
833 | */ | | 833 | */ |
834 | protocol = htons(PPP_IPV6); | | 834 | protocol = htons(PPP_IPV6); |
835 | if (sp->state[IDX_IPV6CP] != STATE_OPENED) | | 835 | if (sp->state[IDX_IPV6CP] != STATE_OPENED) |
836 | error = ENETDOWN; | | 836 | error = ENETDOWN; |
837 | } | | 837 | } |
838 | break; | | 838 | break; |
839 | #endif | | 839 | #endif |
840 | #ifdef IPX | | 840 | #ifdef IPX |
841 | case AF_IPX: /* Novell IPX Protocol */ | | 841 | case AF_IPX: /* Novell IPX Protocol */ |
842 | protocol = htons((sp->pp_flags & PP_CISCO) ? | | 842 | protocol = htons((sp->pp_flags & PP_CISCO) ? |
843 | ETHERTYPE_IPX : PPP_IPX); | | 843 | ETHERTYPE_IPX : PPP_IPX); |
844 | break; | | 844 | break; |
845 | #endif | | 845 | #endif |
846 | #ifdef ISO | | 846 | #ifdef ISO |
847 | case AF_ISO: /* ISO OSI Protocol */ | | 847 | case AF_ISO: /* ISO OSI Protocol */ |
848 | if (sp->pp_flags & PP_CISCO) | | 848 | if (sp->pp_flags & PP_CISCO) |
849 | goto nosupport; | | 849 | goto nosupport; |
850 | protocol = htons(PPP_ISO); | | 850 | protocol = htons(PPP_ISO); |
851 | break; | | 851 | break; |
852 | nosupport: | | 852 | nosupport: |
853 | #endif | | 853 | #endif |
854 | default: | | 854 | default: |
855 | m_freem(m); | | 855 | m_freem(m); |
856 | ++ifp->if_oerrors; | | 856 | ++ifp->if_oerrors; |
857 | splx(s); | | 857 | splx(s); |
858 | return (EAFNOSUPPORT); | | 858 | return (EAFNOSUPPORT); |
859 | } | | 859 | } |
860 | | | 860 | |
861 | if (sp->pp_flags & PP_NOFRAMING) { | | 861 | if (sp->pp_flags & PP_NOFRAMING) { |
862 | M_PREPEND(m, 2, M_DONTWAIT); | | 862 | M_PREPEND(m, 2, M_DONTWAIT); |
863 | if (m == NULL) { | | 863 | if (m == NULL) { |
864 | if (ifp->if_flags & IFF_DEBUG) | | 864 | if (ifp->if_flags & IFF_DEBUG) |
865 | log(LOG_DEBUG, "%s: no memory for transmit header\n", | | 865 | log(LOG_DEBUG, "%s: no memory for transmit header\n", |
866 | ifp->if_xname); | | 866 | ifp->if_xname); |
867 | ++ifp->if_oerrors; | | 867 | ++ifp->if_oerrors; |
868 | splx(s); | | 868 | splx(s); |
869 | return (ENOBUFS); | | 869 | return (ENOBUFS); |
870 | } | | 870 | } |
871 | *mtod(m, uint16_t *) = protocol; | | 871 | *mtod(m, uint16_t *) = protocol; |
872 | } else { | | 872 | } else { |
873 | h->protocol = protocol; | | 873 | h->protocol = protocol; |
874 | } | | 874 | } |
875 | | | 875 | |
876 | | | 876 | |
877 | error = ifq_enqueue2(ifp, ifq, m ALTQ_COMMA ALTQ_DECL(&pktattr)); | | 877 | error = ifq_enqueue2(ifp, ifq, m ALTQ_COMMA ALTQ_DECL(&pktattr)); |
878 | | | 878 | |
879 | if (error == 0) { | | 879 | if (error == 0) { |
880 | /* | | 880 | /* |
881 | * Count output packets and bytes. | | 881 | * Count output packets and bytes. |
882 | * The packet length includes header + additional hardware | | 882 | * The packet length includes header + additional hardware |
883 | * framing according to RFC 1333. | | 883 | * framing according to RFC 1333. |
884 | */ | | 884 | */ |
885 | if (!(ifp->if_flags & IFF_OACTIVE)) | | 885 | if (!(ifp->if_flags & IFF_OACTIVE)) |
886 | (*ifp->if_start)(ifp); | | 886 | (*ifp->if_start)(ifp); |
887 | ifp->if_obytes += m->m_pkthdr.len + sp->pp_framebytes; | | 887 | ifp->if_obytes += m->m_pkthdr.len + sp->pp_framebytes; |
888 | } | | 888 | } |
889 | splx(s); | | 889 | splx(s); |
890 | return error; | | 890 | return error; |
891 | } | | 891 | } |
892 | | | 892 | |
893 | void | | 893 | void |
894 | sppp_attach(struct ifnet *ifp) | | 894 | sppp_attach(struct ifnet *ifp) |
895 | { | | 895 | { |
896 | struct sppp *sp = (struct sppp *) ifp; | | 896 | struct sppp *sp = (struct sppp *) ifp; |
897 | | | 897 | |
898 | /* Initialize keepalive handler. */ | | 898 | /* Initialize keepalive handler. */ |
899 | if (! spppq) { | | 899 | if (! spppq) { |
900 | callout_init(&keepalive_ch, 0); | | 900 | callout_init(&keepalive_ch, 0); |
901 | callout_reset(&keepalive_ch, hz * LCP_KEEPALIVE_INTERVAL, sppp_keepalive, NULL); | | 901 | callout_reset(&keepalive_ch, hz * LCP_KEEPALIVE_INTERVAL, sppp_keepalive, NULL); |
902 | } | | 902 | } |
903 | | | 903 | |
904 | /* Insert new entry into the keepalive list. */ | | 904 | /* Insert new entry into the keepalive list. */ |
905 | sp->pp_next = spppq; | | 905 | sp->pp_next = spppq; |
906 | spppq = sp; | | 906 | spppq = sp; |
907 | | | 907 | |
908 | sp->pp_if.if_type = IFT_PPP; | | 908 | sp->pp_if.if_type = IFT_PPP; |
909 | sp->pp_if.if_output = sppp_output; | | 909 | sp->pp_if.if_output = sppp_output; |
910 | sp->pp_fastq.ifq_maxlen = 32; | | 910 | sp->pp_fastq.ifq_maxlen = 32; |
911 | sp->pp_cpq.ifq_maxlen = 20; | | 911 | sp->pp_cpq.ifq_maxlen = 20; |
912 | sp->pp_loopcnt = 0; | | 912 | sp->pp_loopcnt = 0; |
913 | sp->pp_alivecnt = 0; | | 913 | sp->pp_alivecnt = 0; |
914 | sp->pp_last_activity = 0; | | 914 | sp->pp_last_activity = 0; |
915 | sp->pp_last_receive = 0; | | 915 | sp->pp_last_receive = 0; |
916 | sp->pp_maxalive = DEFAULT_MAXALIVECNT; | | 916 | sp->pp_maxalive = DEFAULT_MAXALIVECNT; |
917 | sp->pp_max_noreceive = DEFAULT_NORECV_TIME; | | 917 | sp->pp_max_noreceive = DEFAULT_NORECV_TIME; |
918 | sp->pp_idle_timeout = 0; | | 918 | sp->pp_idle_timeout = 0; |
919 | memset(&sp->pp_seq[0], 0, sizeof(sp->pp_seq)); | | 919 | memset(&sp->pp_seq[0], 0, sizeof(sp->pp_seq)); |
920 | memset(&sp->pp_rseq[0], 0, sizeof(sp->pp_rseq)); | | 920 | memset(&sp->pp_rseq[0], 0, sizeof(sp->pp_rseq)); |
921 | sp->pp_auth_failures = 0; | | 921 | sp->pp_auth_failures = 0; |
922 | sp->pp_max_auth_fail = DEFAULT_MAX_AUTH_FAILURES; | | 922 | sp->pp_max_auth_fail = DEFAULT_MAX_AUTH_FAILURES; |
923 | sp->pp_phase = SPPP_PHASE_DEAD; | | 923 | sp->pp_phase = SPPP_PHASE_DEAD; |
924 | sp->pp_up = lcp.Up; | | 924 | sp->pp_up = lcp.Up; |
925 | sp->pp_down = lcp.Down; | | 925 | sp->pp_down = lcp.Down; |
926 | | | 926 | |
927 | if_alloc_sadl(ifp); | | 927 | if_alloc_sadl(ifp); |
928 | | | 928 | |
929 | memset(&sp->myauth, 0, sizeof sp->myauth); | | 929 | memset(&sp->myauth, 0, sizeof sp->myauth); |
930 | memset(&sp->hisauth, 0, sizeof sp->hisauth); | | 930 | memset(&sp->hisauth, 0, sizeof sp->hisauth); |
931 | sppp_lcp_init(sp); | | 931 | sppp_lcp_init(sp); |
932 | sppp_ipcp_init(sp); | | 932 | sppp_ipcp_init(sp); |
933 | sppp_ipv6cp_init(sp); | | 933 | sppp_ipv6cp_init(sp); |
934 | sppp_pap_init(sp); | | 934 | sppp_pap_init(sp); |
935 | sppp_chap_init(sp); | | 935 | sppp_chap_init(sp); |
936 | } | | 936 | } |
937 | | | 937 | |
938 | void | | 938 | void |
939 | sppp_detach(struct ifnet *ifp) | | 939 | sppp_detach(struct ifnet *ifp) |
940 | { | | 940 | { |
941 | struct sppp **q, *p, *sp = (struct sppp *) ifp; | | 941 | struct sppp **q, *p, *sp = (struct sppp *) ifp; |
942 | | | 942 | |
943 | /* Remove the entry from the keepalive list. */ | | 943 | /* Remove the entry from the keepalive list. */ |
944 | for (q = &spppq; (p = *q); q = &p->pp_next) | | 944 | for (q = &spppq; (p = *q); q = &p->pp_next) |
945 | if (p == sp) { | | 945 | if (p == sp) { |
946 | *q = p->pp_next; | | 946 | *q = p->pp_next; |
947 | break; | | 947 | break; |
948 | } | | 948 | } |
949 | | | 949 | |
950 | /* Stop keepalive handler. */ | | 950 | /* Stop keepalive handler. */ |
951 | if (! spppq) { | | 951 | if (! spppq) { |
952 | callout_stop(&keepalive_ch); | | 952 | callout_stop(&keepalive_ch); |
953 | } | | 953 | } |
954 | | | 954 | |
955 | callout_stop(&sp->ch[IDX_LCP]); | | 955 | callout_stop(&sp->ch[IDX_LCP]); |
956 | callout_stop(&sp->ch[IDX_IPCP]); | | 956 | callout_stop(&sp->ch[IDX_IPCP]); |
957 | callout_stop(&sp->ch[IDX_PAP]); | | 957 | callout_stop(&sp->ch[IDX_PAP]); |
958 | callout_stop(&sp->ch[IDX_CHAP]); | | 958 | callout_stop(&sp->ch[IDX_CHAP]); |
959 | #ifdef INET6 | | 959 | #ifdef INET6 |
960 | callout_stop(&sp->ch[IDX_IPV6CP]); | | 960 | callout_stop(&sp->ch[IDX_IPV6CP]); |
961 | #endif | | 961 | #endif |
962 | callout_stop(&sp->pap_my_to_ch); | | 962 | callout_stop(&sp->pap_my_to_ch); |
963 | | | 963 | |
964 | /* free authentication info */ | | 964 | /* free authentication info */ |
965 | if (sp->myauth.name) free(sp->myauth.name, M_DEVBUF); | | 965 | if (sp->myauth.name) free(sp->myauth.name, M_DEVBUF); |
966 | if (sp->myauth.secret) free(sp->myauth.secret, M_DEVBUF); | | 966 | if (sp->myauth.secret) free(sp->myauth.secret, M_DEVBUF); |
967 | if (sp->hisauth.name) free(sp->hisauth.name, M_DEVBUF); | | 967 | if (sp->hisauth.name) free(sp->hisauth.name, M_DEVBUF); |
968 | if (sp->hisauth.secret) free(sp->hisauth.secret, M_DEVBUF); | | 968 | if (sp->hisauth.secret) free(sp->hisauth.secret, M_DEVBUF); |
969 | | | 969 | |
970 | #if 0 /* done in if_detach() */ | | 970 | #if 0 /* done in if_detach() */ |
971 | if_free_sadl(ifp); | | 971 | if_free_sadl(ifp); |
972 | #endif | | 972 | #endif |
973 | } | | 973 | } |
974 | | | 974 | |
975 | /* | | 975 | /* |
976 | * Flush the interface output queue. | | 976 | * Flush the interface output queue. |
977 | */ | | 977 | */ |
978 | void | | 978 | void |
979 | sppp_flush(struct ifnet *ifp) | | 979 | sppp_flush(struct ifnet *ifp) |
980 | { | | 980 | { |
981 | struct sppp *sp = (struct sppp *) ifp; | | 981 | struct sppp *sp = (struct sppp *) ifp; |
982 | | | 982 | |
983 | IFQ_PURGE(&sp->pp_if.if_snd); | | 983 | IFQ_PURGE(&sp->pp_if.if_snd); |
984 | IF_PURGE(&sp->pp_fastq); | | 984 | IF_PURGE(&sp->pp_fastq); |
985 | IF_PURGE(&sp->pp_cpq); | | 985 | IF_PURGE(&sp->pp_cpq); |
986 | } | | 986 | } |
987 | | | 987 | |
988 | /* | | 988 | /* |
989 | * Check if the output queue is empty. | | 989 | * Check if the output queue is empty. |
990 | */ | | 990 | */ |
991 | int | | 991 | int |
992 | sppp_isempty(struct ifnet *ifp) | | 992 | sppp_isempty(struct ifnet *ifp) |
993 | { | | 993 | { |
994 | struct sppp *sp = (struct sppp *) ifp; | | 994 | struct sppp *sp = (struct sppp *) ifp; |
995 | int empty, s; | | 995 | int empty, s; |
996 | | | 996 | |
997 | s = splnet(); | | 997 | s = splnet(); |
998 | empty = IF_IS_EMPTY(&sp->pp_fastq) && IF_IS_EMPTY(&sp->pp_cpq) && | | 998 | empty = IF_IS_EMPTY(&sp->pp_fastq) && IF_IS_EMPTY(&sp->pp_cpq) && |
999 | IFQ_IS_EMPTY(&sp->pp_if.if_snd); | | 999 | IFQ_IS_EMPTY(&sp->pp_if.if_snd); |
1000 | splx(s); | | 1000 | splx(s); |
1001 | return (empty); | | 1001 | return (empty); |
1002 | } | | 1002 | } |
1003 | | | 1003 | |
1004 | /* | | 1004 | /* |
1005 | * Get next packet to send. | | 1005 | * Get next packet to send. |
1006 | */ | | 1006 | */ |
1007 | struct mbuf * | | 1007 | struct mbuf * |
1008 | sppp_dequeue(struct ifnet *ifp) | | 1008 | sppp_dequeue(struct ifnet *ifp) |
1009 | { | | 1009 | { |
1010 | struct sppp *sp = (struct sppp *) ifp; | | 1010 | struct sppp *sp = (struct sppp *) ifp; |
1011 | struct mbuf *m; | | 1011 | struct mbuf *m; |
1012 | int s; | | 1012 | int s; |
1013 | | | 1013 | |
1014 | s = splnet(); | | 1014 | s = splnet(); |
1015 | /* | | 1015 | /* |
1016 | * Process only the control protocol queue until we have at | | 1016 | * Process only the control protocol queue until we have at |
1017 | * least one NCP open. | | 1017 | * least one NCP open. |
1018 | * | | 1018 | * |
1019 | * Do always serve all three queues in Cisco mode. | | 1019 | * Do always serve all three queues in Cisco mode. |
1020 | */ | | 1020 | */ |
1021 | IF_DEQUEUE(&sp->pp_cpq, m); | | 1021 | IF_DEQUEUE(&sp->pp_cpq, m); |
1022 | if (m == NULL && | | 1022 | if (m == NULL && |
1023 | (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) { | | 1023 | (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) { |
1024 | IF_DEQUEUE(&sp->pp_fastq, m); | | 1024 | IF_DEQUEUE(&sp->pp_fastq, m); |
1025 | if (m == NULL) | | 1025 | if (m == NULL) |
1026 | IFQ_DEQUEUE(&sp->pp_if.if_snd, m); | | 1026 | IFQ_DEQUEUE(&sp->pp_if.if_snd, m); |
1027 | } | | 1027 | } |
1028 | splx(s); | | 1028 | splx(s); |
1029 | return m; | | 1029 | return m; |
1030 | } | | 1030 | } |
1031 | | | 1031 | |
1032 | /* | | 1032 | /* |
1033 | * Process an ioctl request. Called on low priority level. | | 1033 | * Process an ioctl request. Called on low priority level. |
1034 | */ | | 1034 | */ |
1035 | int | | 1035 | int |
1036 | sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data) | | 1036 | sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
1037 | { | | 1037 | { |
1038 | struct lwp *l = curlwp; /* XXX */ | | 1038 | struct lwp *l = curlwp; /* XXX */ |
1039 | struct ifreq *ifr = (struct ifreq *) data; | | 1039 | struct ifreq *ifr = (struct ifreq *) data; |
1040 | struct sppp *sp = (struct sppp *) ifp; | | 1040 | struct sppp *sp = (struct sppp *) ifp; |
1041 | int s, error=0, going_up, going_down, newmode; | | 1041 | int s, error=0, going_up, going_down, newmode; |
1042 | | | 1042 | |
1043 | s = splnet(); | | 1043 | s = splnet(); |
| @@ -2454,1999 +2454,1999 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct | | | @@ -2454,1999 +2454,1999 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct |
2454 | if (debug) | | 2454 | if (debug) |
2455 | addlog(" %s", sppp_lcp_opt_name(*p)); | | 2455 | addlog(" %s", sppp_lcp_opt_name(*p)); |
2456 | switch (*p) { | | 2456 | switch (*p) { |
2457 | case LCP_OPT_MAGIC: | | 2457 | case LCP_OPT_MAGIC: |
2458 | /* Magic number -- renegotiate */ | | 2458 | /* Magic number -- renegotiate */ |
2459 | if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && | | 2459 | if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && |
2460 | len >= 6 && p[1] == 6) { | | 2460 | len >= 6 && p[1] == 6) { |
2461 | magic = (uint32_t)p[2] << 24 | | | 2461 | magic = (uint32_t)p[2] << 24 | |
2462 | (uint32_t)p[3] << 16 | p[4] << 8 | p[5]; | | 2462 | (uint32_t)p[3] << 16 | p[4] << 8 | p[5]; |
2463 | /* | | 2463 | /* |
2464 | * If the remote magic is our negated one, | | 2464 | * If the remote magic is our negated one, |
2465 | * this looks like a loopback problem. | | 2465 | * this looks like a loopback problem. |
2466 | * Suggest a new magic to make sure. | | 2466 | * Suggest a new magic to make sure. |
2467 | */ | | 2467 | */ |
2468 | if (magic == ~sp->lcp.magic) { | | 2468 | if (magic == ~sp->lcp.magic) { |
2469 | if (debug) | | 2469 | if (debug) |
2470 | addlog(" magic glitch"); | | 2470 | addlog(" magic glitch"); |
2471 | sp->lcp.magic = arc4random(); | | 2471 | sp->lcp.magic = arc4random(); |
2472 | } else { | | 2472 | } else { |
2473 | sp->lcp.magic = magic; | | 2473 | sp->lcp.magic = magic; |
2474 | if (debug) | | 2474 | if (debug) |
2475 | addlog(" %d", magic); | | 2475 | addlog(" %d", magic); |
2476 | } | | 2476 | } |
2477 | } | | 2477 | } |
2478 | break; | | 2478 | break; |
2479 | case LCP_OPT_MRU: | | 2479 | case LCP_OPT_MRU: |
2480 | /* | | 2480 | /* |
2481 | * Peer wants to advise us to negotiate an MRU. | | 2481 | * Peer wants to advise us to negotiate an MRU. |
2482 | * Agree on it if it's reasonable, or use | | 2482 | * Agree on it if it's reasonable, or use |
2483 | * default otherwise. | | 2483 | * default otherwise. |
2484 | */ | | 2484 | */ |
2485 | if (len >= 4 && p[1] == 4) { | | 2485 | if (len >= 4 && p[1] == 4) { |
2486 | u_int mru = p[2] * 256 + p[3]; | | 2486 | u_int mru = p[2] * 256 + p[3]; |
2487 | if (debug) | | 2487 | if (debug) |
2488 | addlog(" %d", mru); | | 2488 | addlog(" %d", mru); |
2489 | if (mru < PPP_MINMRU || mru > sp->pp_if.if_mtu) | | 2489 | if (mru < PPP_MINMRU || mru > sp->pp_if.if_mtu) |
2490 | mru = sp->pp_if.if_mtu; | | 2490 | mru = sp->pp_if.if_mtu; |
2491 | sp->lcp.mru = mru; | | 2491 | sp->lcp.mru = mru; |
2492 | sp->lcp.opts |= (1 << LCP_OPT_MRU); | | 2492 | sp->lcp.opts |= (1 << LCP_OPT_MRU); |
2493 | } | | 2493 | } |
2494 | break; | | 2494 | break; |
2495 | case LCP_OPT_AUTH_PROTO: | | 2495 | case LCP_OPT_AUTH_PROTO: |
2496 | /* | | 2496 | /* |
2497 | * Peer doesn't like our authentication method, | | 2497 | * Peer doesn't like our authentication method, |
2498 | * deny. | | 2498 | * deny. |
2499 | */ | | 2499 | */ |
2500 | if (debug) | | 2500 | if (debug) |
2501 | addlog("[access denied]\n"); | | 2501 | addlog("[access denied]\n"); |
2502 | lcp.Close(sp); | | 2502 | lcp.Close(sp); |
2503 | break; | | 2503 | break; |
2504 | } | | 2504 | } |
2505 | } | | 2505 | } |
2506 | if (debug) | | 2506 | if (debug) |
2507 | addlog("\n"); | | 2507 | addlog("\n"); |
2508 | drop: | | 2508 | drop: |
2509 | free(buf, M_TEMP); | | 2509 | free(buf, M_TEMP); |
2510 | return; | | 2510 | return; |
2511 | } | | 2511 | } |
2512 | | | 2512 | |
2513 | static void | | 2513 | static void |
2514 | sppp_lcp_tlu(struct sppp *sp) | | 2514 | sppp_lcp_tlu(struct sppp *sp) |
2515 | { | | 2515 | { |
2516 | STDDCL; | | 2516 | STDDCL; |
2517 | int i; | | 2517 | int i; |
2518 | uint32_t mask; | | 2518 | uint32_t mask; |
2519 | | | 2519 | |
2520 | /* XXX ? */ | | 2520 | /* XXX ? */ |
2521 | if (! (ifp->if_flags & IFF_UP) && | | 2521 | if (! (ifp->if_flags & IFF_UP) && |
2522 | (ifp->if_flags & IFF_RUNNING)) { | | 2522 | (ifp->if_flags & IFF_RUNNING)) { |
2523 | /* Coming out of loopback mode. */ | | 2523 | /* Coming out of loopback mode. */ |
2524 | if_up(ifp); | | 2524 | if_up(ifp); |
2525 | } | | 2525 | } |
2526 | | | 2526 | |
2527 | for (i = 0; i < IDX_COUNT; i++) | | 2527 | for (i = 0; i < IDX_COUNT; i++) |
2528 | if ((cps[i])->flags & CP_QUAL) | | 2528 | if ((cps[i])->flags & CP_QUAL) |
2529 | (cps[i])->Open(sp); | | 2529 | (cps[i])->Open(sp); |
2530 | | | 2530 | |
2531 | if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || | | 2531 | if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || |
2532 | (sp->pp_flags & PP_NEEDAUTH) != 0) | | 2532 | (sp->pp_flags & PP_NEEDAUTH) != 0) |
2533 | sp->pp_phase = SPPP_PHASE_AUTHENTICATE; | | 2533 | sp->pp_phase = SPPP_PHASE_AUTHENTICATE; |
2534 | else | | 2534 | else |
2535 | sp->pp_phase = SPPP_PHASE_NETWORK; | | 2535 | sp->pp_phase = SPPP_PHASE_NETWORK; |
2536 | | | 2536 | |
2537 | if (debug) | | 2537 | if (debug) |
2538 | { | | 2538 | { |
2539 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, | | 2539 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, |
2540 | sppp_phase_name(sp->pp_phase)); | | 2540 | sppp_phase_name(sp->pp_phase)); |
2541 | } | | 2541 | } |
2542 | | | 2542 | |
2543 | /* | | 2543 | /* |
2544 | * Open all authentication protocols. This is even required | | 2544 | * Open all authentication protocols. This is even required |
2545 | * if we already proceeded to network phase, since it might be | | 2545 | * if we already proceeded to network phase, since it might be |
2546 | * that remote wants us to authenticate, so we might have to | | 2546 | * that remote wants us to authenticate, so we might have to |
2547 | * send a PAP request. Undesired authentication protocols | | 2547 | * send a PAP request. Undesired authentication protocols |
2548 | * don't do anything when they get an Open event. | | 2548 | * don't do anything when they get an Open event. |
2549 | */ | | 2549 | */ |
2550 | for (i = 0; i < IDX_COUNT; i++) | | 2550 | for (i = 0; i < IDX_COUNT; i++) |
2551 | if ((cps[i])->flags & CP_AUTH) | | 2551 | if ((cps[i])->flags & CP_AUTH) |
2552 | (cps[i])->Open(sp); | | 2552 | (cps[i])->Open(sp); |
2553 | | | 2553 | |
2554 | if (sp->pp_phase == SPPP_PHASE_NETWORK) { | | 2554 | if (sp->pp_phase == SPPP_PHASE_NETWORK) { |
2555 | /* Notify all NCPs. */ | | 2555 | /* Notify all NCPs. */ |
2556 | for (i = 0; i < IDX_COUNT; i++) | | 2556 | for (i = 0; i < IDX_COUNT; i++) |
2557 | if ((cps[i])->flags & CP_NCP) | | 2557 | if ((cps[i])->flags & CP_NCP) |
2558 | (cps[i])->Open(sp); | | 2558 | (cps[i])->Open(sp); |
2559 | } | | 2559 | } |
2560 | | | 2560 | |
2561 | /* Send Up events to all started protos. */ | | 2561 | /* Send Up events to all started protos. */ |
2562 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) | | 2562 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) |
2563 | if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) | | 2563 | if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) |
2564 | (cps[i])->Up(sp); | | 2564 | (cps[i])->Up(sp); |
2565 | | | 2565 | |
2566 | /* notify low-level driver of state change */ | | 2566 | /* notify low-level driver of state change */ |
2567 | if (sp->pp_chg) | | 2567 | if (sp->pp_chg) |
2568 | sp->pp_chg(sp, (int)sp->pp_phase); | | 2568 | sp->pp_chg(sp, (int)sp->pp_phase); |
2569 | | | 2569 | |
2570 | if (sp->pp_phase == SPPP_PHASE_NETWORK) | | 2570 | if (sp->pp_phase == SPPP_PHASE_NETWORK) |
2571 | /* if no NCP is starting, close down */ | | 2571 | /* if no NCP is starting, close down */ |
2572 | sppp_lcp_check_and_close(sp); | | 2572 | sppp_lcp_check_and_close(sp); |
2573 | } | | 2573 | } |
2574 | | | 2574 | |
2575 | static void | | 2575 | static void |
2576 | sppp_lcp_tld(struct sppp *sp) | | 2576 | sppp_lcp_tld(struct sppp *sp) |
2577 | { | | 2577 | { |
2578 | STDDCL; | | 2578 | STDDCL; |
2579 | int i; | | 2579 | int i; |
2580 | uint32_t mask; | | 2580 | uint32_t mask; |
2581 | | | 2581 | |
2582 | sp->pp_phase = SPPP_PHASE_TERMINATE; | | 2582 | sp->pp_phase = SPPP_PHASE_TERMINATE; |
2583 | | | 2583 | |
2584 | if (debug) | | 2584 | if (debug) |
2585 | { | | 2585 | { |
2586 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, | | 2586 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, |
2587 | sppp_phase_name(sp->pp_phase)); | | 2587 | sppp_phase_name(sp->pp_phase)); |
2588 | } | | 2588 | } |
2589 | | | 2589 | |
2590 | /* | | 2590 | /* |
2591 | * Take upper layers down. We send the Down event first and | | 2591 | * Take upper layers down. We send the Down event first and |
2592 | * the Close second to prevent the upper layers from sending | | 2592 | * the Close second to prevent the upper layers from sending |
2593 | * ``a flurry of terminate-request packets'', as the RFC | | 2593 | * ``a flurry of terminate-request packets'', as the RFC |
2594 | * describes it. | | 2594 | * describes it. |
2595 | */ | | 2595 | */ |
2596 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) | | 2596 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) |
2597 | if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { | | 2597 | if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { |
2598 | (cps[i])->Down(sp); | | 2598 | (cps[i])->Down(sp); |
2599 | (cps[i])->Close(sp); | | 2599 | (cps[i])->Close(sp); |
2600 | } | | 2600 | } |
2601 | } | | 2601 | } |
2602 | | | 2602 | |
2603 | static void | | 2603 | static void |
2604 | sppp_lcp_tls(struct sppp *sp) | | 2604 | sppp_lcp_tls(struct sppp *sp) |
2605 | { | | 2605 | { |
2606 | STDDCL; | | 2606 | STDDCL; |
2607 | | | 2607 | |
2608 | if (sp->pp_max_auth_fail != 0 && sp->pp_auth_failures >= sp->pp_max_auth_fail) { | | 2608 | if (sp->pp_max_auth_fail != 0 && sp->pp_auth_failures >= sp->pp_max_auth_fail) { |
2609 | printf("%s: authentication failed %d times, not retrying again\n", | | 2609 | printf("%s: authentication failed %d times, not retrying again\n", |
2610 | sp->pp_if.if_xname, sp->pp_auth_failures); | | 2610 | sp->pp_if.if_xname, sp->pp_auth_failures); |
2611 | if_down(&sp->pp_if); | | 2611 | if_down(&sp->pp_if); |
2612 | return; | | 2612 | return; |
2613 | } | | 2613 | } |
2614 | | | 2614 | |
2615 | sp->pp_phase = SPPP_PHASE_ESTABLISH; | | 2615 | sp->pp_phase = SPPP_PHASE_ESTABLISH; |
2616 | | | 2616 | |
2617 | if (debug) | | 2617 | if (debug) |
2618 | { | | 2618 | { |
2619 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, | | 2619 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, |
2620 | sppp_phase_name(sp->pp_phase)); | | 2620 | sppp_phase_name(sp->pp_phase)); |
2621 | } | | 2621 | } |
2622 | | | 2622 | |
2623 | /* Notify lower layer if desired. */ | | 2623 | /* Notify lower layer if desired. */ |
2624 | if (sp->pp_tls) | | 2624 | if (sp->pp_tls) |
2625 | (sp->pp_tls)(sp); | | 2625 | (sp->pp_tls)(sp); |
2626 | } | | 2626 | } |
2627 | | | 2627 | |
2628 | static void | | 2628 | static void |
2629 | sppp_lcp_tlf(struct sppp *sp) | | 2629 | sppp_lcp_tlf(struct sppp *sp) |
2630 | { | | 2630 | { |
2631 | STDDCL; | | 2631 | STDDCL; |
2632 | | | 2632 | |
2633 | sp->pp_phase = SPPP_PHASE_DEAD; | | 2633 | sp->pp_phase = SPPP_PHASE_DEAD; |
2634 | | | 2634 | |
2635 | if (debug) | | 2635 | if (debug) |
2636 | { | | 2636 | { |
2637 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, | | 2637 | log(LOG_INFO, "%s: phase %s\n", ifp->if_xname, |
2638 | sppp_phase_name(sp->pp_phase)); | | 2638 | sppp_phase_name(sp->pp_phase)); |
2639 | } | | 2639 | } |
2640 | | | 2640 | |
2641 | /* Notify lower layer if desired. */ | | 2641 | /* Notify lower layer if desired. */ |
2642 | if (sp->pp_tlf) | | 2642 | if (sp->pp_tlf) |
2643 | (sp->pp_tlf)(sp); | | 2643 | (sp->pp_tlf)(sp); |
2644 | } | | 2644 | } |
2645 | | | 2645 | |
2646 | static void | | 2646 | static void |
2647 | sppp_lcp_scr(struct sppp *sp) | | 2647 | sppp_lcp_scr(struct sppp *sp) |
2648 | { | | 2648 | { |
2649 | char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; | | 2649 | char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; |
2650 | int i = 0; | | 2650 | int i = 0; |
2651 | u_short authproto; | | 2651 | u_short authproto; |
2652 | | | 2652 | |
2653 | if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { | | 2653 | if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { |
2654 | if (! sp->lcp.magic) | | 2654 | if (! sp->lcp.magic) |
2655 | sp->lcp.magic = arc4random(); | | 2655 | sp->lcp.magic = arc4random(); |
2656 | opt[i++] = LCP_OPT_MAGIC; | | 2656 | opt[i++] = LCP_OPT_MAGIC; |
2657 | opt[i++] = 6; | | 2657 | opt[i++] = 6; |
2658 | opt[i++] = sp->lcp.magic >> 24; | | 2658 | opt[i++] = sp->lcp.magic >> 24; |
2659 | opt[i++] = sp->lcp.magic >> 16; | | 2659 | opt[i++] = sp->lcp.magic >> 16; |
2660 | opt[i++] = sp->lcp.magic >> 8; | | 2660 | opt[i++] = sp->lcp.magic >> 8; |
2661 | opt[i++] = sp->lcp.magic; | | 2661 | opt[i++] = sp->lcp.magic; |
2662 | } | | 2662 | } |
2663 | | | 2663 | |
2664 | if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { | | 2664 | if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { |
2665 | opt[i++] = LCP_OPT_MRU; | | 2665 | opt[i++] = LCP_OPT_MRU; |
2666 | opt[i++] = 4; | | 2666 | opt[i++] = 4; |
2667 | opt[i++] = sp->lcp.mru >> 8; | | 2667 | opt[i++] = sp->lcp.mru >> 8; |
2668 | opt[i++] = sp->lcp.mru; | | 2668 | opt[i++] = sp->lcp.mru; |
2669 | } | | 2669 | } |
2670 | | | 2670 | |
2671 | if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { | | 2671 | if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { |
2672 | authproto = sp->hisauth.proto; | | 2672 | authproto = sp->hisauth.proto; |
2673 | opt[i++] = LCP_OPT_AUTH_PROTO; | | 2673 | opt[i++] = LCP_OPT_AUTH_PROTO; |
2674 | opt[i++] = authproto == PPP_CHAP? 5: 4; | | 2674 | opt[i++] = authproto == PPP_CHAP? 5: 4; |
2675 | opt[i++] = authproto >> 8; | | 2675 | opt[i++] = authproto >> 8; |
2676 | opt[i++] = authproto; | | 2676 | opt[i++] = authproto; |
2677 | if (authproto == PPP_CHAP) | | 2677 | if (authproto == PPP_CHAP) |
2678 | opt[i++] = CHAP_MD5; | | 2678 | opt[i++] = CHAP_MD5; |
2679 | } | | 2679 | } |
2680 | | | 2680 | |
2681 | sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; | | 2681 | sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; |
2682 | sppp_cp_send(sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); | | 2682 | sppp_cp_send(sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); |
2683 | } | | 2683 | } |
2684 | | | 2684 | |
2685 | /* | | 2685 | /* |
2686 | * Check the open NCPs, return true if at least one NCP is open. | | 2686 | * Check the open NCPs, return true if at least one NCP is open. |
2687 | */ | | 2687 | */ |
2688 | static int | | 2688 | static int |
2689 | sppp_ncp_check(struct sppp *sp) | | 2689 | sppp_ncp_check(struct sppp *sp) |
2690 | { | | 2690 | { |
2691 | int i, mask; | | 2691 | int i, mask; |
2692 | | | 2692 | |
2693 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) | | 2693 | for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) |
2694 | if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) | | 2694 | if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) |
2695 | return 1; | | 2695 | return 1; |
2696 | return 0; | | 2696 | return 0; |
2697 | } | | 2697 | } |
2698 | | | 2698 | |
2699 | /* | | 2699 | /* |
2700 | * Re-check the open NCPs and see if we should terminate the link. | | 2700 | * Re-check the open NCPs and see if we should terminate the link. |
2701 | * Called by the NCPs during their tlf action handling. | | 2701 | * Called by the NCPs during their tlf action handling. |
2702 | */ | | 2702 | */ |
2703 | static void | | 2703 | static void |
2704 | sppp_lcp_check_and_close(struct sppp *sp) | | 2704 | sppp_lcp_check_and_close(struct sppp *sp) |
2705 | { | | 2705 | { |
2706 | | | 2706 | |
2707 | if (sp->pp_phase < SPPP_PHASE_NETWORK) | | 2707 | if (sp->pp_phase < SPPP_PHASE_NETWORK) |
2708 | /* don't bother, we are already going down */ | | 2708 | /* don't bother, we are already going down */ |
2709 | return; | | 2709 | return; |
2710 | | | 2710 | |
2711 | if (sppp_ncp_check(sp)) | | 2711 | if (sppp_ncp_check(sp)) |
2712 | return; | | 2712 | return; |
2713 | | | 2713 | |
2714 | lcp.Close(sp); | | 2714 | lcp.Close(sp); |
2715 | } | | 2715 | } |
2716 | | | 2716 | |
2717 | | | 2717 | |
2718 | /* | | 2718 | /* |
2719 | *--------------------------------------------------------------------------* | | 2719 | *--------------------------------------------------------------------------* |
2720 | * * | | 2720 | * * |
2721 | * The IPCP implementation. * | | 2721 | * The IPCP implementation. * |
2722 | * * | | 2722 | * * |
2723 | *--------------------------------------------------------------------------* | | 2723 | *--------------------------------------------------------------------------* |
2724 | */ | | 2724 | */ |
2725 | | | 2725 | |
2726 | static void | | 2726 | static void |
2727 | sppp_ipcp_init(struct sppp *sp) | | 2727 | sppp_ipcp_init(struct sppp *sp) |
2728 | { | | 2728 | { |
2729 | sp->ipcp.opts = 0; | | 2729 | sp->ipcp.opts = 0; |
2730 | sp->ipcp.flags = 0; | | 2730 | sp->ipcp.flags = 0; |
2731 | sp->state[IDX_IPCP] = STATE_INITIAL; | | 2731 | sp->state[IDX_IPCP] = STATE_INITIAL; |
2732 | sp->fail_counter[IDX_IPCP] = 0; | | 2732 | sp->fail_counter[IDX_IPCP] = 0; |
2733 | sp->pp_seq[IDX_IPCP] = 0; | | 2733 | sp->pp_seq[IDX_IPCP] = 0; |
2734 | sp->pp_rseq[IDX_IPCP] = 0; | | 2734 | sp->pp_rseq[IDX_IPCP] = 0; |
2735 | callout_init(&sp->ch[IDX_IPCP], 0); | | 2735 | callout_init(&sp->ch[IDX_IPCP], 0); |
2736 | } | | 2736 | } |
2737 | | | 2737 | |
2738 | static void | | 2738 | static void |
2739 | sppp_ipcp_up(struct sppp *sp) | | 2739 | sppp_ipcp_up(struct sppp *sp) |
2740 | { | | 2740 | { |
2741 | sppp_up_event(&ipcp, sp); | | 2741 | sppp_up_event(&ipcp, sp); |
2742 | } | | 2742 | } |
2743 | | | 2743 | |
2744 | static void | | 2744 | static void |
2745 | sppp_ipcp_down(struct sppp *sp) | | 2745 | sppp_ipcp_down(struct sppp *sp) |
2746 | { | | 2746 | { |
2747 | sppp_down_event(&ipcp, sp); | | 2747 | sppp_down_event(&ipcp, sp); |
2748 | } | | 2748 | } |
2749 | | | 2749 | |
2750 | static void | | 2750 | static void |
2751 | sppp_ipcp_open(struct sppp *sp) | | 2751 | sppp_ipcp_open(struct sppp *sp) |
2752 | { | | 2752 | { |
2753 | STDDCL; | | 2753 | STDDCL; |
2754 | uint32_t myaddr, hisaddr; | | 2754 | uint32_t myaddr, hisaddr; |
2755 | | | 2755 | |
2756 | sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN|IPCP_HISADDR_DYN); | | 2756 | sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN|IPCP_HISADDR_DYN); |
2757 | sp->ipcp.req_myaddr = 0; | | 2757 | sp->ipcp.req_myaddr = 0; |
2758 | sp->ipcp.req_hisaddr = 0; | | 2758 | sp->ipcp.req_hisaddr = 0; |
2759 | memset(&sp->dns_addrs, 0, sizeof sp->dns_addrs); | | 2759 | memset(&sp->dns_addrs, 0, sizeof sp->dns_addrs); |
2760 | | | 2760 | |
2761 | #ifdef INET | | 2761 | #ifdef INET |
2762 | sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); | | 2762 | sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); |
2763 | #else | | 2763 | #else |
2764 | myaddr = hisaddr = 0; | | 2764 | myaddr = hisaddr = 0; |
2765 | #endif | | 2765 | #endif |
2766 | /* | | 2766 | /* |
2767 | * If we don't have his address, this probably means our | | 2767 | * If we don't have his address, this probably means our |
2768 | * interface doesn't want to talk IP at all. (This could | | 2768 | * interface doesn't want to talk IP at all. (This could |
2769 | * be the case if somebody wants to speak only IPX, for | | 2769 | * be the case if somebody wants to speak only IPX, for |
2770 | * example.) Don't open IPCP in this case. | | 2770 | * example.) Don't open IPCP in this case. |
2771 | */ | | 2771 | */ |
2772 | if (hisaddr == 0) { | | 2772 | if (hisaddr == 0) { |
2773 | /* XXX this message should go away */ | | 2773 | /* XXX this message should go away */ |
2774 | if (debug) | | 2774 | if (debug) |
2775 | log(LOG_DEBUG, "%s: ipcp_open(): no IP interface\n", | | 2775 | log(LOG_DEBUG, "%s: ipcp_open(): no IP interface\n", |
2776 | ifp->if_xname); | | 2776 | ifp->if_xname); |
2777 | return; | | 2777 | return; |
2778 | } | | 2778 | } |
2779 | | | 2779 | |
2780 | if (myaddr == 0) { | | 2780 | if (myaddr == 0) { |
2781 | /* | | 2781 | /* |
2782 | * I don't have an assigned address, so i need to | | 2782 | * I don't have an assigned address, so i need to |
2783 | * negotiate my address. | | 2783 | * negotiate my address. |
2784 | */ | | 2784 | */ |
2785 | sp->ipcp.flags |= IPCP_MYADDR_DYN; | | 2785 | sp->ipcp.flags |= IPCP_MYADDR_DYN; |
2786 | sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); | | 2786 | sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); |
2787 | } | | 2787 | } |
2788 | if (hisaddr == 1) { | | 2788 | if (hisaddr == 1) { |
2789 | /* | | 2789 | /* |
2790 | * XXX - remove this hack! | | 2790 | * XXX - remove this hack! |
2791 | * remote has no valid address, we need to get one assigned. | | 2791 | * remote has no valid address, we need to get one assigned. |
2792 | */ | | 2792 | */ |
2793 | sp->ipcp.flags |= IPCP_HISADDR_DYN; | | 2793 | sp->ipcp.flags |= IPCP_HISADDR_DYN; |
2794 | } | | 2794 | } |
2795 | sppp_open_event(&ipcp, sp); | | 2795 | sppp_open_event(&ipcp, sp); |
2796 | } | | 2796 | } |
2797 | | | 2797 | |
2798 | static void | | 2798 | static void |
2799 | sppp_ipcp_close(struct sppp *sp) | | 2799 | sppp_ipcp_close(struct sppp *sp) |
2800 | { | | 2800 | { |
2801 | STDDCL; | | 2801 | STDDCL; |
2802 | | | 2802 | |
2803 | sppp_close_event(&ipcp, sp); | | 2803 | sppp_close_event(&ipcp, sp); |
2804 | #ifdef INET | | 2804 | #ifdef INET |
2805 | if (sp->ipcp.flags & (IPCP_MYADDR_DYN|IPCP_HISADDR_DYN)) | | 2805 | if (sp->ipcp.flags & (IPCP_MYADDR_DYN|IPCP_HISADDR_DYN)) |
2806 | /* | | 2806 | /* |
2807 | * Some address was dynamic, clear it again. | | 2807 | * Some address was dynamic, clear it again. |
2808 | */ | | 2808 | */ |
2809 | sppp_clear_ip_addrs(sp); | | 2809 | sppp_clear_ip_addrs(sp); |
2810 | #endif | | 2810 | #endif |
2811 | | | 2811 | |
2812 | if (sp->pp_saved_mtu > 0) { | | 2812 | if (sp->pp_saved_mtu > 0) { |
2813 | ifp->if_mtu = sp->pp_saved_mtu; | | 2813 | ifp->if_mtu = sp->pp_saved_mtu; |
2814 | sp->pp_saved_mtu = 0; | | 2814 | sp->pp_saved_mtu = 0; |
2815 | if (debug) | | 2815 | if (debug) |
2816 | log(LOG_DEBUG, | | 2816 | log(LOG_DEBUG, |
2817 | "%s: resetting MTU to %" PRIu64 " bytes\n", | | 2817 | "%s: resetting MTU to %" PRIu64 " bytes\n", |
2818 | ifp->if_xname, ifp->if_mtu); | | 2818 | ifp->if_xname, ifp->if_mtu); |
2819 | } | | 2819 | } |
2820 | } | | 2820 | } |
2821 | | | 2821 | |
2822 | static void | | 2822 | static void |
2823 | sppp_ipcp_TO(void *cookie) | | 2823 | sppp_ipcp_TO(void *cookie) |
2824 | { | | 2824 | { |
2825 | sppp_to_event(&ipcp, (struct sppp *)cookie); | | 2825 | sppp_to_event(&ipcp, (struct sppp *)cookie); |
2826 | } | | 2826 | } |
2827 | | | 2827 | |
2828 | /* | | 2828 | /* |
2829 | * Analyze a configure request. Return true if it was agreeable, and | | 2829 | * Analyze a configure request. Return true if it was agreeable, and |
2830 | * caused action sca, false if it has been rejected or nak'ed, and | | 2830 | * caused action sca, false if it has been rejected or nak'ed, and |
2831 | * caused action scn. (The return value is used to make the state | | 2831 | * caused action scn. (The return value is used to make the state |
2832 | * transition decision in the state automaton.) | | 2832 | * transition decision in the state automaton.) |
2833 | */ | | 2833 | */ |
2834 | static int | | 2834 | static int |
2835 | sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) | | 2835 | sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) |
2836 | { | | 2836 | { |
2837 | u_char *buf, *r, *p; | | 2837 | u_char *buf, *r, *p; |
2838 | struct ifnet *ifp = &sp->pp_if; | | 2838 | struct ifnet *ifp = &sp->pp_if; |
2839 | int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; | | 2839 | int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; |
2840 | uint32_t hisaddr, desiredaddr; | | 2840 | uint32_t hisaddr, desiredaddr; |
2841 | | | 2841 | |
2842 | len -= 4; | | 2842 | len -= 4; |
2843 | origlen = len; | | 2843 | origlen = len; |
2844 | /* | | 2844 | /* |
2845 | * Make sure to allocate a buf that can at least hold a | | 2845 | * Make sure to allocate a buf that can at least hold a |
2846 | * conf-nak with an `address' option. We might need it below. | | 2846 | * conf-nak with an `address' option. We might need it below. |
2847 | */ | | 2847 | */ |
2848 | buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); | | 2848 | buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); |
2849 | if (! buf) | | 2849 | if (! buf) |
2850 | return (0); | | 2850 | return (0); |
2851 | | | 2851 | |
2852 | /* pass 1: see if we can recognize them */ | | 2852 | /* pass 1: see if we can recognize them */ |
2853 | if (debug) | | 2853 | if (debug) |
2854 | log(LOG_DEBUG, "%s: ipcp parse opts:", | | 2854 | log(LOG_DEBUG, "%s: ipcp parse opts:", |
2855 | ifp->if_xname); | | 2855 | ifp->if_xname); |
2856 | p = (void *)(h + 1); | | 2856 | p = (void *)(h + 1); |
2857 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { | | 2857 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { |
2858 | /* Sanity check option length */ | | 2858 | /* Sanity check option length */ |
2859 | if (p[1] > len) { | | 2859 | if (p[1] > len) { |
2860 | /* XXX should we just RXJ? */ | | 2860 | /* XXX should we just RXJ? */ |
2861 | addlog("%s: malicious IPCP option received, dropping\n", | | 2861 | addlog("%s: malicious IPCP option received, dropping\n", |
2862 | ifp->if_xname); | | 2862 | ifp->if_xname); |
2863 | goto drop; | | 2863 | goto drop; |
2864 | } | | 2864 | } |
2865 | if (debug) | | 2865 | if (debug) |
2866 | addlog(" %s", sppp_ipcp_opt_name(*p)); | | 2866 | addlog(" %s", sppp_ipcp_opt_name(*p)); |
2867 | switch (*p) { | | 2867 | switch (*p) { |
2868 | #ifdef notyet | | 2868 | #ifdef notyet |
2869 | case IPCP_OPT_COMPRESSION: | | 2869 | case IPCP_OPT_COMPRESSION: |
2870 | if (len >= 6 && p[1] >= 6) { | | 2870 | if (len >= 6 && p[1] >= 6) { |
2871 | /* correctly formed compress option */ | | 2871 | /* correctly formed compress option */ |
2872 | continue; | | 2872 | continue; |
2873 | } | | 2873 | } |
2874 | if (debug) | | 2874 | if (debug) |
2875 | addlog(" [invalid]"); | | 2875 | addlog(" [invalid]"); |
2876 | break; | | 2876 | break; |
2877 | #endif | | 2877 | #endif |
2878 | case IPCP_OPT_ADDRESS: | | 2878 | case IPCP_OPT_ADDRESS: |
2879 | if (len >= 6 && p[1] == 6) { | | 2879 | if (len >= 6 && p[1] == 6) { |
2880 | /* correctly formed address option */ | | 2880 | /* correctly formed address option */ |
2881 | continue; | | 2881 | continue; |
2882 | } | | 2882 | } |
2883 | if (debug) | | 2883 | if (debug) |
2884 | addlog(" [invalid]"); | | 2884 | addlog(" [invalid]"); |
2885 | break; | | 2885 | break; |
2886 | default: | | 2886 | default: |
2887 | /* Others not supported. */ | | 2887 | /* Others not supported. */ |
2888 | if (debug) | | 2888 | if (debug) |
2889 | addlog(" [rej]"); | | 2889 | addlog(" [rej]"); |
2890 | break; | | 2890 | break; |
2891 | } | | 2891 | } |
2892 | /* Add the option to rejected list. */ | | 2892 | /* Add the option to rejected list. */ |
2893 | bcopy (p, r, p[1]); | | 2893 | bcopy (p, r, p[1]); |
2894 | r += p[1]; | | 2894 | r += p[1]; |
2895 | rlen += p[1]; | | 2895 | rlen += p[1]; |
2896 | } | | 2896 | } |
2897 | if (rlen) { | | 2897 | if (rlen) { |
2898 | if (debug) | | 2898 | if (debug) |
2899 | addlog(" send conf-rej\n"); | | 2899 | addlog(" send conf-rej\n"); |
2900 | sppp_cp_send(sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); | | 2900 | sppp_cp_send(sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); |
2901 | goto end; | | 2901 | goto end; |
2902 | } else if (debug) | | 2902 | } else if (debug) |
2903 | addlog("\n"); | | 2903 | addlog("\n"); |
2904 | | | 2904 | |
2905 | /* pass 2: parse option values */ | | 2905 | /* pass 2: parse option values */ |
2906 | if (sp->ipcp.flags & IPCP_HISADDR_SEEN) | | 2906 | if (sp->ipcp.flags & IPCP_HISADDR_SEEN) |
2907 | hisaddr = sp->ipcp.req_hisaddr; /* we already aggreed on that */ | | 2907 | hisaddr = sp->ipcp.req_hisaddr; /* we already aggreed on that */ |
2908 | else | | 2908 | else |
2909 | #ifdef INET | | 2909 | #ifdef INET |
2910 | sppp_get_ip_addrs(sp, 0, &hisaddr, 0); /* user configuration */ | | 2910 | sppp_get_ip_addrs(sp, 0, &hisaddr, 0); /* user configuration */ |
2911 | #else | | 2911 | #else |
2912 | hisaddr = 0; | | 2912 | hisaddr = 0; |
2913 | #endif | | 2913 | #endif |
2914 | if (debug) | | 2914 | if (debug) |
2915 | log(LOG_DEBUG, "%s: ipcp parse opt values: ", | | 2915 | log(LOG_DEBUG, "%s: ipcp parse opt values: ", |
2916 | ifp->if_xname); | | 2916 | ifp->if_xname); |
2917 | p = (void *)(h + 1); | | 2917 | p = (void *)(h + 1); |
2918 | len = origlen; | | 2918 | len = origlen; |
2919 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { | | 2919 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { |
2920 | if (debug) | | 2920 | if (debug) |
2921 | addlog(" %s", sppp_ipcp_opt_name(*p)); | | 2921 | addlog(" %s", sppp_ipcp_opt_name(*p)); |
2922 | switch (*p) { | | 2922 | switch (*p) { |
2923 | #ifdef notyet | | 2923 | #ifdef notyet |
2924 | case IPCP_OPT_COMPRESSION: | | 2924 | case IPCP_OPT_COMPRESSION: |
2925 | continue; | | 2925 | continue; |
2926 | #endif | | 2926 | #endif |
2927 | case IPCP_OPT_ADDRESS: | | 2927 | case IPCP_OPT_ADDRESS: |
2928 | desiredaddr = p[2] << 24 | p[3] << 16 | | | 2928 | desiredaddr = p[2] << 24 | p[3] << 16 | |
2929 | p[4] << 8 | p[5]; | | 2929 | p[4] << 8 | p[5]; |
2930 | if (desiredaddr == hisaddr || | | 2930 | if (desiredaddr == hisaddr || |
2931 | ((sp->ipcp.flags & IPCP_HISADDR_DYN) && desiredaddr != 0)) { | | 2931 | ((sp->ipcp.flags & IPCP_HISADDR_DYN) && desiredaddr != 0)) { |
2932 | /* | | 2932 | /* |
2933 | * Peer's address is same as our value, | | 2933 | * Peer's address is same as our value, |
2934 | * this is agreeable. Gonna conf-ack | | 2934 | * this is agreeable. Gonna conf-ack |
2935 | * it. | | 2935 | * it. |
2936 | */ | | 2936 | */ |
2937 | if (debug) | | 2937 | if (debug) |
2938 | addlog(" %s [ack]", | | 2938 | addlog(" %s [ack]", |
2939 | sppp_dotted_quad(hisaddr)); | | 2939 | sppp_dotted_quad(hisaddr)); |
2940 | /* record that we've seen it already */ | | 2940 | /* record that we've seen it already */ |
2941 | sp->ipcp.flags |= IPCP_HISADDR_SEEN; | | 2941 | sp->ipcp.flags |= IPCP_HISADDR_SEEN; |
2942 | sp->ipcp.req_hisaddr = desiredaddr; | | 2942 | sp->ipcp.req_hisaddr = desiredaddr; |
2943 | hisaddr = desiredaddr; | | 2943 | hisaddr = desiredaddr; |
2944 | continue; | | 2944 | continue; |
2945 | } | | 2945 | } |
2946 | /* | | 2946 | /* |
2947 | * The address wasn't agreeable. This is either | | 2947 | * The address wasn't agreeable. This is either |
2948 | * he sent us 0.0.0.0, asking to assign him an | | 2948 | * he sent us 0.0.0.0, asking to assign him an |
2949 | * address, or he send us another address not | | 2949 | * address, or he send us another address not |
2950 | * matching our value. Either case, we gonna | | 2950 | * matching our value. Either case, we gonna |
2951 | * conf-nak it with our value. | | 2951 | * conf-nak it with our value. |
2952 | */ | | 2952 | */ |
2953 | if (debug) { | | 2953 | if (debug) { |
2954 | if (desiredaddr == 0) | | 2954 | if (desiredaddr == 0) |
2955 | addlog(" [addr requested]"); | | 2955 | addlog(" [addr requested]"); |
2956 | else | | 2956 | else |
2957 | addlog(" %s [not agreed]", | | 2957 | addlog(" %s [not agreed]", |
2958 | sppp_dotted_quad(desiredaddr)); | | 2958 | sppp_dotted_quad(desiredaddr)); |
2959 | } | | 2959 | } |
2960 | | | 2960 | |
2961 | p[2] = hisaddr >> 24; | | 2961 | p[2] = hisaddr >> 24; |
2962 | p[3] = hisaddr >> 16; | | 2962 | p[3] = hisaddr >> 16; |
2963 | p[4] = hisaddr >> 8; | | 2963 | p[4] = hisaddr >> 8; |
2964 | p[5] = hisaddr; | | 2964 | p[5] = hisaddr; |
2965 | break; | | 2965 | break; |
2966 | } | | 2966 | } |
2967 | /* Add the option to nak'ed list. */ | | 2967 | /* Add the option to nak'ed list. */ |
2968 | bcopy (p, r, p[1]); | | 2968 | bcopy (p, r, p[1]); |
2969 | r += p[1]; | | 2969 | r += p[1]; |
2970 | rlen += p[1]; | | 2970 | rlen += p[1]; |
2971 | } | | 2971 | } |
2972 | | | 2972 | |
2973 | /* | | 2973 | /* |
2974 | * If we are about to conf-ack the request, but haven't seen | | 2974 | * If we are about to conf-ack the request, but haven't seen |
2975 | * his address so far, gonna conf-nak it instead, with the | | 2975 | * his address so far, gonna conf-nak it instead, with the |
2976 | * `address' option present and our idea of his address being | | 2976 | * `address' option present and our idea of his address being |
2977 | * filled in there, to request negotiation of both addresses. | | 2977 | * filled in there, to request negotiation of both addresses. |
2978 | * | | 2978 | * |
2979 | * XXX This can result in an endless req - nak loop if peer | | 2979 | * XXX This can result in an endless req - nak loop if peer |
2980 | * doesn't want to send us his address. Q: What should we do | | 2980 | * doesn't want to send us his address. Q: What should we do |
2981 | * about it? XXX A: implement the max-failure counter. | | 2981 | * about it? XXX A: implement the max-failure counter. |
2982 | */ | | 2982 | */ |
2983 | if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { | | 2983 | if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { |
2984 | buf[0] = IPCP_OPT_ADDRESS; | | 2984 | buf[0] = IPCP_OPT_ADDRESS; |
2985 | buf[1] = 6; | | 2985 | buf[1] = 6; |
2986 | buf[2] = hisaddr >> 24; | | 2986 | buf[2] = hisaddr >> 24; |
2987 | buf[3] = hisaddr >> 16; | | 2987 | buf[3] = hisaddr >> 16; |
2988 | buf[4] = hisaddr >> 8; | | 2988 | buf[4] = hisaddr >> 8; |
2989 | buf[5] = hisaddr; | | 2989 | buf[5] = hisaddr; |
2990 | rlen = 6; | | 2990 | rlen = 6; |
2991 | if (debug) | | 2991 | if (debug) |
2992 | addlog(" still need hisaddr"); | | 2992 | addlog(" still need hisaddr"); |
2993 | } | | 2993 | } |
2994 | | | 2994 | |
2995 | if (rlen) { | | 2995 | if (rlen) { |
2996 | if (debug) | | 2996 | if (debug) |
2997 | addlog(" send conf-nak\n"); | | 2997 | addlog(" send conf-nak\n"); |
2998 | sppp_cp_send(sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); | | 2998 | sppp_cp_send(sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); |
2999 | } else { | | 2999 | } else { |
3000 | if (debug) | | 3000 | if (debug) |
3001 | addlog(" send conf-ack\n"); | | 3001 | addlog(" send conf-ack\n"); |
3002 | sppp_cp_send(sp, PPP_IPCP, CONF_ACK, h->ident, origlen, h + 1); | | 3002 | sppp_cp_send(sp, PPP_IPCP, CONF_ACK, h->ident, origlen, h + 1); |
3003 | } | | 3003 | } |
3004 | | | 3004 | |
3005 | end: | | 3005 | end: |
3006 | free(buf, M_TEMP); | | 3006 | free(buf, M_TEMP); |
3007 | return (rlen == 0); | | 3007 | return (rlen == 0); |
3008 | | | 3008 | |
3009 | drop: | | 3009 | drop: |
3010 | free(buf, M_TEMP); | | 3010 | free(buf, M_TEMP); |
3011 | return -1; | | 3011 | return -1; |
3012 | } | | 3012 | } |
3013 | | | 3013 | |
3014 | /* | | 3014 | /* |
3015 | * Analyze the IPCP Configure-Reject option list, and adjust our | | 3015 | * Analyze the IPCP Configure-Reject option list, and adjust our |
3016 | * negotiation. | | 3016 | * negotiation. |
3017 | */ | | 3017 | */ |
3018 | static void | | 3018 | static void |
3019 | sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) | | 3019 | sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) |
3020 | { | | 3020 | { |
3021 | u_char *buf, *p; | | 3021 | u_char *buf, *p; |
3022 | struct ifnet *ifp = &sp->pp_if; | | 3022 | struct ifnet *ifp = &sp->pp_if; |
3023 | int debug = ifp->if_flags & IFF_DEBUG; | | 3023 | int debug = ifp->if_flags & IFF_DEBUG; |
3024 | | | 3024 | |
3025 | len -= 4; | | 3025 | len -= 4; |
3026 | buf = malloc (len, M_TEMP, M_NOWAIT); | | 3026 | buf = malloc (len, M_TEMP, M_NOWAIT); |
3027 | if (!buf) | | 3027 | if (!buf) |
3028 | return; | | 3028 | return; |
3029 | | | 3029 | |
3030 | if (debug) | | 3030 | if (debug) |
3031 | log(LOG_DEBUG, "%s: ipcp rej opts:", | | 3031 | log(LOG_DEBUG, "%s: ipcp rej opts:", |
3032 | ifp->if_xname); | | 3032 | ifp->if_xname); |
3033 | | | 3033 | |
3034 | p = (void *)(h + 1); | | 3034 | p = (void *)(h + 1); |
3035 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { | | 3035 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { |
3036 | /* Sanity check option length */ | | 3036 | /* Sanity check option length */ |
3037 | if (p[1] > len) { | | 3037 | if (p[1] > len) { |
3038 | /* XXX should we just RXJ? */ | | 3038 | /* XXX should we just RXJ? */ |
3039 | addlog("%s: malicious IPCP option received, dropping\n", | | 3039 | addlog("%s: malicious IPCP option received, dropping\n", |
3040 | ifp->if_xname); | | 3040 | ifp->if_xname); |
3041 | goto drop; | | 3041 | goto drop; |
3042 | } | | 3042 | } |
3043 | if (debug) | | 3043 | if (debug) |
3044 | addlog(" %s", sppp_ipcp_opt_name(*p)); | | 3044 | addlog(" %s", sppp_ipcp_opt_name(*p)); |
3045 | switch (*p) { | | 3045 | switch (*p) { |
3046 | case IPCP_OPT_ADDRESS: | | 3046 | case IPCP_OPT_ADDRESS: |
3047 | /* | | 3047 | /* |
3048 | * Peer doesn't grok address option. This is | | 3048 | * Peer doesn't grok address option. This is |
3049 | * bad. XXX Should we better give up here? | | 3049 | * bad. XXX Should we better give up here? |
3050 | */ | | 3050 | */ |
3051 | sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); | | 3051 | sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); |
3052 | break; | | 3052 | break; |
3053 | #ifdef notyet | | 3053 | #ifdef notyet |
3054 | case IPCP_OPT_COMPRESS: | | 3054 | case IPCP_OPT_COMPRESS: |
3055 | sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); | | 3055 | sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); |
3056 | break; | | 3056 | break; |
3057 | #endif | | 3057 | #endif |
3058 | } | | 3058 | } |
3059 | } | | 3059 | } |
3060 | if (debug) | | 3060 | if (debug) |
3061 | addlog("\n"); | | 3061 | addlog("\n"); |
3062 | drop: | | 3062 | drop: |
3063 | free(buf, M_TEMP); | | 3063 | free(buf, M_TEMP); |
3064 | return; | | 3064 | return; |
3065 | } | | 3065 | } |
3066 | | | 3066 | |
3067 | /* | | 3067 | /* |
3068 | * Analyze the IPCP Configure-NAK option list, and adjust our | | 3068 | * Analyze the IPCP Configure-NAK option list, and adjust our |
3069 | * negotiation. | | 3069 | * negotiation. |
3070 | */ | | 3070 | */ |
3071 | static void | | 3071 | static void |
3072 | sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) | | 3072 | sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) |
3073 | { | | 3073 | { |
3074 | u_char *p; | | 3074 | u_char *p; |
3075 | struct ifnet *ifp = &sp->pp_if; | | 3075 | struct ifnet *ifp = &sp->pp_if; |
3076 | int debug = ifp->if_flags & IFF_DEBUG; | | 3076 | int debug = ifp->if_flags & IFF_DEBUG; |
3077 | uint32_t wantaddr; | | 3077 | uint32_t wantaddr; |
3078 | | | 3078 | |
3079 | len -= 4; | | 3079 | len -= 4; |
3080 | | | 3080 | |
3081 | if (debug) | | 3081 | if (debug) |
3082 | log(LOG_DEBUG, "%s: ipcp nak opts:", | | 3082 | log(LOG_DEBUG, "%s: ipcp nak opts:", |
3083 | ifp->if_xname); | | 3083 | ifp->if_xname); |
3084 | | | 3084 | |
3085 | p = (void *)(h + 1); | | 3085 | p = (void *)(h + 1); |
3086 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { | | 3086 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { |
3087 | /* Sanity check option length */ | | 3087 | /* Sanity check option length */ |
3088 | if (p[1] > len) { | | 3088 | if (p[1] > len) { |
3089 | /* XXX should we just RXJ? */ | | 3089 | /* XXX should we just RXJ? */ |
3090 | addlog("%s: malicious IPCP option received, dropping\n", | | 3090 | addlog("%s: malicious IPCP option received, dropping\n", |
3091 | ifp->if_xname); | | 3091 | ifp->if_xname); |
3092 | return; | | 3092 | return; |
3093 | } | | 3093 | } |
3094 | if (debug) | | 3094 | if (debug) |
3095 | addlog(" %s", sppp_ipcp_opt_name(*p)); | | 3095 | addlog(" %s", sppp_ipcp_opt_name(*p)); |
3096 | switch (*p) { | | 3096 | switch (*p) { |
3097 | case IPCP_OPT_ADDRESS: | | 3097 | case IPCP_OPT_ADDRESS: |
3098 | /* | | 3098 | /* |
3099 | * Peer doesn't like our local IP address. See | | 3099 | * Peer doesn't like our local IP address. See |
3100 | * if we can do something for him. We'll drop | | 3100 | * if we can do something for him. We'll drop |
3101 | * him our address then. | | 3101 | * him our address then. |
3102 | */ | | 3102 | */ |
3103 | if (len >= 6 && p[1] == 6) { | | 3103 | if (len >= 6 && p[1] == 6) { |
3104 | wantaddr = p[2] << 24 | p[3] << 16 | | | 3104 | wantaddr = p[2] << 24 | p[3] << 16 | |
3105 | p[4] << 8 | p[5]; | | 3105 | p[4] << 8 | p[5]; |
3106 | sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); | | 3106 | sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); |
3107 | if (debug) | | 3107 | if (debug) |
3108 | addlog(" [wantaddr %s]", | | 3108 | addlog(" [wantaddr %s]", |
3109 | sppp_dotted_quad(wantaddr)); | | 3109 | sppp_dotted_quad(wantaddr)); |
3110 | /* | | 3110 | /* |
3111 | * When doing dynamic address assignment, | | 3111 | * When doing dynamic address assignment, |
3112 | * we accept his offer. Otherwise, we | | 3112 | * we accept his offer. Otherwise, we |
3113 | * ignore it and thus continue to negotiate | | 3113 | * ignore it and thus continue to negotiate |
3114 | * our already existing value. | | 3114 | * our already existing value. |
3115 | */ | | 3115 | */ |
3116 | if (sp->ipcp.flags & IPCP_MYADDR_DYN) { | | 3116 | if (sp->ipcp.flags & IPCP_MYADDR_DYN) { |
3117 | if (debug) | | 3117 | if (debug) |
3118 | addlog(" [agree]"); | | 3118 | addlog(" [agree]"); |
3119 | sp->ipcp.flags |= IPCP_MYADDR_SEEN; | | 3119 | sp->ipcp.flags |= IPCP_MYADDR_SEEN; |
3120 | sp->ipcp.req_myaddr = wantaddr; | | 3120 | sp->ipcp.req_myaddr = wantaddr; |
3121 | } | | 3121 | } |
3122 | } | | 3122 | } |
3123 | break; | | 3123 | break; |
3124 | | | 3124 | |
3125 | case IPCP_OPT_PRIMDNS: | | 3125 | case IPCP_OPT_PRIMDNS: |
3126 | if (len >= 6 && p[1] == 6) { | | 3126 | if (len >= 6 && p[1] == 6) { |
3127 | sp->dns_addrs[0] = p[2] << 24 | p[3] << 16 | | | 3127 | sp->dns_addrs[0] = p[2] << 24 | p[3] << 16 | |
3128 | p[4] << 8 | p[5]; | | 3128 | p[4] << 8 | p[5]; |
3129 | } | | 3129 | } |
3130 | break; | | 3130 | break; |
3131 | | | 3131 | |
3132 | case IPCP_OPT_SECDNS: | | 3132 | case IPCP_OPT_SECDNS: |
3133 | if (len >= 6 && p[1] == 6) { | | 3133 | if (len >= 6 && p[1] == 6) { |
3134 | sp->dns_addrs[1] = p[2] << 24 | p[3] << 16 | | | 3134 | sp->dns_addrs[1] = p[2] << 24 | p[3] << 16 | |
3135 | p[4] << 8 | p[5]; | | 3135 | p[4] << 8 | p[5]; |
3136 | } | | 3136 | } |
3137 | break; | | 3137 | break; |
3138 | #ifdef notyet | | 3138 | #ifdef notyet |
3139 | case IPCP_OPT_COMPRESS: | | 3139 | case IPCP_OPT_COMPRESS: |
3140 | /* | | 3140 | /* |
3141 | * Peer wants different compression parameters. | | 3141 | * Peer wants different compression parameters. |
3142 | */ | | 3142 | */ |
3143 | break; | | 3143 | break; |
3144 | #endif | | 3144 | #endif |
3145 | } | | 3145 | } |
3146 | } | | 3146 | } |
3147 | if (debug) | | 3147 | if (debug) |
3148 | addlog("\n"); | | 3148 | addlog("\n"); |
3149 | } | | 3149 | } |
3150 | | | 3150 | |
3151 | static void | | 3151 | static void |
3152 | sppp_ipcp_tlu(struct sppp *sp) | | 3152 | sppp_ipcp_tlu(struct sppp *sp) |
3153 | { | | 3153 | { |
3154 | #ifdef INET | | 3154 | #ifdef INET |
3155 | /* we are up. Set addresses and notify anyone interested */ | | 3155 | /* we are up. Set addresses and notify anyone interested */ |
3156 | STDDCL; | | 3156 | STDDCL; |
3157 | uint32_t myaddr, hisaddr; | | 3157 | uint32_t myaddr, hisaddr; |
3158 | | | 3158 | |
3159 | sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); | | 3159 | sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); |
3160 | if ((sp->ipcp.flags & IPCP_MYADDR_DYN) && (sp->ipcp.flags & IPCP_MYADDR_SEEN)) | | 3160 | if ((sp->ipcp.flags & IPCP_MYADDR_DYN) && (sp->ipcp.flags & IPCP_MYADDR_SEEN)) |
3161 | myaddr = sp->ipcp.req_myaddr; | | 3161 | myaddr = sp->ipcp.req_myaddr; |
3162 | if ((sp->ipcp.flags & IPCP_HISADDR_DYN) && (sp->ipcp.flags & IPCP_HISADDR_SEEN)) | | 3162 | if ((sp->ipcp.flags & IPCP_HISADDR_DYN) && (sp->ipcp.flags & IPCP_HISADDR_SEEN)) |
3163 | hisaddr = sp->ipcp.req_hisaddr; | | 3163 | hisaddr = sp->ipcp.req_hisaddr; |
3164 | sppp_set_ip_addrs(sp, myaddr, hisaddr); | | 3164 | sppp_set_ip_addrs(sp, myaddr, hisaddr); |
3165 | | | 3165 | |
3166 | if (ifp->if_mtu > sp->lcp.their_mru) { | | 3166 | if (ifp->if_mtu > sp->lcp.their_mru) { |
3167 | sp->pp_saved_mtu = ifp->if_mtu; | | 3167 | sp->pp_saved_mtu = ifp->if_mtu; |
3168 | ifp->if_mtu = sp->lcp.their_mru; | | 3168 | ifp->if_mtu = sp->lcp.their_mru; |
3169 | if (debug) | | 3169 | if (debug) |
3170 | log(LOG_DEBUG, | | 3170 | log(LOG_DEBUG, |
3171 | "%s: setting MTU to %" PRIu64 " bytes\n", | | 3171 | "%s: setting MTU to %" PRIu64 " bytes\n", |
3172 | ifp->if_xname, ifp->if_mtu); | | 3172 | ifp->if_xname, ifp->if_mtu); |
3173 | } | | 3173 | } |
3174 | | | 3174 | |
3175 | if (sp->pp_con) | | 3175 | if (sp->pp_con) |
3176 | sp->pp_con(sp); | | 3176 | sp->pp_con(sp); |
3177 | #endif | | 3177 | #endif |
3178 | } | | 3178 | } |
3179 | | | 3179 | |
3180 | static void | | 3180 | static void |
3181 | sppp_ipcp_tld(struct sppp *sp) | | 3181 | sppp_ipcp_tld(struct sppp *sp) |
3182 | { | | 3182 | { |
3183 | } | | 3183 | } |
3184 | | | 3184 | |
3185 | static void | | 3185 | static void |
3186 | sppp_ipcp_tls(struct sppp *sp) | | 3186 | sppp_ipcp_tls(struct sppp *sp) |
3187 | { | | 3187 | { |
3188 | /* indicate to LCP that it must stay alive */ | | 3188 | /* indicate to LCP that it must stay alive */ |
3189 | sp->lcp.protos |= (1 << IDX_IPCP); | | 3189 | sp->lcp.protos |= (1 << IDX_IPCP); |
3190 | } | | 3190 | } |
3191 | | | 3191 | |
3192 | static void | | 3192 | static void |
3193 | sppp_ipcp_tlf(struct sppp *sp) | | 3193 | sppp_ipcp_tlf(struct sppp *sp) |
3194 | { | | 3194 | { |
3195 | /* we no longer need LCP */ | | 3195 | /* we no longer need LCP */ |
3196 | sp->lcp.protos &= ~(1 << IDX_IPCP); | | 3196 | sp->lcp.protos &= ~(1 << IDX_IPCP); |
3197 | } | | 3197 | } |
3198 | | | 3198 | |
3199 | static void | | 3199 | static void |
3200 | sppp_ipcp_scr(struct sppp *sp) | | 3200 | sppp_ipcp_scr(struct sppp *sp) |
3201 | { | | 3201 | { |
3202 | char opt[6 /* compression */ + 6 /* address */ + 12 /* dns addresses */]; | | 3202 | char opt[6 /* compression */ + 6 /* address */ + 12 /* dns addresses */]; |
3203 | #ifdef INET | | 3203 | #ifdef INET |
3204 | uint32_t ouraddr; | | 3204 | uint32_t ouraddr; |
3205 | #endif | | 3205 | #endif |
3206 | int i = 0; | | 3206 | int i = 0; |
3207 | | | 3207 | |
3208 | #ifdef notyet | | 3208 | #ifdef notyet |
3209 | if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { | | 3209 | if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { |
3210 | opt[i++] = IPCP_OPT_COMPRESSION; | | 3210 | opt[i++] = IPCP_OPT_COMPRESSION; |
3211 | opt[i++] = 6; | | 3211 | opt[i++] = 6; |
3212 | opt[i++] = 0; /* VJ header compression */ | | 3212 | opt[i++] = 0; /* VJ header compression */ |
3213 | opt[i++] = 0x2d; /* VJ header compression */ | | 3213 | opt[i++] = 0x2d; /* VJ header compression */ |
3214 | opt[i++] = max_slot_id; | | 3214 | opt[i++] = max_slot_id; |
3215 | opt[i++] = comp_slot_id; | | 3215 | opt[i++] = comp_slot_id; |
3216 | } | | 3216 | } |
3217 | #endif | | 3217 | #endif |
3218 | | | 3218 | |
3219 | #ifdef INET | | 3219 | #ifdef INET |
3220 | if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { | | 3220 | if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { |
3221 | if (sp->ipcp.flags & IPCP_MYADDR_SEEN) | | 3221 | if (sp->ipcp.flags & IPCP_MYADDR_SEEN) |
3222 | ouraddr = sp->ipcp.req_myaddr; /* not sure if this can ever happen */ | | 3222 | ouraddr = sp->ipcp.req_myaddr; /* not sure if this can ever happen */ |
3223 | else | | 3223 | else |
3224 | sppp_get_ip_addrs(sp, &ouraddr, 0, 0); | | 3224 | sppp_get_ip_addrs(sp, &ouraddr, 0, 0); |
3225 | opt[i++] = IPCP_OPT_ADDRESS; | | 3225 | opt[i++] = IPCP_OPT_ADDRESS; |
3226 | opt[i++] = 6; | | 3226 | opt[i++] = 6; |
3227 | opt[i++] = ouraddr >> 24; | | 3227 | opt[i++] = ouraddr >> 24; |
3228 | opt[i++] = ouraddr >> 16; | | 3228 | opt[i++] = ouraddr >> 16; |
3229 | opt[i++] = ouraddr >> 8; | | 3229 | opt[i++] = ouraddr >> 8; |
3230 | opt[i++] = ouraddr; | | 3230 | opt[i++] = ouraddr; |
3231 | } | | 3231 | } |
3232 | #endif | | 3232 | #endif |
3233 | | | 3233 | |
3234 | if (sp->query_dns & 1) { | | 3234 | if (sp->query_dns & 1) { |
3235 | opt[i++] = IPCP_OPT_PRIMDNS; | | 3235 | opt[i++] = IPCP_OPT_PRIMDNS; |
3236 | opt[i++] = 6; | | 3236 | opt[i++] = 6; |
3237 | opt[i++] = sp->dns_addrs[0] >> 24; | | 3237 | opt[i++] = sp->dns_addrs[0] >> 24; |
3238 | opt[i++] = sp->dns_addrs[0] >> 16; | | 3238 | opt[i++] = sp->dns_addrs[0] >> 16; |
3239 | opt[i++] = sp->dns_addrs[0] >> 8; | | 3239 | opt[i++] = sp->dns_addrs[0] >> 8; |
3240 | opt[i++] = sp->dns_addrs[0]; | | 3240 | opt[i++] = sp->dns_addrs[0]; |
3241 | } | | 3241 | } |
3242 | if (sp->query_dns & 2) { | | 3242 | if (sp->query_dns & 2) { |
3243 | opt[i++] = IPCP_OPT_SECDNS; | | 3243 | opt[i++] = IPCP_OPT_SECDNS; |
3244 | opt[i++] = 6; | | 3244 | opt[i++] = 6; |
3245 | opt[i++] = sp->dns_addrs[1] >> 24; | | 3245 | opt[i++] = sp->dns_addrs[1] >> 24; |
3246 | opt[i++] = sp->dns_addrs[1] >> 16; | | 3246 | opt[i++] = sp->dns_addrs[1] >> 16; |
3247 | opt[i++] = sp->dns_addrs[1] >> 8; | | 3247 | opt[i++] = sp->dns_addrs[1] >> 8; |
3248 | opt[i++] = sp->dns_addrs[1]; | | 3248 | opt[i++] = sp->dns_addrs[1]; |
3249 | } | | 3249 | } |
3250 | | | 3250 | |
3251 | sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; | | 3251 | sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; |
3252 | sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); | | 3252 | sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); |
3253 | } | | 3253 | } |
3254 | | | 3254 | |
3255 | | | 3255 | |
3256 | /* | | 3256 | /* |
3257 | *--------------------------------------------------------------------------* | | 3257 | *--------------------------------------------------------------------------* |
3258 | * * | | 3258 | * * |
3259 | * The IPv6CP implementation. * | | 3259 | * The IPv6CP implementation. * |
3260 | * * | | 3260 | * * |
3261 | *--------------------------------------------------------------------------* | | 3261 | *--------------------------------------------------------------------------* |
3262 | */ | | 3262 | */ |
3263 | | | 3263 | |
3264 | #ifdef INET6 | | 3264 | #ifdef INET6 |
3265 | static void | | 3265 | static void |
3266 | sppp_ipv6cp_init(struct sppp *sp) | | 3266 | sppp_ipv6cp_init(struct sppp *sp) |
3267 | { | | 3267 | { |
3268 | sp->ipv6cp.opts = 0; | | 3268 | sp->ipv6cp.opts = 0; |
3269 | sp->ipv6cp.flags = 0; | | 3269 | sp->ipv6cp.flags = 0; |
3270 | sp->state[IDX_IPV6CP] = STATE_INITIAL; | | 3270 | sp->state[IDX_IPV6CP] = STATE_INITIAL; |
3271 | sp->fail_counter[IDX_IPV6CP] = 0; | | 3271 | sp->fail_counter[IDX_IPV6CP] = 0; |
3272 | sp->pp_seq[IDX_IPV6CP] = 0; | | 3272 | sp->pp_seq[IDX_IPV6CP] = 0; |
3273 | sp->pp_rseq[IDX_IPV6CP] = 0; | | 3273 | sp->pp_rseq[IDX_IPV6CP] = 0; |
3274 | callout_init(&sp->ch[IDX_IPV6CP], 0); | | 3274 | callout_init(&sp->ch[IDX_IPV6CP], 0); |
3275 | } | | 3275 | } |
3276 | | | 3276 | |
3277 | static void | | 3277 | static void |
3278 | sppp_ipv6cp_up(struct sppp *sp) | | 3278 | sppp_ipv6cp_up(struct sppp *sp) |
3279 | { | | 3279 | { |
3280 | sppp_up_event(&ipv6cp, sp); | | 3280 | sppp_up_event(&ipv6cp, sp); |
3281 | } | | 3281 | } |
3282 | | | 3282 | |
3283 | static void | | 3283 | static void |
3284 | sppp_ipv6cp_down(struct sppp *sp) | | 3284 | sppp_ipv6cp_down(struct sppp *sp) |
3285 | { | | 3285 | { |
3286 | sppp_down_event(&ipv6cp, sp); | | 3286 | sppp_down_event(&ipv6cp, sp); |
3287 | } | | 3287 | } |
3288 | | | 3288 | |
3289 | static void | | 3289 | static void |
3290 | sppp_ipv6cp_open(struct sppp *sp) | | 3290 | sppp_ipv6cp_open(struct sppp *sp) |
3291 | { | | 3291 | { |
3292 | STDDCL; | | 3292 | STDDCL; |
3293 | struct in6_addr myaddr, hisaddr; | | 3293 | struct in6_addr myaddr, hisaddr; |
3294 | | | 3294 | |
3295 | #ifdef IPV6CP_MYIFID_DYN | | 3295 | #ifdef IPV6CP_MYIFID_DYN |
3296 | sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); | | 3296 | sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); |
3297 | #else | | 3297 | #else |
3298 | sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; | | 3298 | sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; |
3299 | #endif | | 3299 | #endif |
3300 | | | 3300 | |
3301 | sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); | | 3301 | sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); |
3302 | /* | | 3302 | /* |
3303 | * If we don't have our address, this probably means our | | 3303 | * If we don't have our address, this probably means our |
3304 | * interface doesn't want to talk IPv6 at all. (This could | | 3304 | * interface doesn't want to talk IPv6 at all. (This could |
3305 | * be the case if somebody wants to speak only IPX, for | | 3305 | * be the case if somebody wants to speak only IPX, for |
3306 | * example.) Don't open IPv6CP in this case. | | 3306 | * example.) Don't open IPv6CP in this case. |
3307 | */ | | 3307 | */ |
3308 | if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { | | 3308 | if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { |
3309 | /* XXX this message should go away */ | | 3309 | /* XXX this message should go away */ |
3310 | if (debug) | | 3310 | if (debug) |
3311 | log(LOG_DEBUG, "%s: ipv6cp_open(): no IPv6 interface\n", | | 3311 | log(LOG_DEBUG, "%s: ipv6cp_open(): no IPv6 interface\n", |
3312 | ifp->if_xname); | | 3312 | ifp->if_xname); |
3313 | return; | | 3313 | return; |
3314 | } | | 3314 | } |
3315 | | | 3315 | |
3316 | sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; | | 3316 | sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; |
3317 | sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); | | 3317 | sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); |
3318 | sppp_open_event(&ipv6cp, sp); | | 3318 | sppp_open_event(&ipv6cp, sp); |
3319 | } | | 3319 | } |
3320 | | | 3320 | |
3321 | static void | | 3321 | static void |
3322 | sppp_ipv6cp_close(struct sppp *sp) | | 3322 | sppp_ipv6cp_close(struct sppp *sp) |
3323 | { | | 3323 | { |
3324 | sppp_close_event(&ipv6cp, sp); | | 3324 | sppp_close_event(&ipv6cp, sp); |
3325 | } | | 3325 | } |
3326 | | | 3326 | |
3327 | static void | | 3327 | static void |
3328 | sppp_ipv6cp_TO(void *cookie) | | 3328 | sppp_ipv6cp_TO(void *cookie) |
3329 | { | | 3329 | { |
3330 | sppp_to_event(&ipv6cp, (struct sppp *)cookie); | | 3330 | sppp_to_event(&ipv6cp, (struct sppp *)cookie); |
3331 | } | | 3331 | } |
3332 | | | 3332 | |
3333 | /* | | 3333 | /* |
3334 | * Analyze a configure request. Return true if it was agreeable, and | | 3334 | * Analyze a configure request. Return true if it was agreeable, and |
3335 | * caused action sca, false if it has been rejected or nak'ed, and | | 3335 | * caused action sca, false if it has been rejected or nak'ed, and |
3336 | * caused action scn. (The return value is used to make the state | | 3336 | * caused action scn. (The return value is used to make the state |
3337 | * transition decision in the state automaton.) | | 3337 | * transition decision in the state automaton.) |
3338 | */ | | 3338 | */ |
3339 | static int | | 3339 | static int |
3340 | sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) | | 3340 | sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) |
3341 | { | | 3341 | { |
3342 | u_char *buf, *r, *p; | | 3342 | u_char *buf, *r, *p; |
3343 | struct ifnet *ifp = &sp->pp_if; | | 3343 | struct ifnet *ifp = &sp->pp_if; |
3344 | int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; | | 3344 | int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; |
3345 | struct in6_addr myaddr, desiredaddr, suggestaddr; | | 3345 | struct in6_addr myaddr, desiredaddr, suggestaddr; |
3346 | int ifidcount; | | 3346 | int ifidcount; |
3347 | int type; | | 3347 | int type; |
3348 | int collision, nohisaddr; | | 3348 | int collision, nohisaddr; |
3349 | | | 3349 | |
3350 | len -= 4; | | 3350 | len -= 4; |
3351 | origlen = len; | | 3351 | origlen = len; |
3352 | /* | | 3352 | /* |
3353 | * Make sure to allocate a buf that can at least hold a | | 3353 | * Make sure to allocate a buf that can at least hold a |
3354 | * conf-nak with an `address' option. We might need it below. | | 3354 | * conf-nak with an `address' option. We might need it below. |
3355 | */ | | 3355 | */ |
3356 | buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); | | 3356 | buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); |
3357 | if (! buf) | | 3357 | if (! buf) |
3358 | return (0); | | 3358 | return (0); |
3359 | | | 3359 | |
3360 | /* pass 1: see if we can recognize them */ | | 3360 | /* pass 1: see if we can recognize them */ |
3361 | if (debug) | | 3361 | if (debug) |
3362 | log(LOG_DEBUG, "%s: ipv6cp parse opts:", | | 3362 | log(LOG_DEBUG, "%s: ipv6cp parse opts:", |
3363 | ifp->if_xname); | | 3363 | ifp->if_xname); |
3364 | p = (void *)(h + 1); | | 3364 | p = (void *)(h + 1); |
3365 | ifidcount = 0; | | 3365 | ifidcount = 0; |
3366 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { | | 3366 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { |
3367 | /* Sanity check option length */ | | 3367 | /* Sanity check option length */ |
3368 | if (p[1] > len) { | | 3368 | if (p[1] > len) { |
3369 | /* XXX just RXJ? */ | | 3369 | /* XXX just RXJ? */ |
3370 | addlog("%s: received malicious IPCPv6 option, " | | 3370 | addlog("%s: received malicious IPCPv6 option, " |
3371 | "dropping\n", ifp->if_xname); | | 3371 | "dropping\n", ifp->if_xname); |
3372 | goto drop; | | 3372 | goto drop; |
3373 | } | | 3373 | } |
3374 | if (debug) | | 3374 | if (debug) |
3375 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); | | 3375 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); |
3376 | switch (*p) { | | 3376 | switch (*p) { |
3377 | case IPV6CP_OPT_IFID: | | 3377 | case IPV6CP_OPT_IFID: |
3378 | if (len >= 10 && p[1] == 10 && ifidcount == 0) { | | 3378 | if (len >= 10 && p[1] == 10 && ifidcount == 0) { |
3379 | /* correctly formed address option */ | | 3379 | /* correctly formed address option */ |
3380 | ifidcount++; | | 3380 | ifidcount++; |
3381 | continue; | | 3381 | continue; |
3382 | } | | 3382 | } |
3383 | if (debug) | | 3383 | if (debug) |
3384 | addlog(" [invalid]"); | | 3384 | addlog(" [invalid]"); |
3385 | break; | | 3385 | break; |
3386 | #ifdef notyet | | 3386 | #ifdef notyet |
3387 | case IPV6CP_OPT_COMPRESSION: | | 3387 | case IPV6CP_OPT_COMPRESSION: |
3388 | if (len >= 4 && p[1] >= 4) { | | 3388 | if (len >= 4 && p[1] >= 4) { |
3389 | /* correctly formed compress option */ | | 3389 | /* correctly formed compress option */ |
3390 | continue; | | 3390 | continue; |
3391 | } | | 3391 | } |
3392 | if (debug) | | 3392 | if (debug) |
3393 | addlog(" [invalid]"); | | 3393 | addlog(" [invalid]"); |
3394 | break; | | 3394 | break; |
3395 | #endif | | 3395 | #endif |
3396 | default: | | 3396 | default: |
3397 | /* Others not supported. */ | | 3397 | /* Others not supported. */ |
3398 | if (debug) | | 3398 | if (debug) |
3399 | addlog(" [rej]"); | | 3399 | addlog(" [rej]"); |
3400 | break; | | 3400 | break; |
3401 | } | | 3401 | } |
3402 | /* Add the option to rejected list. */ | | 3402 | /* Add the option to rejected list. */ |
3403 | bcopy (p, r, p[1]); | | 3403 | bcopy (p, r, p[1]); |
3404 | r += p[1]; | | 3404 | r += p[1]; |
3405 | rlen += p[1]; | | 3405 | rlen += p[1]; |
3406 | } | | 3406 | } |
3407 | if (rlen) { | | 3407 | if (rlen) { |
3408 | if (debug) | | 3408 | if (debug) |
3409 | addlog(" send conf-rej\n"); | | 3409 | addlog(" send conf-rej\n"); |
3410 | sppp_cp_send(sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); | | 3410 | sppp_cp_send(sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); |
3411 | goto end; | | 3411 | goto end; |
3412 | } else if (debug) | | 3412 | } else if (debug) |
3413 | addlog("\n"); | | 3413 | addlog("\n"); |
3414 | | | 3414 | |
3415 | /* pass 2: parse option values */ | | 3415 | /* pass 2: parse option values */ |
3416 | sppp_get_ip6_addrs(sp, &myaddr, 0, 0); | | 3416 | sppp_get_ip6_addrs(sp, &myaddr, 0, 0); |
3417 | if (debug) | | 3417 | if (debug) |
3418 | log(LOG_DEBUG, "%s: ipv6cp parse opt values: ", | | 3418 | log(LOG_DEBUG, "%s: ipv6cp parse opt values: ", |
3419 | ifp->if_xname); | | 3419 | ifp->if_xname); |
3420 | p = (void *)(h + 1); | | 3420 | p = (void *)(h + 1); |
3421 | len = origlen; | | 3421 | len = origlen; |
3422 | type = CONF_ACK; | | 3422 | type = CONF_ACK; |
3423 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { | | 3423 | for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { |
3424 | if (debug) | | 3424 | if (debug) |
3425 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); | | 3425 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); |
3426 | switch (*p) { | | 3426 | switch (*p) { |
3427 | #ifdef notyet | | 3427 | #ifdef notyet |
3428 | case IPV6CP_OPT_COMPRESSION: | | 3428 | case IPV6CP_OPT_COMPRESSION: |
3429 | continue; | | 3429 | continue; |
3430 | #endif | | 3430 | #endif |
3431 | case IPV6CP_OPT_IFID: | | 3431 | case IPV6CP_OPT_IFID: |
3432 | memset(&desiredaddr, 0, sizeof(desiredaddr)); | | 3432 | memset(&desiredaddr, 0, sizeof(desiredaddr)); |
3433 | bcopy(&p[2], &desiredaddr.s6_addr[8], 8); | | 3433 | bcopy(&p[2], &desiredaddr.s6_addr[8], 8); |
3434 | collision = (memcmp(&desiredaddr.s6_addr[8], | | 3434 | collision = (memcmp(&desiredaddr.s6_addr[8], |
3435 | &myaddr.s6_addr[8], 8) == 0); | | 3435 | &myaddr.s6_addr[8], 8) == 0); |
3436 | nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); | | 3436 | nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); |
3437 | | | 3437 | |
3438 | desiredaddr.s6_addr16[0] = htons(0xfe80); | | 3438 | desiredaddr.s6_addr16[0] = htons(0xfe80); |
3439 | (void)in6_setscope(&desiredaddr, &sp->pp_if, NULL); | | 3439 | (void)in6_setscope(&desiredaddr, &sp->pp_if, NULL); |
3440 | | | 3440 | |
3441 | if (!collision && !nohisaddr) { | | 3441 | if (!collision && !nohisaddr) { |
3442 | /* no collision, hisaddr known - Conf-Ack */ | | 3442 | /* no collision, hisaddr known - Conf-Ack */ |
3443 | type = CONF_ACK; | | 3443 | type = CONF_ACK; |
3444 | | | 3444 | |
3445 | if (debug) { | | 3445 | if (debug) { |
3446 | addlog(" %s [%s]", | | 3446 | addlog(" %s [%s]", |
3447 | ip6_sprintf(&desiredaddr), | | 3447 | ip6_sprintf(&desiredaddr), |
3448 | sppp_cp_type_name(type)); | | 3448 | sppp_cp_type_name(type)); |
3449 | } | | 3449 | } |
3450 | continue; | | 3450 | continue; |
3451 | } | | 3451 | } |
3452 | | | 3452 | |
3453 | memset(&suggestaddr, 0, sizeof(&suggestaddr)); | | 3453 | memset(&suggestaddr, 0, sizeof(suggestaddr)); |
3454 | if (collision && nohisaddr) { | | 3454 | if (collision && nohisaddr) { |
3455 | /* collision, hisaddr unknown - Conf-Rej */ | | 3455 | /* collision, hisaddr unknown - Conf-Rej */ |
3456 | type = CONF_REJ; | | 3456 | type = CONF_REJ; |
3457 | memset(&p[2], 0, 8); | | 3457 | memset(&p[2], 0, 8); |
3458 | } else { | | 3458 | } else { |
3459 | /* | | 3459 | /* |
3460 | * - no collision, hisaddr unknown, or | | 3460 | * - no collision, hisaddr unknown, or |
3461 | * - collision, hisaddr known | | 3461 | * - collision, hisaddr known |
3462 | * Conf-Nak, suggest hisaddr | | 3462 | * Conf-Nak, suggest hisaddr |
3463 | */ | | 3463 | */ |
3464 | type = CONF_NAK; | | 3464 | type = CONF_NAK; |
3465 | sppp_suggest_ip6_addr(sp, &suggestaddr); | | 3465 | sppp_suggest_ip6_addr(sp, &suggestaddr); |
3466 | bcopy(&suggestaddr.s6_addr[8], &p[2], 8); | | 3466 | bcopy(&suggestaddr.s6_addr[8], &p[2], 8); |
3467 | } | | 3467 | } |
3468 | if (debug) | | 3468 | if (debug) |
3469 | addlog(" %s [%s]", ip6_sprintf(&desiredaddr), | | 3469 | addlog(" %s [%s]", ip6_sprintf(&desiredaddr), |
3470 | sppp_cp_type_name(type)); | | 3470 | sppp_cp_type_name(type)); |
3471 | break; | | 3471 | break; |
3472 | } | | 3472 | } |
3473 | /* Add the option to nak'ed list. */ | | 3473 | /* Add the option to nak'ed list. */ |
3474 | bcopy (p, r, p[1]); | | 3474 | bcopy (p, r, p[1]); |
3475 | r += p[1]; | | 3475 | r += p[1]; |
3476 | rlen += p[1]; | | 3476 | rlen += p[1]; |
3477 | } | | 3477 | } |
3478 | | | 3478 | |
3479 | if (rlen == 0 && type == CONF_ACK) { | | 3479 | if (rlen == 0 && type == CONF_ACK) { |
3480 | if (debug) | | 3480 | if (debug) |
3481 | addlog(" send %s\n", sppp_cp_type_name(type)); | | 3481 | addlog(" send %s\n", sppp_cp_type_name(type)); |
3482 | sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, origlen, h + 1); | | 3482 | sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, origlen, h + 1); |
3483 | } else { | | 3483 | } else { |
3484 | #ifdef notdef | | 3484 | #ifdef notdef |
3485 | if (type == CONF_ACK) | | 3485 | if (type == CONF_ACK) |
3486 | panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); | | 3486 | panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); |
3487 | #endif | | 3487 | #endif |
3488 | | | 3488 | |
3489 | if (debug) { | | 3489 | if (debug) { |
3490 | addlog(" send %s suggest %s\n", | | 3490 | addlog(" send %s suggest %s\n", |
3491 | sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); | | 3491 | sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); |
3492 | } | | 3492 | } |
3493 | sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, rlen, buf); | | 3493 | sppp_cp_send(sp, PPP_IPV6CP, type, h->ident, rlen, buf); |
3494 | } | | 3494 | } |
3495 | | | 3495 | |
3496 | end: | | 3496 | end: |
3497 | free(buf, M_TEMP); | | 3497 | free(buf, M_TEMP); |
3498 | return (rlen == 0); | | 3498 | return (rlen == 0); |
3499 | | | 3499 | |
3500 | drop: | | 3500 | drop: |
3501 | free(buf, M_TEMP); | | 3501 | free(buf, M_TEMP); |
3502 | return -1; | | 3502 | return -1; |
3503 | } | | 3503 | } |
3504 | | | 3504 | |
3505 | /* | | 3505 | /* |
3506 | * Analyze the IPv6CP Configure-Reject option list, and adjust our | | 3506 | * Analyze the IPv6CP Configure-Reject option list, and adjust our |
3507 | * negotiation. | | 3507 | * negotiation. |
3508 | */ | | 3508 | */ |
3509 | static void | | 3509 | static void |
3510 | sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) | | 3510 | sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) |
3511 | { | | 3511 | { |
3512 | u_char *buf, *p; | | 3512 | u_char *buf, *p; |
3513 | struct ifnet *ifp = &sp->pp_if; | | 3513 | struct ifnet *ifp = &sp->pp_if; |
3514 | int debug = ifp->if_flags & IFF_DEBUG; | | 3514 | int debug = ifp->if_flags & IFF_DEBUG; |
3515 | | | 3515 | |
3516 | len -= 4; | | 3516 | len -= 4; |
3517 | buf = malloc (len, M_TEMP, M_NOWAIT); | | 3517 | buf = malloc (len, M_TEMP, M_NOWAIT); |
3518 | if (!buf) | | 3518 | if (!buf) |
3519 | return; | | 3519 | return; |
3520 | | | 3520 | |
3521 | if (debug) | | 3521 | if (debug) |
3522 | log(LOG_DEBUG, "%s: ipv6cp rej opts:", | | 3522 | log(LOG_DEBUG, "%s: ipv6cp rej opts:", |
3523 | ifp->if_xname); | | 3523 | ifp->if_xname); |
3524 | | | 3524 | |
3525 | p = (void *)(h + 1); | | 3525 | p = (void *)(h + 1); |
3526 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { | | 3526 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { |
3527 | if (p[1] > len) { | | 3527 | if (p[1] > len) { |
3528 | /* XXX just RXJ? */ | | 3528 | /* XXX just RXJ? */ |
3529 | addlog("%s: received malicious IPCPv6 option, " | | 3529 | addlog("%s: received malicious IPCPv6 option, " |
3530 | "dropping\n", ifp->if_xname); | | 3530 | "dropping\n", ifp->if_xname); |
3531 | goto drop; | | 3531 | goto drop; |
3532 | } | | 3532 | } |
3533 | if (debug) | | 3533 | if (debug) |
3534 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); | | 3534 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); |
3535 | switch (*p) { | | 3535 | switch (*p) { |
3536 | case IPV6CP_OPT_IFID: | | 3536 | case IPV6CP_OPT_IFID: |
3537 | /* | | 3537 | /* |
3538 | * Peer doesn't grok address option. This is | | 3538 | * Peer doesn't grok address option. This is |
3539 | * bad. XXX Should we better give up here? | | 3539 | * bad. XXX Should we better give up here? |
3540 | */ | | 3540 | */ |
3541 | sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); | | 3541 | sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); |
3542 | break; | | 3542 | break; |
3543 | #ifdef notyet | | 3543 | #ifdef notyet |
3544 | case IPV6CP_OPT_COMPRESS: | | 3544 | case IPV6CP_OPT_COMPRESS: |
3545 | sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); | | 3545 | sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); |
3546 | break; | | 3546 | break; |
3547 | #endif | | 3547 | #endif |
3548 | } | | 3548 | } |
3549 | } | | 3549 | } |
3550 | if (debug) | | 3550 | if (debug) |
3551 | addlog("\n"); | | 3551 | addlog("\n"); |
3552 | drop: | | 3552 | drop: |
3553 | free(buf, M_TEMP); | | 3553 | free(buf, M_TEMP); |
3554 | return; | | 3554 | return; |
3555 | } | | 3555 | } |
3556 | | | 3556 | |
3557 | /* | | 3557 | /* |
3558 | * Analyze the IPv6CP Configure-NAK option list, and adjust our | | 3558 | * Analyze the IPv6CP Configure-NAK option list, and adjust our |
3559 | * negotiation. | | 3559 | * negotiation. |
3560 | */ | | 3560 | */ |
3561 | static void | | 3561 | static void |
3562 | sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) | | 3562 | sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) |
3563 | { | | 3563 | { |
3564 | u_char *buf, *p; | | 3564 | u_char *buf, *p; |
3565 | struct ifnet *ifp = &sp->pp_if; | | 3565 | struct ifnet *ifp = &sp->pp_if; |
3566 | int debug = ifp->if_flags & IFF_DEBUG; | | 3566 | int debug = ifp->if_flags & IFF_DEBUG; |
3567 | struct in6_addr suggestaddr; | | 3567 | struct in6_addr suggestaddr; |
3568 | | | 3568 | |
3569 | len -= 4; | | 3569 | len -= 4; |
3570 | buf = malloc (len, M_TEMP, M_NOWAIT); | | 3570 | buf = malloc (len, M_TEMP, M_NOWAIT); |
3571 | if (!buf) | | 3571 | if (!buf) |
3572 | return; | | 3572 | return; |
3573 | | | 3573 | |
3574 | if (debug) | | 3574 | if (debug) |
3575 | log(LOG_DEBUG, "%s: ipv6cp nak opts:", | | 3575 | log(LOG_DEBUG, "%s: ipv6cp nak opts:", |
3576 | ifp->if_xname); | | 3576 | ifp->if_xname); |
3577 | | | 3577 | |
3578 | p = (void *)(h + 1); | | 3578 | p = (void *)(h + 1); |
3579 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { | | 3579 | for (; len > 1 && p[1]; len -= p[1], p += p[1]) { |
3580 | if (p[1] > len) { | | 3580 | if (p[1] > len) { |
3581 | /* XXX just RXJ? */ | | 3581 | /* XXX just RXJ? */ |
3582 | addlog("%s: received malicious IPCPv6 option, " | | 3582 | addlog("%s: received malicious IPCPv6 option, " |
3583 | "dropping\n", ifp->if_xname); | | 3583 | "dropping\n", ifp->if_xname); |
3584 | goto drop; | | 3584 | goto drop; |
3585 | } | | 3585 | } |
3586 | if (debug) | | 3586 | if (debug) |
3587 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); | | 3587 | addlog(" %s", sppp_ipv6cp_opt_name(*p)); |
3588 | switch (*p) { | | 3588 | switch (*p) { |
3589 | case IPV6CP_OPT_IFID: | | 3589 | case IPV6CP_OPT_IFID: |
3590 | /* | | 3590 | /* |
3591 | * Peer doesn't like our local ifid. See | | 3591 | * Peer doesn't like our local ifid. See |
3592 | * if we can do something for him. We'll drop | | 3592 | * if we can do something for him. We'll drop |
3593 | * him our address then. | | 3593 | * him our address then. |
3594 | */ | | 3594 | */ |
3595 | if (len < 10 || p[1] != 10) | | 3595 | if (len < 10 || p[1] != 10) |
3596 | break; | | 3596 | break; |
3597 | memset(&suggestaddr, 0, sizeof(suggestaddr)); | | 3597 | memset(&suggestaddr, 0, sizeof(suggestaddr)); |
3598 | suggestaddr.s6_addr16[0] = htons(0xfe80); | | 3598 | suggestaddr.s6_addr16[0] = htons(0xfe80); |
3599 | (void)in6_setscope(&suggestaddr, &sp->pp_if, NULL); | | 3599 | (void)in6_setscope(&suggestaddr, &sp->pp_if, NULL); |
3600 | bcopy(&p[2], &suggestaddr.s6_addr[8], 8); | | 3600 | bcopy(&p[2], &suggestaddr.s6_addr[8], 8); |
3601 | | | 3601 | |
3602 | sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); | | 3602 | sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); |
3603 | if (debug) | | 3603 | if (debug) |
3604 | addlog(" [suggestaddr %s]", | | 3604 | addlog(" [suggestaddr %s]", |
3605 | ip6_sprintf(&suggestaddr)); | | 3605 | ip6_sprintf(&suggestaddr)); |
3606 | #ifdef IPV6CP_MYIFID_DYN | | 3606 | #ifdef IPV6CP_MYIFID_DYN |
3607 | /* | | 3607 | /* |
3608 | * When doing dynamic address assignment, | | 3608 | * When doing dynamic address assignment, |
3609 | * we accept his offer. | | 3609 | * we accept his offer. |
3610 | */ | | 3610 | */ |
3611 | if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { | | 3611 | if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { |
3612 | struct in6_addr lastsuggest; | | 3612 | struct in6_addr lastsuggest; |
3613 | /* | | 3613 | /* |
3614 | * If <suggested myaddr from peer> equals to | | 3614 | * If <suggested myaddr from peer> equals to |
3615 | * <hisaddr we have suggested last time>, | | 3615 | * <hisaddr we have suggested last time>, |
3616 | * we have a collision. generate new random | | 3616 | * we have a collision. generate new random |
3617 | * ifid. | | 3617 | * ifid. |
3618 | */ | | 3618 | */ |
3619 | sppp_suggest_ip6_addr(&lastsuggest); | | 3619 | sppp_suggest_ip6_addr(&lastsuggest); |
3620 | if (IN6_ARE_ADDR_EQUAL(&suggestaddr, | | 3620 | if (IN6_ARE_ADDR_EQUAL(&suggestaddr, |
3621 | lastsuggest)) { | | 3621 | lastsuggest)) { |
3622 | if (debug) | | 3622 | if (debug) |
3623 | addlog(" [random]"); | | 3623 | addlog(" [random]"); |
3624 | sppp_gen_ip6_addr(sp, &suggestaddr); | | 3624 | sppp_gen_ip6_addr(sp, &suggestaddr); |
3625 | } | | 3625 | } |
3626 | sppp_set_ip6_addr(sp, &suggestaddr, 0); | | 3626 | sppp_set_ip6_addr(sp, &suggestaddr, 0); |
3627 | if (debug) | | 3627 | if (debug) |
3628 | addlog(" [agree]"); | | 3628 | addlog(" [agree]"); |
3629 | sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; | | 3629 | sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; |
3630 | } | | 3630 | } |
3631 | #else | | 3631 | #else |
3632 | /* | | 3632 | /* |
3633 | * Since we do not do dynamic address assignment, | | 3633 | * Since we do not do dynamic address assignment, |
3634 | * we ignore it and thus continue to negotiate | | 3634 | * we ignore it and thus continue to negotiate |
3635 | * our already existing value. This can possibly | | 3635 | * our already existing value. This can possibly |
3636 | * go into infinite request-reject loop. | | 3636 | * go into infinite request-reject loop. |
3637 | * | | 3637 | * |
3638 | * This is not likely because we normally use | | 3638 | * This is not likely because we normally use |
3639 | * ifid based on MAC-address. | | 3639 | * ifid based on MAC-address. |
3640 | * If you have no ethernet card on the node, too bad. | | 3640 | * If you have no ethernet card on the node, too bad. |
3641 | * XXX should we use fail_counter? | | 3641 | * XXX should we use fail_counter? |
3642 | */ | | 3642 | */ |
3643 | #endif | | 3643 | #endif |
3644 | break; | | 3644 | break; |
3645 | #ifdef notyet | | 3645 | #ifdef notyet |
3646 | case IPV6CP_OPT_COMPRESS: | | 3646 | case IPV6CP_OPT_COMPRESS: |
3647 | /* | | 3647 | /* |
3648 | * Peer wants different compression parameters. | | 3648 | * Peer wants different compression parameters. |
3649 | */ | | 3649 | */ |
3650 | break; | | 3650 | break; |
3651 | #endif | | 3651 | #endif |
3652 | } | | 3652 | } |
3653 | } | | 3653 | } |
3654 | if (debug) | | 3654 | if (debug) |
3655 | addlog("\n"); | | 3655 | addlog("\n"); |
3656 | drop: | | 3656 | drop: |
3657 | free(buf, M_TEMP); | | 3657 | free(buf, M_TEMP); |
3658 | return; | | 3658 | return; |
3659 | } | | 3659 | } |
3660 | | | 3660 | |
3661 | static void | | 3661 | static void |
3662 | sppp_ipv6cp_tlu(struct sppp *sp) | | 3662 | sppp_ipv6cp_tlu(struct sppp *sp) |
3663 | { | | 3663 | { |
3664 | /* we are up - notify isdn daemon */ | | 3664 | /* we are up - notify isdn daemon */ |
3665 | if (sp->pp_con) | | 3665 | if (sp->pp_con) |
3666 | sp->pp_con(sp); | | 3666 | sp->pp_con(sp); |
3667 | } | | 3667 | } |
3668 | | | 3668 | |
3669 | static void | | 3669 | static void |
3670 | sppp_ipv6cp_tld(struct sppp *sp) | | 3670 | sppp_ipv6cp_tld(struct sppp *sp) |
3671 | { | | 3671 | { |
3672 | } | | 3672 | } |
3673 | | | 3673 | |
3674 | static void | | 3674 | static void |
3675 | sppp_ipv6cp_tls(struct sppp *sp) | | 3675 | sppp_ipv6cp_tls(struct sppp *sp) |
3676 | { | | 3676 | { |
3677 | /* indicate to LCP that it must stay alive */ | | 3677 | /* indicate to LCP that it must stay alive */ |
3678 | sp->lcp.protos |= (1 << IDX_IPV6CP); | | 3678 | sp->lcp.protos |= (1 << IDX_IPV6CP); |
3679 | } | | 3679 | } |
3680 | | | 3680 | |
3681 | static void | | 3681 | static void |
3682 | sppp_ipv6cp_tlf(struct sppp *sp) | | 3682 | sppp_ipv6cp_tlf(struct sppp *sp) |
3683 | { | | 3683 | { |
3684 | /* we no longer need LCP */ | | 3684 | /* we no longer need LCP */ |
3685 | sp->lcp.protos &= ~(1 << IDX_IPV6CP); | | 3685 | sp->lcp.protos &= ~(1 << IDX_IPV6CP); |
3686 | } | | 3686 | } |
3687 | | | 3687 | |
3688 | static void | | 3688 | static void |
3689 | sppp_ipv6cp_scr(struct sppp *sp) | | 3689 | sppp_ipv6cp_scr(struct sppp *sp) |
3690 | { | | 3690 | { |
3691 | char opt[10 /* ifid */ + 4 /* compression, minimum */]; | | 3691 | char opt[10 /* ifid */ + 4 /* compression, minimum */]; |
3692 | struct in6_addr ouraddr; | | 3692 | struct in6_addr ouraddr; |
3693 | int i = 0; | | 3693 | int i = 0; |
3694 | | | 3694 | |
3695 | if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { | | 3695 | if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { |
3696 | sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); | | 3696 | sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); |
3697 | opt[i++] = IPV6CP_OPT_IFID; | | 3697 | opt[i++] = IPV6CP_OPT_IFID; |
3698 | opt[i++] = 10; | | 3698 | opt[i++] = 10; |
3699 | bcopy(&ouraddr.s6_addr[8], &opt[i], 8); | | 3699 | bcopy(&ouraddr.s6_addr[8], &opt[i], 8); |
3700 | i += 8; | | 3700 | i += 8; |
3701 | } | | 3701 | } |
3702 | | | 3702 | |
3703 | #ifdef notyet | | 3703 | #ifdef notyet |
3704 | if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { | | 3704 | if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { |
3705 | opt[i++] = IPV6CP_OPT_COMPRESSION; | | 3705 | opt[i++] = IPV6CP_OPT_COMPRESSION; |
3706 | opt[i++] = 4; | | 3706 | opt[i++] = 4; |
3707 | opt[i++] = 0; /* TBD */ | | 3707 | opt[i++] = 0; /* TBD */ |
3708 | opt[i++] = 0; /* TBD */ | | 3708 | opt[i++] = 0; /* TBD */ |
3709 | /* variable length data may follow */ | | 3709 | /* variable length data may follow */ |
3710 | } | | 3710 | } |
3711 | #endif | | 3711 | #endif |
3712 | | | 3712 | |
3713 | sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; | | 3713 | sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; |
3714 | sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); | | 3714 | sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); |
3715 | } | | 3715 | } |
3716 | #else /*INET6*/ | | 3716 | #else /*INET6*/ |
3717 | static void | | 3717 | static void |
3718 | sppp_ipv6cp_init(struct sppp *sp) | | 3718 | sppp_ipv6cp_init(struct sppp *sp) |
3719 | { | | 3719 | { |
3720 | } | | 3720 | } |
3721 | | | 3721 | |
3722 | static void | | 3722 | static void |
3723 | sppp_ipv6cp_up(struct sppp *sp) | | 3723 | sppp_ipv6cp_up(struct sppp *sp) |
3724 | { | | 3724 | { |
3725 | } | | 3725 | } |
3726 | | | 3726 | |
3727 | static void | | 3727 | static void |
3728 | sppp_ipv6cp_down(struct sppp *sp) | | 3728 | sppp_ipv6cp_down(struct sppp *sp) |
3729 | { | | 3729 | { |
3730 | } | | 3730 | } |
3731 | | | 3731 | |
3732 | static void | | 3732 | static void |
3733 | sppp_ipv6cp_open(struct sppp *sp) | | 3733 | sppp_ipv6cp_open(struct sppp *sp) |
3734 | { | | 3734 | { |
3735 | } | | 3735 | } |
3736 | | | 3736 | |
3737 | static void | | 3737 | static void |
3738 | sppp_ipv6cp_close(struct sppp *sp) | | 3738 | sppp_ipv6cp_close(struct sppp *sp) |
3739 | { | | 3739 | { |
3740 | } | | 3740 | } |
3741 | | | 3741 | |
3742 | static void | | 3742 | static void |
3743 | sppp_ipv6cp_TO(void *sp) | | 3743 | sppp_ipv6cp_TO(void *sp) |
3744 | { | | 3744 | { |
3745 | } | | 3745 | } |
3746 | | | 3746 | |
3747 | static int | | 3747 | static int |
3748 | sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, | | 3748 | sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, |
3749 | int len) | | 3749 | int len) |
3750 | { | | 3750 | { |
3751 | return 0; | | 3751 | return 0; |
3752 | } | | 3752 | } |
3753 | | | 3753 | |
3754 | static void | | 3754 | static void |
3755 | sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, | | 3755 | sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, |
3756 | int len) | | 3756 | int len) |
3757 | { | | 3757 | { |
3758 | } | | 3758 | } |
3759 | | | 3759 | |
3760 | static void | | 3760 | static void |
3761 | sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, | | 3761 | sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, |
3762 | int len) | | 3762 | int len) |
3763 | { | | 3763 | { |
3764 | } | | 3764 | } |
3765 | | | 3765 | |
3766 | static void | | 3766 | static void |
3767 | sppp_ipv6cp_tlu(struct sppp *sp) | | 3767 | sppp_ipv6cp_tlu(struct sppp *sp) |
3768 | { | | 3768 | { |
3769 | } | | 3769 | } |
3770 | | | 3770 | |
3771 | static void | | 3771 | static void |
3772 | sppp_ipv6cp_tld(struct sppp *sp) | | 3772 | sppp_ipv6cp_tld(struct sppp *sp) |
3773 | { | | 3773 | { |
3774 | } | | 3774 | } |
3775 | | | 3775 | |
3776 | static void | | 3776 | static void |
3777 | sppp_ipv6cp_tls(struct sppp *sp) | | 3777 | sppp_ipv6cp_tls(struct sppp *sp) |
3778 | { | | 3778 | { |
3779 | } | | 3779 | } |
3780 | | | 3780 | |
3781 | static void | | 3781 | static void |
3782 | sppp_ipv6cp_tlf(struct sppp *sp) | | 3782 | sppp_ipv6cp_tlf(struct sppp *sp) |
3783 | { | | 3783 | { |
3784 | } | | 3784 | } |
3785 | | | 3785 | |
3786 | static void | | 3786 | static void |
3787 | sppp_ipv6cp_scr(struct sppp *sp) | | 3787 | sppp_ipv6cp_scr(struct sppp *sp) |
3788 | { | | 3788 | { |
3789 | } | | 3789 | } |
3790 | #endif /*INET6*/ | | 3790 | #endif /*INET6*/ |
3791 | | | 3791 | |
3792 | | | 3792 | |
3793 | /* | | 3793 | /* |
3794 | *--------------------------------------------------------------------------* | | 3794 | *--------------------------------------------------------------------------* |
3795 | * * | | 3795 | * * |
3796 | * The CHAP implementation. * | | 3796 | * The CHAP implementation. * |
3797 | * * | | 3797 | * * |
3798 | *--------------------------------------------------------------------------* | | 3798 | *--------------------------------------------------------------------------* |
3799 | */ | | 3799 | */ |
3800 | | | 3800 | |
3801 | /* | | 3801 | /* |
3802 | * The authentication protocols don't employ a full-fledged state machine as | | 3802 | * The authentication protocols don't employ a full-fledged state machine as |
3803 | * the control protocols do, since they do have Open and Close events, but | | 3803 | * the control protocols do, since they do have Open and Close events, but |
3804 | * not Up and Down, nor are they explicitly terminated. Also, use of the | | 3804 | * not Up and Down, nor are they explicitly terminated. Also, use of the |
3805 | * authentication protocols may be different in both directions (this makes | | 3805 | * authentication protocols may be different in both directions (this makes |
3806 | * sense, think of a machine that never accepts incoming calls but only | | 3806 | * sense, think of a machine that never accepts incoming calls but only |
3807 | * calls out, it doesn't require the called party to authenticate itself). | | 3807 | * calls out, it doesn't require the called party to authenticate itself). |
3808 | * | | 3808 | * |
3809 | * Our state machine for the local authentication protocol (we are requesting | | 3809 | * Our state machine for the local authentication protocol (we are requesting |
3810 | * the peer to authenticate) looks like: | | 3810 | * the peer to authenticate) looks like: |
3811 | * | | 3811 | * |
3812 | * RCA- | | 3812 | * RCA- |
3813 | * +--------------------------------------------+ | | 3813 | * +--------------------------------------------+ |
3814 | * V scn,tld| | | 3814 | * V scn,tld| |
3815 | * +--------+ Close +---------+ RCA+ | | 3815 | * +--------+ Close +---------+ RCA+ |
3816 | * | |<----------------------------------| |------+ | | 3816 | * | |<----------------------------------| |------+ |
3817 | * +--->| Closed | TO* | Opened | sca | | | 3817 | * +--->| Closed | TO* | Opened | sca | |
3818 | * | | |-----+ +-------| |<-----+ | | 3818 | * | | |-----+ +-------| |<-----+ |
3819 | * | +--------+ irc | | +---------+ | | 3819 | * | +--------+ irc | | +---------+ |
3820 | * | ^ | | ^ | | 3820 | * | ^ | | ^ |
3821 | * | | | | | | | 3821 | * | | | | | |
3822 | * | | | | | | | 3822 | * | | | | | |
3823 | * | TO-| | | | | | 3823 | * | TO-| | | | |
3824 | * | |tld TO+ V | | | | 3824 | * | |tld TO+ V | | |
3825 | * | | +------->+ | | | | 3825 | * | | +------->+ | | |
3826 | * | | | | | | | | 3826 | * | | | | | | |
3827 | * | +--------+ V | | | | 3827 | * | +--------+ V | | |
3828 | * | | |<----+<--------------------+ | | | 3828 | * | | |<----+<--------------------+ | |
3829 | * | | Req- | scr | | | 3829 | * | | Req- | scr | |
3830 | * | | Sent | | | | 3830 | * | | Sent | | |
3831 | * | | | | | | 3831 | * | | | | |
3832 | * | +--------+ | | | 3832 | * | +--------+ | |
3833 | * | RCA- | | RCA+ | | | 3833 | * | RCA- | | RCA+ | |
3834 | * +------+ +------------------------------------------+ | | 3834 | * +------+ +------------------------------------------+ |
3835 | * scn,tld sca,irc,ict,tlu | | 3835 | * scn,tld sca,irc,ict,tlu |
3836 | * | | 3836 | * |
3837 | * | | 3837 | * |
3838 | * with: | | 3838 | * with: |
3839 | * | | 3839 | * |
3840 | * Open: LCP reached authentication phase | | 3840 | * Open: LCP reached authentication phase |
3841 | * Close: LCP reached terminate phase | | 3841 | * Close: LCP reached terminate phase |
3842 | * | | 3842 | * |
3843 | * RCA+: received reply (pap-req, chap-response), acceptable | | 3843 | * RCA+: received reply (pap-req, chap-response), acceptable |
3844 | * RCN: received reply (pap-req, chap-response), not acceptable | | 3844 | * RCN: received reply (pap-req, chap-response), not acceptable |
3845 | * TO+: timeout with restart counter >= 0 | | 3845 | * TO+: timeout with restart counter >= 0 |
3846 | * TO-: timeout with restart counter < 0 | | 3846 | * TO-: timeout with restart counter < 0 |
3847 | * TO*: reschedule timeout for CHAP | | 3847 | * TO*: reschedule timeout for CHAP |
3848 | * | | 3848 | * |
3849 | * scr: send request packet (none for PAP, chap-challenge) | | 3849 | * scr: send request packet (none for PAP, chap-challenge) |
3850 | * sca: send ack packet (pap-ack, chap-success) | | 3850 | * sca: send ack packet (pap-ack, chap-success) |
3851 | * scn: send nak packet (pap-nak, chap-failure) | | 3851 | * scn: send nak packet (pap-nak, chap-failure) |
3852 | * ict: initialize re-challenge timer (CHAP only) | | 3852 | * ict: initialize re-challenge timer (CHAP only) |
3853 | * | | 3853 | * |
3854 | * tlu: this-layer-up, LCP reaches network phase | | 3854 | * tlu: this-layer-up, LCP reaches network phase |
3855 | * tld: this-layer-down, LCP enters terminate phase | | 3855 | * tld: this-layer-down, LCP enters terminate phase |
3856 | * | | 3856 | * |
3857 | * Note that in CHAP mode, after sending a new challenge, while the state | | 3857 | * Note that in CHAP mode, after sending a new challenge, while the state |
3858 | * automaton falls back into Req-Sent state, it doesn't signal a tld | | 3858 | * automaton falls back into Req-Sent state, it doesn't signal a tld |
3859 | * event to LCP, so LCP remains in network phase. Only after not getting | | 3859 | * event to LCP, so LCP remains in network phase. Only after not getting |
3860 | * any response (or after getting an unacceptable response), CHAP closes, | | 3860 | * any response (or after getting an unacceptable response), CHAP closes, |
3861 | * causing LCP to enter terminate phase. | | 3861 | * causing LCP to enter terminate phase. |
3862 | * | | 3862 | * |
3863 | * With PAP, there is no initial request that can be sent. The peer is | | 3863 | * With PAP, there is no initial request that can be sent. The peer is |
3864 | * expected to send one based on the successful negotiation of PAP as | | 3864 | * expected to send one based on the successful negotiation of PAP as |
3865 | * the authentication protocol during the LCP option negotiation. | | 3865 | * the authentication protocol during the LCP option negotiation. |
3866 | * | | 3866 | * |
3867 | * Incoming authentication protocol requests (remote requests | | 3867 | * Incoming authentication protocol requests (remote requests |
3868 | * authentication, we are peer) don't employ a state machine at all, | | 3868 | * authentication, we are peer) don't employ a state machine at all, |
3869 | * they are simply answered. Some peers [Ascend P50 firmware rev | | 3869 | * they are simply answered. Some peers [Ascend P50 firmware rev |
3870 | * 4.50] react allergically when sending IPCP/IPv6CP requests while they are | | 3870 | * 4.50] react allergically when sending IPCP/IPv6CP requests while they are |
3871 | * still in authentication phase (thereby violating the standard that | | 3871 | * still in authentication phase (thereby violating the standard that |
3872 | * demands that these NCP packets are to be discarded), so we keep | | 3872 | * demands that these NCP packets are to be discarded), so we keep |
3873 | * track of the peer demanding us to authenticate, and only proceed to | | 3873 | * track of the peer demanding us to authenticate, and only proceed to |
3874 | * phase network once we've seen a positive acknowledge for the | | 3874 | * phase network once we've seen a positive acknowledge for the |
3875 | * authentication. | | 3875 | * authentication. |
3876 | */ | | 3876 | */ |
3877 | | | 3877 | |
3878 | /* | | 3878 | /* |
3879 | * Handle incoming CHAP packets. | | 3879 | * Handle incoming CHAP packets. |
3880 | */ | | 3880 | */ |
3881 | void | | 3881 | void |
3882 | sppp_chap_input(struct sppp *sp, struct mbuf *m) | | 3882 | sppp_chap_input(struct sppp *sp, struct mbuf *m) |
3883 | { | | 3883 | { |
3884 | STDDCL; | | 3884 | STDDCL; |
3885 | struct lcp_header *h; | | 3885 | struct lcp_header *h; |
3886 | int len, x; | | 3886 | int len, x; |
3887 | u_char *value, *name, digest[sizeof(sp->myauth.challenge)], dsize; | | 3887 | u_char *value, *name, digest[sizeof(sp->myauth.challenge)], dsize; |
3888 | int value_len, name_len; | | 3888 | int value_len, name_len; |
3889 | MD5_CTX ctx; | | 3889 | MD5_CTX ctx; |
3890 | | | 3890 | |
3891 | len = m->m_pkthdr.len; | | 3891 | len = m->m_pkthdr.len; |
3892 | if (len < 4) { | | 3892 | if (len < 4) { |
3893 | if (debug) | | 3893 | if (debug) |
3894 | log(LOG_DEBUG, | | 3894 | log(LOG_DEBUG, |
3895 | "%s: chap invalid packet length: %d bytes\n", | | 3895 | "%s: chap invalid packet length: %d bytes\n", |
3896 | ifp->if_xname, len); | | 3896 | ifp->if_xname, len); |
3897 | return; | | 3897 | return; |
3898 | } | | 3898 | } |
3899 | h = mtod(m, struct lcp_header *); | | 3899 | h = mtod(m, struct lcp_header *); |
3900 | if (len > ntohs(h->len)) | | 3900 | if (len > ntohs(h->len)) |
3901 | len = ntohs(h->len); | | 3901 | len = ntohs(h->len); |
3902 | | | 3902 | |
3903 | switch (h->type) { | | 3903 | switch (h->type) { |
3904 | /* challenge, failure and success are his authproto */ | | 3904 | /* challenge, failure and success are his authproto */ |
3905 | case CHAP_CHALLENGE: | | 3905 | case CHAP_CHALLENGE: |
3906 | if (sp->myauth.secret == NULL || sp->myauth.name == NULL) { | | 3906 | if (sp->myauth.secret == NULL || sp->myauth.name == NULL) { |
3907 | /* can't do anything usefull */ | | 3907 | /* can't do anything usefull */ |
3908 | sp->pp_auth_failures++; | | 3908 | sp->pp_auth_failures++; |
3909 | printf("%s: chap input without my name and my secret being set\n", | | 3909 | printf("%s: chap input without my name and my secret being set\n", |
3910 | ifp->if_xname); | | 3910 | ifp->if_xname); |
3911 | break; | | 3911 | break; |
3912 | } | | 3912 | } |
3913 | value = 1 + (u_char *)(h + 1); | | 3913 | value = 1 + (u_char *)(h + 1); |
3914 | value_len = value[-1]; | | 3914 | value_len = value[-1]; |
3915 | name = value + value_len; | | 3915 | name = value + value_len; |
3916 | name_len = len - value_len - 5; | | 3916 | name_len = len - value_len - 5; |
3917 | if (name_len < 0) { | | 3917 | if (name_len < 0) { |
3918 | if (debug) { | | 3918 | if (debug) { |
3919 | log(LOG_DEBUG, | | 3919 | log(LOG_DEBUG, |
3920 | "%s: chap corrupted challenge " | | 3920 | "%s: chap corrupted challenge " |
3921 | "<%s id=0x%x len=%d", | | 3921 | "<%s id=0x%x len=%d", |
3922 | ifp->if_xname, | | 3922 | ifp->if_xname, |
3923 | sppp_auth_type_name(PPP_CHAP, h->type), | | 3923 | sppp_auth_type_name(PPP_CHAP, h->type), |
3924 | h->ident, ntohs(h->len)); | | 3924 | h->ident, ntohs(h->len)); |
3925 | if (len > 4) | | 3925 | if (len > 4) |
3926 | sppp_print_bytes((u_char *)(h + 1), | | 3926 | sppp_print_bytes((u_char *)(h + 1), |
3927 | len - 4); | | 3927 | len - 4); |
3928 | addlog(">\n"); | | 3928 | addlog(">\n"); |
3929 | } | | 3929 | } |
3930 | break; | | 3930 | break; |
3931 | } | | 3931 | } |
3932 | | | 3932 | |
3933 | if (debug) { | | 3933 | if (debug) { |
3934 | log(LOG_DEBUG, | | 3934 | log(LOG_DEBUG, |
3935 | "%s: chap input <%s id=0x%x len=%d name=", | | 3935 | "%s: chap input <%s id=0x%x len=%d name=", |
3936 | ifp->if_xname, | | 3936 | ifp->if_xname, |
3937 | sppp_auth_type_name(PPP_CHAP, h->type), h->ident, | | 3937 | sppp_auth_type_name(PPP_CHAP, h->type), h->ident, |
3938 | ntohs(h->len)); | | 3938 | ntohs(h->len)); |
3939 | sppp_print_string((char *) name, name_len); | | 3939 | sppp_print_string((char *) name, name_len); |
3940 | addlog(" value-size=%d value=", value_len); | | 3940 | addlog(" value-size=%d value=", value_len); |
3941 | sppp_print_bytes(value, value_len); | | 3941 | sppp_print_bytes(value, value_len); |
3942 | addlog(">\n"); | | 3942 | addlog(">\n"); |
3943 | } | | 3943 | } |
3944 | | | 3944 | |
3945 | /* Compute reply value. */ | | 3945 | /* Compute reply value. */ |
3946 | MD5Init(&ctx); | | 3946 | MD5Init(&ctx); |
3947 | MD5Update(&ctx, &h->ident, 1); | | 3947 | MD5Update(&ctx, &h->ident, 1); |
3948 | MD5Update(&ctx, sp->myauth.secret, sp->myauth.secret_len); | | 3948 | MD5Update(&ctx, sp->myauth.secret, sp->myauth.secret_len); |
3949 | MD5Update(&ctx, value, value_len); | | 3949 | MD5Update(&ctx, value, value_len); |
3950 | MD5Final(digest, &ctx); | | 3950 | MD5Final(digest, &ctx); |
3951 | dsize = sizeof digest; | | 3951 | dsize = sizeof digest; |
3952 | | | 3952 | |
3953 | sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, | | 3953 | sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, |
3954 | sizeof dsize, (const char *)&dsize, | | 3954 | sizeof dsize, (const char *)&dsize, |
3955 | sizeof digest, digest, | | 3955 | sizeof digest, digest, |
3956 | sp->myauth.name_len, | | 3956 | sp->myauth.name_len, |
3957 | sp->myauth.name, | | 3957 | sp->myauth.name, |
3958 | 0); | | 3958 | 0); |
3959 | break; | | 3959 | break; |
3960 | | | 3960 | |
3961 | case CHAP_SUCCESS: | | 3961 | case CHAP_SUCCESS: |
3962 | if (debug) { | | 3962 | if (debug) { |
3963 | log(LOG_DEBUG, "%s: chap success", | | 3963 | log(LOG_DEBUG, "%s: chap success", |
3964 | ifp->if_xname); | | 3964 | ifp->if_xname); |
3965 | if (len > 4) { | | 3965 | if (len > 4) { |
3966 | addlog(": "); | | 3966 | addlog(": "); |
3967 | sppp_print_string((char *)(h + 1), len - 4); | | 3967 | sppp_print_string((char *)(h + 1), len - 4); |
3968 | } | | 3968 | } |
3969 | addlog("\n"); | | 3969 | addlog("\n"); |
3970 | } | | 3970 | } |
3971 | x = splnet(); | | 3971 | x = splnet(); |
3972 | sp->pp_auth_failures = 0; | | 3972 | sp->pp_auth_failures = 0; |
3973 | sp->pp_flags &= ~PP_NEEDAUTH; | | 3973 | sp->pp_flags &= ~PP_NEEDAUTH; |
3974 | if (sp->myauth.proto == PPP_CHAP && | | 3974 | if (sp->myauth.proto == PPP_CHAP && |
3975 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && | | 3975 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && |
3976 | (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { | | 3976 | (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { |
3977 | /* | | 3977 | /* |
3978 | * We are authenticator for CHAP but didn't | | 3978 | * We are authenticator for CHAP but didn't |
3979 | * complete yet. Leave it to tlu to proceed | | 3979 | * complete yet. Leave it to tlu to proceed |
3980 | * to network phase. | | 3980 | * to network phase. |
3981 | */ | | 3981 | */ |
3982 | splx(x); | | 3982 | splx(x); |
3983 | break; | | 3983 | break; |
3984 | } | | 3984 | } |
3985 | splx(x); | | 3985 | splx(x); |
3986 | sppp_phase_network(sp); | | 3986 | sppp_phase_network(sp); |
3987 | break; | | 3987 | break; |
3988 | | | 3988 | |
3989 | case CHAP_FAILURE: | | 3989 | case CHAP_FAILURE: |
3990 | x = splnet(); | | 3990 | x = splnet(); |
3991 | sp->pp_auth_failures++; | | 3991 | sp->pp_auth_failures++; |
3992 | splx(x); | | 3992 | splx(x); |
3993 | if (debug) { | | 3993 | if (debug) { |
3994 | log(LOG_INFO, "%s: chap failure", | | 3994 | log(LOG_INFO, "%s: chap failure", |
3995 | ifp->if_xname); | | 3995 | ifp->if_xname); |
3996 | if (len > 4) { | | 3996 | if (len > 4) { |
3997 | addlog(": "); | | 3997 | addlog(": "); |
3998 | sppp_print_string((char *)(h + 1), len - 4); | | 3998 | sppp_print_string((char *)(h + 1), len - 4); |
3999 | } | | 3999 | } |
4000 | addlog("\n"); | | 4000 | addlog("\n"); |
4001 | } else | | 4001 | } else |
4002 | log(LOG_INFO, "%s: chap failure\n", | | 4002 | log(LOG_INFO, "%s: chap failure\n", |
4003 | ifp->if_xname); | | 4003 | ifp->if_xname); |
4004 | /* await LCP shutdown by authenticator */ | | 4004 | /* await LCP shutdown by authenticator */ |
4005 | break; | | 4005 | break; |
4006 | | | 4006 | |
4007 | /* response is my authproto */ | | 4007 | /* response is my authproto */ |
4008 | case CHAP_RESPONSE: | | 4008 | case CHAP_RESPONSE: |
4009 | if (sp->hisauth.secret == NULL) { | | 4009 | if (sp->hisauth.secret == NULL) { |
4010 | /* can't do anything usefull */ | | 4010 | /* can't do anything usefull */ |
4011 | printf("%s: chap input without his secret being set\n", | | 4011 | printf("%s: chap input without his secret being set\n", |
4012 | ifp->if_xname); | | 4012 | ifp->if_xname); |
4013 | break; | | 4013 | break; |
4014 | } | | 4014 | } |
4015 | value = 1 + (u_char *)(h + 1); | | 4015 | value = 1 + (u_char *)(h + 1); |
4016 | value_len = value[-1]; | | 4016 | value_len = value[-1]; |
4017 | name = value + value_len; | | 4017 | name = value + value_len; |
4018 | name_len = len - value_len - 5; | | 4018 | name_len = len - value_len - 5; |
4019 | if (name_len < 0) { | | 4019 | if (name_len < 0) { |
4020 | if (debug) { | | 4020 | if (debug) { |
4021 | log(LOG_DEBUG, | | 4021 | log(LOG_DEBUG, |
4022 | "%s: chap corrupted response " | | 4022 | "%s: chap corrupted response " |
4023 | "<%s id=0x%x len=%d", | | 4023 | "<%s id=0x%x len=%d", |
4024 | ifp->if_xname, | | 4024 | ifp->if_xname, |
4025 | sppp_auth_type_name(PPP_CHAP, h->type), | | 4025 | sppp_auth_type_name(PPP_CHAP, h->type), |
4026 | h->ident, ntohs(h->len)); | | 4026 | h->ident, ntohs(h->len)); |
4027 | if (len > 4) | | 4027 | if (len > 4) |
4028 | sppp_print_bytes((u_char *)(h + 1), | | 4028 | sppp_print_bytes((u_char *)(h + 1), |
4029 | len - 4); | | 4029 | len - 4); |
4030 | addlog(">\n"); | | 4030 | addlog(">\n"); |
4031 | } | | 4031 | } |
4032 | break; | | 4032 | break; |
4033 | } | | 4033 | } |
4034 | if (h->ident != sp->confid[IDX_CHAP]) { | | 4034 | if (h->ident != sp->confid[IDX_CHAP]) { |
4035 | if (debug) | | 4035 | if (debug) |
4036 | log(LOG_DEBUG, | | 4036 | log(LOG_DEBUG, |
4037 | "%s: chap dropping response for old ID " | | 4037 | "%s: chap dropping response for old ID " |
4038 | "(got %d, expected %d)\n", | | 4038 | "(got %d, expected %d)\n", |
4039 | ifp->if_xname, | | 4039 | ifp->if_xname, |
4040 | h->ident, sp->confid[IDX_CHAP]); | | 4040 | h->ident, sp->confid[IDX_CHAP]); |
4041 | break; | | 4041 | break; |
4042 | } | | 4042 | } |
4043 | if (sp->hisauth.name != NULL && | | 4043 | if (sp->hisauth.name != NULL && |
4044 | (name_len != sp->hisauth.name_len | | 4044 | (name_len != sp->hisauth.name_len |
4045 | || memcmp(name, sp->hisauth.name, name_len) != 0)) { | | 4045 | || memcmp(name, sp->hisauth.name, name_len) != 0)) { |
4046 | log(LOG_INFO, "%s: chap response, his name ", | | 4046 | log(LOG_INFO, "%s: chap response, his name ", |
4047 | ifp->if_xname); | | 4047 | ifp->if_xname); |
4048 | sppp_print_string(name, name_len); | | 4048 | sppp_print_string(name, name_len); |
4049 | addlog(" != expected "); | | 4049 | addlog(" != expected "); |
4050 | sppp_print_string(sp->hisauth.name, | | 4050 | sppp_print_string(sp->hisauth.name, |
4051 | sp->hisauth.name_len); | | 4051 | sp->hisauth.name_len); |
4052 | addlog("\n"); | | 4052 | addlog("\n"); |
4053 | goto chap_failure; | | 4053 | goto chap_failure; |
4054 | } | | 4054 | } |
4055 | if (debug) { | | 4055 | if (debug) { |
4056 | log(LOG_DEBUG, "%s: chap input(%s) " | | 4056 | log(LOG_DEBUG, "%s: chap input(%s) " |
4057 | "<%s id=0x%x len=%d name=", | | 4057 | "<%s id=0x%x len=%d name=", |
4058 | ifp->if_xname, | | 4058 | ifp->if_xname, |
4059 | sppp_state_name(sp->state[IDX_CHAP]), | | 4059 | sppp_state_name(sp->state[IDX_CHAP]), |
4060 | sppp_auth_type_name(PPP_CHAP, h->type), | | 4060 | sppp_auth_type_name(PPP_CHAP, h->type), |
4061 | h->ident, ntohs(h->len)); | | 4061 | h->ident, ntohs(h->len)); |
4062 | sppp_print_string((char *)name, name_len); | | 4062 | sppp_print_string((char *)name, name_len); |
4063 | addlog(" value-size=%d value=", value_len); | | 4063 | addlog(" value-size=%d value=", value_len); |
4064 | sppp_print_bytes(value, value_len); | | 4064 | sppp_print_bytes(value, value_len); |
4065 | addlog(">\n"); | | 4065 | addlog(">\n"); |
4066 | } | | 4066 | } |
4067 | if (value_len != sizeof(sp->myauth.challenge)) { | | 4067 | if (value_len != sizeof(sp->myauth.challenge)) { |
4068 | if (debug) | | 4068 | if (debug) |
4069 | log(LOG_DEBUG, | | 4069 | log(LOG_DEBUG, |
4070 | "%s: chap bad hash value length: " | | 4070 | "%s: chap bad hash value length: " |
4071 | "%d bytes, should be %ld\n", | | 4071 | "%d bytes, should be %ld\n", |
4072 | ifp->if_xname, value_len, | | 4072 | ifp->if_xname, value_len, |
4073 | (long) sizeof(sp->myauth.challenge)); | | 4073 | (long) sizeof(sp->myauth.challenge)); |
4074 | goto chap_failure; | | 4074 | goto chap_failure; |
4075 | } | | 4075 | } |
4076 | | | 4076 | |
4077 | MD5Init(&ctx); | | 4077 | MD5Init(&ctx); |
4078 | MD5Update(&ctx, &h->ident, 1); | | 4078 | MD5Update(&ctx, &h->ident, 1); |
4079 | MD5Update(&ctx, sp->hisauth.secret, sp->hisauth.secret_len); | | 4079 | MD5Update(&ctx, sp->hisauth.secret, sp->hisauth.secret_len); |
4080 | MD5Update(&ctx, sp->myauth.challenge, sizeof(sp->myauth.challenge)); | | 4080 | MD5Update(&ctx, sp->myauth.challenge, sizeof(sp->myauth.challenge)); |
4081 | MD5Final(digest, &ctx); | | 4081 | MD5Final(digest, &ctx); |
4082 | | | 4082 | |
4083 | #define FAILMSG "Failed..." | | 4083 | #define FAILMSG "Failed..." |
4084 | #define SUCCMSG "Welcome!" | | 4084 | #define SUCCMSG "Welcome!" |
4085 | | | 4085 | |
4086 | if (value_len != sizeof digest || | | 4086 | if (value_len != sizeof digest || |
4087 | memcmp(digest, value, value_len) != 0) { | | 4087 | memcmp(digest, value, value_len) != 0) { |
4088 | chap_failure: | | 4088 | chap_failure: |
4089 | /* action scn, tld */ | | 4089 | /* action scn, tld */ |
4090 | x = splnet(); | | 4090 | x = splnet(); |
4091 | sp->pp_auth_failures++; | | 4091 | sp->pp_auth_failures++; |
4092 | splx(x); | | 4092 | splx(x); |
4093 | sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, | | 4093 | sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, |
4094 | sizeof(FAILMSG) - 1, (const u_char *)FAILMSG, | | 4094 | sizeof(FAILMSG) - 1, (const u_char *)FAILMSG, |
4095 | 0); | | 4095 | 0); |
4096 | chap.tld(sp); | | 4096 | chap.tld(sp); |
4097 | break; | | 4097 | break; |
4098 | } | | 4098 | } |
4099 | sp->pp_auth_failures = 0; | | 4099 | sp->pp_auth_failures = 0; |
4100 | /* action sca, perhaps tlu */ | | 4100 | /* action sca, perhaps tlu */ |
4101 | if (sp->state[IDX_CHAP] == STATE_REQ_SENT || | | 4101 | if (sp->state[IDX_CHAP] == STATE_REQ_SENT || |
4102 | sp->state[IDX_CHAP] == STATE_OPENED) | | 4102 | sp->state[IDX_CHAP] == STATE_OPENED) |
4103 | sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, | | 4103 | sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, |
4104 | sizeof(SUCCMSG) - 1, (const u_char *)SUCCMSG, | | 4104 | sizeof(SUCCMSG) - 1, (const u_char *)SUCCMSG, |
4105 | 0); | | 4105 | 0); |
4106 | if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { | | 4106 | if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { |
4107 | sppp_cp_change_state(&chap, sp, STATE_OPENED); | | 4107 | sppp_cp_change_state(&chap, sp, STATE_OPENED); |
4108 | chap.tlu(sp); | | 4108 | chap.tlu(sp); |
4109 | } | | 4109 | } |
4110 | break; | | 4110 | break; |
4111 | | | 4111 | |
4112 | default: | | 4112 | default: |
4113 | /* Unknown CHAP packet type -- ignore. */ | | 4113 | /* Unknown CHAP packet type -- ignore. */ |
4114 | if (debug) { | | 4114 | if (debug) { |
4115 | log(LOG_DEBUG, "%s: chap unknown input(%s) " | | 4115 | log(LOG_DEBUG, "%s: chap unknown input(%s) " |
4116 | "<0x%x id=0x%xh len=%d", | | 4116 | "<0x%x id=0x%xh len=%d", |
4117 | ifp->if_xname, | | 4117 | ifp->if_xname, |
4118 | sppp_state_name(sp->state[IDX_CHAP]), | | 4118 | sppp_state_name(sp->state[IDX_CHAP]), |
4119 | h->type, h->ident, ntohs(h->len)); | | 4119 | h->type, h->ident, ntohs(h->len)); |
4120 | if (len > 4) | | 4120 | if (len > 4) |
4121 | sppp_print_bytes((u_char *)(h + 1), len - 4); | | 4121 | sppp_print_bytes((u_char *)(h + 1), len - 4); |
4122 | addlog(">\n"); | | 4122 | addlog(">\n"); |
4123 | } | | 4123 | } |
4124 | break; | | 4124 | break; |
4125 | | | 4125 | |
4126 | } | | 4126 | } |
4127 | } | | 4127 | } |
4128 | | | 4128 | |
4129 | static void | | 4129 | static void |
4130 | sppp_chap_init(struct sppp *sp) | | 4130 | sppp_chap_init(struct sppp *sp) |
4131 | { | | 4131 | { |
4132 | /* Chap doesn't have STATE_INITIAL at all. */ | | 4132 | /* Chap doesn't have STATE_INITIAL at all. */ |
4133 | sp->state[IDX_CHAP] = STATE_CLOSED; | | 4133 | sp->state[IDX_CHAP] = STATE_CLOSED; |
4134 | sp->fail_counter[IDX_CHAP] = 0; | | 4134 | sp->fail_counter[IDX_CHAP] = 0; |
4135 | sp->pp_seq[IDX_CHAP] = 0; | | 4135 | sp->pp_seq[IDX_CHAP] = 0; |
4136 | sp->pp_rseq[IDX_CHAP] = 0; | | 4136 | sp->pp_rseq[IDX_CHAP] = 0; |
4137 | callout_init(&sp->ch[IDX_CHAP], 0); | | 4137 | callout_init(&sp->ch[IDX_CHAP], 0); |
4138 | } | | 4138 | } |
4139 | | | 4139 | |
4140 | static void | | 4140 | static void |
4141 | sppp_chap_open(struct sppp *sp) | | 4141 | sppp_chap_open(struct sppp *sp) |
4142 | { | | 4142 | { |
4143 | if (sp->myauth.proto == PPP_CHAP && | | 4143 | if (sp->myauth.proto == PPP_CHAP && |
4144 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { | | 4144 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { |
4145 | /* we are authenticator for CHAP, start it */ | | 4145 | /* we are authenticator for CHAP, start it */ |
4146 | chap.scr(sp); | | 4146 | chap.scr(sp); |
4147 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; | | 4147 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; |
4148 | sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); | | 4148 | sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); |
4149 | } | | 4149 | } |
4150 | /* nothing to be done if we are peer, await a challenge */ | | 4150 | /* nothing to be done if we are peer, await a challenge */ |
4151 | } | | 4151 | } |
4152 | | | 4152 | |
4153 | static void | | 4153 | static void |
4154 | sppp_chap_close(struct sppp *sp) | | 4154 | sppp_chap_close(struct sppp *sp) |
4155 | { | | 4155 | { |
4156 | if (sp->state[IDX_CHAP] != STATE_CLOSED) | | 4156 | if (sp->state[IDX_CHAP] != STATE_CLOSED) |
4157 | sppp_cp_change_state(&chap, sp, STATE_CLOSED); | | 4157 | sppp_cp_change_state(&chap, sp, STATE_CLOSED); |
4158 | } | | 4158 | } |
4159 | | | 4159 | |
4160 | static void | | 4160 | static void |
4161 | sppp_chap_TO(void *cookie) | | 4161 | sppp_chap_TO(void *cookie) |
4162 | { | | 4162 | { |
4163 | struct sppp *sp = (struct sppp *)cookie; | | 4163 | struct sppp *sp = (struct sppp *)cookie; |
4164 | STDDCL; | | 4164 | STDDCL; |
4165 | int s; | | 4165 | int s; |
4166 | | | 4166 | |
4167 | s = splnet(); | | 4167 | s = splnet(); |
4168 | if (debug) | | 4168 | if (debug) |
4169 | log(LOG_DEBUG, "%s: chap TO(%s) rst_counter = %d\n", | | 4169 | log(LOG_DEBUG, "%s: chap TO(%s) rst_counter = %d\n", |
4170 | ifp->if_xname, | | 4170 | ifp->if_xname, |
4171 | sppp_state_name(sp->state[IDX_CHAP]), | | 4171 | sppp_state_name(sp->state[IDX_CHAP]), |
4172 | sp->rst_counter[IDX_CHAP]); | | 4172 | sp->rst_counter[IDX_CHAP]); |
4173 | | | 4173 | |
4174 | if (--sp->rst_counter[IDX_CHAP] < 0) | | 4174 | if (--sp->rst_counter[IDX_CHAP] < 0) |
4175 | /* TO- event */ | | 4175 | /* TO- event */ |
4176 | switch (sp->state[IDX_CHAP]) { | | 4176 | switch (sp->state[IDX_CHAP]) { |
4177 | case STATE_REQ_SENT: | | 4177 | case STATE_REQ_SENT: |
4178 | chap.tld(sp); | | 4178 | chap.tld(sp); |
4179 | sppp_cp_change_state(&chap, sp, STATE_CLOSED); | | 4179 | sppp_cp_change_state(&chap, sp, STATE_CLOSED); |
4180 | break; | | 4180 | break; |
4181 | } | | 4181 | } |
4182 | else | | 4182 | else |
4183 | /* TO+ (or TO*) event */ | | 4183 | /* TO+ (or TO*) event */ |
4184 | switch (sp->state[IDX_CHAP]) { | | 4184 | switch (sp->state[IDX_CHAP]) { |
4185 | case STATE_OPENED: | | 4185 | case STATE_OPENED: |
4186 | /* TO* event */ | | 4186 | /* TO* event */ |
4187 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; | | 4187 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; |
4188 | /* fall through */ | | 4188 | /* fall through */ |
4189 | case STATE_REQ_SENT: | | 4189 | case STATE_REQ_SENT: |
4190 | chap.scr(sp); | | 4190 | chap.scr(sp); |
4191 | /* sppp_cp_change_state() will restart the timer */ | | 4191 | /* sppp_cp_change_state() will restart the timer */ |
4192 | sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); | | 4192 | sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); |
4193 | break; | | 4193 | break; |
4194 | } | | 4194 | } |
4195 | | | 4195 | |
4196 | splx(s); | | 4196 | splx(s); |
4197 | } | | 4197 | } |
4198 | | | 4198 | |
4199 | static void | | 4199 | static void |
4200 | sppp_chap_tlu(struct sppp *sp) | | 4200 | sppp_chap_tlu(struct sppp *sp) |
4201 | { | | 4201 | { |
4202 | STDDCL; | | 4202 | STDDCL; |
4203 | int i, x; | | 4203 | int i, x; |
4204 | | | 4204 | |
4205 | i = 0; | | 4205 | i = 0; |
4206 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; | | 4206 | sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; |
4207 | | | 4207 | |
4208 | /* | | 4208 | /* |
4209 | * Some broken CHAP implementations (Conware CoNet, firmware | | 4209 | * Some broken CHAP implementations (Conware CoNet, firmware |
4210 | * 4.0.?) don't want to re-authenticate their CHAP once the | | 4210 | * 4.0.?) don't want to re-authenticate their CHAP once the |
4211 | * initial challenge-response exchange has taken place. | | 4211 | * initial challenge-response exchange has taken place. |
4212 | * Provide for an option to avoid rechallenges. | | 4212 | * Provide for an option to avoid rechallenges. |
4213 | */ | | 4213 | */ |
4214 | if ((sp->hisauth.flags & SPPP_AUTHFLAG_NORECHALLENGE) == 0) { | | 4214 | if ((sp->hisauth.flags & SPPP_AUTHFLAG_NORECHALLENGE) == 0) { |
4215 | /* | | 4215 | /* |
4216 | * Compute the re-challenge timeout. This will yield | | 4216 | * Compute the re-challenge timeout. This will yield |
4217 | * a number between 300 and 810 seconds. | | 4217 | * a number between 300 and 810 seconds. |
4218 | */ | | 4218 | */ |
4219 | i = 300 + ((unsigned)(arc4random() & 0xff00) >> 7); | | 4219 | i = 300 + ((unsigned)(arc4random() & 0xff00) >> 7); |
4220 | | | 4220 | |
4221 | callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, sp); | | 4221 | callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, sp); |
4222 | } | | 4222 | } |
4223 | | | 4223 | |
4224 | if (debug) { | | 4224 | if (debug) { |
4225 | log(LOG_DEBUG, | | 4225 | log(LOG_DEBUG, |
4226 | "%s: chap %s, ", | | 4226 | "%s: chap %s, ", |
4227 | ifp->if_xname, | | 4227 | ifp->if_xname, |
4228 | sp->pp_phase == SPPP_PHASE_NETWORK? "reconfirmed": "tlu"); | | 4228 | sp->pp_phase == SPPP_PHASE_NETWORK? "reconfirmed": "tlu"); |
4229 | if ((sp->hisauth.flags & SPPP_AUTHFLAG_NORECHALLENGE) == 0) | | 4229 | if ((sp->hisauth.flags & SPPP_AUTHFLAG_NORECHALLENGE) == 0) |
4230 | addlog("next re-challenge in %d seconds\n", i); | | 4230 | addlog("next re-challenge in %d seconds\n", i); |
4231 | else | | 4231 | else |
4232 | addlog("re-challenging supressed\n"); | | 4232 | addlog("re-challenging supressed\n"); |
4233 | } | | 4233 | } |
4234 | | | 4234 | |
4235 | x = splnet(); | | 4235 | x = splnet(); |
4236 | sp->pp_auth_failures = 0; | | 4236 | sp->pp_auth_failures = 0; |
4237 | /* indicate to LCP that we need to be closed down */ | | 4237 | /* indicate to LCP that we need to be closed down */ |
4238 | sp->lcp.protos |= (1 << IDX_CHAP); | | 4238 | sp->lcp.protos |= (1 << IDX_CHAP); |
4239 | | | 4239 | |
4240 | if (sp->pp_flags & PP_NEEDAUTH) { | | 4240 | if (sp->pp_flags & PP_NEEDAUTH) { |
4241 | /* | | 4241 | /* |
4242 | * Remote is authenticator, but his auth proto didn't | | 4242 | * Remote is authenticator, but his auth proto didn't |
4243 | * complete yet. Defer the transition to network | | 4243 | * complete yet. Defer the transition to network |
4244 | * phase. | | 4244 | * phase. |
4245 | */ | | 4245 | */ |
4246 | splx(x); | | 4246 | splx(x); |
4247 | return; | | 4247 | return; |
4248 | } | | 4248 | } |
4249 | splx(x); | | 4249 | splx(x); |
4250 | | | 4250 | |
4251 | /* | | 4251 | /* |
4252 | * If we are already in phase network, we are done here. This | | 4252 | * If we are already in phase network, we are done here. This |
4253 | * is the case if this is a dummy tlu event after a re-challenge. | | 4253 | * is the case if this is a dummy tlu event after a re-challenge. |
4254 | */ | | 4254 | */ |
4255 | if (sp->pp_phase != SPPP_PHASE_NETWORK) | | 4255 | if (sp->pp_phase != SPPP_PHASE_NETWORK) |
4256 | sppp_phase_network(sp); | | 4256 | sppp_phase_network(sp); |
4257 | } | | 4257 | } |
4258 | | | 4258 | |
4259 | static void | | 4259 | static void |
4260 | sppp_chap_tld(struct sppp *sp) | | 4260 | sppp_chap_tld(struct sppp *sp) |
4261 | { | | 4261 | { |
4262 | STDDCL; | | 4262 | STDDCL; |
4263 | | | 4263 | |
4264 | if (debug) | | 4264 | if (debug) |
4265 | log(LOG_DEBUG, "%s: chap tld\n", ifp->if_xname); | | 4265 | log(LOG_DEBUG, "%s: chap tld\n", ifp->if_xname); |
4266 | callout_stop(&sp->ch[IDX_CHAP]); | | 4266 | callout_stop(&sp->ch[IDX_CHAP]); |
4267 | sp->lcp.protos &= ~(1 << IDX_CHAP); | | 4267 | sp->lcp.protos &= ~(1 << IDX_CHAP); |
4268 | | | 4268 | |
4269 | lcp.Close(sp); | | 4269 | lcp.Close(sp); |
4270 | } | | 4270 | } |
4271 | | | 4271 | |
4272 | static void | | 4272 | static void |
4273 | sppp_chap_scr(struct sppp *sp) | | 4273 | sppp_chap_scr(struct sppp *sp) |
4274 | { | | 4274 | { |
4275 | uint32_t *ch; | | 4275 | uint32_t *ch; |
4276 | u_char clen; | | 4276 | u_char clen; |
4277 | | | 4277 | |
4278 | if (sp->myauth.name == NULL) { | | 4278 | if (sp->myauth.name == NULL) { |
4279 | /* can't do anything usefull */ | | 4279 | /* can't do anything usefull */ |
4280 | printf("%s: chap starting without my name being set\n", | | 4280 | printf("%s: chap starting without my name being set\n", |
4281 | sp->pp_if.if_xname); | | 4281 | sp->pp_if.if_xname); |
4282 | return; | | 4282 | return; |
4283 | } | | 4283 | } |
4284 | | | 4284 | |
4285 | /* Compute random challenge. */ | | 4285 | /* Compute random challenge. */ |
4286 | ch = (uint32_t *)sp->myauth.challenge; | | 4286 | ch = (uint32_t *)sp->myauth.challenge; |
4287 | ch[0] = arc4random(); | | 4287 | ch[0] = arc4random(); |
4288 | ch[1] = arc4random(); | | 4288 | ch[1] = arc4random(); |
4289 | ch[2] = arc4random(); | | 4289 | ch[2] = arc4random(); |
4290 | ch[3] = arc4random(); | | 4290 | ch[3] = arc4random(); |
4291 | clen = 16; /* 4 * sizeof(uint32_t) */ | | 4291 | clen = 16; /* 4 * sizeof(uint32_t) */ |
4292 | | | 4292 | |
4293 | sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; | | 4293 | sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; |
4294 | | | 4294 | |
4295 | sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], | | 4295 | sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], |
4296 | sizeof clen, (const char *)&clen, | | 4296 | sizeof clen, (const char *)&clen, |
4297 | sizeof(sp->myauth.challenge), sp->myauth.challenge, | | 4297 | sizeof(sp->myauth.challenge), sp->myauth.challenge, |
4298 | sp->myauth.name_len, | | 4298 | sp->myauth.name_len, |
4299 | sp->myauth.name, | | 4299 | sp->myauth.name, |
4300 | 0); | | 4300 | 0); |
4301 | } | | 4301 | } |
4302 | | | 4302 | |
4303 | /* | | 4303 | /* |
4304 | *--------------------------------------------------------------------------* | | 4304 | *--------------------------------------------------------------------------* |
4305 | * * | | 4305 | * * |
4306 | * The PAP implementation. * | | 4306 | * The PAP implementation. * |
4307 | * * | | 4307 | * * |
4308 | *--------------------------------------------------------------------------* | | 4308 | *--------------------------------------------------------------------------* |
4309 | */ | | 4309 | */ |
4310 | /* | | 4310 | /* |
4311 | * For PAP, we need to keep a little state also if we are the peer, not the | | 4311 | * For PAP, we need to keep a little state also if we are the peer, not the |
4312 | * authenticator. This is since we don't get a request to authenticate, but | | 4312 | * authenticator. This is since we don't get a request to authenticate, but |
4313 | * have to repeatedly authenticate ourself until we got a response (or the | | 4313 | * have to repeatedly authenticate ourself until we got a response (or the |
4314 | * retry counter is expired). | | 4314 | * retry counter is expired). |
4315 | */ | | 4315 | */ |
4316 | | | 4316 | |
4317 | /* | | 4317 | /* |
4318 | * Handle incoming PAP packets. */ | | 4318 | * Handle incoming PAP packets. */ |
4319 | static void | | 4319 | static void |
4320 | sppp_pap_input(struct sppp *sp, struct mbuf *m) | | 4320 | sppp_pap_input(struct sppp *sp, struct mbuf *m) |
4321 | { | | 4321 | { |
4322 | STDDCL; | | 4322 | STDDCL; |
4323 | struct lcp_header *h; | | 4323 | struct lcp_header *h; |
4324 | int len, x; | | 4324 | int len, x; |
4325 | u_char mlen; | | 4325 | u_char mlen; |
4326 | char *name, *secret; | | 4326 | char *name, *secret; |
4327 | int name_len, secret_len; | | 4327 | int name_len, secret_len; |
4328 | | | 4328 | |
4329 | /* | | 4329 | /* |
4330 | * Malicious input might leave this uninitialized, so | | 4330 | * Malicious input might leave this uninitialized, so |
4331 | * init to an impossible value. | | 4331 | * init to an impossible value. |
4332 | */ | | 4332 | */ |
4333 | secret_len = -1; | | 4333 | secret_len = -1; |
4334 | | | 4334 | |
4335 | len = m->m_pkthdr.len; | | 4335 | len = m->m_pkthdr.len; |
4336 | if (len < 5) { | | 4336 | if (len < 5) { |
4337 | if (debug) | | 4337 | if (debug) |
4338 | log(LOG_DEBUG, | | 4338 | log(LOG_DEBUG, |
4339 | "%s: pap invalid packet length: %d bytes\n", | | 4339 | "%s: pap invalid packet length: %d bytes\n", |
4340 | ifp->if_xname, len); | | 4340 | ifp->if_xname, len); |
4341 | return; | | 4341 | return; |
4342 | } | | 4342 | } |
4343 | h = mtod(m, struct lcp_header *); | | 4343 | h = mtod(m, struct lcp_header *); |
4344 | if (len > ntohs(h->len)) | | 4344 | if (len > ntohs(h->len)) |
4345 | len = ntohs(h->len); | | 4345 | len = ntohs(h->len); |
4346 | switch (h->type) { | | 4346 | switch (h->type) { |
4347 | /* PAP request is my authproto */ | | 4347 | /* PAP request is my authproto */ |
4348 | case PAP_REQ: | | 4348 | case PAP_REQ: |
4349 | if (sp->hisauth.name == NULL || sp->hisauth.secret == NULL) { | | 4349 | if (sp->hisauth.name == NULL || sp->hisauth.secret == NULL) { |
4350 | /* can't do anything usefull */ | | 4350 | /* can't do anything usefull */ |
4351 | printf("%s: pap request without his name and his secret being set\n", | | 4351 | printf("%s: pap request without his name and his secret being set\n", |
4352 | ifp->if_xname); | | 4352 | ifp->if_xname); |
4353 | break; | | 4353 | break; |
4354 | } | | 4354 | } |
4355 | name = 1 + (u_char *)(h + 1); | | 4355 | name = 1 + (u_char *)(h + 1); |
4356 | name_len = name[-1]; | | 4356 | name_len = name[-1]; |
4357 | secret = name + name_len + 1; | | 4357 | secret = name + name_len + 1; |
4358 | if (name_len > len - 6 || | | 4358 | if (name_len > len - 6 || |
4359 | (secret_len = secret[-1]) > len - 6 - name_len) { | | 4359 | (secret_len = secret[-1]) > len - 6 - name_len) { |
4360 | if (debug) { | | 4360 | if (debug) { |
4361 | log(LOG_DEBUG, "%s: pap corrupted input " | | 4361 | log(LOG_DEBUG, "%s: pap corrupted input " |
4362 | "<%s id=0x%x len=%d", | | 4362 | "<%s id=0x%x len=%d", |
4363 | ifp->if_xname, | | 4363 | ifp->if_xname, |
4364 | sppp_auth_type_name(PPP_PAP, h->type), | | 4364 | sppp_auth_type_name(PPP_PAP, h->type), |
4365 | h->ident, ntohs(h->len)); | | 4365 | h->ident, ntohs(h->len)); |
4366 | if (len > 4) | | 4366 | if (len > 4) |
4367 | sppp_print_bytes((u_char *)(h + 1), | | 4367 | sppp_print_bytes((u_char *)(h + 1), |
4368 | len - 4); | | 4368 | len - 4); |
4369 | addlog(">\n"); | | 4369 | addlog(">\n"); |
4370 | } | | 4370 | } |
4371 | break; | | 4371 | break; |
4372 | } | | 4372 | } |
4373 | if (debug) { | | 4373 | if (debug) { |
4374 | log(LOG_DEBUG, "%s: pap input(%s) " | | 4374 | log(LOG_DEBUG, "%s: pap input(%s) " |
4375 | "<%s id=0x%x len=%d name=", | | 4375 | "<%s id=0x%x len=%d name=", |
4376 | ifp->if_xname, | | 4376 | ifp->if_xname, |
4377 | sppp_state_name(sp->state[IDX_PAP]), | | 4377 | sppp_state_name(sp->state[IDX_PAP]), |
4378 | sppp_auth_type_name(PPP_PAP, h->type), | | 4378 | sppp_auth_type_name(PPP_PAP, h->type), |
4379 | h->ident, ntohs(h->len)); | | 4379 | h->ident, ntohs(h->len)); |
4380 | sppp_print_string((char *)name, name_len); | | 4380 | sppp_print_string((char *)name, name_len); |
4381 | addlog(" secret="); | | 4381 | addlog(" secret="); |
4382 | sppp_print_string((char *)secret, secret_len); | | 4382 | sppp_print_string((char *)secret, secret_len); |
4383 | addlog(">\n"); | | 4383 | addlog(">\n"); |
4384 | } | | 4384 | } |
4385 | if (name_len != sp->hisauth.name_len || | | 4385 | if (name_len != sp->hisauth.name_len || |
4386 | secret_len != sp->hisauth.secret_len || | | 4386 | secret_len != sp->hisauth.secret_len || |
4387 | memcmp(name, sp->hisauth.name, name_len) != 0 || | | 4387 | memcmp(name, sp->hisauth.name, name_len) != 0 || |
4388 | memcmp(secret, sp->hisauth.secret, secret_len) != 0) { | | 4388 | memcmp(secret, sp->hisauth.secret, secret_len) != 0) { |
4389 | /* action scn, tld */ | | 4389 | /* action scn, tld */ |
4390 | sp->pp_auth_failures++; | | 4390 | sp->pp_auth_failures++; |
4391 | mlen = sizeof(FAILMSG) - 1; | | 4391 | mlen = sizeof(FAILMSG) - 1; |
4392 | sppp_auth_send(&pap, sp, PAP_NAK, h->ident, | | 4392 | sppp_auth_send(&pap, sp, PAP_NAK, h->ident, |
4393 | sizeof mlen, (const char *)&mlen, | | 4393 | sizeof mlen, (const char *)&mlen, |
4394 | sizeof(FAILMSG) - 1, (const u_char *)FAILMSG, | | 4394 | sizeof(FAILMSG) - 1, (const u_char *)FAILMSG, |
4395 | 0); | | 4395 | 0); |
4396 | pap.tld(sp); | | 4396 | pap.tld(sp); |
4397 | break; | | 4397 | break; |
4398 | } | | 4398 | } |
4399 | /* action sca, perhaps tlu */ | | 4399 | /* action sca, perhaps tlu */ |
4400 | if (sp->state[IDX_PAP] == STATE_REQ_SENT || | | 4400 | if (sp->state[IDX_PAP] == STATE_REQ_SENT || |
4401 | sp->state[IDX_PAP] == STATE_OPENED) { | | 4401 | sp->state[IDX_PAP] == STATE_OPENED) { |
4402 | mlen = sizeof(SUCCMSG) - 1; | | 4402 | mlen = sizeof(SUCCMSG) - 1; |
4403 | sppp_auth_send(&pap, sp, PAP_ACK, h->ident, | | 4403 | sppp_auth_send(&pap, sp, PAP_ACK, h->ident, |
4404 | sizeof mlen, (const char *)&mlen, | | 4404 | sizeof mlen, (const char *)&mlen, |
4405 | sizeof(SUCCMSG) - 1, (const u_char *)SUCCMSG, | | 4405 | sizeof(SUCCMSG) - 1, (const u_char *)SUCCMSG, |
4406 | 0); | | 4406 | 0); |
4407 | } | | 4407 | } |
4408 | if (sp->state[IDX_PAP] == STATE_REQ_SENT) { | | 4408 | if (sp->state[IDX_PAP] == STATE_REQ_SENT) { |
4409 | sppp_cp_change_state(&pap, sp, STATE_OPENED); | | 4409 | sppp_cp_change_state(&pap, sp, STATE_OPENED); |
4410 | pap.tlu(sp); | | 4410 | pap.tlu(sp); |
4411 | } | | 4411 | } |
4412 | break; | | 4412 | break; |
4413 | | | 4413 | |
4414 | /* ack and nak are his authproto */ | | 4414 | /* ack and nak are his authproto */ |
4415 | case PAP_ACK: | | 4415 | case PAP_ACK: |
4416 | callout_stop(&sp->pap_my_to_ch); | | 4416 | callout_stop(&sp->pap_my_to_ch); |
4417 | if (debug) { | | 4417 | if (debug) { |
4418 | log(LOG_DEBUG, "%s: pap success", | | 4418 | log(LOG_DEBUG, "%s: pap success", |
4419 | ifp->if_xname); | | 4419 | ifp->if_xname); |
4420 | name = 1 + (u_char *)(h + 1); | | 4420 | name = 1 + (u_char *)(h + 1); |
4421 | name_len = name[-1]; | | 4421 | name_len = name[-1]; |
4422 | if (len > 5 && name_len < len+4) { | | 4422 | if (len > 5 && name_len < len+4) { |
4423 | addlog(": "); | | 4423 | addlog(": "); |
4424 | sppp_print_string(name, name_len); | | 4424 | sppp_print_string(name, name_len); |
4425 | } | | 4425 | } |
4426 | addlog("\n"); | | 4426 | addlog("\n"); |
4427 | } | | 4427 | } |
4428 | x = splnet(); | | 4428 | x = splnet(); |
4429 | sp->pp_auth_failures = 0; | | 4429 | sp->pp_auth_failures = 0; |
4430 | sp->pp_flags &= ~PP_NEEDAUTH; | | 4430 | sp->pp_flags &= ~PP_NEEDAUTH; |
4431 | if (sp->myauth.proto == PPP_PAP && | | 4431 | if (sp->myauth.proto == PPP_PAP && |
4432 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && | | 4432 | (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && |
4433 | (sp->lcp.protos & (1 << IDX_PAP)) == 0) { | | 4433 | (sp->lcp.protos & (1 << IDX_PAP)) == 0) { |
4434 | /* | | 4434 | /* |
4435 | * We are authenticator for PAP but didn't | | 4435 | * We are authenticator for PAP but didn't |
4436 | * complete yet. Leave it to tlu to proceed | | 4436 | * complete yet. Leave it to tlu to proceed |
4437 | * to network phase. | | 4437 | * to network phase. |
4438 | */ | | 4438 | */ |
4439 | splx(x); | | 4439 | splx(x); |
4440 | break; | | 4440 | break; |
4441 | } | | 4441 | } |
4442 | splx(x); | | 4442 | splx(x); |
4443 | sppp_phase_network(sp); | | 4443 | sppp_phase_network(sp); |
4444 | break; | | 4444 | break; |
4445 | | | 4445 | |
4446 | case PAP_NAK: | | 4446 | case PAP_NAK: |
4447 | callout_stop(&sp->pap_my_to_ch); | | 4447 | callout_stop(&sp->pap_my_to_ch); |
4448 | sp->pp_auth_failures++; | | 4448 | sp->pp_auth_failures++; |
4449 | if (debug) { | | 4449 | if (debug) { |
4450 | log(LOG_INFO, "%s: pap failure", | | 4450 | log(LOG_INFO, "%s: pap failure", |
4451 | ifp->if_xname); | | 4451 | ifp->if_xname); |
4452 | name = 1 + (u_char *)(h + 1); | | 4452 | name = 1 + (u_char *)(h + 1); |