Thu Nov 5 20:36:03 2015 UTC ()
Pull up following revision(s) (requested by ozaki-r in ticket #982):
	sys/netinet6/icmp6.c: revision 1.177
Update icmp6_redirect_timeout_q when changing net.inet6.icmp6.redirtimeout
We have to update icmp6_redirect_timeout_q as well as icmp6_redirtimeout
when changing net.inet6.icmp6.redirtimeout via sysctl. The updating logic
is copied from sysctl_net_inet_icmp_redirtimeout.
This change is from s-yamaguchi@IIJ (with KNF by ozaki-r) and fixes
PR kern/50240.


(riz)
diff -r1.169 -r1.169.2.1 src/sys/netinet6/icmp6.c

cvs diff -r1.169 -r1.169.2.1 src/sys/netinet6/icmp6.c (switch to unified diff)

--- src/sys/netinet6/icmp6.c 2014/06/06 01:02:47 1.169
+++ src/sys/netinet6/icmp6.c 2015/11/05 20:36:03 1.169.2.1
@@ -1,1064 +1,1064 @@ @@ -1,1064 +1,1064 @@
1/* $NetBSD: icmp6.c,v 1.169 2014/06/06 01:02:47 rmind Exp $ */ 1/* $NetBSD: icmp6.c,v 1.169.2.1 2015/11/05 20:36:03 riz Exp $ */
2/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ 2/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors 16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software 17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission. 18 * without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * Copyright (c) 1982, 1986, 1988, 1993 34 * Copyright (c) 1982, 1986, 1988, 1993
35 * The Regents of the University of California. All rights reserved. 35 * The Regents of the University of California. All rights reserved.
36 * 36 *
37 * Redistribution and use in source and binary forms, with or without 37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions 38 * modification, are permitted provided that the following conditions
39 * are met: 39 * are met:
40 * 1. Redistributions of source code must retain the above copyright 40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer. 41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright 42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the 43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution. 44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors 45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software 46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission. 47 * without specific prior written permission.
48 * 48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE. 59 * SUCH DAMAGE.
60 * 60 *
61 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 61 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
62 */ 62 */
63 63
64#include <sys/cdefs.h> 64#include <sys/cdefs.h>
65__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.169 2014/06/06 01:02:47 rmind Exp $"); 65__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.169.2.1 2015/11/05 20:36:03 riz Exp $");
66 66
67#include "opt_inet.h" 67#include "opt_inet.h"
68#include "opt_ipsec.h" 68#include "opt_ipsec.h"
69 69
70#include <sys/param.h> 70#include <sys/param.h>
71#include <sys/systm.h> 71#include <sys/systm.h>
72#include <sys/kmem.h> 72#include <sys/kmem.h>
73#include <sys/mbuf.h> 73#include <sys/mbuf.h>
74#include <sys/protosw.h> 74#include <sys/protosw.h>
75#include <sys/socket.h> 75#include <sys/socket.h>
76#include <sys/socketvar.h> 76#include <sys/socketvar.h>
77#include <sys/time.h> 77#include <sys/time.h>
78#include <sys/kernel.h> 78#include <sys/kernel.h>
79#include <sys/syslog.h> 79#include <sys/syslog.h>
80#include <sys/domain.h> 80#include <sys/domain.h>
81#include <sys/sysctl.h> 81#include <sys/sysctl.h>
82 82
83#include <net/if.h> 83#include <net/if.h>
84#include <net/route.h> 84#include <net/route.h>
85#include <net/if_dl.h> 85#include <net/if_dl.h>
86#include <net/if_types.h> 86#include <net/if_types.h>
87 87
88#include <netinet/in.h> 88#include <netinet/in.h>
89#include <netinet/in_var.h> 89#include <netinet/in_var.h>
90#include <netinet/ip6.h> 90#include <netinet/ip6.h>
91#include <netinet6/ip6_var.h> 91#include <netinet6/ip6_var.h>
92#include <netinet6/ip6_private.h> 92#include <netinet6/ip6_private.h>
93#include <netinet/icmp6.h> 93#include <netinet/icmp6.h>
94#include <netinet6/icmp6_private.h> 94#include <netinet6/icmp6_private.h>
95#include <netinet6/mld6_var.h> 95#include <netinet6/mld6_var.h>
96#include <netinet6/in6_pcb.h> 96#include <netinet6/in6_pcb.h>
97#include <netinet6/nd6.h> 97#include <netinet6/nd6.h>
98#include <netinet6/in6_ifattach.h> 98#include <netinet6/in6_ifattach.h>
99#include <netinet6/ip6protosw.h> 99#include <netinet6/ip6protosw.h>
100#include <netinet6/scope6_var.h> 100#include <netinet6/scope6_var.h>
101 101
102#ifdef IPSEC 102#ifdef IPSEC
103#include <netipsec/ipsec.h> 103#include <netipsec/ipsec.h>
104#include <netipsec/key.h> 104#include <netipsec/key.h>
105#endif 105#endif
106 106
107 107
108#include "faith.h" 108#include "faith.h"
109#if defined(NFAITH) && 0 < NFAITH 109#if defined(NFAITH) && 0 < NFAITH
110#include <net/if_faith.h> 110#include <net/if_faith.h>
111#endif 111#endif
112 112
113#include <net/net_osdep.h> 113#include <net/net_osdep.h>
114 114
115extern struct domain inet6domain; 115extern struct domain inet6domain;
116 116
117percpu_t *icmp6stat_percpu; 117percpu_t *icmp6stat_percpu;
118 118
119extern struct inpcbtable raw6cbtable; 119extern struct inpcbtable raw6cbtable;
120extern int icmp6errppslim; 120extern int icmp6errppslim;
121static int icmp6errpps_count = 0; 121static int icmp6errpps_count = 0;
122static struct timeval icmp6errppslim_last; 122static struct timeval icmp6errppslim_last;
123extern int icmp6_nodeinfo; 123extern int icmp6_nodeinfo;
124 124
125/* 125/*
126 * List of callbacks to notify when Path MTU changes are made. 126 * List of callbacks to notify when Path MTU changes are made.
127 */ 127 */
128struct icmp6_mtudisc_callback { 128struct icmp6_mtudisc_callback {
129 LIST_ENTRY(icmp6_mtudisc_callback) mc_list; 129 LIST_ENTRY(icmp6_mtudisc_callback) mc_list;
130 void (*mc_func)(struct in6_addr *); 130 void (*mc_func)(struct in6_addr *);
131}; 131};
132 132
133LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks = 133LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks =
134 LIST_HEAD_INITIALIZER(&icmp6_mtudisc_callbacks); 134 LIST_HEAD_INITIALIZER(&icmp6_mtudisc_callbacks);
135 135
136static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL; 136static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;
137extern int pmtu_expire; 137extern int pmtu_expire;
138 138
139/* XXX do these values make any sense? */ 139/* XXX do these values make any sense? */
140static int icmp6_mtudisc_hiwat = 1280; 140static int icmp6_mtudisc_hiwat = 1280;
141static int icmp6_mtudisc_lowat = 256; 141static int icmp6_mtudisc_lowat = 256;
142 142
143/* 143/*
144 * keep track of # of redirect routes. 144 * keep track of # of redirect routes.
145 */ 145 */
146static struct rttimer_queue *icmp6_redirect_timeout_q = NULL; 146static struct rttimer_queue *icmp6_redirect_timeout_q = NULL;
147 147
148/* XXX experimental, turned off */ 148/* XXX experimental, turned off */
149static int icmp6_redirect_hiwat = -1; 149static int icmp6_redirect_hiwat = -1;
150static int icmp6_redirect_lowat = -1; 150static int icmp6_redirect_lowat = -1;
151 151
152static void icmp6_errcount(u_int, int, int); 152static void icmp6_errcount(u_int, int, int);
153static int icmp6_rip6_input(struct mbuf **, int); 153static int icmp6_rip6_input(struct mbuf **, int);
154static int icmp6_ratelimit(const struct in6_addr *, const int, const int); 154static int icmp6_ratelimit(const struct in6_addr *, const int, const int);
155static const char *icmp6_redirect_diag(struct in6_addr *, 155static const char *icmp6_redirect_diag(struct in6_addr *,
156 struct in6_addr *, struct in6_addr *); 156 struct in6_addr *, struct in6_addr *);
157static struct mbuf *ni6_input(struct mbuf *, int); 157static struct mbuf *ni6_input(struct mbuf *, int);
158static struct mbuf *ni6_nametodns(const char *, int, int); 158static struct mbuf *ni6_nametodns(const char *, int, int);
159static int ni6_dnsmatch(const char *, int, const char *, int); 159static int ni6_dnsmatch(const char *, int, const char *, int);
160static int ni6_addrs(struct icmp6_nodeinfo *, struct mbuf *, 160static int ni6_addrs(struct icmp6_nodeinfo *, struct mbuf *,
161 struct ifnet **, char *); 161 struct ifnet **, char *);
162static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *, 162static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
163 struct ifnet *, int); 163 struct ifnet *, int);
164static int icmp6_notify_error(struct mbuf *, int, int, int); 164static int icmp6_notify_error(struct mbuf *, int, int, int);
165static struct rtentry *icmp6_mtudisc_clone(struct sockaddr *); 165static struct rtentry *icmp6_mtudisc_clone(struct sockaddr *);
166static void icmp6_mtudisc_timeout(struct rtentry *, struct rttimer *); 166static void icmp6_mtudisc_timeout(struct rtentry *, struct rttimer *);
167static void icmp6_redirect_timeout(struct rtentry *, struct rttimer *); 167static void icmp6_redirect_timeout(struct rtentry *, struct rttimer *);
168static void sysctl_net_inet6_icmp6_setup(struct sysctllog **); 168static void sysctl_net_inet6_icmp6_setup(struct sysctllog **);
169 169
170 170
171void 171void
172icmp6_init(void) 172icmp6_init(void)
173{ 173{
174 174
175 sysctl_net_inet6_icmp6_setup(NULL); 175 sysctl_net_inet6_icmp6_setup(NULL);
176 mld_init(); 176 mld_init();
177 icmp6_mtudisc_timeout_q = rt_timer_queue_create(pmtu_expire); 177 icmp6_mtudisc_timeout_q = rt_timer_queue_create(pmtu_expire);
178 icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout); 178 icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout);
179 179
180 icmp6stat_percpu = percpu_alloc(sizeof(uint64_t) * ICMP6_NSTATS); 180 icmp6stat_percpu = percpu_alloc(sizeof(uint64_t) * ICMP6_NSTATS);
181} 181}
182 182
183static void 183static void
184icmp6_errcount(u_int base, int type, int code) 184icmp6_errcount(u_int base, int type, int code)
185{ 185{
186 switch (type) { 186 switch (type) {
187 case ICMP6_DST_UNREACH: 187 case ICMP6_DST_UNREACH:
188 switch (code) { 188 switch (code) {
189 case ICMP6_DST_UNREACH_NOROUTE: 189 case ICMP6_DST_UNREACH_NOROUTE:
190 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_NOROUTE); 190 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_NOROUTE);
191 return; 191 return;
192 case ICMP6_DST_UNREACH_ADMIN: 192 case ICMP6_DST_UNREACH_ADMIN:
193 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_ADMIN); 193 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_ADMIN);
194 return; 194 return;
195 case ICMP6_DST_UNREACH_BEYONDSCOPE: 195 case ICMP6_DST_UNREACH_BEYONDSCOPE:
196 ICMP6_STATINC(base + 196 ICMP6_STATINC(base +
197 ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE); 197 ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE);
198 return; 198 return;
199 case ICMP6_DST_UNREACH_ADDR: 199 case ICMP6_DST_UNREACH_ADDR:
200 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_ADDR); 200 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_ADDR);
201 return; 201 return;
202 case ICMP6_DST_UNREACH_NOPORT: 202 case ICMP6_DST_UNREACH_NOPORT:
203 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_NOPORT); 203 ICMP6_STATINC(base + ICMP6_ERRSTAT_DST_UNREACH_NOPORT);
204 return; 204 return;
205 } 205 }
206 break; 206 break;
207 case ICMP6_PACKET_TOO_BIG: 207 case ICMP6_PACKET_TOO_BIG:
208 ICMP6_STATINC(base + ICMP6_ERRSTAT_PACKET_TOO_BIG); 208 ICMP6_STATINC(base + ICMP6_ERRSTAT_PACKET_TOO_BIG);
209 return; 209 return;
210 case ICMP6_TIME_EXCEEDED: 210 case ICMP6_TIME_EXCEEDED:
211 switch (code) { 211 switch (code) {
212 case ICMP6_TIME_EXCEED_TRANSIT: 212 case ICMP6_TIME_EXCEED_TRANSIT:
213 ICMP6_STATINC(base + ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT); 213 ICMP6_STATINC(base + ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT);
214 return; 214 return;
215 case ICMP6_TIME_EXCEED_REASSEMBLY: 215 case ICMP6_TIME_EXCEED_REASSEMBLY:
216 ICMP6_STATINC(base + 216 ICMP6_STATINC(base +
217 ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY); 217 ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY);
218 return; 218 return;
219 } 219 }
220 break; 220 break;
221 case ICMP6_PARAM_PROB: 221 case ICMP6_PARAM_PROB:
222 switch (code) { 222 switch (code) {
223 case ICMP6_PARAMPROB_HEADER: 223 case ICMP6_PARAMPROB_HEADER:
224 ICMP6_STATINC(base + ICMP6_ERRSTAT_PARAMPROB_HEADER); 224 ICMP6_STATINC(base + ICMP6_ERRSTAT_PARAMPROB_HEADER);
225 return; 225 return;
226 case ICMP6_PARAMPROB_NEXTHEADER: 226 case ICMP6_PARAMPROB_NEXTHEADER:
227 ICMP6_STATINC(base + 227 ICMP6_STATINC(base +
228 ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER); 228 ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER);
229 return; 229 return;
230 case ICMP6_PARAMPROB_OPTION: 230 case ICMP6_PARAMPROB_OPTION:
231 ICMP6_STATINC(base + ICMP6_ERRSTAT_PARAMPROB_OPTION); 231 ICMP6_STATINC(base + ICMP6_ERRSTAT_PARAMPROB_OPTION);
232 return; 232 return;
233 } 233 }
234 break; 234 break;
235 case ND_REDIRECT: 235 case ND_REDIRECT:
236 ICMP6_STATINC(base + ICMP6_ERRSTAT_REDIRECT); 236 ICMP6_STATINC(base + ICMP6_ERRSTAT_REDIRECT);
237 return; 237 return;
238 } 238 }
239 ICMP6_STATINC(base + ICMP6_ERRSTAT_UNKNOWN); 239 ICMP6_STATINC(base + ICMP6_ERRSTAT_UNKNOWN);
240} 240}
241 241
242/* 242/*
243 * Register a Path MTU Discovery callback. 243 * Register a Path MTU Discovery callback.
244 */ 244 */
245void 245void
246icmp6_mtudisc_callback_register(void (*func)(struct in6_addr *)) 246icmp6_mtudisc_callback_register(void (*func)(struct in6_addr *))
247{ 247{
248 struct icmp6_mtudisc_callback *mc; 248 struct icmp6_mtudisc_callback *mc;
249 249
250 for (mc = LIST_FIRST(&icmp6_mtudisc_callbacks); mc != NULL; 250 for (mc = LIST_FIRST(&icmp6_mtudisc_callbacks); mc != NULL;
251 mc = LIST_NEXT(mc, mc_list)) { 251 mc = LIST_NEXT(mc, mc_list)) {
252 if (mc->mc_func == func) 252 if (mc->mc_func == func)
253 return; 253 return;
254 } 254 }
255 255
256 mc = kmem_alloc(sizeof(*mc), KM_SLEEP); 256 mc = kmem_alloc(sizeof(*mc), KM_SLEEP);
257 mc->mc_func = func; 257 mc->mc_func = func;
258 LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list); 258 LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list);
259} 259}
260 260
261/* 261/*
262 * A wrapper function for icmp6_error() necessary when the erroneous packet 262 * A wrapper function for icmp6_error() necessary when the erroneous packet
263 * may not contain enough scope zone information. 263 * may not contain enough scope zone information.
264 */ 264 */
265void 265void
266icmp6_error2(struct mbuf *m, int type, int code, int param,  266icmp6_error2(struct mbuf *m, int type, int code, int param,
267 struct ifnet *ifp) 267 struct ifnet *ifp)
268{ 268{
269 struct ip6_hdr *ip6; 269 struct ip6_hdr *ip6;
270 270
271 if (ifp == NULL) 271 if (ifp == NULL)
272 return; 272 return;
273 273
274 if (m->m_len < sizeof(struct ip6_hdr)) { 274 if (m->m_len < sizeof(struct ip6_hdr)) {
275 m = m_pullup(m, sizeof(struct ip6_hdr)); 275 m = m_pullup(m, sizeof(struct ip6_hdr));
276 if (m == NULL) 276 if (m == NULL)
277 return; 277 return;
278 } 278 }
279 279
280 ip6 = mtod(m, struct ip6_hdr *); 280 ip6 = mtod(m, struct ip6_hdr *);
281 281
282 if (in6_setscope(&ip6->ip6_src, ifp, NULL) != 0) 282 if (in6_setscope(&ip6->ip6_src, ifp, NULL) != 0)
283 return; 283 return;
284 if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0) 284 if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
285 return; 285 return;
286 286
287 icmp6_error(m, type, code, param); 287 icmp6_error(m, type, code, param);
288} 288}
289 289
290/* 290/*
291 * Generate an error packet of type error in response to bad IP6 packet. 291 * Generate an error packet of type error in response to bad IP6 packet.
292 */ 292 */
293void 293void
294icmp6_error(struct mbuf *m, int type, int code, int param) 294icmp6_error(struct mbuf *m, int type, int code, int param)
295{ 295{
296 struct ip6_hdr *oip6, *nip6; 296 struct ip6_hdr *oip6, *nip6;
297 struct icmp6_hdr *icmp6; 297 struct icmp6_hdr *icmp6;
298 u_int preplen; 298 u_int preplen;
299 int off; 299 int off;
300 int nxt; 300 int nxt;
301 301
302 ICMP6_STATINC(ICMP6_STAT_ERROR); 302 ICMP6_STATINC(ICMP6_STAT_ERROR);
303 303
304 /* count per-type-code statistics */ 304 /* count per-type-code statistics */
305 icmp6_errcount(ICMP6_STAT_OUTERRHIST, type, code); 305 icmp6_errcount(ICMP6_STAT_OUTERRHIST, type, code);
306 306
307 if (m->m_flags & M_DECRYPTED) { 307 if (m->m_flags & M_DECRYPTED) {
308 ICMP6_STATINC(ICMP6_STAT_CANTERROR); 308 ICMP6_STATINC(ICMP6_STAT_CANTERROR);
309 goto freeit; 309 goto freeit;
310 } 310 }
311 311
312 if (M_UNWRITABLE(m, sizeof(struct ip6_hdr)) && 312 if (M_UNWRITABLE(m, sizeof(struct ip6_hdr)) &&
313 (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) 313 (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL)
314 return; 314 return;
315 oip6 = mtod(m, struct ip6_hdr *); 315 oip6 = mtod(m, struct ip6_hdr *);
316 316
317 /* 317 /*
318 * If the destination address of the erroneous packet is a multicast 318 * If the destination address of the erroneous packet is a multicast
319 * address, or the packet was sent using link-layer multicast, 319 * address, or the packet was sent using link-layer multicast,
320 * we should basically suppress sending an error (RFC 2463, Section 320 * we should basically suppress sending an error (RFC 2463, Section
321 * 2.4). 321 * 2.4).
322 * We have two exceptions (the item e.2 in that section): 322 * We have two exceptions (the item e.2 in that section):
323 * - the Pakcet Too Big message can be sent for path MTU discovery. 323 * - the Pakcet Too Big message can be sent for path MTU discovery.
324 * - the Parameter Problem Message that can be allowed an icmp6 error 324 * - the Parameter Problem Message that can be allowed an icmp6 error
325 * in the option type field. This check has been done in 325 * in the option type field. This check has been done in
326 * ip6_unknown_opt(), so we can just check the type and code. 326 * ip6_unknown_opt(), so we can just check the type and code.
327 */ 327 */
328 if ((m->m_flags & (M_BCAST|M_MCAST) || 328 if ((m->m_flags & (M_BCAST|M_MCAST) ||
329 IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) && 329 IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
330 (type != ICMP6_PACKET_TOO_BIG && 330 (type != ICMP6_PACKET_TOO_BIG &&
331 (type != ICMP6_PARAM_PROB || 331 (type != ICMP6_PARAM_PROB ||
332 code != ICMP6_PARAMPROB_OPTION))) 332 code != ICMP6_PARAMPROB_OPTION)))
333 goto freeit; 333 goto freeit;
334 334
335 /* 335 /*
336 * RFC 2463, 2.4 (e.5): source address check. 336 * RFC 2463, 2.4 (e.5): source address check.
337 * XXX: the case of anycast source? 337 * XXX: the case of anycast source?
338 */ 338 */
339 if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) || 339 if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
340 IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) 340 IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))
341 goto freeit; 341 goto freeit;
342 342
343 /* 343 /*
344 * If we are about to send ICMPv6 against ICMPv6 error/redirect, 344 * If we are about to send ICMPv6 against ICMPv6 error/redirect,
345 * don't do it. 345 * don't do it.
346 */ 346 */
347 nxt = -1; 347 nxt = -1;
348 off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); 348 off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
349 if (off >= 0 && nxt == IPPROTO_ICMPV6) { 349 if (off >= 0 && nxt == IPPROTO_ICMPV6) {
350 struct icmp6_hdr *icp; 350 struct icmp6_hdr *icp;
351 351
352 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off, 352 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
353 sizeof(*icp)); 353 sizeof(*icp));
354 if (icp == NULL) { 354 if (icp == NULL) {
355 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 355 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
356 return; 356 return;
357 } 357 }
358 if (icp->icmp6_type < ICMP6_ECHO_REQUEST || 358 if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
359 icp->icmp6_type == ND_REDIRECT) { 359 icp->icmp6_type == ND_REDIRECT) {
360 /* 360 /*
361 * ICMPv6 error 361 * ICMPv6 error
362 * Special case: for redirect (which is 362 * Special case: for redirect (which is
363 * informational) we must not send icmp6 error. 363 * informational) we must not send icmp6 error.
364 */ 364 */
365 ICMP6_STATINC(ICMP6_STAT_CANTERROR); 365 ICMP6_STATINC(ICMP6_STAT_CANTERROR);
366 goto freeit; 366 goto freeit;
367 } else { 367 } else {
368 /* ICMPv6 informational - send the error */ 368 /* ICMPv6 informational - send the error */
369 } 369 }
370 } 370 }
371#if 0 /* controversial */ 371#if 0 /* controversial */
372 else if (off >= 0 && nxt == IPPROTO_ESP) { 372 else if (off >= 0 && nxt == IPPROTO_ESP) {
373 /* 373 /*
374 * It could be ICMPv6 error inside ESP. Take a safer side, 374 * It could be ICMPv6 error inside ESP. Take a safer side,
375 * don't respond. 375 * don't respond.
376 */ 376 */
377 ICMP6_STATINC(ICMP6_STAT_CANTERROR); 377 ICMP6_STATINC(ICMP6_STAT_CANTERROR);
378 goto freeit; 378 goto freeit;
379 } 379 }
380#endif 380#endif
381 else { 381 else {
382 /* non-ICMPv6 - send the error */ 382 /* non-ICMPv6 - send the error */
383 } 383 }
384 384
385 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */ 385 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
386 386
387 /* Finally, do rate limitation check. */ 387 /* Finally, do rate limitation check. */
388 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) { 388 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
389 ICMP6_STATINC(ICMP6_STAT_TOOFREQ); 389 ICMP6_STATINC(ICMP6_STAT_TOOFREQ);
390 goto freeit; 390 goto freeit;
391 } 391 }
392 392
393 /* 393 /*
394 * OK, ICMP6 can be generated. 394 * OK, ICMP6 can be generated.
395 */ 395 */
396 396
397 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN) 397 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)
398 m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len); 398 m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
399 399
400 preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 400 preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
401 M_PREPEND(m, preplen, M_DONTWAIT); 401 M_PREPEND(m, preplen, M_DONTWAIT);
402 if (m && M_UNWRITABLE(m, preplen)) 402 if (m && M_UNWRITABLE(m, preplen))
403 m = m_pullup(m, preplen); 403 m = m_pullup(m, preplen);
404 if (m == NULL) { 404 if (m == NULL) {
405 nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__)); 405 nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));
406 return; 406 return;
407 } 407 }
408 408
409 nip6 = mtod(m, struct ip6_hdr *); 409 nip6 = mtod(m, struct ip6_hdr *);
410 nip6->ip6_src = oip6->ip6_src; 410 nip6->ip6_src = oip6->ip6_src;
411 nip6->ip6_dst = oip6->ip6_dst; 411 nip6->ip6_dst = oip6->ip6_dst;
412 412
413 in6_clearscope(&oip6->ip6_src); 413 in6_clearscope(&oip6->ip6_src);
414 in6_clearscope(&oip6->ip6_dst); 414 in6_clearscope(&oip6->ip6_dst);
415 415
416 icmp6 = (struct icmp6_hdr *)(nip6 + 1); 416 icmp6 = (struct icmp6_hdr *)(nip6 + 1);
417 icmp6->icmp6_type = type; 417 icmp6->icmp6_type = type;
418 icmp6->icmp6_code = code; 418 icmp6->icmp6_code = code;
419 icmp6->icmp6_pptr = htonl((u_int32_t)param); 419 icmp6->icmp6_pptr = htonl((u_int32_t)param);
420 420
421 /* 421 /*
422 * icmp6_reflect() is designed to be in the input path. 422 * icmp6_reflect() is designed to be in the input path.
423 * icmp6_error() can be called from both input and output path, 423 * icmp6_error() can be called from both input and output path,
424 * and if we are in output path rcvif could contain bogus value. 424 * and if we are in output path rcvif could contain bogus value.
425 * clear m->m_pkthdr.rcvif for safety, we should have enough scope 425 * clear m->m_pkthdr.rcvif for safety, we should have enough scope
426 * information in ip header (nip6). 426 * information in ip header (nip6).
427 */ 427 */
428 m->m_pkthdr.rcvif = NULL; 428 m->m_pkthdr.rcvif = NULL;
429 429
430 ICMP6_STATINC(ICMP6_STAT_OUTHIST + type); 430 ICMP6_STATINC(ICMP6_STAT_OUTHIST + type);
431 icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */ 431 icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
432 432
433 return; 433 return;
434 434
435 freeit: 435 freeit:
436 /* 436 /*
437 * If we can't tell whether or not we can generate ICMP6, free it. 437 * If we can't tell whether or not we can generate ICMP6, free it.
438 */ 438 */
439 m_freem(m); 439 m_freem(m);
440} 440}
441 441
442/* 442/*
443 * Process a received ICMP6 message. 443 * Process a received ICMP6 message.
444 */ 444 */
445int 445int
446icmp6_input(struct mbuf **mp, int *offp, int proto) 446icmp6_input(struct mbuf **mp, int *offp, int proto)
447{ 447{
448 struct mbuf *m = *mp, *n; 448 struct mbuf *m = *mp, *n;
449 struct ip6_hdr *ip6, *nip6; 449 struct ip6_hdr *ip6, *nip6;
450 struct icmp6_hdr *icmp6, *nicmp6; 450 struct icmp6_hdr *icmp6, *nicmp6;
451 int off = *offp; 451 int off = *offp;
452 int icmp6len = m->m_pkthdr.len - *offp; 452 int icmp6len = m->m_pkthdr.len - *offp;
453 int code, sum, noff, i; 453 int code, sum, noff, i;
454 454
455#define ICMP6_MAXLEN (sizeof(*nip6) + sizeof(*nicmp6) + 4) 455#define ICMP6_MAXLEN (sizeof(*nip6) + sizeof(*nicmp6) + 4)
456 KASSERT(ICMP6_MAXLEN < MCLBYTES); 456 KASSERT(ICMP6_MAXLEN < MCLBYTES);
457 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg); 457 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
458 458
459 /* 459 /*
460 * Locate icmp6 structure in mbuf, and check 460 * Locate icmp6 structure in mbuf, and check
461 * that not corrupted and of at least minimum length 461 * that not corrupted and of at least minimum length
462 */ 462 */
463 463
464 if (icmp6len < sizeof(struct icmp6_hdr)) { 464 if (icmp6len < sizeof(struct icmp6_hdr)) {
465 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 465 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
466 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error); 466 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
467 goto freeit; 467 goto freeit;
468 } 468 }
469 469
470 i = off + sizeof(*icmp6); 470 i = off + sizeof(*icmp6);
471 if ((m->m_len < i || M_READONLY(m)) && (m = m_pullup(m, i)) == 0) { 471 if ((m->m_len < i || M_READONLY(m)) && (m = m_pullup(m, i)) == 0) {
472 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 472 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
473#if 0 /* m is 0 here */ 473#if 0 /* m is 0 here */
474 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error); 474 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
475#endif 475#endif
476 goto freeit; 476 goto freeit;
477 } 477 }
478 ip6 = mtod(m, struct ip6_hdr *); 478 ip6 = mtod(m, struct ip6_hdr *);
479 /* 479 /*
480 * calculate the checksum 480 * calculate the checksum
481 */ 481 */
482 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); 482 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
483 if (icmp6 == NULL) { 483 if (icmp6 == NULL) {
484 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 484 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
485 /* m is invalid */ 485 /* m is invalid */
486 /*icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);*/ 486 /*icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);*/
487 return IPPROTO_DONE; 487 return IPPROTO_DONE;
488 } 488 }
489 KASSERT(IP6_HDR_ALIGNED_P(icmp6)); 489 KASSERT(IP6_HDR_ALIGNED_P(icmp6));
490 code = icmp6->icmp6_code; 490 code = icmp6->icmp6_code;
491 491
492 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) { 492 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
493 nd6log((LOG_ERR, 493 nd6log((LOG_ERR,
494 "ICMP6 checksum error(%d|%x) %s\n", 494 "ICMP6 checksum error(%d|%x) %s\n",
495 icmp6->icmp6_type, sum, ip6_sprintf(&ip6->ip6_src))); 495 icmp6->icmp6_type, sum, ip6_sprintf(&ip6->ip6_src)));
496 ICMP6_STATINC(ICMP6_STAT_CHECKSUM); 496 ICMP6_STATINC(ICMP6_STAT_CHECKSUM);
497 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error); 497 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
498 goto freeit; 498 goto freeit;
499 } 499 }
500 500
501#if defined(NFAITH) && 0 < NFAITH 501#if defined(NFAITH) && 0 < NFAITH
502 if (faithprefix(&ip6->ip6_dst)) { 502 if (faithprefix(&ip6->ip6_dst)) {
503 /* 503 /*
504 * Deliver very specific ICMP6 type only. 504 * Deliver very specific ICMP6 type only.
505 * This is important to deliver TOOBIG. Otherwise PMTUD 505 * This is important to deliver TOOBIG. Otherwise PMTUD
506 * will not work. 506 * will not work.
507 */ 507 */
508 switch (icmp6->icmp6_type) { 508 switch (icmp6->icmp6_type) {
509 case ICMP6_DST_UNREACH: 509 case ICMP6_DST_UNREACH:
510 case ICMP6_PACKET_TOO_BIG: 510 case ICMP6_PACKET_TOO_BIG:
511 case ICMP6_TIME_EXCEEDED: 511 case ICMP6_TIME_EXCEEDED:
512 break; 512 break;
513 default: 513 default:
514 goto freeit; 514 goto freeit;
515 } 515 }
516 } 516 }
517#endif 517#endif
518 518
519 ICMP6_STATINC(ICMP6_STAT_INHIST + icmp6->icmp6_type); 519 ICMP6_STATINC(ICMP6_STAT_INHIST + icmp6->icmp6_type);
520 520
521 switch (icmp6->icmp6_type) { 521 switch (icmp6->icmp6_type) {
522 case ICMP6_DST_UNREACH: 522 case ICMP6_DST_UNREACH:
523 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach); 523 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach);
524 switch (code) { 524 switch (code) {
525 case ICMP6_DST_UNREACH_NOROUTE: 525 case ICMP6_DST_UNREACH_NOROUTE:
526 code = PRC_UNREACH_NET; 526 code = PRC_UNREACH_NET;
527 break; 527 break;
528 case ICMP6_DST_UNREACH_ADMIN: 528 case ICMP6_DST_UNREACH_ADMIN:
529 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib); 529 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib);
530 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ 530 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */
531 break; 531 break;
532 case ICMP6_DST_UNREACH_ADDR: 532 case ICMP6_DST_UNREACH_ADDR:
533 code = PRC_HOSTDEAD; 533 code = PRC_HOSTDEAD;
534 break; 534 break;
535#ifdef COMPAT_RFC1885 535#ifdef COMPAT_RFC1885
536 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 536 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
537 code = PRC_UNREACH_SRCFAIL; 537 code = PRC_UNREACH_SRCFAIL;
538 break; 538 break;
539#else 539#else
540 case ICMP6_DST_UNREACH_BEYONDSCOPE: 540 case ICMP6_DST_UNREACH_BEYONDSCOPE:
541 /* I mean "source address was incorrect." */ 541 /* I mean "source address was incorrect." */
542 code = PRC_UNREACH_NET; 542 code = PRC_UNREACH_NET;
543 break; 543 break;
544#endif 544#endif
545 case ICMP6_DST_UNREACH_NOPORT: 545 case ICMP6_DST_UNREACH_NOPORT:
546 code = PRC_UNREACH_PORT; 546 code = PRC_UNREACH_PORT;
547 break; 547 break;
548 default: 548 default:
549 goto badcode; 549 goto badcode;
550 } 550 }
551 goto deliver; 551 goto deliver;
552 552
553 case ICMP6_PACKET_TOO_BIG: 553 case ICMP6_PACKET_TOO_BIG:
554 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig); 554 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
555 555
556 /* 556 /*
557 * MTU is checked in icmp6_mtudisc. 557 * MTU is checked in icmp6_mtudisc.
558 */ 558 */
559 code = PRC_MSGSIZE; 559 code = PRC_MSGSIZE;
560 560
561 /* 561 /*
562 * Updating the path MTU will be done after examining 562 * Updating the path MTU will be done after examining
563 * intermediate extension headers. 563 * intermediate extension headers.
564 */ 564 */
565 goto deliver; 565 goto deliver;
566 566
567 case ICMP6_TIME_EXCEEDED: 567 case ICMP6_TIME_EXCEEDED:
568 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); 568 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed);
569 switch (code) { 569 switch (code) {
570 case ICMP6_TIME_EXCEED_TRANSIT: 570 case ICMP6_TIME_EXCEED_TRANSIT:
571 code = PRC_TIMXCEED_INTRANS; 571 code = PRC_TIMXCEED_INTRANS;
572 break; 572 break;
573 case ICMP6_TIME_EXCEED_REASSEMBLY: 573 case ICMP6_TIME_EXCEED_REASSEMBLY:
574 code = PRC_TIMXCEED_REASS; 574 code = PRC_TIMXCEED_REASS;
575 break; 575 break;
576 default: 576 default:
577 goto badcode; 577 goto badcode;
578 } 578 }
579 goto deliver; 579 goto deliver;
580 580
581 case ICMP6_PARAM_PROB: 581 case ICMP6_PARAM_PROB:
582 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob); 582 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob);
583 switch (code) { 583 switch (code) {
584 case ICMP6_PARAMPROB_NEXTHEADER: 584 case ICMP6_PARAMPROB_NEXTHEADER:
585 code = PRC_UNREACH_PROTOCOL; 585 code = PRC_UNREACH_PROTOCOL;
586 break; 586 break;
587 case ICMP6_PARAMPROB_HEADER: 587 case ICMP6_PARAMPROB_HEADER:
588 case ICMP6_PARAMPROB_OPTION: 588 case ICMP6_PARAMPROB_OPTION:
589 code = PRC_PARAMPROB; 589 code = PRC_PARAMPROB;
590 break; 590 break;
591 default: 591 default:
592 goto badcode; 592 goto badcode;
593 } 593 }
594 goto deliver; 594 goto deliver;
595 595
596 case ICMP6_ECHO_REQUEST: 596 case ICMP6_ECHO_REQUEST:
597 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo); 597 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo);
598 if (code != 0) 598 if (code != 0)
599 goto badcode; 599 goto badcode;
600 /* 600 /*
601 * Copy mbuf to send to two data paths: userland socket(s), 601 * Copy mbuf to send to two data paths: userland socket(s),
602 * and to the querier (echo reply). 602 * and to the querier (echo reply).
603 * m: a copy for socket, n: a copy for querier 603 * m: a copy for socket, n: a copy for querier
604 * 604 *
605 * If the first mbuf is shared, or the first mbuf is too short, 605 * If the first mbuf is shared, or the first mbuf is too short,
606 * copy the first part of the data into a fresh mbuf. 606 * copy the first part of the data into a fresh mbuf.
607 * Otherwise, we will wrongly overwrite both copies. 607 * Otherwise, we will wrongly overwrite both copies.
608 */ 608 */
609 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 609 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
610 /* Give up local */ 610 /* Give up local */
611 n = m; 611 n = m;
612 m = NULL; 612 m = NULL;
613 } else if (M_READONLY(n) || 613 } else if (M_READONLY(n) ||
614 n->m_len < off + sizeof(struct icmp6_hdr)) { 614 n->m_len < off + sizeof(struct icmp6_hdr)) {
615 struct mbuf *n0 = n; 615 struct mbuf *n0 = n;
616 616
617 /* 617 /*
618 * Prepare an internal mbuf. m_pullup() doesn't 618 * Prepare an internal mbuf. m_pullup() doesn't
619 * always copy the length we specified. 619 * always copy the length we specified.
620 */ 620 */
621 if ((n = m_dup(n0, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 621 if ((n = m_dup(n0, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
622 /* Give up local */ 622 /* Give up local */
623 n = m; 623 n = m;
624 m = NULL; 624 m = NULL;
625 } 625 }
626 m_freem(n0); 626 m_freem(n0);
627 } 627 }
628 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off, 628 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off,
629 sizeof(*nicmp6)); 629 sizeof(*nicmp6));
630 if (nicmp6 == NULL) 630 if (nicmp6 == NULL)
631 goto freeit; 631 goto freeit;
632 nicmp6->icmp6_type = ICMP6_ECHO_REPLY; 632 nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
633 nicmp6->icmp6_code = 0; 633 nicmp6->icmp6_code = 0;
634 if (n) { 634 if (n) {
635 uint64_t *icmp6s = ICMP6_STAT_GETREF(); 635 uint64_t *icmp6s = ICMP6_STAT_GETREF();
636 icmp6s[ICMP6_STAT_REFLECT]++; 636 icmp6s[ICMP6_STAT_REFLECT]++;
637 icmp6s[ICMP6_STAT_OUTHIST + ICMP6_ECHO_REPLY]++; 637 icmp6s[ICMP6_STAT_OUTHIST + ICMP6_ECHO_REPLY]++;
638 ICMP6_STAT_PUTREF(); 638 ICMP6_STAT_PUTREF();
639 icmp6_reflect(n, off); 639 icmp6_reflect(n, off);
640 } 640 }
641 if (!m) 641 if (!m)
642 goto freeit; 642 goto freeit;
643 break; 643 break;
644 644
645 case ICMP6_ECHO_REPLY: 645 case ICMP6_ECHO_REPLY:
646 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply); 646 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply);
647 if (code != 0) 647 if (code != 0)
648 goto badcode; 648 goto badcode;
649 break; 649 break;
650 650
651 case MLD_LISTENER_QUERY: 651 case MLD_LISTENER_QUERY:
652 case MLD_LISTENER_REPORT: 652 case MLD_LISTENER_REPORT:
653 if (icmp6len < sizeof(struct mld_hdr)) 653 if (icmp6len < sizeof(struct mld_hdr))
654 goto badlen; 654 goto badlen;
655 if (icmp6->icmp6_type == MLD_LISTENER_QUERY) /* XXX: ugly... */ 655 if (icmp6->icmp6_type == MLD_LISTENER_QUERY) /* XXX: ugly... */
656 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery); 656 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery);
657 else 657 else
658 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport); 658 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport);
659 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 659 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
660 /* give up local */ 660 /* give up local */
661 mld_input(m, off); 661 mld_input(m, off);
662 m = NULL; 662 m = NULL;
663 goto freeit; 663 goto freeit;
664 } 664 }
665 mld_input(n, off); 665 mld_input(n, off);
666 /* m stays. */ 666 /* m stays. */
667 break; 667 break;
668 668
669 case MLD_LISTENER_DONE: 669 case MLD_LISTENER_DONE:
670 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone); 670 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone);
671 if (icmp6len < sizeof(struct mld_hdr)) /* necessary? */ 671 if (icmp6len < sizeof(struct mld_hdr)) /* necessary? */
672 goto badlen; 672 goto badlen;
673 break; /* nothing to be done in kernel */ 673 break; /* nothing to be done in kernel */
674 674
675 case MLD_MTRACE_RESP: 675 case MLD_MTRACE_RESP:
676 case MLD_MTRACE: 676 case MLD_MTRACE:
677 /* XXX: these two are experimental. not officially defined. */ 677 /* XXX: these two are experimental. not officially defined. */
678 /* XXX: per-interface statistics? */ 678 /* XXX: per-interface statistics? */
679 break; /* just pass it to applications */ 679 break; /* just pass it to applications */
680 680
681 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ 681 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */
682 { 682 {
683 enum { WRU, FQDN } mode; 683 enum { WRU, FQDN } mode;
684 684
685 if (!icmp6_nodeinfo) 685 if (!icmp6_nodeinfo)
686 break; 686 break;
687 687
688 if (icmp6len == sizeof(struct icmp6_hdr) + 4) 688 if (icmp6len == sizeof(struct icmp6_hdr) + 4)
689 mode = WRU; 689 mode = WRU;
690 else if (icmp6len >= sizeof(struct icmp6_nodeinfo)) 690 else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
691 mode = FQDN; 691 mode = FQDN;
692 else 692 else
693 goto badlen; 693 goto badlen;
694 694
695 if (mode == FQDN) { 695 if (mode == FQDN) {
696 n = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 696 n = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
697 if (n) 697 if (n)
698 n = ni6_input(n, off); 698 n = ni6_input(n, off);
699 /* XXX meaningless if n == NULL */ 699 /* XXX meaningless if n == NULL */
700 noff = sizeof(struct ip6_hdr); 700 noff = sizeof(struct ip6_hdr);
701 } else { 701 } else {
702 u_char *p; 702 u_char *p;
703 int maxhlen; 703 int maxhlen;
704 704
705 if ((icmp6_nodeinfo & 5) != 5) 705 if ((icmp6_nodeinfo & 5) != 5)
706 break; 706 break;
707 707
708 if (code != 0) 708 if (code != 0)
709 goto badcode; 709 goto badcode;
710 MGETHDR(n, M_DONTWAIT, m->m_type); 710 MGETHDR(n, M_DONTWAIT, m->m_type);
711 if (n && ICMP6_MAXLEN > MHLEN) { 711 if (n && ICMP6_MAXLEN > MHLEN) {
712 MCLGET(n, M_DONTWAIT); 712 MCLGET(n, M_DONTWAIT);
713 if ((n->m_flags & M_EXT) == 0) { 713 if ((n->m_flags & M_EXT) == 0) {
714 m_free(n); 714 m_free(n);
715 n = NULL; 715 n = NULL;
716 } 716 }
717 } 717 }
718 if (n == NULL) { 718 if (n == NULL) {
719 /* Give up remote */ 719 /* Give up remote */
720 break; 720 break;
721 } 721 }
722 n->m_pkthdr.rcvif = NULL; 722 n->m_pkthdr.rcvif = NULL;
723 n->m_len = 0; 723 n->m_len = 0;
724 maxhlen = M_TRAILINGSPACE(n) - ICMP6_MAXLEN; 724 maxhlen = M_TRAILINGSPACE(n) - ICMP6_MAXLEN;
725 if (maxhlen > hostnamelen) 725 if (maxhlen > hostnamelen)
726 maxhlen = hostnamelen; 726 maxhlen = hostnamelen;
727 /* 727 /*
728 * Copy IPv6 and ICMPv6 only. 728 * Copy IPv6 and ICMPv6 only.
729 */ 729 */
730 nip6 = mtod(n, struct ip6_hdr *); 730 nip6 = mtod(n, struct ip6_hdr *);
731 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 731 bcopy(ip6, nip6, sizeof(struct ip6_hdr));
732 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 732 nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
733 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 733 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
734 p = (u_char *)(nicmp6 + 1); 734 p = (u_char *)(nicmp6 + 1);
735 memset(p, 0, 4); 735 memset(p, 0, 4);
736 bcopy(hostname, p + 4, maxhlen); /* meaningless TTL */ 736 bcopy(hostname, p + 4, maxhlen); /* meaningless TTL */
737 noff = sizeof(struct ip6_hdr); 737 noff = sizeof(struct ip6_hdr);
738 M_COPY_PKTHDR(n, m); /* just for rcvif */ 738 M_COPY_PKTHDR(n, m); /* just for rcvif */
739 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + 739 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
740 sizeof(struct icmp6_hdr) + 4 + maxhlen; 740 sizeof(struct icmp6_hdr) + 4 + maxhlen;
741 nicmp6->icmp6_type = ICMP6_WRUREPLY; 741 nicmp6->icmp6_type = ICMP6_WRUREPLY;
742 nicmp6->icmp6_code = 0; 742 nicmp6->icmp6_code = 0;
743 } 743 }
744#undef hostnamelen 744#undef hostnamelen
745 if (n) { 745 if (n) {
746 uint64_t *icmp6s = ICMP6_STAT_GETREF(); 746 uint64_t *icmp6s = ICMP6_STAT_GETREF();
747 icmp6s[ICMP6_STAT_REFLECT]++; 747 icmp6s[ICMP6_STAT_REFLECT]++;
748 icmp6s[ICMP6_STAT_OUTHIST + ICMP6_WRUREPLY]++; 748 icmp6s[ICMP6_STAT_OUTHIST + ICMP6_WRUREPLY]++;
749 ICMP6_STAT_PUTREF(); 749 ICMP6_STAT_PUTREF();
750 icmp6_reflect(n, noff); 750 icmp6_reflect(n, noff);
751 } 751 }
752 break; 752 break;
753 } 753 }
754 754
755 case ICMP6_WRUREPLY: 755 case ICMP6_WRUREPLY:
756 if (code != 0) 756 if (code != 0)
757 goto badcode; 757 goto badcode;
758 break; 758 break;
759 759
760 case ND_ROUTER_SOLICIT: 760 case ND_ROUTER_SOLICIT:
761 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit); 761 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit);
762 if (code != 0) 762 if (code != 0)
763 goto badcode; 763 goto badcode;
764 if (icmp6len < sizeof(struct nd_router_solicit)) 764 if (icmp6len < sizeof(struct nd_router_solicit))
765 goto badlen; 765 goto badlen;
766 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 766 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
767 /* give up local */ 767 /* give up local */
768 nd6_rs_input(m, off, icmp6len); 768 nd6_rs_input(m, off, icmp6len);
769 m = NULL; 769 m = NULL;
770 goto freeit; 770 goto freeit;
771 } 771 }
772 nd6_rs_input(n, off, icmp6len); 772 nd6_rs_input(n, off, icmp6len);
773 /* m stays. */ 773 /* m stays. */
774 break; 774 break;
775 775
776 case ND_ROUTER_ADVERT: 776 case ND_ROUTER_ADVERT:
777 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert); 777 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert);
778 if (code != 0) 778 if (code != 0)
779 goto badcode; 779 goto badcode;
780 if (icmp6len < sizeof(struct nd_router_advert)) 780 if (icmp6len < sizeof(struct nd_router_advert))
781 goto badlen; 781 goto badlen;
782 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 782 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
783 /* give up local */ 783 /* give up local */
784 nd6_ra_input(m, off, icmp6len); 784 nd6_ra_input(m, off, icmp6len);
785 m = NULL; 785 m = NULL;
786 goto freeit; 786 goto freeit;
787 } 787 }
788 nd6_ra_input(n, off, icmp6len); 788 nd6_ra_input(n, off, icmp6len);
789 /* m stays. */ 789 /* m stays. */
790 break; 790 break;
791 791
792 case ND_NEIGHBOR_SOLICIT: 792 case ND_NEIGHBOR_SOLICIT:
793 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit); 793 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit);
794 if (code != 0) 794 if (code != 0)
795 goto badcode; 795 goto badcode;
796 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 796 if (icmp6len < sizeof(struct nd_neighbor_solicit))
797 goto badlen; 797 goto badlen;
798 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 798 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
799 /* give up local */ 799 /* give up local */
800 nd6_ns_input(m, off, icmp6len); 800 nd6_ns_input(m, off, icmp6len);
801 m = NULL; 801 m = NULL;
802 goto freeit; 802 goto freeit;
803 } 803 }
804 nd6_ns_input(n, off, icmp6len); 804 nd6_ns_input(n, off, icmp6len);
805 /* m stays. */ 805 /* m stays. */
806 break; 806 break;
807 807
808 case ND_NEIGHBOR_ADVERT: 808 case ND_NEIGHBOR_ADVERT:
809 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert); 809 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert);
810 if (code != 0) 810 if (code != 0)
811 goto badcode; 811 goto badcode;
812 if (icmp6len < sizeof(struct nd_neighbor_advert)) 812 if (icmp6len < sizeof(struct nd_neighbor_advert))
813 goto badlen; 813 goto badlen;
814 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 814 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
815 /* give up local */ 815 /* give up local */
816 nd6_na_input(m, off, icmp6len); 816 nd6_na_input(m, off, icmp6len);
817 m = NULL; 817 m = NULL;
818 goto freeit; 818 goto freeit;
819 } 819 }
820 nd6_na_input(n, off, icmp6len); 820 nd6_na_input(n, off, icmp6len);
821 /* m stays. */ 821 /* m stays. */
822 break; 822 break;
823 823
824 case ND_REDIRECT: 824 case ND_REDIRECT:
825 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect); 825 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect);
826 if (code != 0) 826 if (code != 0)
827 goto badcode; 827 goto badcode;
828 if (icmp6len < sizeof(struct nd_redirect)) 828 if (icmp6len < sizeof(struct nd_redirect))
829 goto badlen; 829 goto badlen;
830 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 830 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
831 /* give up local */ 831 /* give up local */
832 icmp6_redirect_input(m, off); 832 icmp6_redirect_input(m, off);
833 m = NULL; 833 m = NULL;
834 goto freeit; 834 goto freeit;
835 } 835 }
836 icmp6_redirect_input(n, off); 836 icmp6_redirect_input(n, off);
837 /* m stays. */ 837 /* m stays. */
838 break; 838 break;
839 839
840 case ICMP6_ROUTER_RENUMBERING: 840 case ICMP6_ROUTER_RENUMBERING:
841 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND && 841 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
842 code != ICMP6_ROUTER_RENUMBERING_RESULT) 842 code != ICMP6_ROUTER_RENUMBERING_RESULT)
843 goto badcode; 843 goto badcode;
844 if (icmp6len < sizeof(struct icmp6_router_renum)) 844 if (icmp6len < sizeof(struct icmp6_router_renum))
845 goto badlen; 845 goto badlen;
846 break; 846 break;
847 847
848 default: 848 default:
849 nd6log((LOG_DEBUG, 849 nd6log((LOG_DEBUG,
850 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n", 850 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
851 icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src), 851 icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src),
852 ip6_sprintf(&ip6->ip6_dst), 852 ip6_sprintf(&ip6->ip6_dst),
853 m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0)); 853 m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0));
854 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 854 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
855 /* ICMPv6 error: MUST deliver it by spec... */ 855 /* ICMPv6 error: MUST deliver it by spec... */
856 code = PRC_NCMDS; 856 code = PRC_NCMDS;
857 /* deliver */ 857 /* deliver */
858 } else { 858 } else {
859 /* ICMPv6 informational: MUST not deliver */ 859 /* ICMPv6 informational: MUST not deliver */
860 break; 860 break;
861 } 861 }
862 deliver: 862 deliver:
863 if (icmp6_notify_error(m, off, icmp6len, code)) { 863 if (icmp6_notify_error(m, off, icmp6len, code)) {
864 /* In this case, m should've been freed. */ 864 /* In this case, m should've been freed. */
865 return (IPPROTO_DONE); 865 return (IPPROTO_DONE);
866 } 866 }
867 break; 867 break;
868 868
869 badcode: 869 badcode:
870 ICMP6_STATINC(ICMP6_STAT_BADCODE); 870 ICMP6_STATINC(ICMP6_STAT_BADCODE);
871 break; 871 break;
872 872
873 badlen: 873 badlen:
874 ICMP6_STATINC(ICMP6_STAT_BADLEN); 874 ICMP6_STATINC(ICMP6_STAT_BADLEN);
875 break; 875 break;
876 } 876 }
877 877
878 /* deliver the packet to appropriate sockets */ 878 /* deliver the packet to appropriate sockets */
879 icmp6_rip6_input(&m, *offp); 879 icmp6_rip6_input(&m, *offp);
880 880
881 return IPPROTO_DONE; 881 return IPPROTO_DONE;
882 882
883 freeit: 883 freeit:
884 m_freem(m); 884 m_freem(m);
885 return IPPROTO_DONE; 885 return IPPROTO_DONE;
886} 886}
887 887
888static int 888static int
889icmp6_notify_error(struct mbuf *m, int off, int icmp6len, int code) 889icmp6_notify_error(struct mbuf *m, int off, int icmp6len, int code)
890{ 890{
891 struct icmp6_hdr *icmp6; 891 struct icmp6_hdr *icmp6;
892 struct ip6_hdr *eip6; 892 struct ip6_hdr *eip6;
893 u_int32_t notifymtu; 893 u_int32_t notifymtu;
894 struct sockaddr_in6 icmp6src, icmp6dst; 894 struct sockaddr_in6 icmp6src, icmp6dst;
895 895
896 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { 896 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
897 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 897 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
898 goto freeit; 898 goto freeit;
899 } 899 }
900 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 900 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
901 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 901 sizeof(*icmp6) + sizeof(struct ip6_hdr));
902 if (icmp6 == NULL) { 902 if (icmp6 == NULL) {
903 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 903 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
904 return (-1); 904 return (-1);
905 } 905 }
906 eip6 = (struct ip6_hdr *)(icmp6 + 1); 906 eip6 = (struct ip6_hdr *)(icmp6 + 1);
907 907
908 /* Detect the upper level protocol */ 908 /* Detect the upper level protocol */
909 { 909 {
910 void (*ctlfunc)(int, struct sockaddr *, void *); 910 void (*ctlfunc)(int, struct sockaddr *, void *);
911 u_int8_t nxt = eip6->ip6_nxt; 911 u_int8_t nxt = eip6->ip6_nxt;
912 int eoff = off + sizeof(struct icmp6_hdr) + 912 int eoff = off + sizeof(struct icmp6_hdr) +
913 sizeof(struct ip6_hdr); 913 sizeof(struct ip6_hdr);
914 struct ip6ctlparam ip6cp; 914 struct ip6ctlparam ip6cp;
915 struct in6_addr *finaldst = NULL; 915 struct in6_addr *finaldst = NULL;
916 int icmp6type = icmp6->icmp6_type; 916 int icmp6type = icmp6->icmp6_type;
917 struct ip6_frag *fh; 917 struct ip6_frag *fh;
918 struct ip6_rthdr *rth; 918 struct ip6_rthdr *rth;
919 struct ip6_rthdr0 *rth0; 919 struct ip6_rthdr0 *rth0;
920 int rthlen; 920 int rthlen;
921 921
922 while (1) { /* XXX: should avoid infinite loop explicitly? */ 922 while (1) { /* XXX: should avoid infinite loop explicitly? */
923 struct ip6_ext *eh; 923 struct ip6_ext *eh;
924 924
925 switch (nxt) { 925 switch (nxt) {
926 case IPPROTO_HOPOPTS: 926 case IPPROTO_HOPOPTS:
927 case IPPROTO_DSTOPTS: 927 case IPPROTO_DSTOPTS:
928 case IPPROTO_AH: 928 case IPPROTO_AH:
929 IP6_EXTHDR_GET(eh, struct ip6_ext *, m, 929 IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
930 eoff, sizeof(*eh)); 930 eoff, sizeof(*eh));
931 if (eh == NULL) { 931 if (eh == NULL) {
932 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 932 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
933 return (-1); 933 return (-1);
934 } 934 }
935 935
936 if (nxt == IPPROTO_AH) 936 if (nxt == IPPROTO_AH)
937 eoff += (eh->ip6e_len + 2) << 2; 937 eoff += (eh->ip6e_len + 2) << 2;
938 else 938 else
939 eoff += (eh->ip6e_len + 1) << 3; 939 eoff += (eh->ip6e_len + 1) << 3;
940 nxt = eh->ip6e_nxt; 940 nxt = eh->ip6e_nxt;
941 break; 941 break;
942 case IPPROTO_ROUTING: 942 case IPPROTO_ROUTING:
943 /* 943 /*
944 * When the erroneous packet contains a 944 * When the erroneous packet contains a
945 * routing header, we should examine the 945 * routing header, we should examine the
946 * header to determine the final destination. 946 * header to determine the final destination.
947 * Otherwise, we can't properly update 947 * Otherwise, we can't properly update
948 * information that depends on the final 948 * information that depends on the final
949 * destination (e.g. path MTU). 949 * destination (e.g. path MTU).
950 */ 950 */
951 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, 951 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
952 eoff, sizeof(*rth)); 952 eoff, sizeof(*rth));
953 if (rth == NULL) { 953 if (rth == NULL) {
954 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 954 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
955 return (-1); 955 return (-1);
956 } 956 }
957 rthlen = (rth->ip6r_len + 1) << 3; 957 rthlen = (rth->ip6r_len + 1) << 3;
958 /* 958 /*
959 * XXX: currently there is no 959 * XXX: currently there is no
960 * officially defined type other 960 * officially defined type other
961 * than type-0. 961 * than type-0.
962 * Note that if the segment left field 962 * Note that if the segment left field
963 * is 0, all intermediate hops must 963 * is 0, all intermediate hops must
964 * have been passed. 964 * have been passed.
965 */ 965 */
966 if (rth->ip6r_segleft && 966 if (rth->ip6r_segleft &&
967 rth->ip6r_type == IPV6_RTHDR_TYPE_0) { 967 rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
968 int hops; 968 int hops;
969 969
970 IP6_EXTHDR_GET(rth0, 970 IP6_EXTHDR_GET(rth0,
971 struct ip6_rthdr0 *, m, 971 struct ip6_rthdr0 *, m,
972 eoff, rthlen); 972 eoff, rthlen);
973 if (rth0 == NULL) { 973 if (rth0 == NULL) {
974 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 974 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
975 return (-1); 975 return (-1);
976 } 976 }
977 /* just ignore a bogus header */ 977 /* just ignore a bogus header */
978 if ((rth0->ip6r0_len % 2) == 0 && 978 if ((rth0->ip6r0_len % 2) == 0 &&
979 (hops = rth0->ip6r0_len/2)) 979 (hops = rth0->ip6r0_len/2))
980 finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1); 980 finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1);
981 } 981 }
982 eoff += rthlen; 982 eoff += rthlen;
983 nxt = rth->ip6r_nxt; 983 nxt = rth->ip6r_nxt;
984 break; 984 break;
985 case IPPROTO_FRAGMENT: 985 case IPPROTO_FRAGMENT:
986 IP6_EXTHDR_GET(fh, struct ip6_frag *, m, 986 IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
987 eoff, sizeof(*fh)); 987 eoff, sizeof(*fh));
988 if (fh == NULL) { 988 if (fh == NULL) {
989 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 989 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
990 return (-1); 990 return (-1);
991 } 991 }
992 /* 992 /*
993 * Data after a fragment header is meaningless 993 * Data after a fragment header is meaningless
994 * unless it is the first fragment, but 994 * unless it is the first fragment, but
995 * we'll go to the notify label for path MTU 995 * we'll go to the notify label for path MTU
996 * discovery. 996 * discovery.
997 */ 997 */
998 if (fh->ip6f_offlg & IP6F_OFF_MASK) 998 if (fh->ip6f_offlg & IP6F_OFF_MASK)
999 goto notify; 999 goto notify;
1000 1000
1001 eoff += sizeof(struct ip6_frag); 1001 eoff += sizeof(struct ip6_frag);
1002 nxt = fh->ip6f_nxt; 1002 nxt = fh->ip6f_nxt;
1003 break; 1003 break;
1004 default: 1004 default:
1005 /* 1005 /*
1006 * This case includes ESP and the No Next 1006 * This case includes ESP and the No Next
1007 * Header. In such cases going to the notify 1007 * Header. In such cases going to the notify
1008 * label does not have any meaning 1008 * label does not have any meaning
1009 * (i.e. ctlfunc will be NULL), but we go 1009 * (i.e. ctlfunc will be NULL), but we go
1010 * anyway since we might have to update 1010 * anyway since we might have to update
1011 * path MTU information. 1011 * path MTU information.
1012 */ 1012 */
1013 goto notify; 1013 goto notify;
1014 } 1014 }
1015 } 1015 }
1016 notify: 1016 notify:
1017 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 1017 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
1018 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 1018 sizeof(*icmp6) + sizeof(struct ip6_hdr));
1019 if (icmp6 == NULL) { 1019 if (icmp6 == NULL) {
1020 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 1020 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
1021 return (-1); 1021 return (-1);
1022 } 1022 }
1023 1023
1024 /* 1024 /*
1025 * retrieve parameters from the inner IPv6 header, and convert 1025 * retrieve parameters from the inner IPv6 header, and convert
1026 * them into sockaddr structures. 1026 * them into sockaddr structures.
1027 * XXX: there is no guarantee that the source or destination 1027 * XXX: there is no guarantee that the source or destination
1028 * addresses of the inner packet are in the same scope zone as 1028 * addresses of the inner packet are in the same scope zone as
1029 * the addresses of the icmp packet. But there is no other 1029 * the addresses of the icmp packet. But there is no other
1030 * way to determine the zone. 1030 * way to determine the zone.
1031 */ 1031 */
1032 eip6 = (struct ip6_hdr *)(icmp6 + 1); 1032 eip6 = (struct ip6_hdr *)(icmp6 + 1);
1033 1033
1034 sockaddr_in6_init(&icmp6dst, 1034 sockaddr_in6_init(&icmp6dst,
1035 (finaldst == NULL) ? &eip6->ip6_dst : finaldst, 0, 0, 0); 1035 (finaldst == NULL) ? &eip6->ip6_dst : finaldst, 0, 0, 0);
1036 if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL)) 1036 if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
1037 goto freeit; 1037 goto freeit;
1038 sockaddr_in6_init(&icmp6src, &eip6->ip6_src, 0, 0, 0); 1038 sockaddr_in6_init(&icmp6src, &eip6->ip6_src, 0, 0, 0);
1039 if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL)) 1039 if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL))
1040 goto freeit; 1040 goto freeit;
1041 icmp6src.sin6_flowinfo = 1041 icmp6src.sin6_flowinfo =
1042 (eip6->ip6_flow & IPV6_FLOWLABEL_MASK); 1042 (eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
1043 1043
1044 if (finaldst == NULL) 1044 if (finaldst == NULL)
1045 finaldst = &eip6->ip6_dst; 1045 finaldst = &eip6->ip6_dst;
1046 ip6cp.ip6c_m = m; 1046 ip6cp.ip6c_m = m;
1047 ip6cp.ip6c_icmp6 = icmp6; 1047 ip6cp.ip6c_icmp6 = icmp6;
1048 ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1); 1048 ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
1049 ip6cp.ip6c_off = eoff; 1049 ip6cp.ip6c_off = eoff;
1050 ip6cp.ip6c_finaldst = finaldst; 1050 ip6cp.ip6c_finaldst = finaldst;
1051 ip6cp.ip6c_src = &icmp6src; 1051 ip6cp.ip6c_src = &icmp6src;
1052 ip6cp.ip6c_nxt = nxt; 1052 ip6cp.ip6c_nxt = nxt;
1053 1053
1054 if (icmp6type == ICMP6_PACKET_TOO_BIG) { 1054 if (icmp6type == ICMP6_PACKET_TOO_BIG) {
1055 notifymtu = ntohl(icmp6->icmp6_mtu); 1055 notifymtu = ntohl(icmp6->icmp6_mtu);
1056 ip6cp.ip6c_cmdarg = (void *)&notifymtu; 1056 ip6cp.ip6c_cmdarg = (void *)&notifymtu;
1057 } 1057 }
1058 1058
1059 ctlfunc = (void (*)(int, struct sockaddr *, void *)) 1059 ctlfunc = (void (*)(int, struct sockaddr *, void *))
1060 (inet6sw[ip6_protox[nxt]].pr_ctlinput); 1060 (inet6sw[ip6_protox[nxt]].pr_ctlinput);
1061 if (ctlfunc) { 1061 if (ctlfunc) {
1062 (void) (*ctlfunc)(code, (struct sockaddr *)&icmp6dst, 1062 (void) (*ctlfunc)(code, (struct sockaddr *)&icmp6dst,
1063 &ip6cp); 1063 &ip6cp);
1064 } 1064 }
@@ -1760,1160 +1760,1193 @@ ni6_store_addrs(struct icmp6_nodeinfo *n @@ -1760,1160 +1760,1193 @@ ni6_store_addrs(struct icmp6_nodeinfo *n
1760 break; 1760 break;
1761 case IPV6_ADDR_SCOPE_SITELOCAL: 1761 case IPV6_ADDR_SCOPE_SITELOCAL:
1762 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0) 1762 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
1763 continue; 1763 continue;
1764 break; 1764 break;
1765 case IPV6_ADDR_SCOPE_GLOBAL: 1765 case IPV6_ADDR_SCOPE_GLOBAL:
1766 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0) 1766 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
1767 continue; 1767 continue;
1768 break; 1768 break;
1769 default: 1769 default:
1770 continue; 1770 continue;
1771 } 1771 }
1772 1772
1773 /* 1773 /*
1774 * check if anycast is okay. 1774 * check if anycast is okay.
1775 * XXX: just experimental. not in the spec. 1775 * XXX: just experimental. not in the spec.
1776 */ 1776 */
1777 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 && 1777 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1778 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) 1778 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1779 continue; 1779 continue;
1780 1780
1781 /* now we can copy the address */ 1781 /* now we can copy the address */
1782 if (resid < sizeof(struct in6_addr) + 1782 if (resid < sizeof(struct in6_addr) +
1783 sizeof(u_int32_t)) { 1783 sizeof(u_int32_t)) {
1784 /* 1784 /*
1785 * We give up much more copy. 1785 * We give up much more copy.
1786 * Set the truncate flag and return. 1786 * Set the truncate flag and return.
1787 */ 1787 */
1788 nni6->ni_flags |= NI_NODEADDR_FLAG_TRUNCATE; 1788 nni6->ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
1789 return (copied); 1789 return (copied);
1790 } 1790 }
1791 1791
1792 /* 1792 /*
1793 * Set the TTL of the address. 1793 * Set the TTL of the address.
1794 * The TTL value should be one of the following 1794 * The TTL value should be one of the following
1795 * according to the specification: 1795 * according to the specification:
1796 * 1796 *
1797 * 1. The remaining lifetime of a DHCP lease on the 1797 * 1. The remaining lifetime of a DHCP lease on the
1798 * address, or 1798 * address, or
1799 * 2. The remaining Valid Lifetime of a prefix from 1799 * 2. The remaining Valid Lifetime of a prefix from
1800 * which the address was derived through Stateless 1800 * which the address was derived through Stateless
1801 * Autoconfiguration. 1801 * Autoconfiguration.
1802 * 1802 *
1803 * Note that we currently do not support stateful 1803 * Note that we currently do not support stateful
1804 * address configuration by DHCPv6, so the former 1804 * address configuration by DHCPv6, so the former
1805 * case can't happen. 1805 * case can't happen.
1806 * 1806 *
1807 * TTL must be 2^31 > TTL >= 0. 1807 * TTL must be 2^31 > TTL >= 0.
1808 */ 1808 */
1809 if (ifa6->ia6_lifetime.ia6t_expire == 0) 1809 if (ifa6->ia6_lifetime.ia6t_expire == 0)
1810 ltime = ND6_INFINITE_LIFETIME; 1810 ltime = ND6_INFINITE_LIFETIME;
1811 else { 1811 else {
1812 if (ifa6->ia6_lifetime.ia6t_expire > 1812 if (ifa6->ia6_lifetime.ia6t_expire >
1813 time_second) 1813 time_second)
1814 ltime = ifa6->ia6_lifetime.ia6t_expire - 1814 ltime = ifa6->ia6_lifetime.ia6t_expire -
1815 time_second; 1815 time_second;
1816 else 1816 else
1817 ltime = 0; 1817 ltime = 0;
1818 } 1818 }
1819 if (ltime > 0x7fffffff) 1819 if (ltime > 0x7fffffff)
1820 ltime = 0x7fffffff; 1820 ltime = 0x7fffffff;
1821 ltime = htonl(ltime); 1821 ltime = htonl(ltime);
1822 1822
1823 bcopy(&ltime, cp, sizeof(u_int32_t)); 1823 bcopy(&ltime, cp, sizeof(u_int32_t));
1824 cp += sizeof(u_int32_t); 1824 cp += sizeof(u_int32_t);
1825 1825
1826 /* copy the address itself */ 1826 /* copy the address itself */
1827 bcopy(&ifa6->ia_addr.sin6_addr, cp, 1827 bcopy(&ifa6->ia_addr.sin6_addr, cp,
1828 sizeof(struct in6_addr)); 1828 sizeof(struct in6_addr));
1829 in6_clearscope((struct in6_addr *)cp); /* XXX */ 1829 in6_clearscope((struct in6_addr *)cp); /* XXX */
1830 cp += sizeof(struct in6_addr); 1830 cp += sizeof(struct in6_addr);
1831 1831
1832 resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t)); 1832 resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
1833 copied += (sizeof(struct in6_addr) + sizeof(u_int32_t)); 1833 copied += (sizeof(struct in6_addr) + sizeof(u_int32_t));
1834 } 1834 }
1835 if (ifp0) /* we need search only on the specified IF */ 1835 if (ifp0) /* we need search only on the specified IF */
1836 break; 1836 break;
1837 } 1837 }
1838 1838
1839 if (allow_deprecated == 0 && ifp_dep != NULL) { 1839 if (allow_deprecated == 0 && ifp_dep != NULL) {
1840 ifp = ifp_dep; 1840 ifp = ifp_dep;
1841 allow_deprecated = 1; 1841 allow_deprecated = 1;
1842 1842
1843 goto again; 1843 goto again;
1844 } 1844 }
1845 1845
1846 return (copied); 1846 return (copied);
1847} 1847}
1848 1848
1849/* 1849/*
1850 * XXX almost dup'ed code with rip6_input. 1850 * XXX almost dup'ed code with rip6_input.
1851 */ 1851 */
1852static int 1852static int
1853icmp6_rip6_input(struct mbuf **mp, int off) 1853icmp6_rip6_input(struct mbuf **mp, int off)
1854{ 1854{
1855 struct mbuf *m = *mp; 1855 struct mbuf *m = *mp;
1856 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1856 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1857 struct inpcb_hdr *inph; 1857 struct inpcb_hdr *inph;
1858 struct in6pcb *in6p; 1858 struct in6pcb *in6p;
1859 struct in6pcb *last = NULL; 1859 struct in6pcb *last = NULL;
1860 struct sockaddr_in6 rip6src; 1860 struct sockaddr_in6 rip6src;
1861 struct icmp6_hdr *icmp6; 1861 struct icmp6_hdr *icmp6;
1862 struct mbuf *opts = NULL; 1862 struct mbuf *opts = NULL;
1863 1863
1864 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); 1864 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
1865 if (icmp6 == NULL) { 1865 if (icmp6 == NULL) {
1866 /* m is already reclaimed */ 1866 /* m is already reclaimed */
1867 return IPPROTO_DONE; 1867 return IPPROTO_DONE;
1868 } 1868 }
1869 1869
1870 /* 1870 /*
1871 * XXX: the address may have embedded scope zone ID, which should be 1871 * XXX: the address may have embedded scope zone ID, which should be
1872 * hidden from applications. 1872 * hidden from applications.
1873 */ 1873 */
1874 sockaddr_in6_init(&rip6src, &ip6->ip6_src, 0, 0, 0); 1874 sockaddr_in6_init(&rip6src, &ip6->ip6_src, 0, 0, 0);
1875 if (sa6_recoverscope(&rip6src)) { 1875 if (sa6_recoverscope(&rip6src)) {
1876 m_freem(m); 1876 m_freem(m);
1877 return (IPPROTO_DONE); 1877 return (IPPROTO_DONE);
1878 } 1878 }
1879 1879
1880 TAILQ_FOREACH(inph, &raw6cbtable.inpt_queue, inph_queue) { 1880 TAILQ_FOREACH(inph, &raw6cbtable.inpt_queue, inph_queue) {
1881 in6p = (struct in6pcb *)inph; 1881 in6p = (struct in6pcb *)inph;
1882 if (in6p->in6p_af != AF_INET6) 1882 if (in6p->in6p_af != AF_INET6)
1883 continue; 1883 continue;
1884 if (in6p->in6p_ip6.ip6_nxt != IPPROTO_ICMPV6) 1884 if (in6p->in6p_ip6.ip6_nxt != IPPROTO_ICMPV6)
1885 continue; 1885 continue;
1886 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 1886 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1887 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 1887 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
1888 continue; 1888 continue;
1889 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 1889 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
1890 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 1890 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
1891 continue; 1891 continue;
1892 if (in6p->in6p_icmp6filt 1892 if (in6p->in6p_icmp6filt
1893 && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type, 1893 && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
1894 in6p->in6p_icmp6filt)) 1894 in6p->in6p_icmp6filt))
1895 continue; 1895 continue;
1896 if (last) { 1896 if (last) {
1897 struct mbuf *n; 1897 struct mbuf *n;
1898 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 1898 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
1899 if (last->in6p_flags & IN6P_CONTROLOPTS) 1899 if (last->in6p_flags & IN6P_CONTROLOPTS)
1900 ip6_savecontrol(last, &opts, ip6, n); 1900 ip6_savecontrol(last, &opts, ip6, n);
1901 /* strip intermediate headers */ 1901 /* strip intermediate headers */
1902 m_adj(n, off); 1902 m_adj(n, off);
1903 if (sbappendaddr(&last->in6p_socket->so_rcv, 1903 if (sbappendaddr(&last->in6p_socket->so_rcv,
1904 (struct sockaddr *)&rip6src, 1904 (struct sockaddr *)&rip6src,
1905 n, opts) == 0) { 1905 n, opts) == 0) {
1906 /* should notify about lost packet */ 1906 /* should notify about lost packet */
1907 m_freem(n); 1907 m_freem(n);
1908 if (opts) 1908 if (opts)
1909 m_freem(opts); 1909 m_freem(opts);
1910 } else 1910 } else
1911 sorwakeup(last->in6p_socket); 1911 sorwakeup(last->in6p_socket);
1912 opts = NULL; 1912 opts = NULL;
1913 } 1913 }
1914 } 1914 }
1915 last = in6p; 1915 last = in6p;
1916 } 1916 }
1917 if (last) { 1917 if (last) {
1918 if (last->in6p_flags & IN6P_CONTROLOPTS) 1918 if (last->in6p_flags & IN6P_CONTROLOPTS)
1919 ip6_savecontrol(last, &opts, ip6, m); 1919 ip6_savecontrol(last, &opts, ip6, m);
1920 /* strip intermediate headers */ 1920 /* strip intermediate headers */
1921 m_adj(m, off); 1921 m_adj(m, off);
1922 if (sbappendaddr(&last->in6p_socket->so_rcv, 1922 if (sbappendaddr(&last->in6p_socket->so_rcv,
1923 (struct sockaddr *)&rip6src, m, opts) == 0) { 1923 (struct sockaddr *)&rip6src, m, opts) == 0) {
1924 m_freem(m); 1924 m_freem(m);
1925 if (opts) 1925 if (opts)
1926 m_freem(opts); 1926 m_freem(opts);
1927 } else 1927 } else
1928 sorwakeup(last->in6p_socket); 1928 sorwakeup(last->in6p_socket);
1929 } else { 1929 } else {
1930 m_freem(m); 1930 m_freem(m);
1931 IP6_STATDEC(IP6_STAT_DELIVERED); 1931 IP6_STATDEC(IP6_STAT_DELIVERED);
1932 } 1932 }
1933 return IPPROTO_DONE; 1933 return IPPROTO_DONE;
1934} 1934}
1935 1935
1936/* 1936/*
1937 * Reflect the ip6 packet back to the source. 1937 * Reflect the ip6 packet back to the source.
1938 * OFF points to the icmp6 header, counted from the top of the mbuf. 1938 * OFF points to the icmp6 header, counted from the top of the mbuf.
1939 * 1939 *
1940 * Note: RFC 1885 required that an echo reply should be truncated if it 1940 * Note: RFC 1885 required that an echo reply should be truncated if it
1941 * did not fit in with (return) path MTU, and KAME code supported the 1941 * did not fit in with (return) path MTU, and KAME code supported the
1942 * behavior. However, as a clarification after the RFC, this limitation 1942 * behavior. However, as a clarification after the RFC, this limitation
1943 * was removed in a revised version of the spec, RFC 2463. We had kept the 1943 * was removed in a revised version of the spec, RFC 2463. We had kept the
1944 * old behavior, with a (non-default) ifdef block, while the new version of 1944 * old behavior, with a (non-default) ifdef block, while the new version of
1945 * the spec was an internet-draft status, and even after the new RFC was 1945 * the spec was an internet-draft status, and even after the new RFC was
1946 * published. But it would rather make sense to clean the obsoleted part 1946 * published. But it would rather make sense to clean the obsoleted part
1947 * up, and to make the code simpler at this stage. 1947 * up, and to make the code simpler at this stage.
1948 */ 1948 */
1949void 1949void
1950icmp6_reflect(struct mbuf *m, size_t off) 1950icmp6_reflect(struct mbuf *m, size_t off)
1951{ 1951{
1952 struct ip6_hdr *ip6; 1952 struct ip6_hdr *ip6;
1953 struct icmp6_hdr *icmp6; 1953 struct icmp6_hdr *icmp6;
1954 const struct in6_ifaddr *ia; 1954 const struct in6_ifaddr *ia;
1955 const struct ip6aux *ip6a; 1955 const struct ip6aux *ip6a;
1956 int plen; 1956 int plen;
1957 int type, code; 1957 int type, code;
1958 struct ifnet *outif = NULL; 1958 struct ifnet *outif = NULL;
1959 struct in6_addr origdst; 1959 struct in6_addr origdst;
1960 const struct in6_addr *src = NULL; 1960 const struct in6_addr *src = NULL;
1961 1961
1962 /* too short to reflect */ 1962 /* too short to reflect */
1963 if (off < sizeof(struct ip6_hdr)) { 1963 if (off < sizeof(struct ip6_hdr)) {
1964 nd6log((LOG_DEBUG, 1964 nd6log((LOG_DEBUG,
1965 "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n", 1965 "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
1966 (u_long)off, (u_long)sizeof(struct ip6_hdr), 1966 (u_long)off, (u_long)sizeof(struct ip6_hdr),
1967 __FILE__, __LINE__)); 1967 __FILE__, __LINE__));
1968 goto bad; 1968 goto bad;
1969 } 1969 }
1970 1970
1971 /* 1971 /*
1972 * If there are extra headers between IPv6 and ICMPv6, strip 1972 * If there are extra headers between IPv6 and ICMPv6, strip
1973 * off that header first. 1973 * off that header first.
1974 */ 1974 */
1975#ifdef DIAGNOSTIC 1975#ifdef DIAGNOSTIC
1976 if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN) 1976 if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)
1977 panic("assumption failed in icmp6_reflect"); 1977 panic("assumption failed in icmp6_reflect");
1978#endif 1978#endif
1979 if (off > sizeof(struct ip6_hdr)) { 1979 if (off > sizeof(struct ip6_hdr)) {
1980 size_t l; 1980 size_t l;
1981 struct ip6_hdr nip6; 1981 struct ip6_hdr nip6;
1982 1982
1983 l = off - sizeof(struct ip6_hdr); 1983 l = off - sizeof(struct ip6_hdr);
1984 m_copydata(m, 0, sizeof(nip6), (void *)&nip6); 1984 m_copydata(m, 0, sizeof(nip6), (void *)&nip6);
1985 m_adj(m, l); 1985 m_adj(m, l);
1986 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1986 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1987 if (m->m_len < l) { 1987 if (m->m_len < l) {
1988 if ((m = m_pullup(m, l)) == NULL) 1988 if ((m = m_pullup(m, l)) == NULL)
1989 return; 1989 return;
1990 } 1990 }
1991 bcopy((void *)&nip6, mtod(m, void *), sizeof(nip6)); 1991 bcopy((void *)&nip6, mtod(m, void *), sizeof(nip6));
1992 } else /* off == sizeof(struct ip6_hdr) */ { 1992 } else /* off == sizeof(struct ip6_hdr) */ {
1993 size_t l; 1993 size_t l;
1994 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1994 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
1995 if (m->m_len < l) { 1995 if (m->m_len < l) {
1996 if ((m = m_pullup(m, l)) == NULL) 1996 if ((m = m_pullup(m, l)) == NULL)
1997 return; 1997 return;
1998 } 1998 }
1999 } 1999 }
2000 plen = m->m_pkthdr.len - sizeof(struct ip6_hdr); 2000 plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
2001 ip6 = mtod(m, struct ip6_hdr *); 2001 ip6 = mtod(m, struct ip6_hdr *);
2002 ip6->ip6_nxt = IPPROTO_ICMPV6; 2002 ip6->ip6_nxt = IPPROTO_ICMPV6;
2003 icmp6 = (struct icmp6_hdr *)(ip6 + 1); 2003 icmp6 = (struct icmp6_hdr *)(ip6 + 1);
2004 type = icmp6->icmp6_type; /* keep type for statistics */ 2004 type = icmp6->icmp6_type; /* keep type for statistics */
2005 code = icmp6->icmp6_code; /* ditto. */ 2005 code = icmp6->icmp6_code; /* ditto. */
2006 2006
2007 origdst = ip6->ip6_dst; 2007 origdst = ip6->ip6_dst;
2008 /* 2008 /*
2009 * ip6_input() drops a packet if its src is multicast. 2009 * ip6_input() drops a packet if its src is multicast.
2010 * So, the src is never multicast. 2010 * So, the src is never multicast.
2011 */ 2011 */
2012 ip6->ip6_dst = ip6->ip6_src; 2012 ip6->ip6_dst = ip6->ip6_src;
2013 2013
2014 /* 2014 /*
2015 * If the incoming packet was addressed directly to us (i.e. unicast), 2015 * If the incoming packet was addressed directly to us (i.e. unicast),
2016 * use dst as the src for the reply. 2016 * use dst as the src for the reply.
2017 * The IN6_IFF_NOTREADY case should be VERY rare, but is possible 2017 * The IN6_IFF_NOTREADY case should be VERY rare, but is possible
2018 * (for example) when we encounter an error while forwarding procedure 2018 * (for example) when we encounter an error while forwarding procedure
2019 * destined to a duplicated address of ours. 2019 * destined to a duplicated address of ours.
2020 * Note that ip6_getdstifaddr() may fail if we are in an error handling 2020 * Note that ip6_getdstifaddr() may fail if we are in an error handling
2021 * procedure of an outgoing packet of our own, in which case we need 2021 * procedure of an outgoing packet of our own, in which case we need
2022 * to search in the ifaddr list. 2022 * to search in the ifaddr list.
2023 */ 2023 */
2024 if (IN6_IS_ADDR_MULTICAST(&origdst)) 2024 if (IN6_IS_ADDR_MULTICAST(&origdst))
2025 ; 2025 ;
2026 else if ((ip6a = ip6_getdstifaddr(m)) != NULL) { 2026 else if ((ip6a = ip6_getdstifaddr(m)) != NULL) {
2027 if ((ip6a->ip6a_flags & 2027 if ((ip6a->ip6a_flags &
2028 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) 2028 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0)
2029 src = &ip6a->ip6a_src; 2029 src = &ip6a->ip6a_src;
2030 } else { 2030 } else {
2031 union { 2031 union {
2032 struct sockaddr_in6 sin6; 2032 struct sockaddr_in6 sin6;
2033 struct sockaddr sa; 2033 struct sockaddr sa;
2034 } u; 2034 } u;
2035 2035
2036 sockaddr_in6_init(&u.sin6, &origdst, 0, 0, 0); 2036 sockaddr_in6_init(&u.sin6, &origdst, 0, 0, 0);
2037 2037
2038 ia = (struct in6_ifaddr *)ifa_ifwithaddr(&u.sa); 2038 ia = (struct in6_ifaddr *)ifa_ifwithaddr(&u.sa);
2039 2039
2040 if (ia == NULL) 2040 if (ia == NULL)
2041 ; 2041 ;
2042 else if ((ia->ia6_flags & 2042 else if ((ia->ia6_flags &
2043 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) 2043 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0)
2044 src = &ia->ia_addr.sin6_addr; 2044 src = &ia->ia_addr.sin6_addr;
2045 } 2045 }
2046 2046
2047 if (src == NULL) { 2047 if (src == NULL) {
2048 int e; 2048 int e;
2049 struct sockaddr_in6 sin6; 2049 struct sockaddr_in6 sin6;
2050 struct route ro; 2050 struct route ro;
2051 2051
2052 /* 2052 /*
2053 * This case matches to multicasts, our anycast, or unicasts 2053 * This case matches to multicasts, our anycast, or unicasts
2054 * that we do not own. Select a source address based on the 2054 * that we do not own. Select a source address based on the
2055 * source address of the erroneous packet. 2055 * source address of the erroneous packet.
2056 */ 2056 */
2057 /* zone ID should be embedded */ 2057 /* zone ID should be embedded */
2058 sockaddr_in6_init(&sin6, &ip6->ip6_dst, 0, 0, 0); 2058 sockaddr_in6_init(&sin6, &ip6->ip6_dst, 0, 0, 0);
2059 2059
2060 memset(&ro, 0, sizeof(ro)); 2060 memset(&ro, 0, sizeof(ro));
2061 src = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, &outif, &e); 2061 src = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, &outif, &e);
2062 rtcache_free(&ro); 2062 rtcache_free(&ro);
2063 if (src == NULL) { 2063 if (src == NULL) {
2064 nd6log((LOG_DEBUG, 2064 nd6log((LOG_DEBUG,
2065 "icmp6_reflect: source can't be determined: " 2065 "icmp6_reflect: source can't be determined: "
2066 "dst=%s, error=%d\n", 2066 "dst=%s, error=%d\n",
2067 ip6_sprintf(&sin6.sin6_addr), e)); 2067 ip6_sprintf(&sin6.sin6_addr), e));
2068 goto bad; 2068 goto bad;
2069 } 2069 }
2070 } 2070 }
2071 2071
2072 ip6->ip6_src = *src; 2072 ip6->ip6_src = *src;
2073 ip6->ip6_flow = 0; 2073 ip6->ip6_flow = 0;
2074 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 2074 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2075 ip6->ip6_vfc |= IPV6_VERSION; 2075 ip6->ip6_vfc |= IPV6_VERSION;
2076 ip6->ip6_nxt = IPPROTO_ICMPV6; 2076 ip6->ip6_nxt = IPPROTO_ICMPV6;
2077 if (m->m_pkthdr.rcvif) { 2077 if (m->m_pkthdr.rcvif) {
2078 /* XXX: This may not be the outgoing interface */ 2078 /* XXX: This may not be the outgoing interface */
2079 ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim; 2079 ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
2080 } else 2080 } else
2081 ip6->ip6_hlim = ip6_defhlim; 2081 ip6->ip6_hlim = ip6_defhlim;
2082 2082
2083 m->m_pkthdr.csum_flags = 0; 2083 m->m_pkthdr.csum_flags = 0;
2084 icmp6->icmp6_cksum = 0; 2084 icmp6->icmp6_cksum = 0;
2085 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6, 2085 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
2086 sizeof(struct ip6_hdr), plen); 2086 sizeof(struct ip6_hdr), plen);
2087 2087
2088 /* 2088 /*
2089 * XXX option handling 2089 * XXX option handling
2090 */ 2090 */
2091 2091
2092 m->m_flags &= ~(M_BCAST|M_MCAST); 2092 m->m_flags &= ~(M_BCAST|M_MCAST);
2093 2093
2094 /* 2094 /*
2095 * To avoid a "too big" situation at an intermediate router 2095 * To avoid a "too big" situation at an intermediate router
2096 * and the path MTU discovery process, specify the IPV6_MINMTU flag. 2096 * and the path MTU discovery process, specify the IPV6_MINMTU flag.
2097 * Note that only echo and node information replies are affected, 2097 * Note that only echo and node information replies are affected,
2098 * since the length of ICMP6 errors is limited to the minimum MTU. 2098 * since the length of ICMP6 errors is limited to the minimum MTU.
2099 */ 2099 */
2100 if (ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL, &outif) != 0 && 2100 if (ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL, &outif) != 0 &&
2101 outif) 2101 outif)
2102 icmp6_ifstat_inc(outif, ifs6_out_error); 2102 icmp6_ifstat_inc(outif, ifs6_out_error);
2103 2103
2104 if (outif) 2104 if (outif)
2105 icmp6_ifoutstat_inc(outif, type, code); 2105 icmp6_ifoutstat_inc(outif, type, code);
2106 2106
2107 return; 2107 return;
2108 2108
2109 bad: 2109 bad:
2110 m_freem(m); 2110 m_freem(m);
2111 return; 2111 return;
2112} 2112}
2113 2113
2114static const char * 2114static const char *
2115icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6,  2115icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6,
2116 struct in6_addr *tgt6) 2116 struct in6_addr *tgt6)
2117{ 2117{
2118 static char buf[1024]; 2118 static char buf[1024];
2119 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)", 2119 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
2120 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6)); 2120 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6));
2121 return buf; 2121 return buf;
2122} 2122}
2123 2123
2124void 2124void
2125icmp6_redirect_input(struct mbuf *m, int off) 2125icmp6_redirect_input(struct mbuf *m, int off)
2126{ 2126{
2127 struct ifnet *ifp = m->m_pkthdr.rcvif; 2127 struct ifnet *ifp = m->m_pkthdr.rcvif;
2128 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 2128 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
2129 struct nd_redirect *nd_rd; 2129 struct nd_redirect *nd_rd;
2130 int icmp6len = ntohs(ip6->ip6_plen); 2130 int icmp6len = ntohs(ip6->ip6_plen);
2131 char *lladdr = NULL; 2131 char *lladdr = NULL;
2132 int lladdrlen = 0; 2132 int lladdrlen = 0;
2133 struct rtentry *rt = NULL; 2133 struct rtentry *rt = NULL;
2134 int is_router; 2134 int is_router;
2135 int is_onlink; 2135 int is_onlink;
2136 struct in6_addr src6 = ip6->ip6_src; 2136 struct in6_addr src6 = ip6->ip6_src;
2137 struct in6_addr redtgt6; 2137 struct in6_addr redtgt6;
2138 struct in6_addr reddst6; 2138 struct in6_addr reddst6;
2139 union nd_opts ndopts; 2139 union nd_opts ndopts;
2140 2140
2141 if (!ifp) 2141 if (!ifp)
2142 return; 2142 return;
2143 2143
2144 /* XXX if we are router, we don't update route by icmp6 redirect */ 2144 /* XXX if we are router, we don't update route by icmp6 redirect */
2145 if (ip6_forwarding) 2145 if (ip6_forwarding)
2146 goto freeit; 2146 goto freeit;
2147 if (!icmp6_rediraccept) 2147 if (!icmp6_rediraccept)
2148 goto freeit; 2148 goto freeit;
2149 2149
2150 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); 2150 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
2151 if (nd_rd == NULL) { 2151 if (nd_rd == NULL) {
2152 ICMP6_STATINC(ICMP6_STAT_TOOSHORT); 2152 ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
2153 return; 2153 return;
2154 } 2154 }
2155 redtgt6 = nd_rd->nd_rd_target; 2155 redtgt6 = nd_rd->nd_rd_target;
2156 reddst6 = nd_rd->nd_rd_dst; 2156 reddst6 = nd_rd->nd_rd_dst;
2157 2157
2158 if (in6_setscope(&redtgt6, m->m_pkthdr.rcvif, NULL) || 2158 if (in6_setscope(&redtgt6, m->m_pkthdr.rcvif, NULL) ||
2159 in6_setscope(&reddst6, m->m_pkthdr.rcvif, NULL)) { 2159 in6_setscope(&reddst6, m->m_pkthdr.rcvif, NULL)) {
2160 goto freeit; 2160 goto freeit;
2161 } 2161 }
2162 2162
2163 /* validation */ 2163 /* validation */
2164 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { 2164 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
2165 nd6log((LOG_ERR, 2165 nd6log((LOG_ERR,
2166 "ICMP6 redirect sent from %s rejected; " 2166 "ICMP6 redirect sent from %s rejected; "
2167 "must be from linklocal\n", ip6_sprintf(&src6))); 2167 "must be from linklocal\n", ip6_sprintf(&src6)));
2168 goto bad; 2168 goto bad;
2169 } 2169 }
2170 if (ip6->ip6_hlim != 255) { 2170 if (ip6->ip6_hlim != 255) {
2171 nd6log((LOG_ERR, 2171 nd6log((LOG_ERR,
2172 "ICMP6 redirect sent from %s rejected; " 2172 "ICMP6 redirect sent from %s rejected; "
2173 "hlim=%d (must be 255)\n", 2173 "hlim=%d (must be 255)\n",
2174 ip6_sprintf(&src6), ip6->ip6_hlim)); 2174 ip6_sprintf(&src6), ip6->ip6_hlim));
2175 goto bad; 2175 goto bad;
2176 } 2176 }
2177 { 2177 {
2178 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ 2178 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
2179 struct sockaddr_in6 sin6; 2179 struct sockaddr_in6 sin6;
2180 struct in6_addr *gw6; 2180 struct in6_addr *gw6;
2181 2181
2182 sockaddr_in6_init(&sin6, &reddst6, 0, 0, 0); 2182 sockaddr_in6_init(&sin6, &reddst6, 0, 0, 0);
2183 rt = rtalloc1((struct sockaddr *)&sin6, 0); 2183 rt = rtalloc1((struct sockaddr *)&sin6, 0);
2184 if (rt) { 2184 if (rt) {
2185 if (rt->rt_gateway == NULL || 2185 if (rt->rt_gateway == NULL ||
2186 rt->rt_gateway->sa_family != AF_INET6) { 2186 rt->rt_gateway->sa_family != AF_INET6) {
2187 nd6log((LOG_ERR, 2187 nd6log((LOG_ERR,
2188 "ICMP6 redirect rejected; no route " 2188 "ICMP6 redirect rejected; no route "
2189 "with inet6 gateway found for redirect dst: %s\n", 2189 "with inet6 gateway found for redirect dst: %s\n",
2190 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2190 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2191 rtfree(rt); 2191 rtfree(rt);
2192 goto bad; 2192 goto bad;
2193 } 2193 }
2194 2194
2195 gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr); 2195 gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr);
2196 if (memcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { 2196 if (memcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
2197 nd6log((LOG_ERR, 2197 nd6log((LOG_ERR,
2198 "ICMP6 redirect rejected; " 2198 "ICMP6 redirect rejected; "
2199 "not equal to gw-for-src=%s (must be same): " 2199 "not equal to gw-for-src=%s (must be same): "
2200 "%s\n", 2200 "%s\n",
2201 ip6_sprintf(gw6), 2201 ip6_sprintf(gw6),
2202 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2202 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2203 rtfree(rt); 2203 rtfree(rt);
2204 goto bad; 2204 goto bad;
2205 } 2205 }
2206 } else { 2206 } else {
2207 nd6log((LOG_ERR, 2207 nd6log((LOG_ERR,
2208 "ICMP6 redirect rejected; " 2208 "ICMP6 redirect rejected; "
2209 "no route found for redirect dst: %s\n", 2209 "no route found for redirect dst: %s\n",
2210 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2210 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2211 goto bad; 2211 goto bad;
2212 } 2212 }
2213 rtfree(rt); 2213 rtfree(rt);
2214 rt = NULL; 2214 rt = NULL;
2215 } 2215 }
2216 if (IN6_IS_ADDR_MULTICAST(&reddst6)) { 2216 if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
2217 nd6log((LOG_ERR, 2217 nd6log((LOG_ERR,
2218 "ICMP6 redirect rejected; " 2218 "ICMP6 redirect rejected; "
2219 "redirect dst must be unicast: %s\n", 2219 "redirect dst must be unicast: %s\n",
2220 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2220 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2221 goto bad; 2221 goto bad;
2222 } 2222 }
2223 2223
2224 is_router = is_onlink = 0; 2224 is_router = is_onlink = 0;
2225 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 2225 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
2226 is_router = 1; /* router case */ 2226 is_router = 1; /* router case */
2227 if (memcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) 2227 if (memcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0)
2228 is_onlink = 1; /* on-link destination case */ 2228 is_onlink = 1; /* on-link destination case */
2229 if (!is_router && !is_onlink) { 2229 if (!is_router && !is_onlink) {
2230 nd6log((LOG_ERR, 2230 nd6log((LOG_ERR,
2231 "ICMP6 redirect rejected; " 2231 "ICMP6 redirect rejected; "
2232 "neither router case nor onlink case: %s\n", 2232 "neither router case nor onlink case: %s\n",
2233 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2233 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2234 goto bad; 2234 goto bad;
2235 } 2235 }
2236 /* validation passed */ 2236 /* validation passed */
2237 2237
2238 icmp6len -= sizeof(*nd_rd); 2238 icmp6len -= sizeof(*nd_rd);
2239 nd6_option_init(nd_rd + 1, icmp6len, &ndopts); 2239 nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
2240 if (nd6_options(&ndopts) < 0) { 2240 if (nd6_options(&ndopts) < 0) {
2241 nd6log((LOG_INFO, "icmp6_redirect_input: " 2241 nd6log((LOG_INFO, "icmp6_redirect_input: "
2242 "invalid ND option, rejected: %s\n", 2242 "invalid ND option, rejected: %s\n",
2243 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2243 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2244 /* nd6_options have incremented stats */ 2244 /* nd6_options have incremented stats */
2245 goto freeit; 2245 goto freeit;
2246 } 2246 }
2247 2247
2248 if (ndopts.nd_opts_tgt_lladdr) { 2248 if (ndopts.nd_opts_tgt_lladdr) {
2249 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 2249 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
2250 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 2250 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
2251 } 2251 }
2252 2252
2253 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 2253 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
2254 nd6log((LOG_INFO, 2254 nd6log((LOG_INFO,
2255 "icmp6_redirect_input: lladdrlen mismatch for %s " 2255 "icmp6_redirect_input: lladdrlen mismatch for %s "
2256 "(if %d, icmp6 packet %d): %s\n", 2256 "(if %d, icmp6 packet %d): %s\n",
2257 ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2, 2257 ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
2258 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2258 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
2259 goto bad; 2259 goto bad;
2260 } 2260 }
2261 2261
2262 /* RFC 2461 8.3 */ 2262 /* RFC 2461 8.3 */
2263 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, 2263 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
2264 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); 2264 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
2265 2265
2266 if (!is_onlink) { /* better router case. perform rtredirect. */ 2266 if (!is_onlink) { /* better router case. perform rtredirect. */
2267 /* perform rtredirect */ 2267 /* perform rtredirect */
2268 struct sockaddr_in6 sdst; 2268 struct sockaddr_in6 sdst;
2269 struct sockaddr_in6 sgw; 2269 struct sockaddr_in6 sgw;
2270 struct sockaddr_in6 ssrc; 2270 struct sockaddr_in6 ssrc;
2271 unsigned long rtcount; 2271 unsigned long rtcount;
2272 struct rtentry *newrt = NULL; 2272 struct rtentry *newrt = NULL;
2273 2273
2274 /* 2274 /*
2275 * do not install redirect route, if the number of entries 2275 * do not install redirect route, if the number of entries
2276 * is too much (> hiwat). note that, the node (= host) will 2276 * is too much (> hiwat). note that, the node (= host) will
2277 * work just fine even if we do not install redirect route 2277 * work just fine even if we do not install redirect route
2278 * (there will be additional hops, though). 2278 * (there will be additional hops, though).
2279 */ 2279 */
2280 rtcount = rt_timer_count(icmp6_redirect_timeout_q); 2280 rtcount = rt_timer_count(icmp6_redirect_timeout_q);
2281 if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes) 2281 if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes)
2282 goto freeit; 2282 goto freeit;
2283 if (0 <= icmp6_redirect_hiwat && rtcount > icmp6_redirect_hiwat) 2283 if (0 <= icmp6_redirect_hiwat && rtcount > icmp6_redirect_hiwat)
2284 return; 2284 return;
2285 else if (0 <= icmp6_redirect_lowat && 2285 else if (0 <= icmp6_redirect_lowat &&
2286 rtcount > icmp6_redirect_lowat) { 2286 rtcount > icmp6_redirect_lowat) {
2287 /* 2287 /*
2288 * XXX nuke a victim, install the new one. 2288 * XXX nuke a victim, install the new one.
2289 */ 2289 */
2290 } 2290 }
2291 2291
2292 memset(&sdst, 0, sizeof(sdst)); 2292 memset(&sdst, 0, sizeof(sdst));
2293 memset(&sgw, 0, sizeof(sgw)); 2293 memset(&sgw, 0, sizeof(sgw));
2294 memset(&ssrc, 0, sizeof(ssrc)); 2294 memset(&ssrc, 0, sizeof(ssrc));
2295 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; 2295 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6;
2296 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = 2296 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len =
2297 sizeof(struct sockaddr_in6); 2297 sizeof(struct sockaddr_in6);
2298 bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr)); 2298 bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
2299 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); 2299 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
2300 bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr)); 2300 bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
2301 rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw, 2301 rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
2302 NULL, RTF_GATEWAY | RTF_HOST, 2302 NULL, RTF_GATEWAY | RTF_HOST,
2303 (struct sockaddr *)&ssrc, 2303 (struct sockaddr *)&ssrc,
2304 &newrt); 2304 &newrt);
2305 2305
2306 if (newrt) { 2306 if (newrt) {
2307 (void)rt_timer_add(newrt, icmp6_redirect_timeout, 2307 (void)rt_timer_add(newrt, icmp6_redirect_timeout,
2308 icmp6_redirect_timeout_q); 2308 icmp6_redirect_timeout_q);
2309 rtfree(newrt); 2309 rtfree(newrt);
2310 } 2310 }
2311 } 2311 }
2312 /* finally update cached route in each socket via pfctlinput */ 2312 /* finally update cached route in each socket via pfctlinput */
2313 { 2313 {
2314 struct sockaddr_in6 sdst; 2314 struct sockaddr_in6 sdst;
2315 2315
2316 sockaddr_in6_init(&sdst, &reddst6, 0, 0, 0); 2316 sockaddr_in6_init(&sdst, &reddst6, 0, 0, 0);
2317 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst); 2317 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
2318#if defined(IPSEC) 2318#if defined(IPSEC)
2319 if (ipsec_used) 2319 if (ipsec_used)
2320 key_sa_routechange((struct sockaddr *)&sdst); 2320 key_sa_routechange((struct sockaddr *)&sdst);
2321#endif 2321#endif
2322 } 2322 }
2323 2323
2324 freeit: 2324 freeit:
2325 m_freem(m); 2325 m_freem(m);
2326 return; 2326 return;
2327 2327
2328 bad: 2328 bad:
2329 ICMP6_STATINC(ICMP6_STAT_BADREDIRECT); 2329 ICMP6_STATINC(ICMP6_STAT_BADREDIRECT);
2330 m_freem(m); 2330 m_freem(m);
2331} 2331}
2332 2332
2333void 2333void
2334icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) 2334icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
2335{ 2335{
2336 struct ifnet *ifp; /* my outgoing interface */ 2336 struct ifnet *ifp; /* my outgoing interface */
2337 struct in6_addr *ifp_ll6; 2337 struct in6_addr *ifp_ll6;
2338 struct in6_addr *nexthop; 2338 struct in6_addr *nexthop;
2339 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */ 2339 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */
2340 struct mbuf *m = NULL; /* newly allocated one */ 2340 struct mbuf *m = NULL; /* newly allocated one */
2341 struct ip6_hdr *ip6; /* m as struct ip6_hdr */ 2341 struct ip6_hdr *ip6; /* m as struct ip6_hdr */
2342 struct nd_redirect *nd_rd; 2342 struct nd_redirect *nd_rd;
2343 size_t maxlen; 2343 size_t maxlen;
2344 u_char *p; 2344 u_char *p;
2345 struct sockaddr_in6 src_sa; 2345 struct sockaddr_in6 src_sa;
2346 2346
2347 icmp6_errcount(ICMP6_STAT_OUTERRHIST, ND_REDIRECT, 0); 2347 icmp6_errcount(ICMP6_STAT_OUTERRHIST, ND_REDIRECT, 0);
2348 2348
2349 /* if we are not router, we don't send icmp6 redirect */ 2349 /* if we are not router, we don't send icmp6 redirect */
2350 if (!ip6_forwarding) 2350 if (!ip6_forwarding)
2351 goto fail; 2351 goto fail;
2352 2352
2353 /* sanity check */ 2353 /* sanity check */
2354 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp)) 2354 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
2355 goto fail; 2355 goto fail;
2356 2356
2357 /* 2357 /*
2358 * Address check: 2358 * Address check:
2359 * the source address must identify a neighbor, and 2359 * the source address must identify a neighbor, and
2360 * the destination address must not be a multicast address 2360 * the destination address must not be a multicast address
2361 * [RFC 2461, sec 8.2] 2361 * [RFC 2461, sec 8.2]
2362 */ 2362 */
2363 sip6 = mtod(m0, struct ip6_hdr *); 2363 sip6 = mtod(m0, struct ip6_hdr *);
2364 sockaddr_in6_init(&src_sa, &sip6->ip6_src, 0, 0, 0); 2364 sockaddr_in6_init(&src_sa, &sip6->ip6_src, 0, 0, 0);
2365 if (nd6_is_addr_neighbor(&src_sa, ifp) == 0) 2365 if (nd6_is_addr_neighbor(&src_sa, ifp) == 0)
2366 goto fail; 2366 goto fail;
2367 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) 2367 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
2368 goto fail; /* what should we do here? */ 2368 goto fail; /* what should we do here? */
2369 2369
2370 /* rate limit */ 2370 /* rate limit */
2371 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) 2371 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0))
2372 goto fail; 2372 goto fail;
2373 2373
2374 /* 2374 /*
2375 * Since we are going to append up to 1280 bytes (= IPV6_MMTU), 2375 * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
2376 * we almost always ask for an mbuf cluster for simplicity. 2376 * we almost always ask for an mbuf cluster for simplicity.
2377 * (MHLEN < IPV6_MMTU is almost always true) 2377 * (MHLEN < IPV6_MMTU is almost always true)
2378 */ 2378 */
2379 MGETHDR(m, M_DONTWAIT, MT_HEADER); 2379 MGETHDR(m, M_DONTWAIT, MT_HEADER);
2380 if (m && IPV6_MMTU >= MHLEN) { 2380 if (m && IPV6_MMTU >= MHLEN) {
2381#if IPV6_MMTU >= MCLBYTES 2381#if IPV6_MMTU >= MCLBYTES
2382 _MCLGET(m, mcl_cache, IPV6_MMTU, M_DONTWAIT); 2382 _MCLGET(m, mcl_cache, IPV6_MMTU, M_DONTWAIT);
2383#else 2383#else
2384 MCLGET(m, M_DONTWAIT); 2384 MCLGET(m, M_DONTWAIT);
2385#endif 2385#endif
2386 } 2386 }
2387 2387
2388 if (!m) 2388 if (!m)
2389 goto fail; 2389 goto fail;
2390 m->m_pkthdr.rcvif = NULL; 2390 m->m_pkthdr.rcvif = NULL;
2391 m->m_len = 0; 2391 m->m_len = 0;
2392 maxlen = M_TRAILINGSPACE(m); 2392 maxlen = M_TRAILINGSPACE(m);
2393 maxlen = min(IPV6_MMTU, maxlen); 2393 maxlen = min(IPV6_MMTU, maxlen);
2394 /* just for safety */ 2394 /* just for safety */
2395 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 2395 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
2396 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) { 2396 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
2397 goto fail; 2397 goto fail;
2398 } 2398 }
2399 2399
2400 { 2400 {
2401 /* get ip6 linklocal address for ifp(my outgoing interface). */ 2401 /* get ip6 linklocal address for ifp(my outgoing interface). */
2402 struct in6_ifaddr *ia; 2402 struct in6_ifaddr *ia;
2403 if ((ia = in6ifa_ifpforlinklocal(ifp, 2403 if ((ia = in6ifa_ifpforlinklocal(ifp,
2404 IN6_IFF_NOTREADY| 2404 IN6_IFF_NOTREADY|
2405 IN6_IFF_ANYCAST)) == NULL) 2405 IN6_IFF_ANYCAST)) == NULL)
2406 goto fail; 2406 goto fail;
2407 ifp_ll6 = &ia->ia_addr.sin6_addr; 2407 ifp_ll6 = &ia->ia_addr.sin6_addr;
2408 } 2408 }
2409 2409
2410 /* get ip6 linklocal address for the router. */ 2410 /* get ip6 linklocal address for the router. */
2411 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) { 2411 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
2412 struct sockaddr_in6 *sin6; 2412 struct sockaddr_in6 *sin6;
2413 sin6 = (struct sockaddr_in6 *)rt->rt_gateway; 2413 sin6 = (struct sockaddr_in6 *)rt->rt_gateway;
2414 nexthop = &sin6->sin6_addr; 2414 nexthop = &sin6->sin6_addr;
2415 if (!IN6_IS_ADDR_LINKLOCAL(nexthop)) 2415 if (!IN6_IS_ADDR_LINKLOCAL(nexthop))
2416 nexthop = NULL; 2416 nexthop = NULL;
2417 } else 2417 } else
2418 nexthop = NULL; 2418 nexthop = NULL;
2419 2419
2420 /* ip6 */ 2420 /* ip6 */
2421 ip6 = mtod(m, struct ip6_hdr *); 2421 ip6 = mtod(m, struct ip6_hdr *);
2422 ip6->ip6_flow = 0; 2422 ip6->ip6_flow = 0;
2423 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 2423 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2424 ip6->ip6_vfc |= IPV6_VERSION; 2424 ip6->ip6_vfc |= IPV6_VERSION;
2425 /* ip6->ip6_plen will be set later */ 2425 /* ip6->ip6_plen will be set later */
2426 ip6->ip6_nxt = IPPROTO_ICMPV6; 2426 ip6->ip6_nxt = IPPROTO_ICMPV6;
2427 ip6->ip6_hlim = 255; 2427 ip6->ip6_hlim = 255;
2428 /* ip6->ip6_src must be linklocal addr for my outgoing if. */ 2428 /* ip6->ip6_src must be linklocal addr for my outgoing if. */
2429 bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr)); 2429 bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
2430 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr)); 2430 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
2431 2431
2432 /* ND Redirect */ 2432 /* ND Redirect */
2433 nd_rd = (struct nd_redirect *)(ip6 + 1); 2433 nd_rd = (struct nd_redirect *)(ip6 + 1);
2434 nd_rd->nd_rd_type = ND_REDIRECT; 2434 nd_rd->nd_rd_type = ND_REDIRECT;
2435 nd_rd->nd_rd_code = 0; 2435 nd_rd->nd_rd_code = 0;
2436 nd_rd->nd_rd_reserved = 0; 2436 nd_rd->nd_rd_reserved = 0;
2437 if (rt->rt_flags & RTF_GATEWAY) { 2437 if (rt->rt_flags & RTF_GATEWAY) {
2438 /* 2438 /*
2439 * nd_rd->nd_rd_target must be a link-local address in 2439 * nd_rd->nd_rd_target must be a link-local address in
2440 * better router cases. 2440 * better router cases.
2441 */ 2441 */
2442 if (!nexthop) 2442 if (!nexthop)
2443 goto fail; 2443 goto fail;
2444 bcopy(nexthop, &nd_rd->nd_rd_target, 2444 bcopy(nexthop, &nd_rd->nd_rd_target,
2445 sizeof(nd_rd->nd_rd_target)); 2445 sizeof(nd_rd->nd_rd_target));
2446 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 2446 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2447 sizeof(nd_rd->nd_rd_dst)); 2447 sizeof(nd_rd->nd_rd_dst));
2448 } else { 2448 } else {
2449 /* make sure redtgt == reddst */ 2449 /* make sure redtgt == reddst */
2450 nexthop = &sip6->ip6_dst; 2450 nexthop = &sip6->ip6_dst;
2451 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target, 2451 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
2452 sizeof(nd_rd->nd_rd_target)); 2452 sizeof(nd_rd->nd_rd_target));
2453 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 2453 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
2454 sizeof(nd_rd->nd_rd_dst)); 2454 sizeof(nd_rd->nd_rd_dst));
2455 } 2455 }
2456 2456
2457 p = (u_char *)(nd_rd + 1); 2457 p = (u_char *)(nd_rd + 1);
2458 2458
2459 { 2459 {
2460 /* target lladdr option */ 2460 /* target lladdr option */
2461 struct rtentry *rt_nexthop = NULL; 2461 struct rtentry *rt_nexthop = NULL;
2462 int len; 2462 int len;
2463 const struct sockaddr_dl *sdl; 2463 const struct sockaddr_dl *sdl;
2464 struct nd_opt_hdr *nd_opt; 2464 struct nd_opt_hdr *nd_opt;
2465 char *lladdr; 2465 char *lladdr;
2466 2466
2467 rt_nexthop = nd6_lookup(nexthop, 0, ifp); 2467 rt_nexthop = nd6_lookup(nexthop, 0, ifp);
2468 if (!rt_nexthop) 2468 if (!rt_nexthop)
2469 goto nolladdropt; 2469 goto nolladdropt;
2470 len = sizeof(*nd_opt) + ifp->if_addrlen; 2470 len = sizeof(*nd_opt) + ifp->if_addrlen;
2471 len = (len + 7) & ~7; /* round by 8 */ 2471 len = (len + 7) & ~7; /* round by 8 */
2472 /* safety check */ 2472 /* safety check */
2473 if (len + (p - (u_char *)ip6) > maxlen) 2473 if (len + (p - (u_char *)ip6) > maxlen)
2474 goto nolladdropt; 2474 goto nolladdropt;
2475 if (!(rt_nexthop->rt_flags & RTF_GATEWAY) && 2475 if (!(rt_nexthop->rt_flags & RTF_GATEWAY) &&
2476 (rt_nexthop->rt_flags & RTF_LLINFO) && 2476 (rt_nexthop->rt_flags & RTF_LLINFO) &&
2477 (rt_nexthop->rt_gateway->sa_family == AF_LINK) && 2477 (rt_nexthop->rt_gateway->sa_family == AF_LINK) &&
2478 (sdl = satocsdl(rt_nexthop->rt_gateway)) && 2478 (sdl = satocsdl(rt_nexthop->rt_gateway)) &&
2479 sdl->sdl_alen) { 2479 sdl->sdl_alen) {
2480 nd_opt = (struct nd_opt_hdr *)p; 2480 nd_opt = (struct nd_opt_hdr *)p;
2481 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; 2481 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
2482 nd_opt->nd_opt_len = len >> 3; 2482 nd_opt->nd_opt_len = len >> 3;
2483 lladdr = (char *)(nd_opt + 1); 2483 lladdr = (char *)(nd_opt + 1);
2484 memcpy(lladdr, CLLADDR(sdl), ifp->if_addrlen); 2484 memcpy(lladdr, CLLADDR(sdl), ifp->if_addrlen);
2485 p += len; 2485 p += len;
2486 } 2486 }
2487 } 2487 }
2488 nolladdropt:; 2488 nolladdropt:;
2489 2489
2490 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 2490 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2491 2491
2492 /* just to be safe */ 2492 /* just to be safe */
2493 if (m0->m_flags & M_DECRYPTED) 2493 if (m0->m_flags & M_DECRYPTED)
2494 goto noredhdropt; 2494 goto noredhdropt;
2495 if (p - (u_char *)ip6 > maxlen) 2495 if (p - (u_char *)ip6 > maxlen)
2496 goto noredhdropt; 2496 goto noredhdropt;
2497 2497
2498 { 2498 {
2499 /* redirected header option */ 2499 /* redirected header option */
2500 int len; 2500 int len;
2501 struct nd_opt_rd_hdr *nd_opt_rh; 2501 struct nd_opt_rd_hdr *nd_opt_rh;
2502 2502
2503 /* 2503 /*
2504 * compute the maximum size for icmp6 redirect header option. 2504 * compute the maximum size for icmp6 redirect header option.
2505 * XXX room for auth header? 2505 * XXX room for auth header?
2506 */ 2506 */
2507 len = maxlen - (p - (u_char *)ip6); 2507 len = maxlen - (p - (u_char *)ip6);
2508 len &= ~7; 2508 len &= ~7;
2509 2509
2510 /* 2510 /*
2511 * Redirected header option spec (RFC2461 4.6.3) talks nothing 2511 * Redirected header option spec (RFC2461 4.6.3) talks nothing
2512 * about padding/truncate rule for the original IP packet. 2512 * about padding/truncate rule for the original IP packet.
2513 * From the discussion on IPv6imp in Feb 1999, 2513 * From the discussion on IPv6imp in Feb 1999,
2514 * the consensus was: 2514 * the consensus was:
2515 * - "attach as much as possible" is the goal 2515 * - "attach as much as possible" is the goal
2516 * - pad if not aligned (original size can be guessed by 2516 * - pad if not aligned (original size can be guessed by
2517 * original ip6 header) 2517 * original ip6 header)
2518 * Following code adds the padding if it is simple enough, 2518 * Following code adds the padding if it is simple enough,
2519 * and truncates if not. 2519 * and truncates if not.
2520 */ 2520 */
2521 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) { 2521 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
2522 /* not enough room, truncate */ 2522 /* not enough room, truncate */
2523 m_adj(m0, (len - sizeof(*nd_opt_rh)) - 2523 m_adj(m0, (len - sizeof(*nd_opt_rh)) -
2524 m0->m_pkthdr.len); 2524 m0->m_pkthdr.len);
2525 } else { 2525 } else {
2526 /* 2526 /*
2527 * enough room, truncate if not aligned. 2527 * enough room, truncate if not aligned.
2528 * we don't pad here for simplicity. 2528 * we don't pad here for simplicity.
2529 */ 2529 */
2530 size_t extra; 2530 size_t extra;
2531 2531
2532 extra = m0->m_pkthdr.len % 8; 2532 extra = m0->m_pkthdr.len % 8;
2533 if (extra) { 2533 if (extra) {
2534 /* truncate */ 2534 /* truncate */
2535 m_adj(m0, -extra); 2535 m_adj(m0, -extra);
2536 } 2536 }
2537 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh); 2537 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
2538 } 2538 }
2539 2539
2540 nd_opt_rh = (struct nd_opt_rd_hdr *)p; 2540 nd_opt_rh = (struct nd_opt_rd_hdr *)p;
2541 memset(nd_opt_rh, 0, sizeof(*nd_opt_rh)); 2541 memset(nd_opt_rh, 0, sizeof(*nd_opt_rh));
2542 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER; 2542 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
2543 nd_opt_rh->nd_opt_rh_len = len >> 3; 2543 nd_opt_rh->nd_opt_rh_len = len >> 3;
2544 p += sizeof(*nd_opt_rh); 2544 p += sizeof(*nd_opt_rh);
2545 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 2545 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
2546 2546
2547 /* connect m0 to m */ 2547 /* connect m0 to m */
2548 m->m_pkthdr.len += m0->m_pkthdr.len; 2548 m->m_pkthdr.len += m0->m_pkthdr.len;
2549 m_cat(m, m0); 2549 m_cat(m, m0);
2550 m0 = NULL; 2550 m0 = NULL;
2551 } 2551 }
2552noredhdropt: 2552noredhdropt:
2553 if (m0) { 2553 if (m0) {
2554 m_freem(m0); 2554 m_freem(m0);
2555 m0 = NULL; 2555 m0 = NULL;
2556 } 2556 }
2557 2557
2558 /* XXX: clear embedded link IDs in the inner header */ 2558 /* XXX: clear embedded link IDs in the inner header */
2559 in6_clearscope(&sip6->ip6_src); 2559 in6_clearscope(&sip6->ip6_src);
2560 in6_clearscope(&sip6->ip6_dst); 2560 in6_clearscope(&sip6->ip6_dst);
2561 in6_clearscope(&nd_rd->nd_rd_target); 2561 in6_clearscope(&nd_rd->nd_rd_target);
2562 in6_clearscope(&nd_rd->nd_rd_dst); 2562 in6_clearscope(&nd_rd->nd_rd_dst);
2563 2563
2564 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 2564 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
2565 2565
2566 nd_rd->nd_rd_cksum = 0; 2566 nd_rd->nd_rd_cksum = 0;
2567 nd_rd->nd_rd_cksum 2567 nd_rd->nd_rd_cksum
2568 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen)); 2568 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen));
2569 2569
2570 /* send the packet to outside... */ 2570 /* send the packet to outside... */
2571 if (ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL) != 0) 2571 if (ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL) != 0)
2572 icmp6_ifstat_inc(ifp, ifs6_out_error); 2572 icmp6_ifstat_inc(ifp, ifs6_out_error);
2573 2573
2574 icmp6_ifstat_inc(ifp, ifs6_out_msg); 2574 icmp6_ifstat_inc(ifp, ifs6_out_msg);
2575 icmp6_ifstat_inc(ifp, ifs6_out_redirect); 2575 icmp6_ifstat_inc(ifp, ifs6_out_redirect);
2576 ICMP6_STATINC(ICMP6_STAT_OUTHIST + ND_REDIRECT); 2576 ICMP6_STATINC(ICMP6_STAT_OUTHIST + ND_REDIRECT);
2577 2577
2578 return; 2578 return;
2579 2579
2580fail: 2580fail:
2581 if (m) 2581 if (m)
2582 m_freem(m); 2582 m_freem(m);
2583 if (m0) 2583 if (m0)
2584 m_freem(m0); 2584 m_freem(m0);
2585} 2585}
2586 2586
2587/* 2587/*
2588 * ICMPv6 socket option processing. 2588 * ICMPv6 socket option processing.
2589 */ 2589 */
2590int 2590int
2591icmp6_ctloutput(int op, struct socket *so, struct sockopt *sopt) 2591icmp6_ctloutput(int op, struct socket *so, struct sockopt *sopt)
2592{ 2592{
2593 int error = 0; 2593 int error = 0;
2594 struct in6pcb *in6p = sotoin6pcb(so); 2594 struct in6pcb *in6p = sotoin6pcb(so);
2595 2595
2596 if (sopt->sopt_level != IPPROTO_ICMPV6) 2596 if (sopt->sopt_level != IPPROTO_ICMPV6)
2597 return rip6_ctloutput(op, so, sopt); 2597 return rip6_ctloutput(op, so, sopt);
2598 2598
2599 switch (op) { 2599 switch (op) {
2600 case PRCO_SETOPT: 2600 case PRCO_SETOPT:
2601 switch (sopt->sopt_name) { 2601 switch (sopt->sopt_name) {
2602 case ICMP6_FILTER: 2602 case ICMP6_FILTER:
2603 { 2603 {
2604 struct icmp6_filter fil; 2604 struct icmp6_filter fil;
2605 2605
2606 error = sockopt_get(sopt, &fil, sizeof(fil)); 2606 error = sockopt_get(sopt, &fil, sizeof(fil));
2607 if (error) 2607 if (error)
2608 break; 2608 break;
2609 memcpy(in6p->in6p_icmp6filt, &fil, 2609 memcpy(in6p->in6p_icmp6filt, &fil,
2610 sizeof(struct icmp6_filter)); 2610 sizeof(struct icmp6_filter));
2611 error = 0; 2611 error = 0;
2612 break; 2612 break;
2613 } 2613 }
2614 2614
2615 default: 2615 default:
2616 error = ENOPROTOOPT; 2616 error = ENOPROTOOPT;
2617 break; 2617 break;
2618 } 2618 }
2619 break; 2619 break;
2620 2620
2621 case PRCO_GETOPT: 2621 case PRCO_GETOPT:
2622 switch (sopt->sopt_name) { 2622 switch (sopt->sopt_name) {
2623 case ICMP6_FILTER: 2623 case ICMP6_FILTER:
2624 { 2624 {
2625 if (in6p->in6p_icmp6filt == NULL) { 2625 if (in6p->in6p_icmp6filt == NULL) {
2626 error = EINVAL; 2626 error = EINVAL;
2627 break; 2627 break;
2628 } 2628 }
2629 error = sockopt_set(sopt, in6p->in6p_icmp6filt, 2629 error = sockopt_set(sopt, in6p->in6p_icmp6filt,
2630 sizeof(struct icmp6_filter)); 2630 sizeof(struct icmp6_filter));
2631 break; 2631 break;
2632 } 2632 }
2633 2633
2634 default: 2634 default:
2635 error = ENOPROTOOPT; 2635 error = ENOPROTOOPT;
2636 break; 2636 break;
2637 } 2637 }
2638 break; 2638 break;
2639 } 2639 }
2640 2640
2641 return (error); 2641 return (error);
2642} 2642}
2643 2643
2644/* 2644/*
2645 * Perform rate limit check. 2645 * Perform rate limit check.
2646 * Returns 0 if it is okay to send the icmp6 packet. 2646 * Returns 0 if it is okay to send the icmp6 packet.
2647 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate 2647 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
2648 * limitation. 2648 * limitation.
2649 * 2649 *
2650 * XXX per-destination/type check necessary? 2650 * XXX per-destination/type check necessary?
2651 */ 2651 */
2652static int 2652static int
2653icmp6_ratelimit( 2653icmp6_ratelimit(
2654 const struct in6_addr *dst, /* not used at this moment */ 2654 const struct in6_addr *dst, /* not used at this moment */
2655 const int type, /* not used at this moment */ 2655 const int type, /* not used at this moment */
2656 const int code) /* not used at this moment */ 2656 const int code) /* not used at this moment */
2657{ 2657{
2658 int ret; 2658 int ret;
2659 2659
2660 ret = 0; /* okay to send */ 2660 ret = 0; /* okay to send */
2661 2661
2662 /* PPS limit */ 2662 /* PPS limit */
2663 if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count, 2663 if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
2664 icmp6errppslim)) { 2664 icmp6errppslim)) {
2665 /* The packet is subject to rate limit */ 2665 /* The packet is subject to rate limit */
2666 ret++; 2666 ret++;
2667 } 2667 }
2668 2668
2669 return ret; 2669 return ret;
2670} 2670}
2671 2671
2672static struct rtentry * 2672static struct rtentry *
2673icmp6_mtudisc_clone(struct sockaddr *dst) 2673icmp6_mtudisc_clone(struct sockaddr *dst)
2674{ 2674{
2675 struct rtentry *rt; 2675 struct rtentry *rt;
2676 int error; 2676 int error;
2677 2677
2678 rt = rtalloc1(dst, 1); 2678 rt = rtalloc1(dst, 1);
2679 if (rt == 0) 2679 if (rt == 0)
2680 return NULL; 2680 return NULL;
2681 2681
2682 /* If we didn't get a host route, allocate one */ 2682 /* If we didn't get a host route, allocate one */
2683 if ((rt->rt_flags & RTF_HOST) == 0) { 2683 if ((rt->rt_flags & RTF_HOST) == 0) {
2684 struct rtentry *nrt; 2684 struct rtentry *nrt;
2685 2685
2686 error = rtrequest((int) RTM_ADD, dst, 2686 error = rtrequest((int) RTM_ADD, dst,
2687 (struct sockaddr *) rt->rt_gateway, NULL, 2687 (struct sockaddr *) rt->rt_gateway, NULL,
2688 RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt); 2688 RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt);
2689 if (error) { 2689 if (error) {
2690 rtfree(rt); 2690 rtfree(rt);
2691 return NULL; 2691 return NULL;
2692 } 2692 }
2693 nrt->rt_rmx = rt->rt_rmx; 2693 nrt->rt_rmx = rt->rt_rmx;
2694 rtfree(rt); 2694 rtfree(rt);
2695 rt = nrt; 2695 rt = nrt;
2696 } 2696 }
2697 error = rt_timer_add(rt, icmp6_mtudisc_timeout, 2697 error = rt_timer_add(rt, icmp6_mtudisc_timeout,
2698 icmp6_mtudisc_timeout_q); 2698 icmp6_mtudisc_timeout_q);
2699 if (error) { 2699 if (error) {
2700 rtfree(rt); 2700 rtfree(rt);
2701 return NULL; 2701 return NULL;
2702 } 2702 }
2703 2703
2704 return rt; /* caller need to call rtfree() */ 2704 return rt; /* caller need to call rtfree() */
2705} 2705}
2706 2706
2707static void 2707static void
2708icmp6_mtudisc_timeout(struct rtentry *rt, struct rttimer *r) 2708icmp6_mtudisc_timeout(struct rtentry *rt, struct rttimer *r)
2709{ 2709{
2710 if (rt == NULL) 2710 if (rt == NULL)
2711 panic("icmp6_mtudisc_timeout: bad route to timeout"); 2711 panic("icmp6_mtudisc_timeout: bad route to timeout");
2712 if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) == 2712 if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
2713 (RTF_DYNAMIC | RTF_HOST)) { 2713 (RTF_DYNAMIC | RTF_HOST)) {
2714 rtrequest((int) RTM_DELETE, rt_getkey(rt), 2714 rtrequest((int) RTM_DELETE, rt_getkey(rt),
2715 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); 2715 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
2716 } else { 2716 } else {
2717 if (!(rt->rt_rmx.rmx_locks & RTV_MTU)) 2717 if (!(rt->rt_rmx.rmx_locks & RTV_MTU))
2718 rt->rt_rmx.rmx_mtu = 0; 2718 rt->rt_rmx.rmx_mtu = 0;
2719 } 2719 }
2720} 2720}
2721 2721
2722static void 2722static void
2723icmp6_redirect_timeout(struct rtentry *rt, struct rttimer *r) 2723icmp6_redirect_timeout(struct rtentry *rt, struct rttimer *r)
2724{ 2724{
2725 if (rt == NULL) 2725 if (rt == NULL)
2726 panic("icmp6_redirect_timeout: bad route to timeout"); 2726 panic("icmp6_redirect_timeout: bad route to timeout");
2727 if ((rt->rt_flags & (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) == 2727 if ((rt->rt_flags & (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) ==
2728 (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) { 2728 (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) {
2729 rtrequest((int) RTM_DELETE, rt_getkey(rt), 2729 rtrequest((int) RTM_DELETE, rt_getkey(rt),
2730 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); 2730 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
2731 } 2731 }
2732} 2732}
2733 2733
2734/* 2734/*
2735 * sysctl helper routine for the net.inet6.icmp6.nd6 nodes. silly? 2735 * sysctl helper routine for the net.inet6.icmp6.nd6 nodes. silly?
2736 */ 2736 */
2737static int 2737static int
2738sysctl_net_inet6_icmp6_nd6(SYSCTLFN_ARGS) 2738sysctl_net_inet6_icmp6_nd6(SYSCTLFN_ARGS)
2739{ 2739{
2740 (void)&name; 2740 (void)&name;
2741 (void)&l; 2741 (void)&l;
2742 (void)&oname; 2742 (void)&oname;
2743 2743
2744 if (namelen != 0) 2744 if (namelen != 0)
2745 return (EINVAL); 2745 return (EINVAL);
2746 2746
2747 return (nd6_sysctl(rnode->sysctl_num, oldp, oldlenp, 2747 return (nd6_sysctl(rnode->sysctl_num, oldp, oldlenp,
2748 /*XXXUNCONST*/ 2748 /*XXXUNCONST*/
2749 __UNCONST(newp), newlen)); 2749 __UNCONST(newp), newlen));
2750} 2750}
2751 2751
2752static int 2752static int
2753sysctl_net_inet6_icmp6_stats(SYSCTLFN_ARGS) 2753sysctl_net_inet6_icmp6_stats(SYSCTLFN_ARGS)
2754{ 2754{
2755 2755
2756 return (NETSTAT_SYSCTL(icmp6stat_percpu, ICMP6_NSTATS)); 2756 return (NETSTAT_SYSCTL(icmp6stat_percpu, ICMP6_NSTATS));
2757} 2757}
2758 2758
 2759static int
 2760sysctl_net_inet6_icmp6_redirtimeout(SYSCTLFN_ARGS)
 2761{
 2762 int error, tmp;
 2763 struct sysctlnode node;
 2764
 2765 node = *rnode;
 2766 node.sysctl_data = &tmp;
 2767 tmp = icmp6_redirtimeout;
 2768 error = sysctl_lookup(SYSCTLFN_CALL(&node));
 2769 if (error || newp == NULL)
 2770 return error;
 2771 if (tmp < 0)
 2772 return EINVAL;
 2773 icmp6_redirtimeout = tmp;
 2774
 2775 if (icmp6_redirect_timeout_q != NULL) {
 2776 if (icmp6_redirtimeout == 0) {
 2777 rt_timer_queue_destroy(icmp6_redirect_timeout_q,
 2778 true);
 2779 } else {
 2780 rt_timer_queue_change(icmp6_redirect_timeout_q,
 2781 icmp6_redirtimeout);
 2782 }
 2783 } else if (icmp6_redirtimeout > 0) {
 2784 icmp6_redirect_timeout_q =
 2785 rt_timer_queue_create(icmp6_redirtimeout);
 2786 }
 2787
 2788 return 0;
 2789}
 2790
2759static void 2791static void
2760sysctl_net_inet6_icmp6_setup(struct sysctllog **clog) 2792sysctl_net_inet6_icmp6_setup(struct sysctllog **clog)
2761{ 2793{
2762 extern int nd6_maxqueuelen; /* defined in nd6.c */ 2794 extern int nd6_maxqueuelen; /* defined in nd6.c */
2763 2795
2764 sysctl_createv(clog, 0, NULL, NULL, 2796 sysctl_createv(clog, 0, NULL, NULL,
2765 CTLFLAG_PERMANENT, 2797 CTLFLAG_PERMANENT,
2766 CTLTYPE_NODE, "inet6", NULL, 2798 CTLTYPE_NODE, "inet6", NULL,
2767 NULL, 0, NULL, 0, 2799 NULL, 0, NULL, 0,
2768 CTL_NET, PF_INET6, CTL_EOL); 2800 CTL_NET, PF_INET6, CTL_EOL);
2769 sysctl_createv(clog, 0, NULL, NULL, 2801 sysctl_createv(clog, 0, NULL, NULL,
2770 CTLFLAG_PERMANENT, 2802 CTLFLAG_PERMANENT,
2771 CTLTYPE_NODE, "icmp6", 2803 CTLTYPE_NODE, "icmp6",
2772 SYSCTL_DESCR("ICMPv6 related settings"), 2804 SYSCTL_DESCR("ICMPv6 related settings"),
2773 NULL, 0, NULL, 0, 2805 NULL, 0, NULL, 0,
2774 CTL_NET, PF_INET6, IPPROTO_ICMPV6, CTL_EOL); 2806 CTL_NET, PF_INET6, IPPROTO_ICMPV6, CTL_EOL);
2775 2807
2776 sysctl_createv(clog, 0, NULL, NULL, 2808 sysctl_createv(clog, 0, NULL, NULL,
2777 CTLFLAG_PERMANENT, 2809 CTLFLAG_PERMANENT,
2778 CTLTYPE_STRUCT, "stats", 2810 CTLTYPE_STRUCT, "stats",
2779 SYSCTL_DESCR("ICMPv6 transmission statistics"), 2811 SYSCTL_DESCR("ICMPv6 transmission statistics"),
2780 sysctl_net_inet6_icmp6_stats, 0, NULL, 0, 2812 sysctl_net_inet6_icmp6_stats, 0, NULL, 0,
2781 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2813 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2782 ICMPV6CTL_STATS, CTL_EOL); 2814 ICMPV6CTL_STATS, CTL_EOL);
2783 sysctl_createv(clog, 0, NULL, NULL, 2815 sysctl_createv(clog, 0, NULL, NULL,
2784 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2816 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2785 CTLTYPE_INT, "rediraccept", 2817 CTLTYPE_INT, "rediraccept",
2786 SYSCTL_DESCR("Accept and process redirect messages"), 2818 SYSCTL_DESCR("Accept and process redirect messages"),
2787 NULL, 0, &icmp6_rediraccept, 0, 2819 NULL, 0, &icmp6_rediraccept, 0,
2788 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2820 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2789 ICMPV6CTL_REDIRACCEPT, CTL_EOL); 2821 ICMPV6CTL_REDIRACCEPT, CTL_EOL);
2790 sysctl_createv(clog, 0, NULL, NULL, 2822 sysctl_createv(clog, 0, NULL, NULL,
2791 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2823 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2792 CTLTYPE_INT, "redirtimeout", 2824 CTLTYPE_INT, "redirtimeout",
2793 SYSCTL_DESCR("Redirect generated route lifetime"), 2825 SYSCTL_DESCR("Redirect generated route lifetime"),
2794 NULL, 0, &icmp6_redirtimeout, 0, 2826 sysctl_net_inet6_icmp6_redirtimeout, 0,
 2827 &icmp6_redirtimeout, 0,
2795 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2828 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2796 ICMPV6CTL_REDIRTIMEOUT, CTL_EOL); 2829 ICMPV6CTL_REDIRTIMEOUT, CTL_EOL);
2797#if 0 /* obsoleted */ 2830#if 0 /* obsoleted */
2798 sysctl_createv(clog, 0, NULL, NULL, 2831 sysctl_createv(clog, 0, NULL, NULL,
2799 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2832 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2800 CTLTYPE_INT, "errratelimit", NULL, 2833 CTLTYPE_INT, "errratelimit", NULL,
2801 NULL, 0, &icmp6_errratelimit, 0, 2834 NULL, 0, &icmp6_errratelimit, 0,
2802 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2835 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2803 ICMPV6CTL_ERRRATELIMIT, CTL_EOL); 2836 ICMPV6CTL_ERRRATELIMIT, CTL_EOL);
2804#endif 2837#endif
2805 sysctl_createv(clog, 0, NULL, NULL, 2838 sysctl_createv(clog, 0, NULL, NULL,
2806 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2839 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2807 CTLTYPE_INT, "nd6_prune", 2840 CTLTYPE_INT, "nd6_prune",
2808 SYSCTL_DESCR("Neighbor discovery prune interval"), 2841 SYSCTL_DESCR("Neighbor discovery prune interval"),
2809 NULL, 0, &nd6_prune, 0, 2842 NULL, 0, &nd6_prune, 0,
2810 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2843 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2811 ICMPV6CTL_ND6_PRUNE, CTL_EOL); 2844 ICMPV6CTL_ND6_PRUNE, CTL_EOL);
2812 sysctl_createv(clog, 0, NULL, NULL, 2845 sysctl_createv(clog, 0, NULL, NULL,
2813 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2846 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2814 CTLTYPE_INT, "nd6_delay", 2847 CTLTYPE_INT, "nd6_delay",
2815 SYSCTL_DESCR("First probe delay time"), 2848 SYSCTL_DESCR("First probe delay time"),
2816 NULL, 0, &nd6_delay, 0, 2849 NULL, 0, &nd6_delay, 0,
2817 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2850 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2818 ICMPV6CTL_ND6_DELAY, CTL_EOL); 2851 ICMPV6CTL_ND6_DELAY, CTL_EOL);
2819 sysctl_createv(clog, 0, NULL, NULL, 2852 sysctl_createv(clog, 0, NULL, NULL,
2820 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2853 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2821 CTLTYPE_INT, "nd6_umaxtries", 2854 CTLTYPE_INT, "nd6_umaxtries",
2822 SYSCTL_DESCR("Number of unicast discovery attempts"), 2855 SYSCTL_DESCR("Number of unicast discovery attempts"),
2823 NULL, 0, &nd6_umaxtries, 0, 2856 NULL, 0, &nd6_umaxtries, 0,
2824 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2857 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2825 ICMPV6CTL_ND6_UMAXTRIES, CTL_EOL); 2858 ICMPV6CTL_ND6_UMAXTRIES, CTL_EOL);
2826 sysctl_createv(clog, 0, NULL, NULL, 2859 sysctl_createv(clog, 0, NULL, NULL,
2827 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2860 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2828 CTLTYPE_INT, "nd6_mmaxtries", 2861 CTLTYPE_INT, "nd6_mmaxtries",
2829 SYSCTL_DESCR("Number of multicast discovery attempts"), 2862 SYSCTL_DESCR("Number of multicast discovery attempts"),
2830 NULL, 0, &nd6_mmaxtries, 0, 2863 NULL, 0, &nd6_mmaxtries, 0,
2831 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2864 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2832 ICMPV6CTL_ND6_MMAXTRIES, CTL_EOL); 2865 ICMPV6CTL_ND6_MMAXTRIES, CTL_EOL);
2833 sysctl_createv(clog, 0, NULL, NULL, 2866 sysctl_createv(clog, 0, NULL, NULL,
2834 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2867 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2835 CTLTYPE_INT, "nd6_useloopback", 2868 CTLTYPE_INT, "nd6_useloopback",
2836 SYSCTL_DESCR("Use loopback interface for local traffic"), 2869 SYSCTL_DESCR("Use loopback interface for local traffic"),
2837 NULL, 0, &nd6_useloopback, 0, 2870 NULL, 0, &nd6_useloopback, 0,
2838 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2871 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2839 ICMPV6CTL_ND6_USELOOPBACK, CTL_EOL); 2872 ICMPV6CTL_ND6_USELOOPBACK, CTL_EOL);
2840#if 0 /* obsoleted */ 2873#if 0 /* obsoleted */
2841 sysctl_createv(clog, 0, NULL, NULL, 2874 sysctl_createv(clog, 0, NULL, NULL,
2842 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2875 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2843 CTLTYPE_INT, "nd6_proxyall", NULL, 2876 CTLTYPE_INT, "nd6_proxyall", NULL,
2844 NULL, 0, &nd6_proxyall, 0, 2877 NULL, 0, &nd6_proxyall, 0,
2845 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2878 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2846 ICMPV6CTL_ND6_PROXYALL, CTL_EOL); 2879 ICMPV6CTL_ND6_PROXYALL, CTL_EOL);
2847#endif 2880#endif
2848 sysctl_createv(clog, 0, NULL, NULL, 2881 sysctl_createv(clog, 0, NULL, NULL,
2849 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2882 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2850 CTLTYPE_INT, "nodeinfo", 2883 CTLTYPE_INT, "nodeinfo",
2851 SYSCTL_DESCR("Respond to node information requests"), 2884 SYSCTL_DESCR("Respond to node information requests"),
2852 NULL, 0, &icmp6_nodeinfo, 0, 2885 NULL, 0, &icmp6_nodeinfo, 0,
2853 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2886 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2854 ICMPV6CTL_NODEINFO, CTL_EOL); 2887 ICMPV6CTL_NODEINFO, CTL_EOL);
2855 sysctl_createv(clog, 0, NULL, NULL, 2888 sysctl_createv(clog, 0, NULL, NULL,
2856 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2889 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2857 CTLTYPE_INT, "errppslimit", 2890 CTLTYPE_INT, "errppslimit",
2858 SYSCTL_DESCR("Maximum ICMP errors sent per second"), 2891 SYSCTL_DESCR("Maximum ICMP errors sent per second"),
2859 NULL, 0, &icmp6errppslim, 0, 2892 NULL, 0, &icmp6errppslim, 0,
2860 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2893 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2861 ICMPV6CTL_ERRPPSLIMIT, CTL_EOL); 2894 ICMPV6CTL_ERRPPSLIMIT, CTL_EOL);
2862 sysctl_createv(clog, 0, NULL, NULL, 2895 sysctl_createv(clog, 0, NULL, NULL,
2863 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2896 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2864 CTLTYPE_INT, "nd6_maxnudhint", 2897 CTLTYPE_INT, "nd6_maxnudhint",
2865 SYSCTL_DESCR("Maximum neighbor unreachable hint count"), 2898 SYSCTL_DESCR("Maximum neighbor unreachable hint count"),
2866 NULL, 0, &nd6_maxnudhint, 0, 2899 NULL, 0, &nd6_maxnudhint, 0,
2867 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2900 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2868 ICMPV6CTL_ND6_MAXNUDHINT, CTL_EOL); 2901 ICMPV6CTL_ND6_MAXNUDHINT, CTL_EOL);
2869 sysctl_createv(clog, 0, NULL, NULL, 2902 sysctl_createv(clog, 0, NULL, NULL,
2870 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2903 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2871 CTLTYPE_INT, "mtudisc_hiwat", 2904 CTLTYPE_INT, "mtudisc_hiwat",
2872 SYSCTL_DESCR("Low mark on MTU Discovery route timers"), 2905 SYSCTL_DESCR("Low mark on MTU Discovery route timers"),
2873 NULL, 0, &icmp6_mtudisc_hiwat, 0, 2906 NULL, 0, &icmp6_mtudisc_hiwat, 0,
2874 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2907 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2875 ICMPV6CTL_MTUDISC_HIWAT, CTL_EOL); 2908 ICMPV6CTL_MTUDISC_HIWAT, CTL_EOL);
2876 sysctl_createv(clog, 0, NULL, NULL, 2909 sysctl_createv(clog, 0, NULL, NULL,
2877 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2910 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2878 CTLTYPE_INT, "mtudisc_lowat", 2911 CTLTYPE_INT, "mtudisc_lowat",
2879 SYSCTL_DESCR("Low mark on MTU Discovery route timers"), 2912 SYSCTL_DESCR("Low mark on MTU Discovery route timers"),
2880 NULL, 0, &icmp6_mtudisc_lowat, 0, 2913 NULL, 0, &icmp6_mtudisc_lowat, 0,
2881 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2914 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2882 ICMPV6CTL_MTUDISC_LOWAT, CTL_EOL); 2915 ICMPV6CTL_MTUDISC_LOWAT, CTL_EOL);
2883 sysctl_createv(clog, 0, NULL, NULL, 2916 sysctl_createv(clog, 0, NULL, NULL,
2884 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2917 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2885 CTLTYPE_INT, "nd6_debug", 2918 CTLTYPE_INT, "nd6_debug",
2886 SYSCTL_DESCR("Enable neighbor discovery debug output"), 2919 SYSCTL_DESCR("Enable neighbor discovery debug output"),
2887 NULL, 0, &nd6_debug, 0, 2920 NULL, 0, &nd6_debug, 0,
2888 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2921 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2889 ICMPV6CTL_ND6_DEBUG, CTL_EOL); 2922 ICMPV6CTL_ND6_DEBUG, CTL_EOL);
2890 sysctl_createv(clog, 0, NULL, NULL, 2923 sysctl_createv(clog, 0, NULL, NULL,
2891 CTLFLAG_PERMANENT, 2924 CTLFLAG_PERMANENT,
2892 CTLTYPE_STRUCT, "nd6_drlist", 2925 CTLTYPE_STRUCT, "nd6_drlist",
2893 SYSCTL_DESCR("Default router list"), 2926 SYSCTL_DESCR("Default router list"),
2894 sysctl_net_inet6_icmp6_nd6, 0, NULL, 0, 2927 sysctl_net_inet6_icmp6_nd6, 0, NULL, 0,
2895 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2928 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2896 ICMPV6CTL_ND6_DRLIST, CTL_EOL); 2929 ICMPV6CTL_ND6_DRLIST, CTL_EOL);
2897 sysctl_createv(clog, 0, NULL, NULL, 2930 sysctl_createv(clog, 0, NULL, NULL,
2898 CTLFLAG_PERMANENT, 2931 CTLFLAG_PERMANENT,
2899 CTLTYPE_STRUCT, "nd6_prlist", 2932 CTLTYPE_STRUCT, "nd6_prlist",
2900 SYSCTL_DESCR("Prefix list"), 2933 SYSCTL_DESCR("Prefix list"),
2901 sysctl_net_inet6_icmp6_nd6, 0, NULL, 0, 2934 sysctl_net_inet6_icmp6_nd6, 0, NULL, 0,
2902 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2935 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2903 ICMPV6CTL_ND6_PRLIST, CTL_EOL); 2936 ICMPV6CTL_ND6_PRLIST, CTL_EOL);
2904 sysctl_createv(clog, 0, NULL, NULL, 2937 sysctl_createv(clog, 0, NULL, NULL,
2905 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 2938 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2906 CTLTYPE_INT, "maxqueuelen", 2939 CTLTYPE_INT, "maxqueuelen",
2907 SYSCTL_DESCR("max packet queue len for a unresolved ND"), 2940 SYSCTL_DESCR("max packet queue len for a unresolved ND"),
2908 NULL, 1, &nd6_maxqueuelen, 0, 2941 NULL, 1, &nd6_maxqueuelen, 0,
2909 CTL_NET, PF_INET6, IPPROTO_ICMPV6, 2942 CTL_NET, PF_INET6, IPPROTO_ICMPV6,
2910 ICMPV6CTL_ND6_MAXQLEN, CTL_EOL); 2943 ICMPV6CTL_ND6_MAXQLEN, CTL_EOL);
2911} 2944}
2912 2945
2913void 2946void
2914icmp6_statinc(u_int stat) 2947icmp6_statinc(u_int stat)
2915{ 2948{
2916 2949
2917 KASSERT(stat < ICMP6_NSTATS); 2950 KASSERT(stat < ICMP6_NSTATS);
2918 ICMP6_STATINC(stat); 2951 ICMP6_STATINC(stat);
2919} 2952}