Tidy up nd6_timer initializationdiff -r1.155 -r1.156 src/sys/netinet6/ip6_input.c
(ozaki-r)
--- src/sys/netinet6/ip6_input.c 2016/02/04 02:48:37 1.155
+++ src/sys/netinet6/ip6_input.c 2016/04/01 05:11:38 1.156
@@ -1,1204 +1,1200 @@ | @@ -1,1204 +1,1200 @@ | |||
1 | /* $NetBSD: ip6_input.c,v 1.155 2016/02/04 02:48:37 riastradh Exp $ */ | 1 | /* $NetBSD: ip6_input.c,v 1.156 2016/04/01 05:11:38 ozaki-r Exp $ */ | |
2 | /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ | 2 | /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun 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_input.c 8.2 (Berkeley) 1/4/94 | 61 | * @(#)ip_input.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: ip6_input.c,v 1.155 2016/02/04 02:48:37 riastradh Exp $"); | 65 | __KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.156 2016/04/01 05:11:38 ozaki-r Exp $"); | |
66 | 66 | |||
67 | #ifdef _KERNEL_OPT | 67 | #ifdef _KERNEL_OPT | |
68 | #include "opt_gateway.h" | 68 | #include "opt_gateway.h" | |
69 | #include "opt_inet.h" | 69 | #include "opt_inet.h" | |
70 | #include "opt_inet6.h" | 70 | #include "opt_inet6.h" | |
71 | #include "opt_ipsec.h" | 71 | #include "opt_ipsec.h" | |
72 | #include "opt_compat_netbsd.h" | 72 | #include "opt_compat_netbsd.h" | |
73 | #endif | 73 | #endif | |
74 | 74 | |||
75 | #include <sys/param.h> | 75 | #include <sys/param.h> | |
76 | #include <sys/systm.h> | 76 | #include <sys/systm.h> | |
77 | #include <sys/malloc.h> | 77 | #include <sys/malloc.h> | |
78 | #include <sys/mbuf.h> | 78 | #include <sys/mbuf.h> | |
79 | #include <sys/domain.h> | 79 | #include <sys/domain.h> | |
80 | #include <sys/protosw.h> | 80 | #include <sys/protosw.h> | |
81 | #include <sys/socket.h> | 81 | #include <sys/socket.h> | |
82 | #include <sys/socketvar.h> | 82 | #include <sys/socketvar.h> | |
83 | #include <sys/errno.h> | 83 | #include <sys/errno.h> | |
84 | #include <sys/time.h> | 84 | #include <sys/time.h> | |
85 | #include <sys/kernel.h> | 85 | #include <sys/kernel.h> | |
86 | #include <sys/syslog.h> | 86 | #include <sys/syslog.h> | |
87 | #include <sys/proc.h> | 87 | #include <sys/proc.h> | |
88 | #include <sys/sysctl.h> | 88 | #include <sys/sysctl.h> | |
89 | #include <sys/cprng.h> | 89 | #include <sys/cprng.h> | |
90 | 90 | |||
91 | #include <net/if.h> | 91 | #include <net/if.h> | |
92 | #include <net/if_types.h> | 92 | #include <net/if_types.h> | |
93 | #include <net/if_dl.h> | 93 | #include <net/if_dl.h> | |
94 | #include <net/route.h> | 94 | #include <net/route.h> | |
95 | #include <net/pktqueue.h> | 95 | #include <net/pktqueue.h> | |
96 | #include <net/pfil.h> | 96 | #include <net/pfil.h> | |
97 | 97 | |||
98 | #include <netinet/in.h> | 98 | #include <netinet/in.h> | |
99 | #include <netinet/in_systm.h> | 99 | #include <netinet/in_systm.h> | |
100 | #ifdef INET | 100 | #ifdef INET | |
101 | #include <netinet/ip.h> | 101 | #include <netinet/ip.h> | |
102 | #include <netinet/ip_var.h> | 102 | #include <netinet/ip_var.h> | |
103 | #include <netinet/ip_icmp.h> | 103 | #include <netinet/ip_icmp.h> | |
104 | #endif /* INET */ | 104 | #endif /* INET */ | |
105 | #include <netinet/ip6.h> | 105 | #include <netinet/ip6.h> | |
106 | #include <netinet/portalgo.h> | 106 | #include <netinet/portalgo.h> | |
107 | #include <netinet6/in6_var.h> | 107 | #include <netinet6/in6_var.h> | |
108 | #include <netinet6/ip6_var.h> | 108 | #include <netinet6/ip6_var.h> | |
109 | #include <netinet6/ip6_private.h> | 109 | #include <netinet6/ip6_private.h> | |
110 | #include <netinet6/in6_pcb.h> | 110 | #include <netinet6/in6_pcb.h> | |
111 | #include <netinet/icmp6.h> | 111 | #include <netinet/icmp6.h> | |
112 | #include <netinet6/scope6_var.h> | 112 | #include <netinet6/scope6_var.h> | |
113 | #include <netinet6/in6_ifattach.h> | 113 | #include <netinet6/in6_ifattach.h> | |
114 | #include <netinet6/nd6.h> | 114 | #include <netinet6/nd6.h> | |
115 | 115 | |||
116 | #ifdef IPSEC | 116 | #ifdef IPSEC | |
117 | #include <netipsec/ipsec.h> | 117 | #include <netipsec/ipsec.h> | |
118 | #include <netipsec/ipsec6.h> | 118 | #include <netipsec/ipsec6.h> | |
119 | #include <netipsec/key.h> | 119 | #include <netipsec/key.h> | |
120 | #endif /* IPSEC */ | 120 | #endif /* IPSEC */ | |
121 | 121 | |||
122 | #ifdef COMPAT_50 | 122 | #ifdef COMPAT_50 | |
123 | #include <compat/sys/time.h> | 123 | #include <compat/sys/time.h> | |
124 | #include <compat/sys/socket.h> | 124 | #include <compat/sys/socket.h> | |
125 | #endif | 125 | #endif | |
126 | 126 | |||
127 | #include <netinet6/ip6protosw.h> | 127 | #include <netinet6/ip6protosw.h> | |
128 | 128 | |||
129 | #include "faith.h" | 129 | #include "faith.h" | |
130 | 130 | |||
131 | #include <net/net_osdep.h> | 131 | #include <net/net_osdep.h> | |
132 | 132 | |||
133 | extern struct domain inet6domain; | 133 | extern struct domain inet6domain; | |
134 | 134 | |||
135 | u_char ip6_protox[IPPROTO_MAX]; | 135 | u_char ip6_protox[IPPROTO_MAX]; | |
136 | struct in6_ifaddr *in6_ifaddr; | 136 | struct in6_ifaddr *in6_ifaddr; | |
137 | pktqueue_t *ip6_pktq __read_mostly; | 137 | pktqueue_t *ip6_pktq __read_mostly; | |
138 | 138 | |||
139 | int ip6_forward_srcrt; /* XXX */ | 139 | int ip6_forward_srcrt; /* XXX */ | |
140 | int ip6_sourcecheck; /* XXX */ | 140 | int ip6_sourcecheck; /* XXX */ | |
141 | int ip6_sourcecheck_interval; /* XXX */ | 141 | int ip6_sourcecheck_interval; /* XXX */ | |
142 | 142 | |||
143 | pfil_head_t *inet6_pfil_hook; | 143 | pfil_head_t *inet6_pfil_hook; | |
144 | 144 | |||
145 | percpu_t *ip6stat_percpu; | 145 | percpu_t *ip6stat_percpu; | |
146 | 146 | |||
147 | static void ip6_init2(void *); | 147 | static void ip6_init2(void); | |
148 | static void ip6intr(void *); | 148 | static void ip6intr(void *); | |
149 | static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); | 149 | static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); | |
150 | 150 | |||
151 | static int ip6_process_hopopts(struct mbuf *, u_int8_t *, int, u_int32_t *, | 151 | static int ip6_process_hopopts(struct mbuf *, u_int8_t *, int, u_int32_t *, | |
152 | u_int32_t *); | 152 | u_int32_t *); | |
153 | static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); | 153 | static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); | |
154 | static void sysctl_net_inet6_ip6_setup(struct sysctllog **); | 154 | static void sysctl_net_inet6_ip6_setup(struct sysctllog **); | |
155 | 155 | |||
156 | /* | 156 | /* | |
157 | * IP6 initialization: fill in IP6 protocol switch table. | 157 | * IP6 initialization: fill in IP6 protocol switch table. | |
158 | * All protocols not implemented in kernel go to raw IP6 protocol handler. | 158 | * All protocols not implemented in kernel go to raw IP6 protocol handler. | |
159 | */ | 159 | */ | |
160 | void | 160 | void | |
161 | ip6_init(void) | 161 | ip6_init(void) | |
162 | { | 162 | { | |
163 | const struct ip6protosw *pr; | 163 | const struct ip6protosw *pr; | |
164 | int i; | 164 | int i; | |
165 | 165 | |||
166 | sysctl_net_inet6_ip6_setup(NULL); | 166 | sysctl_net_inet6_ip6_setup(NULL); | |
167 | pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); | 167 | pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); | |
168 | if (pr == 0) | 168 | if (pr == 0) | |
169 | panic("ip6_init"); | 169 | panic("ip6_init"); | |
170 | for (i = 0; i < IPPROTO_MAX; i++) | 170 | for (i = 0; i < IPPROTO_MAX; i++) | |
171 | ip6_protox[i] = pr - inet6sw; | 171 | ip6_protox[i] = pr - inet6sw; | |
172 | for (pr = (const struct ip6protosw *)inet6domain.dom_protosw; | 172 | for (pr = (const struct ip6protosw *)inet6domain.dom_protosw; | |
173 | pr < (const struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) | 173 | pr < (const struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) | |
174 | if (pr->pr_domain->dom_family == PF_INET6 && | 174 | if (pr->pr_domain->dom_family == PF_INET6 && | |
175 | pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) | 175 | pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) | |
176 | ip6_protox[pr->pr_protocol] = pr - inet6sw; | 176 | ip6_protox[pr->pr_protocol] = pr - inet6sw; | |
177 | 177 | |||
178 | ip6_pktq = pktq_create(IFQ_MAXLEN, ip6intr, NULL); | 178 | ip6_pktq = pktq_create(IFQ_MAXLEN, ip6intr, NULL); | |
179 | KASSERT(ip6_pktq != NULL); | 179 | KASSERT(ip6_pktq != NULL); | |
180 | 180 | |||
181 | scope6_init(); | 181 | scope6_init(); | |
182 | addrsel_policy_init(); | 182 | addrsel_policy_init(); | |
183 | nd6_init(); | 183 | nd6_init(); | |
184 | frag6_init(); | 184 | frag6_init(); | |
185 | ip6_desync_factor = cprng_fast32() % MAX_TEMP_DESYNC_FACTOR; | 185 | ip6_desync_factor = cprng_fast32() % MAX_TEMP_DESYNC_FACTOR; | |
186 | 186 | |||
187 | ip6_init2(NULL); | 187 | ip6_init2(); | |
188 | #ifdef GATEWAY | 188 | #ifdef GATEWAY | |
189 | ip6flow_init(ip6_hashsize); | 189 | ip6flow_init(ip6_hashsize); | |
190 | #endif | 190 | #endif | |
191 | /* Register our Packet Filter hook. */ | 191 | /* Register our Packet Filter hook. */ | |
192 | inet6_pfil_hook = pfil_head_create(PFIL_TYPE_AF, (void *)AF_INET6); | 192 | inet6_pfil_hook = pfil_head_create(PFIL_TYPE_AF, (void *)AF_INET6); | |
193 | KASSERT(inet6_pfil_hook != NULL); | 193 | KASSERT(inet6_pfil_hook != NULL); | |
194 | 194 | |||
195 | ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); | 195 | ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); | |
196 | } | 196 | } | |
197 | 197 | |||
198 | static void | 198 | static void | |
199 | ip6_init2(void *dummy) | 199 | ip6_init2(void) | |
200 | { | 200 | { | |
201 | 201 | |||
202 | /* nd6_timer_init */ | |||
203 | callout_init(&nd6_timer_ch, CALLOUT_MPSAFE); | |||
204 | callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL); | |||
205 | ||||
206 | /* timer for regeneranation of temporary addresses randomize ID */ | 202 | /* timer for regeneranation of temporary addresses randomize ID */ | |
207 | callout_init(&in6_tmpaddrtimer_ch, CALLOUT_MPSAFE); | 203 | callout_init(&in6_tmpaddrtimer_ch, CALLOUT_MPSAFE); | |
208 | callout_reset(&in6_tmpaddrtimer_ch, | 204 | callout_reset(&in6_tmpaddrtimer_ch, | |
209 | (ip6_temp_preferred_lifetime - ip6_desync_factor - | 205 | (ip6_temp_preferred_lifetime - ip6_desync_factor - | |
210 | ip6_temp_regen_advance) * hz, | 206 | ip6_temp_regen_advance) * hz, | |
211 | in6_tmpaddrtimer, NULL); | 207 | in6_tmpaddrtimer, NULL); | |
212 | } | 208 | } | |
213 | 209 | |||
214 | /* | 210 | /* | |
215 | * IP6 input interrupt handling. Just pass the packet to ip6_input. | 211 | * IP6 input interrupt handling. Just pass the packet to ip6_input. | |
216 | */ | 212 | */ | |
217 | static void | 213 | static void | |
218 | ip6intr(void *arg __unused) | 214 | ip6intr(void *arg __unused) | |
219 | { | 215 | { | |
220 | struct mbuf *m; | 216 | struct mbuf *m; | |
221 | 217 | |||
222 | mutex_enter(softnet_lock); | 218 | mutex_enter(softnet_lock); | |
223 | while ((m = pktq_dequeue(ip6_pktq)) != NULL) { | 219 | while ((m = pktq_dequeue(ip6_pktq)) != NULL) { | |
224 | const ifnet_t *ifp = m->m_pkthdr.rcvif; | 220 | const ifnet_t *ifp = m->m_pkthdr.rcvif; | |
225 | 221 | |||
226 | /* | 222 | /* | |
227 | * Drop the packet if IPv6 is disabled on the interface. | 223 | * Drop the packet if IPv6 is disabled on the interface. | |
228 | */ | 224 | */ | |
229 | if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) { | 225 | if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) { | |
230 | m_freem(m); | 226 | m_freem(m); | |
231 | continue; | 227 | continue; | |
232 | } | 228 | } | |
233 | ip6_input(m); | 229 | ip6_input(m); | |
234 | } | 230 | } | |
235 | mutex_exit(softnet_lock); | 231 | mutex_exit(softnet_lock); | |
236 | } | 232 | } | |
237 | 233 | |||
238 | extern struct route ip6_forward_rt; | 234 | extern struct route ip6_forward_rt; | |
239 | 235 | |||
240 | void | 236 | void | |
241 | ip6_input(struct mbuf *m) | 237 | ip6_input(struct mbuf *m) | |
242 | { | 238 | { | |
243 | struct ip6_hdr *ip6; | 239 | struct ip6_hdr *ip6; | |
244 | int hit, off = sizeof(struct ip6_hdr), nest; | 240 | int hit, off = sizeof(struct ip6_hdr), nest; | |
245 | u_int32_t plen; | 241 | u_int32_t plen; | |
246 | u_int32_t rtalert = ~0; | 242 | u_int32_t rtalert = ~0; | |
247 | int nxt, ours = 0, rh_present = 0; | 243 | int nxt, ours = 0, rh_present = 0; | |
248 | struct ifnet *deliverifp = NULL; | 244 | struct ifnet *deliverifp = NULL; | |
249 | int srcrt = 0; | 245 | int srcrt = 0; | |
250 | const struct rtentry *rt; | 246 | const struct rtentry *rt; | |
251 | union { | 247 | union { | |
252 | struct sockaddr dst; | 248 | struct sockaddr dst; | |
253 | struct sockaddr_in6 dst6; | 249 | struct sockaddr_in6 dst6; | |
254 | } u; | 250 | } u; | |
255 | 251 | |||
256 | /* | 252 | /* | |
257 | * make sure we don't have onion peering information into m_tag. | 253 | * make sure we don't have onion peering information into m_tag. | |
258 | */ | 254 | */ | |
259 | ip6_delaux(m); | 255 | ip6_delaux(m); | |
260 | 256 | |||
261 | /* | 257 | /* | |
262 | * mbuf statistics | 258 | * mbuf statistics | |
263 | */ | 259 | */ | |
264 | if (m->m_flags & M_EXT) { | 260 | if (m->m_flags & M_EXT) { | |
265 | if (m->m_next) | 261 | if (m->m_next) | |
266 | IP6_STATINC(IP6_STAT_MEXT2M); | 262 | IP6_STATINC(IP6_STAT_MEXT2M); | |
267 | else | 263 | else | |
268 | IP6_STATINC(IP6_STAT_MEXT1); | 264 | IP6_STATINC(IP6_STAT_MEXT1); | |
269 | } else { | 265 | } else { | |
270 | #define M2MMAX 32 | 266 | #define M2MMAX 32 | |
271 | if (m->m_next) { | 267 | if (m->m_next) { | |
272 | if (m->m_flags & M_LOOP) { | 268 | if (m->m_flags & M_LOOP) { | |
273 | /*XXX*/ IP6_STATINC(IP6_STAT_M2M + lo0ifp->if_index); | 269 | /*XXX*/ IP6_STATINC(IP6_STAT_M2M + lo0ifp->if_index); | |
274 | } else if (m->m_pkthdr.rcvif->if_index < M2MMAX) { | 270 | } else if (m->m_pkthdr.rcvif->if_index < M2MMAX) { | |
275 | IP6_STATINC(IP6_STAT_M2M + | 271 | IP6_STATINC(IP6_STAT_M2M + | |
276 | m->m_pkthdr.rcvif->if_index); | 272 | m->m_pkthdr.rcvif->if_index); | |
277 | } else | 273 | } else | |
278 | IP6_STATINC(IP6_STAT_M2M); | 274 | IP6_STATINC(IP6_STAT_M2M); | |
279 | } else | 275 | } else | |
280 | IP6_STATINC(IP6_STAT_M1); | 276 | IP6_STATINC(IP6_STAT_M1); | |
281 | #undef M2MMAX | 277 | #undef M2MMAX | |
282 | } | 278 | } | |
283 | 279 | |||
284 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive); | 280 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive); | |
285 | IP6_STATINC(IP6_STAT_TOTAL); | 281 | IP6_STATINC(IP6_STAT_TOTAL); | |
286 | 282 | |||
287 | /* | 283 | /* | |
288 | * If the IPv6 header is not aligned, slurp it up into a new | 284 | * If the IPv6 header is not aligned, slurp it up into a new | |
289 | * mbuf with space for link headers, in the event we forward | 285 | * mbuf with space for link headers, in the event we forward | |
290 | * it. Otherwise, if it is aligned, make sure the entire base | 286 | * it. Otherwise, if it is aligned, make sure the entire base | |
291 | * IPv6 header is in the first mbuf of the chain. | 287 | * IPv6 header is in the first mbuf of the chain. | |
292 | */ | 288 | */ | |
293 | if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) { | 289 | if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) { | |
294 | struct ifnet *inifp = m->m_pkthdr.rcvif; | 290 | struct ifnet *inifp = m->m_pkthdr.rcvif; | |
295 | if ((m = m_copyup(m, sizeof(struct ip6_hdr), | 291 | if ((m = m_copyup(m, sizeof(struct ip6_hdr), | |
296 | (max_linkhdr + 3) & ~3)) == NULL) { | 292 | (max_linkhdr + 3) & ~3)) == NULL) { | |
297 | /* XXXJRT new stat, please */ | 293 | /* XXXJRT new stat, please */ | |
298 | IP6_STATINC(IP6_STAT_TOOSMALL); | 294 | IP6_STATINC(IP6_STAT_TOOSMALL); | |
299 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); | 295 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); | |
300 | return; | 296 | return; | |
301 | } | 297 | } | |
302 | } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) { | 298 | } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) { | |
303 | struct ifnet *inifp = m->m_pkthdr.rcvif; | 299 | struct ifnet *inifp = m->m_pkthdr.rcvif; | |
304 | if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { | 300 | if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { | |
305 | IP6_STATINC(IP6_STAT_TOOSMALL); | 301 | IP6_STATINC(IP6_STAT_TOOSMALL); | |
306 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); | 302 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); | |
307 | return; | 303 | return; | |
308 | } | 304 | } | |
309 | } | 305 | } | |
310 | 306 | |||
311 | ip6 = mtod(m, struct ip6_hdr *); | 307 | ip6 = mtod(m, struct ip6_hdr *); | |
312 | 308 | |||
313 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { | 309 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { | |
314 | IP6_STATINC(IP6_STAT_BADVERS); | 310 | IP6_STATINC(IP6_STAT_BADVERS); | |
315 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | 311 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | |
316 | goto bad; | 312 | goto bad; | |
317 | } | 313 | } | |
318 | 314 | |||
319 | /* | 315 | /* | |
320 | * Assume that we can create a fast-forward IP flow entry | 316 | * Assume that we can create a fast-forward IP flow entry | |
321 | * based on this packet. | 317 | * based on this packet. | |
322 | */ | 318 | */ | |
323 | m->m_flags |= M_CANFASTFWD; | 319 | m->m_flags |= M_CANFASTFWD; | |
324 | 320 | |||
325 | /* | 321 | /* | |
326 | * Run through list of hooks for input packets. If there are any | 322 | * Run through list of hooks for input packets. If there are any | |
327 | * filters which require that additional packets in the flow are | 323 | * filters which require that additional packets in the flow are | |
328 | * not fast-forwarded, they must clear the M_CANFASTFWD flag. | 324 | * not fast-forwarded, they must clear the M_CANFASTFWD flag. | |
329 | * Note that filters must _never_ set this flag, as another filter | 325 | * Note that filters must _never_ set this flag, as another filter | |
330 | * in the list may have previously cleared it. | 326 | * in the list may have previously cleared it. | |
331 | */ | 327 | */ | |
332 | /* | 328 | /* | |
333 | * let ipfilter look at packet on the wire, | 329 | * let ipfilter look at packet on the wire, | |
334 | * not the decapsulated packet. | 330 | * not the decapsulated packet. | |
335 | */ | 331 | */ | |
336 | #if defined(IPSEC) | 332 | #if defined(IPSEC) | |
337 | if (!ipsec_used || !ipsec_indone(m)) | 333 | if (!ipsec_used || !ipsec_indone(m)) | |
338 | #else | 334 | #else | |
339 | if (1) | 335 | if (1) | |
340 | #endif | 336 | #endif | |
341 | { | 337 | { | |
342 | struct in6_addr odst; | 338 | struct in6_addr odst; | |
343 | 339 | |||
344 | odst = ip6->ip6_dst; | 340 | odst = ip6->ip6_dst; | |
345 | if (pfil_run_hooks(inet6_pfil_hook, &m, m->m_pkthdr.rcvif, | 341 | if (pfil_run_hooks(inet6_pfil_hook, &m, m->m_pkthdr.rcvif, | |
346 | PFIL_IN) != 0) | 342 | PFIL_IN) != 0) | |
347 | return; | 343 | return; | |
348 | if (m == NULL) | 344 | if (m == NULL) | |
349 | return; | 345 | return; | |
350 | ip6 = mtod(m, struct ip6_hdr *); | 346 | ip6 = mtod(m, struct ip6_hdr *); | |
351 | srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); | 347 | srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); | |
352 | } | 348 | } | |
353 | 349 | |||
354 | IP6_STATINC(IP6_STAT_NXTHIST + ip6->ip6_nxt); | 350 | IP6_STATINC(IP6_STAT_NXTHIST + ip6->ip6_nxt); | |
355 | 351 | |||
356 | #ifdef ALTQ | 352 | #ifdef ALTQ | |
357 | if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) { | 353 | if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) { | |
358 | /* packet is dropped by traffic conditioner */ | 354 | /* packet is dropped by traffic conditioner */ | |
359 | return; | 355 | return; | |
360 | } | 356 | } | |
361 | #endif | 357 | #endif | |
362 | 358 | |||
363 | /* | 359 | /* | |
364 | * Check against address spoofing/corruption. | 360 | * Check against address spoofing/corruption. | |
365 | */ | 361 | */ | |
366 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || | 362 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || | |
367 | IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { | 363 | IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { | |
368 | /* | 364 | /* | |
369 | * XXX: "badscope" is not very suitable for a multicast source. | 365 | * XXX: "badscope" is not very suitable for a multicast source. | |
370 | */ | 366 | */ | |
371 | IP6_STATINC(IP6_STAT_BADSCOPE); | 367 | IP6_STATINC(IP6_STAT_BADSCOPE); | |
372 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | 368 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | |
373 | goto bad; | 369 | goto bad; | |
374 | } | 370 | } | |
375 | /* | 371 | /* | |
376 | * The following check is not documented in specs. A malicious | 372 | * The following check is not documented in specs. A malicious | |
377 | * party may be able to use IPv4 mapped addr to confuse tcp/udp stack | 373 | * party may be able to use IPv4 mapped addr to confuse tcp/udp stack | |
378 | * and bypass security checks (act as if it was from 127.0.0.1 by using | 374 | * and bypass security checks (act as if it was from 127.0.0.1 by using | |
379 | * IPv6 src ::ffff:127.0.0.1). Be cautious. | 375 | * IPv6 src ::ffff:127.0.0.1). Be cautious. | |
380 | * | 376 | * | |
381 | * This check chokes if we are in an SIIT cloud. As none of BSDs | 377 | * This check chokes if we are in an SIIT cloud. As none of BSDs | |
382 | * support IPv4-less kernel compilation, we cannot support SIIT | 378 | * support IPv4-less kernel compilation, we cannot support SIIT | |
383 | * environment at all. So, it makes more sense for us to reject any | 379 | * environment at all. So, it makes more sense for us to reject any | |
384 | * malicious packets for non-SIIT environment, than try to do a | 380 | * malicious packets for non-SIIT environment, than try to do a | |
385 | * partial support for SIIT environment. | 381 | * partial support for SIIT environment. | |
386 | */ | 382 | */ | |
387 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || | 383 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || | |
388 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { | 384 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { | |
389 | IP6_STATINC(IP6_STAT_BADSCOPE); | 385 | IP6_STATINC(IP6_STAT_BADSCOPE); | |
390 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | 386 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | |
391 | goto bad; | 387 | goto bad; | |
392 | } | 388 | } | |
393 | #if 0 | 389 | #if 0 | |
394 | /* | 390 | /* | |
395 | * Reject packets with IPv4 compatible addresses (auto tunnel). | 391 | * Reject packets with IPv4 compatible addresses (auto tunnel). | |
396 | * | 392 | * | |
397 | * The code forbids auto tunnel relay case in RFC1933 (the check is | 393 | * The code forbids auto tunnel relay case in RFC1933 (the check is | |
398 | * stronger than RFC1933). We may want to re-enable it if mech-xx | 394 | * stronger than RFC1933). We may want to re-enable it if mech-xx | |
399 | * is revised to forbid relaying case. | 395 | * is revised to forbid relaying case. | |
400 | */ | 396 | */ | |
401 | if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || | 397 | if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || | |
402 | IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { | 398 | IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { | |
403 | IP6_STATINC(IP6_STAT_BADSCOPE); | 399 | IP6_STATINC(IP6_STAT_BADSCOPE); | |
404 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | 400 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | |
405 | goto bad; | 401 | goto bad; | |
406 | } | 402 | } | |
407 | #endif | 403 | #endif | |
408 | 404 | |||
409 | /* | 405 | /* | |
410 | * Disambiguate address scope zones (if there is ambiguity). | 406 | * Disambiguate address scope zones (if there is ambiguity). | |
411 | * We first make sure that the original source or destination address | 407 | * We first make sure that the original source or destination address | |
412 | * is not in our internal form for scoped addresses. Such addresses | 408 | * is not in our internal form for scoped addresses. Such addresses | |
413 | * are not necessarily invalid spec-wise, but we cannot accept them due | 409 | * are not necessarily invalid spec-wise, but we cannot accept them due | |
414 | * to the usage conflict. | 410 | * to the usage conflict. | |
415 | * in6_setscope() then also checks and rejects the cases where src or | 411 | * in6_setscope() then also checks and rejects the cases where src or | |
416 | * dst are the loopback address and the receiving interface | 412 | * dst are the loopback address and the receiving interface | |
417 | * is not loopback. | 413 | * is not loopback. | |
418 | */ | 414 | */ | |
419 | if (__predict_false( | 415 | if (__predict_false( | |
420 | m_makewritable(&m, 0, sizeof(struct ip6_hdr), M_DONTWAIT))) | 416 | m_makewritable(&m, 0, sizeof(struct ip6_hdr), M_DONTWAIT))) | |
421 | goto bad; | 417 | goto bad; | |
422 | ip6 = mtod(m, struct ip6_hdr *); | 418 | ip6 = mtod(m, struct ip6_hdr *); | |
423 | if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) { | 419 | if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) { | |
424 | IP6_STATINC(IP6_STAT_BADSCOPE); /* XXX */ | 420 | IP6_STATINC(IP6_STAT_BADSCOPE); /* XXX */ | |
425 | goto bad; | 421 | goto bad; | |
426 | } | 422 | } | |
427 | if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) || | 423 | if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) || | |
428 | in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) { | 424 | in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) { | |
429 | IP6_STATINC(IP6_STAT_BADSCOPE); | 425 | IP6_STATINC(IP6_STAT_BADSCOPE); | |
430 | goto bad; | 426 | goto bad; | |
431 | } | 427 | } | |
432 | 428 | |||
433 | /* | 429 | /* | |
434 | * Multicast check | 430 | * Multicast check | |
435 | */ | 431 | */ | |
436 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | 432 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | |
437 | struct in6_multi *in6m = 0; | 433 | struct in6_multi *in6m = 0; | |
438 | 434 | |||
439 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast); | 435 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast); | |
440 | /* | 436 | /* | |
441 | * See if we belong to the destination multicast group on the | 437 | * See if we belong to the destination multicast group on the | |
442 | * arrival interface. | 438 | * arrival interface. | |
443 | */ | 439 | */ | |
444 | IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m); | 440 | IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m); | |
445 | if (in6m) | 441 | if (in6m) | |
446 | ours = 1; | 442 | ours = 1; | |
447 | else if (!ip6_mrouter) { | 443 | else if (!ip6_mrouter) { | |
448 | uint64_t *ip6s = IP6_STAT_GETREF(); | 444 | uint64_t *ip6s = IP6_STAT_GETREF(); | |
449 | ip6s[IP6_STAT_NOTMEMBER]++; | 445 | ip6s[IP6_STAT_NOTMEMBER]++; | |
450 | ip6s[IP6_STAT_CANTFORWARD]++; | 446 | ip6s[IP6_STAT_CANTFORWARD]++; | |
451 | IP6_STAT_PUTREF(); | 447 | IP6_STAT_PUTREF(); | |
452 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | 448 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | |
453 | goto bad; | 449 | goto bad; | |
454 | } | 450 | } | |
455 | deliverifp = m->m_pkthdr.rcvif; | 451 | deliverifp = m->m_pkthdr.rcvif; | |
456 | goto hbhcheck; | 452 | goto hbhcheck; | |
457 | } | 453 | } | |
458 | 454 | |||
459 | sockaddr_in6_init(&u.dst6, &ip6->ip6_dst, 0, 0, 0); | 455 | sockaddr_in6_init(&u.dst6, &ip6->ip6_dst, 0, 0, 0); | |
460 | 456 | |||
461 | /* | 457 | /* | |
462 | * Unicast check | 458 | * Unicast check | |
463 | */ | 459 | */ | |
464 | rt = rtcache_lookup2(&ip6_forward_rt, &u.dst, 1, &hit); | 460 | rt = rtcache_lookup2(&ip6_forward_rt, &u.dst, 1, &hit); | |
465 | if (hit) | 461 | if (hit) | |
466 | IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); | 462 | IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); | |
467 | else | 463 | else | |
468 | IP6_STATINC(IP6_STAT_FORWARD_CACHEMISS); | 464 | IP6_STATINC(IP6_STAT_FORWARD_CACHEMISS); | |
469 | 465 | |||
470 | #define rt6_getkey(__rt) satocsin6(rt_getkey(__rt)) | 466 | #define rt6_getkey(__rt) satocsin6(rt_getkey(__rt)) | |
471 | 467 | |||
472 | /* | 468 | /* | |
473 | * Accept the packet if the forwarding interface to the destination | 469 | * Accept the packet if the forwarding interface to the destination | |
474 | * according to the routing table is the loopback interface, | 470 | * according to the routing table is the loopback interface, | |
475 | * unless the associated route has a gateway. | 471 | * unless the associated route has a gateway. | |
476 | * Note that this approach causes to accept a packet if there is a | 472 | * Note that this approach causes to accept a packet if there is a | |
477 | * route to the loopback interface for the destination of the packet. | 473 | * route to the loopback interface for the destination of the packet. | |
478 | * But we think it's even useful in some situations, e.g. when using | 474 | * But we think it's even useful in some situations, e.g. when using | |
479 | * a special daemon which wants to intercept the packet. | 475 | * a special daemon which wants to intercept the packet. | |
480 | */ | 476 | */ | |
481 | if (rt != NULL && | 477 | if (rt != NULL && | |
482 | (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST && | 478 | (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST && | |
483 | !(rt->rt_flags & RTF_CLONED) && | 479 | !(rt->rt_flags & RTF_CLONED) && | |
484 | #if 0 | 480 | #if 0 | |
485 | /* | 481 | /* | |
486 | * The check below is redundant since the comparison of | 482 | * The check below is redundant since the comparison of | |
487 | * the destination and the key of the rtentry has | 483 | * the destination and the key of the rtentry has | |
488 | * already done through looking up the routing table. | 484 | * already done through looking up the routing table. | |
489 | */ | 485 | */ | |
490 | IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &rt6_getkey(rt)->sin6_addr) && | 486 | IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &rt6_getkey(rt)->sin6_addr) && | |
491 | #endif | 487 | #endif | |
492 | rt->rt_ifp->if_type == IFT_LOOP) { | 488 | rt->rt_ifp->if_type == IFT_LOOP) { | |
493 | struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa; | 489 | struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa; | |
494 | if (ia6->ia6_flags & IN6_IFF_ANYCAST) | 490 | if (ia6->ia6_flags & IN6_IFF_ANYCAST) | |
495 | m->m_flags |= M_ANYCAST6; | 491 | m->m_flags |= M_ANYCAST6; | |
496 | /* | 492 | /* | |
497 | * packets to a tentative, duplicated, or somehow invalid | 493 | * packets to a tentative, duplicated, or somehow invalid | |
498 | * address must not be accepted. | 494 | * address must not be accepted. | |
499 | */ | 495 | */ | |
500 | if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { | 496 | if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { | |
501 | /* this address is ready */ | 497 | /* this address is ready */ | |
502 | ours = 1; | 498 | ours = 1; | |
503 | deliverifp = ia6->ia_ifp; /* correct? */ | 499 | deliverifp = ia6->ia_ifp; /* correct? */ | |
504 | goto hbhcheck; | 500 | goto hbhcheck; | |
505 | } else { | 501 | } else { | |
506 | /* address is not ready, so discard the packet. */ | 502 | /* address is not ready, so discard the packet. */ | |
507 | nd6log((LOG_INFO, | 503 | nd6log((LOG_INFO, | |
508 | "ip6_input: packet to an unready address %s->%s\n", | 504 | "ip6_input: packet to an unready address %s->%s\n", | |
509 | ip6_sprintf(&ip6->ip6_src), | 505 | ip6_sprintf(&ip6->ip6_src), | |
510 | ip6_sprintf(&ip6->ip6_dst))); | 506 | ip6_sprintf(&ip6->ip6_dst))); | |
511 | 507 | |||
512 | goto bad; | 508 | goto bad; | |
513 | } | 509 | } | |
514 | } | 510 | } | |
515 | 511 | |||
516 | /* | 512 | /* | |
517 | * FAITH (Firewall Aided Internet Translator) | 513 | * FAITH (Firewall Aided Internet Translator) | |
518 | */ | 514 | */ | |
519 | #if defined(NFAITH) && 0 < NFAITH | 515 | #if defined(NFAITH) && 0 < NFAITH | |
520 | if (ip6_keepfaith) { | 516 | if (ip6_keepfaith) { | |
521 | if (rt != NULL && rt->rt_ifp != NULL && | 517 | if (rt != NULL && rt->rt_ifp != NULL && | |
522 | rt->rt_ifp->if_type == IFT_FAITH) { | 518 | rt->rt_ifp->if_type == IFT_FAITH) { | |
523 | /* XXX do we need more sanity checks? */ | 519 | /* XXX do we need more sanity checks? */ | |
524 | ours = 1; | 520 | ours = 1; | |
525 | deliverifp = rt->rt_ifp; /* faith */ | 521 | deliverifp = rt->rt_ifp; /* faith */ | |
526 | goto hbhcheck; | 522 | goto hbhcheck; | |
527 | } | 523 | } | |
528 | } | 524 | } | |
529 | #endif | 525 | #endif | |
530 | 526 | |||
531 | #if 0 | 527 | #if 0 | |
532 | { | 528 | { | |
533 | /* | 529 | /* | |
534 | * Last resort: check in6_ifaddr for incoming interface. | 530 | * Last resort: check in6_ifaddr for incoming interface. | |
535 | * The code is here until I update the "goto ours hack" code above | 531 | * The code is here until I update the "goto ours hack" code above | |
536 | * working right. | 532 | * working right. | |
537 | */ | 533 | */ | |
538 | struct ifaddr *ifa; | 534 | struct ifaddr *ifa; | |
539 | IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) { | 535 | IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) { | |
540 | if (ifa->ifa_addr == NULL) | 536 | if (ifa->ifa_addr == NULL) | |
541 | continue; /* just for safety */ | 537 | continue; /* just for safety */ | |
542 | if (ifa->ifa_addr->sa_family != AF_INET6) | 538 | if (ifa->ifa_addr->sa_family != AF_INET6) | |
543 | continue; | 539 | continue; | |
544 | if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { | 540 | if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { | |
545 | ours = 1; | 541 | ours = 1; | |
546 | deliverifp = ifa->ifa_ifp; | 542 | deliverifp = ifa->ifa_ifp; | |
547 | goto hbhcheck; | 543 | goto hbhcheck; | |
548 | } | 544 | } | |
549 | } | 545 | } | |
550 | } | 546 | } | |
551 | #endif | 547 | #endif | |
552 | 548 | |||
553 | /* | 549 | /* | |
554 | * Now there is no reason to process the packet if it's not our own | 550 | * Now there is no reason to process the packet if it's not our own | |
555 | * and we're not a router. | 551 | * and we're not a router. | |
556 | */ | 552 | */ | |
557 | if (!ip6_forwarding) { | 553 | if (!ip6_forwarding) { | |
558 | IP6_STATINC(IP6_STAT_CANTFORWARD); | 554 | IP6_STATINC(IP6_STAT_CANTFORWARD); | |
559 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | 555 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | |
560 | goto bad; | 556 | goto bad; | |
561 | } | 557 | } | |
562 | 558 | |||
563 | hbhcheck: | 559 | hbhcheck: | |
564 | /* | 560 | /* | |
565 | * record address information into m_tag, if we don't have one yet. | 561 | * record address information into m_tag, if we don't have one yet. | |
566 | * note that we are unable to record it, if the address is not listed | 562 | * note that we are unable to record it, if the address is not listed | |
567 | * as our interface address (e.g. multicast addresses, addresses | 563 | * as our interface address (e.g. multicast addresses, addresses | |
568 | * within FAITH prefixes and such). | 564 | * within FAITH prefixes and such). | |
569 | */ | 565 | */ | |
570 | if (deliverifp && ip6_getdstifaddr(m) == NULL) { | 566 | if (deliverifp && ip6_getdstifaddr(m) == NULL) { | |
571 | struct in6_ifaddr *ia6; | 567 | struct in6_ifaddr *ia6; | |
572 | 568 | |||
573 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); | 569 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); | |
574 | if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) { | 570 | if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) { | |
575 | /* | 571 | /* | |
576 | * XXX maybe we should drop the packet here, | 572 | * XXX maybe we should drop the packet here, | |
577 | * as we could not provide enough information | 573 | * as we could not provide enough information | |
578 | * to the upper layers. | 574 | * to the upper layers. | |
579 | */ | 575 | */ | |
580 | } | 576 | } | |
581 | } | 577 | } | |
582 | 578 | |||
583 | /* | 579 | /* | |
584 | * Process Hop-by-Hop options header if it's contained. | 580 | * Process Hop-by-Hop options header if it's contained. | |
585 | * m may be modified in ip6_hopopts_input(). | 581 | * m may be modified in ip6_hopopts_input(). | |
586 | * If a JumboPayload option is included, plen will also be modified. | 582 | * If a JumboPayload option is included, plen will also be modified. | |
587 | */ | 583 | */ | |
588 | plen = (u_int32_t)ntohs(ip6->ip6_plen); | 584 | plen = (u_int32_t)ntohs(ip6->ip6_plen); | |
589 | if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { | 585 | if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { | |
590 | struct ip6_hbh *hbh; | 586 | struct ip6_hbh *hbh; | |
591 | 587 | |||
592 | if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { | 588 | if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { | |
593 | #if 0 /*touches NULL pointer*/ | 589 | #if 0 /*touches NULL pointer*/ | |
594 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | 590 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | |
595 | #endif | 591 | #endif | |
596 | return; /* m have already been freed */ | 592 | return; /* m have already been freed */ | |
597 | } | 593 | } | |
598 | 594 | |||
599 | /* adjust pointer */ | 595 | /* adjust pointer */ | |
600 | ip6 = mtod(m, struct ip6_hdr *); | 596 | ip6 = mtod(m, struct ip6_hdr *); | |
601 | 597 | |||
602 | /* | 598 | /* | |
603 | * if the payload length field is 0 and the next header field | 599 | * if the payload length field is 0 and the next header field | |
604 | * indicates Hop-by-Hop Options header, then a Jumbo Payload | 600 | * indicates Hop-by-Hop Options header, then a Jumbo Payload | |
605 | * option MUST be included. | 601 | * option MUST be included. | |
606 | */ | 602 | */ | |
607 | if (ip6->ip6_plen == 0 && plen == 0) { | 603 | if (ip6->ip6_plen == 0 && plen == 0) { | |
608 | /* | 604 | /* | |
609 | * Note that if a valid jumbo payload option is | 605 | * Note that if a valid jumbo payload option is | |
610 | * contained, ip6_hopopts_input() must set a valid | 606 | * contained, ip6_hopopts_input() must set a valid | |
611 | * (non-zero) payload length to the variable plen. | 607 | * (non-zero) payload length to the variable plen. | |
612 | */ | 608 | */ | |
613 | IP6_STATINC(IP6_STAT_BADOPTIONS); | 609 | IP6_STATINC(IP6_STAT_BADOPTIONS); | |
614 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | 610 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | |
615 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | 611 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | |
616 | icmp6_error(m, ICMP6_PARAM_PROB, | 612 | icmp6_error(m, ICMP6_PARAM_PROB, | |
617 | ICMP6_PARAMPROB_HEADER, | 613 | ICMP6_PARAMPROB_HEADER, | |
618 | (char *)&ip6->ip6_plen - (char *)ip6); | 614 | (char *)&ip6->ip6_plen - (char *)ip6); | |
619 | return; | 615 | return; | |
620 | } | 616 | } | |
621 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), | 617 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), | |
622 | sizeof(struct ip6_hbh)); | 618 | sizeof(struct ip6_hbh)); | |
623 | if (hbh == NULL) { | 619 | if (hbh == NULL) { | |
624 | IP6_STATINC(IP6_STAT_TOOSHORT); | 620 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
625 | return; | 621 | return; | |
626 | } | 622 | } | |
627 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); | 623 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); | |
628 | nxt = hbh->ip6h_nxt; | 624 | nxt = hbh->ip6h_nxt; | |
629 | 625 | |||
630 | /* | 626 | /* | |
631 | * accept the packet if a router alert option is included | 627 | * accept the packet if a router alert option is included | |
632 | * and we act as an IPv6 router. | 628 | * and we act as an IPv6 router. | |
633 | */ | 629 | */ | |
634 | if (rtalert != ~0 && ip6_forwarding) | 630 | if (rtalert != ~0 && ip6_forwarding) | |
635 | ours = 1; | 631 | ours = 1; | |
636 | } else | 632 | } else | |
637 | nxt = ip6->ip6_nxt; | 633 | nxt = ip6->ip6_nxt; | |
638 | 634 | |||
639 | /* | 635 | /* | |
640 | * Check that the amount of data in the buffers | 636 | * Check that the amount of data in the buffers | |
641 | * is as at least much as the IPv6 header would have us expect. | 637 | * is as at least much as the IPv6 header would have us expect. | |
642 | * Trim mbufs if longer than we expect. | 638 | * Trim mbufs if longer than we expect. | |
643 | * Drop packet if shorter than we expect. | 639 | * Drop packet if shorter than we expect. | |
644 | */ | 640 | */ | |
645 | if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { | 641 | if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { | |
646 | IP6_STATINC(IP6_STAT_TOOSHORT); | 642 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
647 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | 643 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | |
648 | goto bad; | 644 | goto bad; | |
649 | } | 645 | } | |
650 | if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { | 646 | if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { | |
651 | if (m->m_len == m->m_pkthdr.len) { | 647 | if (m->m_len == m->m_pkthdr.len) { | |
652 | m->m_len = sizeof(struct ip6_hdr) + plen; | 648 | m->m_len = sizeof(struct ip6_hdr) + plen; | |
653 | m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; | 649 | m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; | |
654 | } else | 650 | } else | |
655 | m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); | 651 | m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); | |
656 | } | 652 | } | |
657 | 653 | |||
658 | /* | 654 | /* | |
659 | * Forward if desirable. | 655 | * Forward if desirable. | |
660 | */ | 656 | */ | |
661 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | 657 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | |
662 | /* | 658 | /* | |
663 | * If we are acting as a multicast router, all | 659 | * If we are acting as a multicast router, all | |
664 | * incoming multicast packets are passed to the | 660 | * incoming multicast packets are passed to the | |
665 | * kernel-level multicast forwarding function. | 661 | * kernel-level multicast forwarding function. | |
666 | * The packet is returned (relatively) intact; if | 662 | * The packet is returned (relatively) intact; if | |
667 | * ip6_mforward() returns a non-zero value, the packet | 663 | * ip6_mforward() returns a non-zero value, the packet | |
668 | * must be discarded, else it may be accepted below. | 664 | * must be discarded, else it may be accepted below. | |
669 | */ | 665 | */ | |
670 | if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { | 666 | if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { | |
671 | IP6_STATINC(IP6_STAT_CANTFORWARD); | 667 | IP6_STATINC(IP6_STAT_CANTFORWARD); | |
672 | m_freem(m); | 668 | m_freem(m); | |
673 | return; | 669 | return; | |
674 | } | 670 | } | |
675 | if (!ours) { | 671 | if (!ours) { | |
676 | m_freem(m); | 672 | m_freem(m); | |
677 | return; | 673 | return; | |
678 | } | 674 | } | |
679 | } else if (!ours) { | 675 | } else if (!ours) { | |
680 | ip6_forward(m, srcrt); | 676 | ip6_forward(m, srcrt); | |
681 | return; | 677 | return; | |
682 | } | 678 | } | |
683 | 679 | |||
684 | ip6 = mtod(m, struct ip6_hdr *); | 680 | ip6 = mtod(m, struct ip6_hdr *); | |
685 | 681 | |||
686 | /* | 682 | /* | |
687 | * Malicious party may be able to use IPv4 mapped addr to confuse | 683 | * Malicious party may be able to use IPv4 mapped addr to confuse | |
688 | * tcp/udp stack and bypass security checks (act as if it was from | 684 | * tcp/udp stack and bypass security checks (act as if it was from | |
689 | * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious. | 685 | * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious. | |
690 | * | 686 | * | |
691 | * For SIIT end node behavior, you may want to disable the check. | 687 | * For SIIT end node behavior, you may want to disable the check. | |
692 | * However, you will become vulnerable to attacks using IPv4 mapped | 688 | * However, you will become vulnerable to attacks using IPv4 mapped | |
693 | * source. | 689 | * source. | |
694 | */ | 690 | */ | |
695 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || | 691 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || | |
696 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { | 692 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { | |
697 | IP6_STATINC(IP6_STAT_BADSCOPE); | 693 | IP6_STATINC(IP6_STAT_BADSCOPE); | |
698 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | 694 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | |
699 | goto bad; | 695 | goto bad; | |
700 | } | 696 | } | |
701 | 697 | |||
702 | /* | 698 | /* | |
703 | * Tell launch routine the next header | 699 | * Tell launch routine the next header | |
704 | */ | 700 | */ | |
705 | #ifdef IFA_STATS | 701 | #ifdef IFA_STATS | |
706 | if (deliverifp != NULL) { | 702 | if (deliverifp != NULL) { | |
707 | struct in6_ifaddr *ia6; | 703 | struct in6_ifaddr *ia6; | |
708 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); | 704 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); | |
709 | if (ia6) | 705 | if (ia6) | |
710 | ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; | 706 | ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; | |
711 | } | 707 | } | |
712 | #endif | 708 | #endif | |
713 | IP6_STATINC(IP6_STAT_DELIVERED); | 709 | IP6_STATINC(IP6_STAT_DELIVERED); | |
714 | in6_ifstat_inc(deliverifp, ifs6_in_deliver); | 710 | in6_ifstat_inc(deliverifp, ifs6_in_deliver); | |
715 | nest = 0; | 711 | nest = 0; | |
716 | 712 | |||
717 | rh_present = 0; | 713 | rh_present = 0; | |
718 | while (nxt != IPPROTO_DONE) { | 714 | while (nxt != IPPROTO_DONE) { | |
719 | if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { | 715 | if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { | |
720 | IP6_STATINC(IP6_STAT_TOOMANYHDR); | 716 | IP6_STATINC(IP6_STAT_TOOMANYHDR); | |
721 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | 717 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | |
722 | goto bad; | 718 | goto bad; | |
723 | } | 719 | } | |
724 | 720 | |||
725 | /* | 721 | /* | |
726 | * protection against faulty packet - there should be | 722 | * protection against faulty packet - there should be | |
727 | * more sanity checks in header chain processing. | 723 | * more sanity checks in header chain processing. | |
728 | */ | 724 | */ | |
729 | if (m->m_pkthdr.len < off) { | 725 | if (m->m_pkthdr.len < off) { | |
730 | IP6_STATINC(IP6_STAT_TOOSHORT); | 726 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
731 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | 727 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | |
732 | goto bad; | 728 | goto bad; | |
733 | } | 729 | } | |
734 | 730 | |||
735 | if (nxt == IPPROTO_ROUTING) { | 731 | if (nxt == IPPROTO_ROUTING) { | |
736 | if (rh_present++) { | 732 | if (rh_present++) { | |
737 | in6_ifstat_inc(m->m_pkthdr.rcvif, | 733 | in6_ifstat_inc(m->m_pkthdr.rcvif, | |
738 | ifs6_in_hdrerr); | 734 | ifs6_in_hdrerr); | |
739 | IP6_STATINC(IP6_STAT_BADOPTIONS); | 735 | IP6_STATINC(IP6_STAT_BADOPTIONS); | |
740 | goto bad; | 736 | goto bad; | |
741 | } | 737 | } | |
742 | } | 738 | } | |
743 | 739 | |||
744 | #ifdef IPSEC | 740 | #ifdef IPSEC | |
745 | if (ipsec_used) { | 741 | if (ipsec_used) { | |
746 | /* | 742 | /* | |
747 | * enforce IPsec policy checking if we are seeing last | 743 | * enforce IPsec policy checking if we are seeing last | |
748 | * header. note that we do not visit this with | 744 | * header. note that we do not visit this with | |
749 | * protocols with pcb layer code - like udp/tcp/raw ip. | 745 | * protocols with pcb layer code - like udp/tcp/raw ip. | |
750 | */ | 746 | */ | |
751 | if ((inet6sw[ip_protox[nxt]].pr_flags | 747 | if ((inet6sw[ip_protox[nxt]].pr_flags | |
752 | & PR_LASTHDR) != 0) { | 748 | & PR_LASTHDR) != 0) { | |
753 | int error = ipsec6_input(m); | 749 | int error = ipsec6_input(m); | |
754 | if (error) | 750 | if (error) | |
755 | goto bad; | 751 | goto bad; | |
756 | } | 752 | } | |
757 | } | 753 | } | |
758 | #endif /* IPSEC */ | 754 | #endif /* IPSEC */ | |
759 | 755 | |||
760 | nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); | 756 | nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); | |
761 | } | 757 | } | |
762 | return; | 758 | return; | |
763 | bad: | 759 | bad: | |
764 | m_freem(m); | 760 | m_freem(m); | |
765 | } | 761 | } | |
766 | 762 | |||
767 | /* | 763 | /* | |
768 | * set/grab in6_ifaddr correspond to IPv6 destination address. | 764 | * set/grab in6_ifaddr correspond to IPv6 destination address. | |
769 | */ | 765 | */ | |
770 | static struct m_tag * | 766 | static struct m_tag * | |
771 | ip6_setdstifaddr(struct mbuf *m, const struct in6_ifaddr *ia) | 767 | ip6_setdstifaddr(struct mbuf *m, const struct in6_ifaddr *ia) | |
772 | { | 768 | { | |
773 | struct m_tag *mtag; | 769 | struct m_tag *mtag; | |
774 | struct ip6aux *ip6a; | 770 | struct ip6aux *ip6a; | |
775 | 771 | |||
776 | mtag = ip6_addaux(m); | 772 | mtag = ip6_addaux(m); | |
777 | if (mtag == NULL) | 773 | if (mtag == NULL) | |
778 | return NULL; | 774 | return NULL; | |
779 | 775 | |||
780 | ip6a = (struct ip6aux *)(mtag + 1); | 776 | ip6a = (struct ip6aux *)(mtag + 1); | |
781 | if (in6_setscope(&ip6a->ip6a_src, ia->ia_ifp, &ip6a->ip6a_scope_id)) { | 777 | if (in6_setscope(&ip6a->ip6a_src, ia->ia_ifp, &ip6a->ip6a_scope_id)) { | |
782 | IP6_STATINC(IP6_STAT_BADSCOPE); | 778 | IP6_STATINC(IP6_STAT_BADSCOPE); | |
783 | return NULL; | 779 | return NULL; | |
784 | } | 780 | } | |
785 | 781 | |||
786 | ip6a->ip6a_src = ia->ia_addr.sin6_addr; | 782 | ip6a->ip6a_src = ia->ia_addr.sin6_addr; | |
787 | ip6a->ip6a_flags = ia->ia6_flags; | 783 | ip6a->ip6a_flags = ia->ia6_flags; | |
788 | return mtag; | 784 | return mtag; | |
789 | } | 785 | } | |
790 | 786 | |||
791 | const struct ip6aux * | 787 | const struct ip6aux * | |
792 | ip6_getdstifaddr(struct mbuf *m) | 788 | ip6_getdstifaddr(struct mbuf *m) | |
793 | { | 789 | { | |
794 | struct m_tag *mtag; | 790 | struct m_tag *mtag; | |
795 | 791 | |||
796 | mtag = ip6_findaux(m); | 792 | mtag = ip6_findaux(m); | |
797 | if (mtag != NULL) | 793 | if (mtag != NULL) | |
798 | return (struct ip6aux *)(mtag + 1); | 794 | return (struct ip6aux *)(mtag + 1); | |
799 | else | 795 | else | |
800 | return NULL; | 796 | return NULL; | |
801 | } | 797 | } | |
802 | 798 | |||
803 | /* | 799 | /* | |
804 | * Hop-by-Hop options header processing. If a valid jumbo payload option is | 800 | * Hop-by-Hop options header processing. If a valid jumbo payload option is | |
805 | * included, the real payload length will be stored in plenp. | 801 | * included, the real payload length will be stored in plenp. | |
806 | * | 802 | * | |
807 | * rtalertp - XXX: should be stored more smart way | 803 | * rtalertp - XXX: should be stored more smart way | |
808 | */ | 804 | */ | |
809 | int | 805 | int | |
810 | ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp, | 806 | ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp, | |
811 | struct mbuf **mp, int *offp) | 807 | struct mbuf **mp, int *offp) | |
812 | { | 808 | { | |
813 | struct mbuf *m = *mp; | 809 | struct mbuf *m = *mp; | |
814 | int off = *offp, hbhlen; | 810 | int off = *offp, hbhlen; | |
815 | struct ip6_hbh *hbh; | 811 | struct ip6_hbh *hbh; | |
816 | 812 | |||
817 | /* validation of the length of the header */ | 813 | /* validation of the length of the header */ | |
818 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, | 814 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, | |
819 | sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); | 815 | sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); | |
820 | if (hbh == NULL) { | 816 | if (hbh == NULL) { | |
821 | IP6_STATINC(IP6_STAT_TOOSHORT); | 817 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
822 | return -1; | 818 | return -1; | |
823 | } | 819 | } | |
824 | hbhlen = (hbh->ip6h_len + 1) << 3; | 820 | hbhlen = (hbh->ip6h_len + 1) << 3; | |
825 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), | 821 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), | |
826 | hbhlen); | 822 | hbhlen); | |
827 | if (hbh == NULL) { | 823 | if (hbh == NULL) { | |
828 | IP6_STATINC(IP6_STAT_TOOSHORT); | 824 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
829 | return -1; | 825 | return -1; | |
830 | } | 826 | } | |
831 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); | 827 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); | |
832 | off += hbhlen; | 828 | off += hbhlen; | |
833 | hbhlen -= sizeof(struct ip6_hbh); | 829 | hbhlen -= sizeof(struct ip6_hbh); | |
834 | 830 | |||
835 | if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), | 831 | if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), | |
836 | hbhlen, rtalertp, plenp) < 0) | 832 | hbhlen, rtalertp, plenp) < 0) | |
837 | return (-1); | 833 | return (-1); | |
838 | 834 | |||
839 | *offp = off; | 835 | *offp = off; | |
840 | *mp = m; | 836 | *mp = m; | |
841 | return (0); | 837 | return (0); | |
842 | } | 838 | } | |
843 | 839 | |||
844 | /* | 840 | /* | |
845 | * Search header for all Hop-by-hop options and process each option. | 841 | * Search header for all Hop-by-hop options and process each option. | |
846 | * This function is separate from ip6_hopopts_input() in order to | 842 | * This function is separate from ip6_hopopts_input() in order to | |
847 | * handle a case where the sending node itself process its hop-by-hop | 843 | * handle a case where the sending node itself process its hop-by-hop | |
848 | * options header. In such a case, the function is called from ip6_output(). | 844 | * options header. In such a case, the function is called from ip6_output(). | |
849 | * | 845 | * | |
850 | * The function assumes that hbh header is located right after the IPv6 header | 846 | * The function assumes that hbh header is located right after the IPv6 header | |
851 | * (RFC2460 p7), opthead is pointer into data content in m, and opthead to | 847 | * (RFC2460 p7), opthead is pointer into data content in m, and opthead to | |
852 | * opthead + hbhlen is located in continuous memory region. | 848 | * opthead + hbhlen is located in continuous memory region. | |
853 | */ | 849 | */ | |
854 | static int | 850 | static int | |
855 | ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen, | 851 | ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen, | |
856 | u_int32_t *rtalertp, u_int32_t *plenp) | 852 | u_int32_t *rtalertp, u_int32_t *plenp) | |
857 | { | 853 | { | |
858 | struct ip6_hdr *ip6; | 854 | struct ip6_hdr *ip6; | |
859 | int optlen = 0; | 855 | int optlen = 0; | |
860 | u_int8_t *opt = opthead; | 856 | u_int8_t *opt = opthead; | |
861 | u_int16_t rtalert_val; | 857 | u_int16_t rtalert_val; | |
862 | u_int32_t jumboplen; | 858 | u_int32_t jumboplen; | |
863 | const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); | 859 | const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); | |
864 | 860 | |||
865 | for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { | 861 | for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { | |
866 | switch (*opt) { | 862 | switch (*opt) { | |
867 | case IP6OPT_PAD1: | 863 | case IP6OPT_PAD1: | |
868 | optlen = 1; | 864 | optlen = 1; | |
869 | break; | 865 | break; | |
870 | case IP6OPT_PADN: | 866 | case IP6OPT_PADN: | |
871 | if (hbhlen < IP6OPT_MINLEN) { | 867 | if (hbhlen < IP6OPT_MINLEN) { | |
872 | IP6_STATINC(IP6_STAT_TOOSMALL); | 868 | IP6_STATINC(IP6_STAT_TOOSMALL); | |
873 | goto bad; | 869 | goto bad; | |
874 | } | 870 | } | |
875 | optlen = *(opt + 1) + 2; | 871 | optlen = *(opt + 1) + 2; | |
876 | break; | 872 | break; | |
877 | case IP6OPT_RTALERT: | 873 | case IP6OPT_RTALERT: | |
878 | /* XXX may need check for alignment */ | 874 | /* XXX may need check for alignment */ | |
879 | if (hbhlen < IP6OPT_RTALERT_LEN) { | 875 | if (hbhlen < IP6OPT_RTALERT_LEN) { | |
880 | IP6_STATINC(IP6_STAT_TOOSMALL); | 876 | IP6_STATINC(IP6_STAT_TOOSMALL); | |
881 | goto bad; | 877 | goto bad; | |
882 | } | 878 | } | |
883 | if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { | 879 | if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { | |
884 | /* XXX stat */ | 880 | /* XXX stat */ | |
885 | icmp6_error(m, ICMP6_PARAM_PROB, | 881 | icmp6_error(m, ICMP6_PARAM_PROB, | |
886 | ICMP6_PARAMPROB_HEADER, | 882 | ICMP6_PARAMPROB_HEADER, | |
887 | erroff + opt + 1 - opthead); | 883 | erroff + opt + 1 - opthead); | |
888 | return (-1); | 884 | return (-1); | |
889 | } | 885 | } | |
890 | optlen = IP6OPT_RTALERT_LEN; | 886 | optlen = IP6OPT_RTALERT_LEN; | |
891 | memcpy((void *)&rtalert_val, (void *)(opt + 2), 2); | 887 | memcpy((void *)&rtalert_val, (void *)(opt + 2), 2); | |
892 | *rtalertp = ntohs(rtalert_val); | 888 | *rtalertp = ntohs(rtalert_val); | |
893 | break; | 889 | break; | |
894 | case IP6OPT_JUMBO: | 890 | case IP6OPT_JUMBO: | |
895 | /* XXX may need check for alignment */ | 891 | /* XXX may need check for alignment */ | |
896 | if (hbhlen < IP6OPT_JUMBO_LEN) { | 892 | if (hbhlen < IP6OPT_JUMBO_LEN) { | |
897 | IP6_STATINC(IP6_STAT_TOOSMALL); | 893 | IP6_STATINC(IP6_STAT_TOOSMALL); | |
898 | goto bad; | 894 | goto bad; | |
899 | } | 895 | } | |
900 | if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { | 896 | if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { | |
901 | /* XXX stat */ | 897 | /* XXX stat */ | |
902 | icmp6_error(m, ICMP6_PARAM_PROB, | 898 | icmp6_error(m, ICMP6_PARAM_PROB, | |
903 | ICMP6_PARAMPROB_HEADER, | 899 | ICMP6_PARAMPROB_HEADER, | |
904 | erroff + opt + 1 - opthead); | 900 | erroff + opt + 1 - opthead); | |
905 | return (-1); | 901 | return (-1); | |
906 | } | 902 | } | |
907 | optlen = IP6OPT_JUMBO_LEN; | 903 | optlen = IP6OPT_JUMBO_LEN; | |
908 | 904 | |||
909 | /* | 905 | /* | |
910 | * IPv6 packets that have non 0 payload length | 906 | * IPv6 packets that have non 0 payload length | |
911 | * must not contain a jumbo payload option. | 907 | * must not contain a jumbo payload option. | |
912 | */ | 908 | */ | |
913 | ip6 = mtod(m, struct ip6_hdr *); | 909 | ip6 = mtod(m, struct ip6_hdr *); | |
914 | if (ip6->ip6_plen) { | 910 | if (ip6->ip6_plen) { | |
915 | IP6_STATINC(IP6_STAT_BADOPTIONS); | 911 | IP6_STATINC(IP6_STAT_BADOPTIONS); | |
916 | icmp6_error(m, ICMP6_PARAM_PROB, | 912 | icmp6_error(m, ICMP6_PARAM_PROB, | |
917 | ICMP6_PARAMPROB_HEADER, | 913 | ICMP6_PARAMPROB_HEADER, | |
918 | erroff + opt - opthead); | 914 | erroff + opt - opthead); | |
919 | return (-1); | 915 | return (-1); | |
920 | } | 916 | } | |
921 | 917 | |||
922 | /* | 918 | /* | |
923 | * We may see jumbolen in unaligned location, so | 919 | * We may see jumbolen in unaligned location, so | |
924 | * we'd need to perform bcopy(). | 920 | * we'd need to perform bcopy(). | |
925 | */ | 921 | */ | |
926 | memcpy(&jumboplen, opt + 2, sizeof(jumboplen)); | 922 | memcpy(&jumboplen, opt + 2, sizeof(jumboplen)); | |
927 | jumboplen = (u_int32_t)htonl(jumboplen); | 923 | jumboplen = (u_int32_t)htonl(jumboplen); | |
928 | 924 | |||
929 | #if 1 | 925 | #if 1 | |
930 | /* | 926 | /* | |
931 | * if there are multiple jumbo payload options, | 927 | * if there are multiple jumbo payload options, | |
932 | * *plenp will be non-zero and the packet will be | 928 | * *plenp will be non-zero and the packet will be | |
933 | * rejected. | 929 | * rejected. | |
934 | * the behavior may need some debate in ipngwg - | 930 | * the behavior may need some debate in ipngwg - | |
935 | * multiple options does not make sense, however, | 931 | * multiple options does not make sense, however, | |
936 | * there's no explicit mention in specification. | 932 | * there's no explicit mention in specification. | |
937 | */ | 933 | */ | |
938 | if (*plenp != 0) { | 934 | if (*plenp != 0) { | |
939 | IP6_STATINC(IP6_STAT_BADOPTIONS); | 935 | IP6_STATINC(IP6_STAT_BADOPTIONS); | |
940 | icmp6_error(m, ICMP6_PARAM_PROB, | 936 | icmp6_error(m, ICMP6_PARAM_PROB, | |
941 | ICMP6_PARAMPROB_HEADER, | 937 | ICMP6_PARAMPROB_HEADER, | |
942 | erroff + opt + 2 - opthead); | 938 | erroff + opt + 2 - opthead); | |
943 | return (-1); | 939 | return (-1); | |
944 | } | 940 | } | |
945 | #endif | 941 | #endif | |
946 | 942 | |||
947 | /* | 943 | /* | |
948 | * jumbo payload length must be larger than 65535. | 944 | * jumbo payload length must be larger than 65535. | |
949 | */ | 945 | */ | |
950 | if (jumboplen <= IPV6_MAXPACKET) { | 946 | if (jumboplen <= IPV6_MAXPACKET) { | |
951 | IP6_STATINC(IP6_STAT_BADOPTIONS); | 947 | IP6_STATINC(IP6_STAT_BADOPTIONS); | |
952 | icmp6_error(m, ICMP6_PARAM_PROB, | 948 | icmp6_error(m, ICMP6_PARAM_PROB, | |
953 | ICMP6_PARAMPROB_HEADER, | 949 | ICMP6_PARAMPROB_HEADER, | |
954 | erroff + opt + 2 - opthead); | 950 | erroff + opt + 2 - opthead); | |
955 | return (-1); | 951 | return (-1); | |
956 | } | 952 | } | |
957 | *plenp = jumboplen; | 953 | *plenp = jumboplen; | |
958 | 954 | |||
959 | break; | 955 | break; | |
960 | default: /* unknown option */ | 956 | default: /* unknown option */ | |
961 | if (hbhlen < IP6OPT_MINLEN) { | 957 | if (hbhlen < IP6OPT_MINLEN) { | |
962 | IP6_STATINC(IP6_STAT_TOOSMALL); | 958 | IP6_STATINC(IP6_STAT_TOOSMALL); | |
963 | goto bad; | 959 | goto bad; | |
964 | } | 960 | } | |
965 | optlen = ip6_unknown_opt(opt, m, | 961 | optlen = ip6_unknown_opt(opt, m, | |
966 | erroff + opt - opthead); | 962 | erroff + opt - opthead); | |
967 | if (optlen == -1) | 963 | if (optlen == -1) | |
968 | return (-1); | 964 | return (-1); | |
969 | optlen += 2; | 965 | optlen += 2; | |
970 | break; | 966 | break; | |
971 | } | 967 | } | |
972 | } | 968 | } | |
973 | 969 | |||
974 | return (0); | 970 | return (0); | |
975 | 971 | |||
976 | bad: | 972 | bad: | |
977 | m_freem(m); | 973 | m_freem(m); | |
978 | return (-1); | 974 | return (-1); | |
979 | } | 975 | } | |
980 | 976 | |||
981 | /* | 977 | /* | |
982 | * Unknown option processing. | 978 | * Unknown option processing. | |
983 | * The third argument `off' is the offset from the IPv6 header to the option, | 979 | * The third argument `off' is the offset from the IPv6 header to the option, | |
984 | * which is necessary if the IPv6 header the and option header and IPv6 header | 980 | * which is necessary if the IPv6 header the and option header and IPv6 header | |
985 | * is not continuous in order to return an ICMPv6 error. | 981 | * is not continuous in order to return an ICMPv6 error. | |
986 | */ | 982 | */ | |
987 | int | 983 | int | |
988 | ip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off) | 984 | ip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off) | |
989 | { | 985 | { | |
990 | struct ip6_hdr *ip6; | 986 | struct ip6_hdr *ip6; | |
991 | 987 | |||
992 | switch (IP6OPT_TYPE(*optp)) { | 988 | switch (IP6OPT_TYPE(*optp)) { | |
993 | case IP6OPT_TYPE_SKIP: /* ignore the option */ | 989 | case IP6OPT_TYPE_SKIP: /* ignore the option */ | |
994 | return ((int)*(optp + 1)); | 990 | return ((int)*(optp + 1)); | |
995 | case IP6OPT_TYPE_DISCARD: /* silently discard */ | 991 | case IP6OPT_TYPE_DISCARD: /* silently discard */ | |
996 | m_freem(m); | 992 | m_freem(m); | |
997 | return (-1); | 993 | return (-1); | |
998 | case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ | 994 | case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ | |
999 | IP6_STATINC(IP6_STAT_BADOPTIONS); | 995 | IP6_STATINC(IP6_STAT_BADOPTIONS); | |
1000 | icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); | 996 | icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); | |
1001 | return (-1); | 997 | return (-1); | |
1002 | case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ | 998 | case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ | |
1003 | IP6_STATINC(IP6_STAT_BADOPTIONS); | 999 | IP6_STATINC(IP6_STAT_BADOPTIONS); | |
1004 | ip6 = mtod(m, struct ip6_hdr *); | 1000 | ip6 = mtod(m, struct ip6_hdr *); | |
1005 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || | 1001 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || | |
1006 | (m->m_flags & (M_BCAST|M_MCAST))) | 1002 | (m->m_flags & (M_BCAST|M_MCAST))) | |
1007 | m_freem(m); | 1003 | m_freem(m); | |
1008 | else | 1004 | else | |
1009 | icmp6_error(m, ICMP6_PARAM_PROB, | 1005 | icmp6_error(m, ICMP6_PARAM_PROB, | |
1010 | ICMP6_PARAMPROB_OPTION, off); | 1006 | ICMP6_PARAMPROB_OPTION, off); | |
1011 | return (-1); | 1007 | return (-1); | |
1012 | } | 1008 | } | |
1013 | 1009 | |||
1014 | m_freem(m); /* XXX: NOTREACHED */ | 1010 | m_freem(m); /* XXX: NOTREACHED */ | |
1015 | return (-1); | 1011 | return (-1); | |
1016 | } | 1012 | } | |
1017 | 1013 | |||
1018 | /* | 1014 | /* | |
1019 | * Create the "control" list for this pcb. | 1015 | * Create the "control" list for this pcb. | |
1020 | * | 1016 | * | |
1021 | * The routine will be called from upper layer handlers like tcp6_input(). | 1017 | * The routine will be called from upper layer handlers like tcp6_input(). | |
1022 | * Thus the routine assumes that the caller (tcp6_input) have already | 1018 | * Thus the routine assumes that the caller (tcp6_input) have already | |
1023 | * called IP6_EXTHDR_CHECK() and all the extension headers are located in the | 1019 | * called IP6_EXTHDR_CHECK() and all the extension headers are located in the | |
1024 | * very first mbuf on the mbuf chain. | 1020 | * very first mbuf on the mbuf chain. | |
1025 | * We may want to add some infinite loop prevention or sanity checks for safety. | 1021 | * We may want to add some infinite loop prevention or sanity checks for safety. | |
1026 | * (This applies only when you are using KAME mbuf chain restriction, i.e. | 1022 | * (This applies only when you are using KAME mbuf chain restriction, i.e. | |
1027 | * you are using IP6_EXTHDR_CHECK() not m_pulldown()) | 1023 | * you are using IP6_EXTHDR_CHECK() not m_pulldown()) | |
1028 | */ | 1024 | */ | |
1029 | void | 1025 | void | |
1030 | ip6_savecontrol(struct in6pcb *in6p, struct mbuf **mp, | 1026 | ip6_savecontrol(struct in6pcb *in6p, struct mbuf **mp, | |
1031 | struct ip6_hdr *ip6, struct mbuf *m) | 1027 | struct ip6_hdr *ip6, struct mbuf *m) | |
1032 | { | 1028 | { | |
1033 | #ifdef RFC2292 | 1029 | #ifdef RFC2292 | |
1034 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) | 1030 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) | |
1035 | #else | 1031 | #else | |
1036 | #define IS2292(x, y) (y) | 1032 | #define IS2292(x, y) (y) | |
1037 | #endif | 1033 | #endif | |
1038 | 1034 | |||
1039 | if (in6p->in6p_socket->so_options & SO_TIMESTAMP | 1035 | if (in6p->in6p_socket->so_options & SO_TIMESTAMP | |
1040 | #ifdef SO_OTIMESTAMP | 1036 | #ifdef SO_OTIMESTAMP | |
1041 | || in6p->in6p_socket->so_options & SO_OTIMESTAMP | 1037 | || in6p->in6p_socket->so_options & SO_OTIMESTAMP | |
1042 | #endif | 1038 | #endif | |
1043 | ) { | 1039 | ) { | |
1044 | struct timeval tv; | 1040 | struct timeval tv; | |
1045 | 1041 | |||
1046 | microtime(&tv); | 1042 | microtime(&tv); | |
1047 | #ifdef SO_OTIMESTAMP | 1043 | #ifdef SO_OTIMESTAMP | |
1048 | if (in6p->in6p_socket->so_options & SO_OTIMESTAMP) { | 1044 | if (in6p->in6p_socket->so_options & SO_OTIMESTAMP) { | |
1049 | struct timeval50 tv50; | 1045 | struct timeval50 tv50; | |
1050 | timeval_to_timeval50(&tv, &tv50); | 1046 | timeval_to_timeval50(&tv, &tv50); | |
1051 | *mp = sbcreatecontrol((void *) &tv50, sizeof(tv50), | 1047 | *mp = sbcreatecontrol((void *) &tv50, sizeof(tv50), | |
1052 | SCM_OTIMESTAMP, SOL_SOCKET); | 1048 | SCM_OTIMESTAMP, SOL_SOCKET); | |
1053 | } else | 1049 | } else | |
1054 | #endif | 1050 | #endif | |
1055 | *mp = sbcreatecontrol((void *) &tv, sizeof(tv), | 1051 | *mp = sbcreatecontrol((void *) &tv, sizeof(tv), | |
1056 | SCM_TIMESTAMP, SOL_SOCKET); | 1052 | SCM_TIMESTAMP, SOL_SOCKET); | |
1057 | if (*mp) | 1053 | if (*mp) | |
1058 | mp = &(*mp)->m_next; | 1054 | mp = &(*mp)->m_next; | |
1059 | } | 1055 | } | |
1060 | 1056 | |||
1061 | /* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */ | 1057 | /* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */ | |
1062 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) | 1058 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) | |
1063 | return; | 1059 | return; | |
1064 | 1060 | |||
1065 | /* RFC 2292 sec. 5 */ | 1061 | /* RFC 2292 sec. 5 */ | |
1066 | if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) { | 1062 | if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) { | |
1067 | struct in6_pktinfo pi6; | 1063 | struct in6_pktinfo pi6; | |
1068 | 1064 | |||
1069 | memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr)); | 1065 | memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr)); | |
1070 | in6_clearscope(&pi6.ipi6_addr); /* XXX */ | 1066 | in6_clearscope(&pi6.ipi6_addr); /* XXX */ | |
1071 | pi6.ipi6_ifindex = m->m_pkthdr.rcvif ? | 1067 | pi6.ipi6_ifindex = m->m_pkthdr.rcvif ? | |
1072 | m->m_pkthdr.rcvif->if_index : 0; | 1068 | m->m_pkthdr.rcvif->if_index : 0; | |
1073 | *mp = sbcreatecontrol((void *) &pi6, | 1069 | *mp = sbcreatecontrol((void *) &pi6, | |
1074 | sizeof(struct in6_pktinfo), | 1070 | sizeof(struct in6_pktinfo), | |
1075 | IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6); | 1071 | IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6); | |
1076 | if (*mp) | 1072 | if (*mp) | |
1077 | mp = &(*mp)->m_next; | 1073 | mp = &(*mp)->m_next; | |
1078 | } | 1074 | } | |
1079 | 1075 | |||
1080 | if (in6p->in6p_flags & IN6P_HOPLIMIT) { | 1076 | if (in6p->in6p_flags & IN6P_HOPLIMIT) { | |
1081 | int hlim = ip6->ip6_hlim & 0xff; | 1077 | int hlim = ip6->ip6_hlim & 0xff; | |
1082 | 1078 | |||
1083 | *mp = sbcreatecontrol((void *) &hlim, sizeof(int), | 1079 | *mp = sbcreatecontrol((void *) &hlim, sizeof(int), | |
1084 | IS2292(IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), IPPROTO_IPV6); | 1080 | IS2292(IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), IPPROTO_IPV6); | |
1085 | if (*mp) | 1081 | if (*mp) | |
1086 | mp = &(*mp)->m_next; | 1082 | mp = &(*mp)->m_next; | |
1087 | } | 1083 | } | |
1088 | 1084 | |||
1089 | if ((in6p->in6p_flags & IN6P_TCLASS) != 0) { | 1085 | if ((in6p->in6p_flags & IN6P_TCLASS) != 0) { | |
1090 | u_int32_t flowinfo; | 1086 | u_int32_t flowinfo; | |
1091 | int tclass; | 1087 | int tclass; | |
1092 | 1088 | |||
1093 | flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); | 1089 | flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); | |
1094 | flowinfo >>= 20; | 1090 | flowinfo >>= 20; | |
1095 | 1091 | |||
1096 | tclass = flowinfo & 0xff; | 1092 | tclass = flowinfo & 0xff; | |
1097 | *mp = sbcreatecontrol((void *)&tclass, sizeof(tclass), | 1093 | *mp = sbcreatecontrol((void *)&tclass, sizeof(tclass), | |
1098 | IPV6_TCLASS, IPPROTO_IPV6); | 1094 | IPV6_TCLASS, IPPROTO_IPV6); | |
1099 | 1095 | |||
1100 | if (*mp) | 1096 | if (*mp) | |
1101 | mp = &(*mp)->m_next; | 1097 | mp = &(*mp)->m_next; | |
1102 | } | 1098 | } | |
1103 | 1099 | |||
1104 | /* | 1100 | /* | |
1105 | * IPV6_HOPOPTS socket option. Recall that we required super-user | 1101 | * IPV6_HOPOPTS socket option. Recall that we required super-user | |
1106 | * privilege for the option (see ip6_ctloutput), but it might be too | 1102 | * privilege for the option (see ip6_ctloutput), but it might be too | |
1107 | * strict, since there might be some hop-by-hop options which can be | 1103 | * strict, since there might be some hop-by-hop options which can be | |
1108 | * returned to normal user. | 1104 | * returned to normal user. | |
1109 | * See also RFC3542 section 8 (or RFC2292 section 6). | 1105 | * See also RFC3542 section 8 (or RFC2292 section 6). | |
1110 | */ | 1106 | */ | |
1111 | if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) { | 1107 | if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) { | |
1112 | /* | 1108 | /* | |
1113 | * Check if a hop-by-hop options header is contatined in the | 1109 | * Check if a hop-by-hop options header is contatined in the | |
1114 | * received packet, and if so, store the options as ancillary | 1110 | * received packet, and if so, store the options as ancillary | |
1115 | * data. Note that a hop-by-hop options header must be | 1111 | * data. Note that a hop-by-hop options header must be | |
1116 | * just after the IPv6 header, which fact is assured through | 1112 | * just after the IPv6 header, which fact is assured through | |
1117 | * the IPv6 input processing. | 1113 | * the IPv6 input processing. | |
1118 | */ | 1114 | */ | |
1119 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); | 1115 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); | |
1120 | if (xip6->ip6_nxt == IPPROTO_HOPOPTS) { | 1116 | if (xip6->ip6_nxt == IPPROTO_HOPOPTS) { | |
1121 | struct ip6_hbh *hbh; | 1117 | struct ip6_hbh *hbh; | |
1122 | int hbhlen; | 1118 | int hbhlen; | |
1123 | struct mbuf *ext; | 1119 | struct mbuf *ext; | |
1124 | 1120 | |||
1125 | ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr), | 1121 | ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr), | |
1126 | xip6->ip6_nxt); | 1122 | xip6->ip6_nxt); | |
1127 | if (ext == NULL) { | 1123 | if (ext == NULL) { | |
1128 | IP6_STATINC(IP6_STAT_TOOSHORT); | 1124 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
1129 | return; | 1125 | return; | |
1130 | } | 1126 | } | |
1131 | hbh = mtod(ext, struct ip6_hbh *); | 1127 | hbh = mtod(ext, struct ip6_hbh *); | |
1132 | hbhlen = (hbh->ip6h_len + 1) << 3; | 1128 | hbhlen = (hbh->ip6h_len + 1) << 3; | |
1133 | if (hbhlen != ext->m_len) { | 1129 | if (hbhlen != ext->m_len) { | |
1134 | m_freem(ext); | 1130 | m_freem(ext); | |
1135 | IP6_STATINC(IP6_STAT_TOOSHORT); | 1131 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
1136 | return; | 1132 | return; | |
1137 | } | 1133 | } | |
1138 | 1134 | |||
1139 | /* | 1135 | /* | |
1140 | * XXX: We copy whole the header even if a jumbo | 1136 | * XXX: We copy whole the header even if a jumbo | |
1141 | * payload option is included, which option is to | 1137 | * payload option is included, which option is to | |
1142 | * be removed before returning in the RFC 2292. | 1138 | * be removed before returning in the RFC 2292. | |
1143 | * Note: this constraint is removed in RFC3542. | 1139 | * Note: this constraint is removed in RFC3542. | |
1144 | */ | 1140 | */ | |
1145 | *mp = sbcreatecontrol((void *)hbh, hbhlen, | 1141 | *mp = sbcreatecontrol((void *)hbh, hbhlen, | |
1146 | IS2292(IPV6_2292HOPOPTS, IPV6_HOPOPTS), | 1142 | IS2292(IPV6_2292HOPOPTS, IPV6_HOPOPTS), | |
1147 | IPPROTO_IPV6); | 1143 | IPPROTO_IPV6); | |
1148 | if (*mp) | 1144 | if (*mp) | |
1149 | mp = &(*mp)->m_next; | 1145 | mp = &(*mp)->m_next; | |
1150 | m_freem(ext); | 1146 | m_freem(ext); | |
1151 | } | 1147 | } | |
1152 | } | 1148 | } | |
1153 | 1149 | |||
1154 | /* IPV6_DSTOPTS and IPV6_RTHDR socket options */ | 1150 | /* IPV6_DSTOPTS and IPV6_RTHDR socket options */ | |
1155 | if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) { | 1151 | if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) { | |
1156 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); | 1152 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); | |
1157 | int nxt = xip6->ip6_nxt, off = sizeof(struct ip6_hdr); | 1153 | int nxt = xip6->ip6_nxt, off = sizeof(struct ip6_hdr); | |
1158 | 1154 | |||
1159 | /* | 1155 | /* | |
1160 | * Search for destination options headers or routing | 1156 | * Search for destination options headers or routing | |
1161 | * header(s) through the header chain, and stores each | 1157 | * header(s) through the header chain, and stores each | |
1162 | * header as ancillary data. | 1158 | * header as ancillary data. | |
1163 | * Note that the order of the headers remains in | 1159 | * Note that the order of the headers remains in | |
1164 | * the chain of ancillary data. | 1160 | * the chain of ancillary data. | |
1165 | */ | 1161 | */ | |
1166 | for (;;) { /* is explicit loop prevention necessary? */ | 1162 | for (;;) { /* is explicit loop prevention necessary? */ | |
1167 | struct ip6_ext *ip6e = NULL; | 1163 | struct ip6_ext *ip6e = NULL; | |
1168 | int elen; | 1164 | int elen; | |
1169 | struct mbuf *ext = NULL; | 1165 | struct mbuf *ext = NULL; | |
1170 | 1166 | |||
1171 | /* | 1167 | /* | |
1172 | * if it is not an extension header, don't try to | 1168 | * if it is not an extension header, don't try to | |
1173 | * pull it from the chain. | 1169 | * pull it from the chain. | |
1174 | */ | 1170 | */ | |
1175 | switch (nxt) { | 1171 | switch (nxt) { | |
1176 | case IPPROTO_DSTOPTS: | 1172 | case IPPROTO_DSTOPTS: | |
1177 | case IPPROTO_ROUTING: | 1173 | case IPPROTO_ROUTING: | |
1178 | case IPPROTO_HOPOPTS: | 1174 | case IPPROTO_HOPOPTS: | |
1179 | case IPPROTO_AH: /* is it possible? */ | 1175 | case IPPROTO_AH: /* is it possible? */ | |
1180 | break; | 1176 | break; | |
1181 | default: | 1177 | default: | |
1182 | goto loopend; | 1178 | goto loopend; | |
1183 | } | 1179 | } | |
1184 | 1180 | |||
1185 | ext = ip6_pullexthdr(m, off, nxt); | 1181 | ext = ip6_pullexthdr(m, off, nxt); | |
1186 | if (ext == NULL) { | 1182 | if (ext == NULL) { | |
1187 | IP6_STATINC(IP6_STAT_TOOSHORT); | 1183 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
1188 | return; | 1184 | return; | |
1189 | } | 1185 | } | |
1190 | ip6e = mtod(ext, struct ip6_ext *); | 1186 | ip6e = mtod(ext, struct ip6_ext *); | |
1191 | if (nxt == IPPROTO_AH) | 1187 | if (nxt == IPPROTO_AH) | |
1192 | elen = (ip6e->ip6e_len + 2) << 2; | 1188 | elen = (ip6e->ip6e_len + 2) << 2; | |
1193 | else | 1189 | else | |
1194 | elen = (ip6e->ip6e_len + 1) << 3; | 1190 | elen = (ip6e->ip6e_len + 1) << 3; | |
1195 | if (elen != ext->m_len) { | 1191 | if (elen != ext->m_len) { | |
1196 | m_freem(ext); | 1192 | m_freem(ext); | |
1197 | IP6_STATINC(IP6_STAT_TOOSHORT); | 1193 | IP6_STATINC(IP6_STAT_TOOSHORT); | |
1198 | return; | 1194 | return; | |
1199 | } | 1195 | } | |
1200 | KASSERT(IP6_HDR_ALIGNED_P(ip6e)); | 1196 | KASSERT(IP6_HDR_ALIGNED_P(ip6e)); | |
1201 | 1197 | |||
1202 | switch (nxt) { | 1198 | switch (nxt) { | |
1203 | case IPPROTO_DSTOPTS: | 1199 | case IPPROTO_DSTOPTS: | |
1204 | if (!(in6p->in6p_flags & IN6P_DSTOPTS)) | 1200 | if (!(in6p->in6p_flags & IN6P_DSTOPTS)) |
--- src/sys/netinet6/nd6.c 2016/02/04 02:48:37 1.185
+++ src/sys/netinet6/nd6.c 2016/04/01 05:11:38 1.186
@@ -1,1594 +1,1588 @@ | @@ -1,1594 +1,1588 @@ | |||
1 | /* $NetBSD: nd6.c,v 1.185 2016/02/04 02:48:37 riastradh Exp $ */ | 1 | /* $NetBSD: nd6.c,v 1.186 2016/04/01 05:11:38 ozaki-r Exp $ */ | |
2 | /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */ | 2 | /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun 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 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.185 2016/02/04 02:48:37 riastradh Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.186 2016/04/01 05:11:38 ozaki-r Exp $"); | |
35 | 35 | |||
36 | #ifdef _KERNEL_OPT | 36 | #ifdef _KERNEL_OPT | |
37 | #include "opt_net_mpsafe.h" | 37 | #include "opt_net_mpsafe.h" | |
38 | #endif | 38 | #endif | |
39 | 39 | |||
40 | #include "bridge.h" | 40 | #include "bridge.h" | |
41 | #include "carp.h" | 41 | #include "carp.h" | |
42 | 42 | |||
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
44 | #include <sys/systm.h> | 44 | #include <sys/systm.h> | |
45 | #include <sys/callout.h> | 45 | #include <sys/callout.h> | |
46 | #include <sys/malloc.h> | 46 | #include <sys/malloc.h> | |
47 | #include <sys/mbuf.h> | 47 | #include <sys/mbuf.h> | |
48 | #include <sys/socket.h> | 48 | #include <sys/socket.h> | |
49 | #include <sys/socketvar.h> | 49 | #include <sys/socketvar.h> | |
50 | #include <sys/sockio.h> | 50 | #include <sys/sockio.h> | |
51 | #include <sys/time.h> | 51 | #include <sys/time.h> | |
52 | #include <sys/kernel.h> | 52 | #include <sys/kernel.h> | |
53 | #include <sys/protosw.h> | 53 | #include <sys/protosw.h> | |
54 | #include <sys/errno.h> | 54 | #include <sys/errno.h> | |
55 | #include <sys/ioctl.h> | 55 | #include <sys/ioctl.h> | |
56 | #include <sys/syslog.h> | 56 | #include <sys/syslog.h> | |
57 | #include <sys/queue.h> | 57 | #include <sys/queue.h> | |
58 | #include <sys/cprng.h> | 58 | #include <sys/cprng.h> | |
59 | 59 | |||
60 | #include <net/if.h> | 60 | #include <net/if.h> | |
61 | #include <net/if_dl.h> | 61 | #include <net/if_dl.h> | |
62 | #include <net/if_llatbl.h> | 62 | #include <net/if_llatbl.h> | |
63 | #include <net/if_types.h> | 63 | #include <net/if_types.h> | |
64 | #include <net/route.h> | 64 | #include <net/route.h> | |
65 | #include <net/if_ether.h> | 65 | #include <net/if_ether.h> | |
66 | #include <net/if_fddi.h> | 66 | #include <net/if_fddi.h> | |
67 | #include <net/if_arc.h> | 67 | #include <net/if_arc.h> | |
68 | 68 | |||
69 | #include <netinet/in.h> | 69 | #include <netinet/in.h> | |
70 | #include <netinet6/in6_var.h> | 70 | #include <netinet6/in6_var.h> | |
71 | #include <netinet/ip6.h> | 71 | #include <netinet/ip6.h> | |
72 | #include <netinet6/ip6_var.h> | 72 | #include <netinet6/ip6_var.h> | |
73 | #include <netinet6/scope6_var.h> | 73 | #include <netinet6/scope6_var.h> | |
74 | #include <netinet6/nd6.h> | 74 | #include <netinet6/nd6.h> | |
75 | #include <netinet6/in6_ifattach.h> | 75 | #include <netinet6/in6_ifattach.h> | |
76 | #include <netinet/icmp6.h> | 76 | #include <netinet/icmp6.h> | |
77 | #include <netinet6/icmp6_private.h> | 77 | #include <netinet6/icmp6_private.h> | |
78 | 78 | |||
79 | #include <net/net_osdep.h> | 79 | #include <net/net_osdep.h> | |
80 | 80 | |||
81 | #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */ | 81 | #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */ | |
82 | #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */ | 82 | #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */ | |
83 | 83 | |||
84 | /* timer values */ | 84 | /* timer values */ | |
85 | int nd6_prune = 1; /* walk list every 1 seconds */ | 85 | int nd6_prune = 1; /* walk list every 1 seconds */ | |
86 | int nd6_delay = 5; /* delay first probe time 5 second */ | 86 | int nd6_delay = 5; /* delay first probe time 5 second */ | |
87 | int nd6_umaxtries = 3; /* maximum unicast query */ | 87 | int nd6_umaxtries = 3; /* maximum unicast query */ | |
88 | int nd6_mmaxtries = 3; /* maximum multicast query */ | 88 | int nd6_mmaxtries = 3; /* maximum multicast query */ | |
89 | int nd6_useloopback = 1; /* use loopback interface for local traffic */ | 89 | int nd6_useloopback = 1; /* use loopback interface for local traffic */ | |
90 | int nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */ | 90 | int nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */ | |
91 | 91 | |||
92 | /* preventing too many loops in ND option parsing */ | 92 | /* preventing too many loops in ND option parsing */ | |
93 | int nd6_maxndopt = 10; /* max # of ND options allowed */ | 93 | int nd6_maxndopt = 10; /* max # of ND options allowed */ | |
94 | 94 | |||
95 | int nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */ | 95 | int nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */ | |
96 | 96 | |||
97 | int nd6_maxqueuelen = 1; /* max # of packets cached in unresolved ND entries */ | 97 | int nd6_maxqueuelen = 1; /* max # of packets cached in unresolved ND entries */ | |
98 | 98 | |||
99 | #ifdef ND6_DEBUG | 99 | #ifdef ND6_DEBUG | |
100 | int nd6_debug = 1; | 100 | int nd6_debug = 1; | |
101 | #else | 101 | #else | |
102 | int nd6_debug = 0; | 102 | int nd6_debug = 0; | |
103 | #endif | 103 | #endif | |
104 | 104 | |||
105 | /* for debugging? */ | 105 | /* for debugging? */ | |
106 | static int nd6_inuse, nd6_allocated; | 106 | static int nd6_inuse, nd6_allocated; | |
107 | 107 | |||
108 | struct nd_drhead nd_defrouter; | 108 | struct nd_drhead nd_defrouter; | |
109 | struct nd_prhead nd_prefix = { 0 }; | 109 | struct nd_prhead nd_prefix = { 0 }; | |
110 | 110 | |||
111 | int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL; | 111 | int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL; | |
112 | static const struct sockaddr_in6 all1_sa = { | 112 | static const struct sockaddr_in6 all1_sa = { | |
113 | .sin6_family = AF_INET6 | 113 | .sin6_family = AF_INET6 | |
114 | , .sin6_len = sizeof(struct sockaddr_in6) | 114 | , .sin6_len = sizeof(struct sockaddr_in6) | |
115 | , .sin6_addr = {.s6_addr = {0xff, 0xff, 0xff, 0xff, | 115 | , .sin6_addr = {.s6_addr = {0xff, 0xff, 0xff, 0xff, | |
116 | 0xff, 0xff, 0xff, 0xff, | 116 | 0xff, 0xff, 0xff, 0xff, | |
117 | 0xff, 0xff, 0xff, 0xff, | 117 | 0xff, 0xff, 0xff, 0xff, | |
118 | 0xff, 0xff, 0xff, 0xff}} | 118 | 0xff, 0xff, 0xff, 0xff}} | |
119 | }; | 119 | }; | |
120 | 120 | |||
121 | static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *); | 121 | static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *); | |
122 | static void nd6_slowtimo(void *); | 122 | static void nd6_slowtimo(void *); | |
123 | static int regen_tmpaddr(struct in6_ifaddr *); | 123 | static int regen_tmpaddr(struct in6_ifaddr *); | |
124 | static void nd6_free(struct rtentry *, struct llentry *, int); | 124 | static void nd6_free(struct rtentry *, struct llentry *, int); | |
125 | static void nd6_llinfo_timer(void *); | 125 | static void nd6_llinfo_timer(void *); | |
126 | static void nd6_timer(void *); | |||
126 | static void clear_llinfo_pqueue(struct llentry *); | 127 | static void clear_llinfo_pqueue(struct llentry *); | |
127 | 128 | |||
128 | callout_t nd6_slowtimo_ch; | 129 | static callout_t nd6_slowtimo_ch; | |
129 | callout_t nd6_timer_ch; | 130 | static callout_t nd6_timer_ch; | |
130 | 131 | |||
131 | static int fill_drlist(void *, size_t *, size_t); | 132 | static int fill_drlist(void *, size_t *, size_t); | |
132 | static int fill_prlist(void *, size_t *, size_t); | 133 | static int fill_prlist(void *, size_t *, size_t); | |
133 | 134 | |||
134 | MALLOC_DEFINE(M_IP6NDP, "NDP", "IPv6 Neighbour Discovery"); | 135 | MALLOC_DEFINE(M_IP6NDP, "NDP", "IPv6 Neighbour Discovery"); | |
135 | 136 | |||
136 | void | 137 | void | |
137 | nd6_init(void) | 138 | nd6_init(void) | |
138 | { | 139 | { | |
139 | static int nd6_init_done = 0; | |||
140 | ||||
141 | if (nd6_init_done) { | |||
142 | log(LOG_NOTICE, "nd6_init called more than once(ignored)\n"); | |||
143 | return; | |||
144 | } | |||
145 | 140 | |||
146 | /* initialization of the default router list */ | 141 | /* initialization of the default router list */ | |
147 | TAILQ_INIT(&nd_defrouter); | 142 | TAILQ_INIT(&nd_defrouter); | |
148 | 143 | |||
149 | nd6_init_done = 1; | |||
150 | ||||
151 | callout_init(&nd6_slowtimo_ch, CALLOUT_MPSAFE); | 144 | callout_init(&nd6_slowtimo_ch, CALLOUT_MPSAFE); | |
152 | callout_init(&nd6_timer_ch, CALLOUT_MPSAFE); | 145 | callout_init(&nd6_timer_ch, CALLOUT_MPSAFE); | |
153 | 146 | |||
154 | /* start timer */ | 147 | /* start timer */ | |
155 | callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz, | 148 | callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz, | |
156 | nd6_slowtimo, NULL); | 149 | nd6_slowtimo, NULL); | |
150 | callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL); | |||
157 | } | 151 | } | |
158 | 152 | |||
159 | struct nd_ifinfo * | 153 | struct nd_ifinfo * | |
160 | nd6_ifattach(struct ifnet *ifp) | 154 | nd6_ifattach(struct ifnet *ifp) | |
161 | { | 155 | { | |
162 | struct nd_ifinfo *nd; | 156 | struct nd_ifinfo *nd; | |
163 | 157 | |||
164 | nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK|M_ZERO); | 158 | nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK|M_ZERO); | |
165 | 159 | |||
166 | nd->initialized = 1; | 160 | nd->initialized = 1; | |
167 | 161 | |||
168 | nd->chlim = IPV6_DEFHLIM; | 162 | nd->chlim = IPV6_DEFHLIM; | |
169 | nd->basereachable = REACHABLE_TIME; | 163 | nd->basereachable = REACHABLE_TIME; | |
170 | nd->reachable = ND_COMPUTE_RTIME(nd->basereachable); | 164 | nd->reachable = ND_COMPUTE_RTIME(nd->basereachable); | |
171 | nd->retrans = RETRANS_TIMER; | 165 | nd->retrans = RETRANS_TIMER; | |
172 | 166 | |||
173 | nd->flags = ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV; | 167 | nd->flags = ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV; | |
174 | 168 | |||
175 | /* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL. | 169 | /* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL. | |
176 | * A bridge interface should not have ND6_IFF_AUTO_LINKLOCAL | 170 | * A bridge interface should not have ND6_IFF_AUTO_LINKLOCAL | |
177 | * because one of its members should. */ | 171 | * because one of its members should. */ | |
178 | if ((ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) || | 172 | if ((ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) || | |
179 | (ifp->if_flags & IFF_LOOPBACK)) | 173 | (ifp->if_flags & IFF_LOOPBACK)) | |
180 | nd->flags |= ND6_IFF_AUTO_LINKLOCAL; | 174 | nd->flags |= ND6_IFF_AUTO_LINKLOCAL; | |
181 | 175 | |||
182 | /* A loopback interface does not need to accept RTADV. | 176 | /* A loopback interface does not need to accept RTADV. | |
183 | * A bridge interface should not accept RTADV | 177 | * A bridge interface should not accept RTADV | |
184 | * because one of its members should. */ | 178 | * because one of its members should. */ | |
185 | if (ip6_accept_rtadv && | 179 | if (ip6_accept_rtadv && | |
186 | !(ifp->if_flags & IFF_LOOPBACK) && | 180 | !(ifp->if_flags & IFF_LOOPBACK) && | |
187 | !(ifp->if_type != IFT_BRIDGE)) | 181 | !(ifp->if_type != IFT_BRIDGE)) | |
188 | nd->flags |= ND6_IFF_ACCEPT_RTADV; | 182 | nd->flags |= ND6_IFF_ACCEPT_RTADV; | |
189 | 183 | |||
190 | /* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */ | 184 | /* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */ | |
191 | nd6_setmtu0(ifp, nd); | 185 | nd6_setmtu0(ifp, nd); | |
192 | 186 | |||
193 | return nd; | 187 | return nd; | |
194 | } | 188 | } | |
195 | 189 | |||
196 | void | 190 | void | |
197 | nd6_ifdetach(struct ifnet *ifp, struct in6_ifextra *ext) | 191 | nd6_ifdetach(struct ifnet *ifp, struct in6_ifextra *ext) | |
198 | { | 192 | { | |
199 | 193 | |||
200 | nd6_purge(ifp, ext); | 194 | nd6_purge(ifp, ext); | |
201 | free(ext->nd_ifinfo, M_IP6NDP); | 195 | free(ext->nd_ifinfo, M_IP6NDP); | |
202 | } | 196 | } | |
203 | 197 | |||
204 | void | 198 | void | |
205 | nd6_setmtu(struct ifnet *ifp) | 199 | nd6_setmtu(struct ifnet *ifp) | |
206 | { | 200 | { | |
207 | nd6_setmtu0(ifp, ND_IFINFO(ifp)); | 201 | nd6_setmtu0(ifp, ND_IFINFO(ifp)); | |
208 | } | 202 | } | |
209 | 203 | |||
210 | void | 204 | void | |
211 | nd6_setmtu0(struct ifnet *ifp, struct nd_ifinfo *ndi) | 205 | nd6_setmtu0(struct ifnet *ifp, struct nd_ifinfo *ndi) | |
212 | { | 206 | { | |
213 | u_int32_t omaxmtu; | 207 | u_int32_t omaxmtu; | |
214 | 208 | |||
215 | omaxmtu = ndi->maxmtu; | 209 | omaxmtu = ndi->maxmtu; | |
216 | 210 | |||
217 | switch (ifp->if_type) { | 211 | switch (ifp->if_type) { | |
218 | case IFT_ARCNET: | 212 | case IFT_ARCNET: | |
219 | ndi->maxmtu = MIN(ARC_PHDS_MAXMTU, ifp->if_mtu); /* RFC2497 */ | 213 | ndi->maxmtu = MIN(ARC_PHDS_MAXMTU, ifp->if_mtu); /* RFC2497 */ | |
220 | break; | 214 | break; | |
221 | case IFT_FDDI: | 215 | case IFT_FDDI: | |
222 | ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu); | 216 | ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu); | |
223 | break; | 217 | break; | |
224 | default: | 218 | default: | |
225 | ndi->maxmtu = ifp->if_mtu; | 219 | ndi->maxmtu = ifp->if_mtu; | |
226 | break; | 220 | break; | |
227 | } | 221 | } | |
228 | 222 | |||
229 | /* | 223 | /* | |
230 | * Decreasing the interface MTU under IPV6 minimum MTU may cause | 224 | * Decreasing the interface MTU under IPV6 minimum MTU may cause | |
231 | * undesirable situation. We thus notify the operator of the change | 225 | * undesirable situation. We thus notify the operator of the change | |
232 | * explicitly. The check for omaxmtu is necessary to restrict the | 226 | * explicitly. The check for omaxmtu is necessary to restrict the | |
233 | * log to the case of changing the MTU, not initializing it. | 227 | * log to the case of changing the MTU, not initializing it. | |
234 | */ | 228 | */ | |
235 | if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) { | 229 | if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) { | |
236 | log(LOG_NOTICE, "nd6_setmtu0: new link MTU on %s (%lu) is too" | 230 | log(LOG_NOTICE, "nd6_setmtu0: new link MTU on %s (%lu) is too" | |
237 | " small for IPv6 which needs %lu\n", | 231 | " small for IPv6 which needs %lu\n", | |
238 | if_name(ifp), (unsigned long)ndi->maxmtu, (unsigned long) | 232 | if_name(ifp), (unsigned long)ndi->maxmtu, (unsigned long) | |
239 | IPV6_MMTU); | 233 | IPV6_MMTU); | |
240 | } | 234 | } | |
241 | 235 | |||
242 | if (ndi->maxmtu > in6_maxmtu) | 236 | if (ndi->maxmtu > in6_maxmtu) | |
243 | in6_setmaxmtu(); /* check all interfaces just in case */ | 237 | in6_setmaxmtu(); /* check all interfaces just in case */ | |
244 | } | 238 | } | |
245 | 239 | |||
246 | void | 240 | void | |
247 | nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts) | 241 | nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts) | |
248 | { | 242 | { | |
249 | 243 | |||
250 | memset(ndopts, 0, sizeof(*ndopts)); | 244 | memset(ndopts, 0, sizeof(*ndopts)); | |
251 | ndopts->nd_opts_search = (struct nd_opt_hdr *)opt; | 245 | ndopts->nd_opts_search = (struct nd_opt_hdr *)opt; | |
252 | ndopts->nd_opts_last | 246 | ndopts->nd_opts_last | |
253 | = (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len); | 247 | = (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len); | |
254 | 248 | |||
255 | if (icmp6len == 0) { | 249 | if (icmp6len == 0) { | |
256 | ndopts->nd_opts_done = 1; | 250 | ndopts->nd_opts_done = 1; | |
257 | ndopts->nd_opts_search = NULL; | 251 | ndopts->nd_opts_search = NULL; | |
258 | } | 252 | } | |
259 | } | 253 | } | |
260 | 254 | |||
261 | /* | 255 | /* | |
262 | * Take one ND option. | 256 | * Take one ND option. | |
263 | */ | 257 | */ | |
264 | struct nd_opt_hdr * | 258 | struct nd_opt_hdr * | |
265 | nd6_option(union nd_opts *ndopts) | 259 | nd6_option(union nd_opts *ndopts) | |
266 | { | 260 | { | |
267 | struct nd_opt_hdr *nd_opt; | 261 | struct nd_opt_hdr *nd_opt; | |
268 | int olen; | 262 | int olen; | |
269 | 263 | |||
270 | KASSERT(ndopts != NULL); | 264 | KASSERT(ndopts != NULL); | |
271 | KASSERT(ndopts->nd_opts_last != NULL); | 265 | KASSERT(ndopts->nd_opts_last != NULL); | |
272 | 266 | |||
273 | if (ndopts->nd_opts_search == NULL) | 267 | if (ndopts->nd_opts_search == NULL) | |
274 | return NULL; | 268 | return NULL; | |
275 | if (ndopts->nd_opts_done) | 269 | if (ndopts->nd_opts_done) | |
276 | return NULL; | 270 | return NULL; | |
277 | 271 | |||
278 | nd_opt = ndopts->nd_opts_search; | 272 | nd_opt = ndopts->nd_opts_search; | |
279 | 273 | |||
280 | /* make sure nd_opt_len is inside the buffer */ | 274 | /* make sure nd_opt_len is inside the buffer */ | |
281 | if ((void *)&nd_opt->nd_opt_len >= (void *)ndopts->nd_opts_last) { | 275 | if ((void *)&nd_opt->nd_opt_len >= (void *)ndopts->nd_opts_last) { | |
282 | memset(ndopts, 0, sizeof(*ndopts)); | 276 | memset(ndopts, 0, sizeof(*ndopts)); | |
283 | return NULL; | 277 | return NULL; | |
284 | } | 278 | } | |
285 | 279 | |||
286 | olen = nd_opt->nd_opt_len << 3; | 280 | olen = nd_opt->nd_opt_len << 3; | |
287 | if (olen == 0) { | 281 | if (olen == 0) { | |
288 | /* | 282 | /* | |
289 | * Message validation requires that all included | 283 | * Message validation requires that all included | |
290 | * options have a length that is greater than zero. | 284 | * options have a length that is greater than zero. | |
291 | */ | 285 | */ | |
292 | memset(ndopts, 0, sizeof(*ndopts)); | 286 | memset(ndopts, 0, sizeof(*ndopts)); | |
293 | return NULL; | 287 | return NULL; | |
294 | } | 288 | } | |
295 | 289 | |||
296 | ndopts->nd_opts_search = (struct nd_opt_hdr *)((char *)nd_opt + olen); | 290 | ndopts->nd_opts_search = (struct nd_opt_hdr *)((char *)nd_opt + olen); | |
297 | if (ndopts->nd_opts_search > ndopts->nd_opts_last) { | 291 | if (ndopts->nd_opts_search > ndopts->nd_opts_last) { | |
298 | /* option overruns the end of buffer, invalid */ | 292 | /* option overruns the end of buffer, invalid */ | |
299 | memset(ndopts, 0, sizeof(*ndopts)); | 293 | memset(ndopts, 0, sizeof(*ndopts)); | |
300 | return NULL; | 294 | return NULL; | |
301 | } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) { | 295 | } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) { | |
302 | /* reached the end of options chain */ | 296 | /* reached the end of options chain */ | |
303 | ndopts->nd_opts_done = 1; | 297 | ndopts->nd_opts_done = 1; | |
304 | ndopts->nd_opts_search = NULL; | 298 | ndopts->nd_opts_search = NULL; | |
305 | } | 299 | } | |
306 | return nd_opt; | 300 | return nd_opt; | |
307 | } | 301 | } | |
308 | 302 | |||
309 | /* | 303 | /* | |
310 | * Parse multiple ND options. | 304 | * Parse multiple ND options. | |
311 | * This function is much easier to use, for ND routines that do not need | 305 | * This function is much easier to use, for ND routines that do not need | |
312 | * multiple options of the same type. | 306 | * multiple options of the same type. | |
313 | */ | 307 | */ | |
314 | int | 308 | int | |
315 | nd6_options(union nd_opts *ndopts) | 309 | nd6_options(union nd_opts *ndopts) | |
316 | { | 310 | { | |
317 | struct nd_opt_hdr *nd_opt; | 311 | struct nd_opt_hdr *nd_opt; | |
318 | int i = 0; | 312 | int i = 0; | |
319 | 313 | |||
320 | KASSERT(ndopts != NULL); | 314 | KASSERT(ndopts != NULL); | |
321 | KASSERT(ndopts->nd_opts_last != NULL); | 315 | KASSERT(ndopts->nd_opts_last != NULL); | |
322 | 316 | |||
323 | if (ndopts->nd_opts_search == NULL) | 317 | if (ndopts->nd_opts_search == NULL) | |
324 | return 0; | 318 | return 0; | |
325 | 319 | |||
326 | while (1) { | 320 | while (1) { | |
327 | nd_opt = nd6_option(ndopts); | 321 | nd_opt = nd6_option(ndopts); | |
328 | if (nd_opt == NULL && ndopts->nd_opts_last == NULL) { | 322 | if (nd_opt == NULL && ndopts->nd_opts_last == NULL) { | |
329 | /* | 323 | /* | |
330 | * Message validation requires that all included | 324 | * Message validation requires that all included | |
331 | * options have a length that is greater than zero. | 325 | * options have a length that is greater than zero. | |
332 | */ | 326 | */ | |
333 | ICMP6_STATINC(ICMP6_STAT_ND_BADOPT); | 327 | ICMP6_STATINC(ICMP6_STAT_ND_BADOPT); | |
334 | memset(ndopts, 0, sizeof(*ndopts)); | 328 | memset(ndopts, 0, sizeof(*ndopts)); | |
335 | return -1; | 329 | return -1; | |
336 | } | 330 | } | |
337 | 331 | |||
338 | if (nd_opt == NULL) | 332 | if (nd_opt == NULL) | |
339 | goto skip1; | 333 | goto skip1; | |
340 | 334 | |||
341 | switch (nd_opt->nd_opt_type) { | 335 | switch (nd_opt->nd_opt_type) { | |
342 | case ND_OPT_SOURCE_LINKADDR: | 336 | case ND_OPT_SOURCE_LINKADDR: | |
343 | case ND_OPT_TARGET_LINKADDR: | 337 | case ND_OPT_TARGET_LINKADDR: | |
344 | case ND_OPT_MTU: | 338 | case ND_OPT_MTU: | |
345 | case ND_OPT_REDIRECTED_HEADER: | 339 | case ND_OPT_REDIRECTED_HEADER: | |
346 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { | 340 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { | |
347 | nd6log((LOG_INFO, | 341 | nd6log((LOG_INFO, | |
348 | "duplicated ND6 option found (type=%d)\n", | 342 | "duplicated ND6 option found (type=%d)\n", | |
349 | nd_opt->nd_opt_type)); | 343 | nd_opt->nd_opt_type)); | |
350 | /* XXX bark? */ | 344 | /* XXX bark? */ | |
351 | } else { | 345 | } else { | |
352 | ndopts->nd_opt_array[nd_opt->nd_opt_type] | 346 | ndopts->nd_opt_array[nd_opt->nd_opt_type] | |
353 | = nd_opt; | 347 | = nd_opt; | |
354 | } | 348 | } | |
355 | break; | 349 | break; | |
356 | case ND_OPT_PREFIX_INFORMATION: | 350 | case ND_OPT_PREFIX_INFORMATION: | |
357 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) { | 351 | if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) { | |
358 | ndopts->nd_opt_array[nd_opt->nd_opt_type] | 352 | ndopts->nd_opt_array[nd_opt->nd_opt_type] | |
359 | = nd_opt; | 353 | = nd_opt; | |
360 | } | 354 | } | |
361 | ndopts->nd_opts_pi_end = | 355 | ndopts->nd_opts_pi_end = | |
362 | (struct nd_opt_prefix_info *)nd_opt; | 356 | (struct nd_opt_prefix_info *)nd_opt; | |
363 | break; | 357 | break; | |
364 | default: | 358 | default: | |
365 | /* | 359 | /* | |
366 | * Unknown options must be silently ignored, | 360 | * Unknown options must be silently ignored, | |
367 | * to accommodate future extension to the protocol. | 361 | * to accommodate future extension to the protocol. | |
368 | */ | 362 | */ | |
369 | nd6log((LOG_DEBUG, | 363 | nd6log((LOG_DEBUG, | |
370 | "nd6_options: unsupported option %d - " | 364 | "nd6_options: unsupported option %d - " | |
371 | "option ignored\n", nd_opt->nd_opt_type)); | 365 | "option ignored\n", nd_opt->nd_opt_type)); | |
372 | } | 366 | } | |
373 | 367 | |||
374 | skip1: | 368 | skip1: | |
375 | i++; | 369 | i++; | |
376 | if (i > nd6_maxndopt) { | 370 | if (i > nd6_maxndopt) { | |
377 | ICMP6_STATINC(ICMP6_STAT_ND_TOOMANYOPT); | 371 | ICMP6_STATINC(ICMP6_STAT_ND_TOOMANYOPT); | |
378 | nd6log((LOG_INFO, "too many loop in nd opt\n")); | 372 | nd6log((LOG_INFO, "too many loop in nd opt\n")); | |
379 | break; | 373 | break; | |
380 | } | 374 | } | |
381 | 375 | |||
382 | if (ndopts->nd_opts_done) | 376 | if (ndopts->nd_opts_done) | |
383 | break; | 377 | break; | |
384 | } | 378 | } | |
385 | 379 | |||
386 | return 0; | 380 | return 0; | |
387 | } | 381 | } | |
388 | 382 | |||
389 | /* | 383 | /* | |
390 | * ND6 timer routine to handle ND6 entries | 384 | * ND6 timer routine to handle ND6 entries | |
391 | */ | 385 | */ | |
392 | void | 386 | void | |
393 | nd6_llinfo_settimer_locked(struct llentry *ln, time_t xtick) | 387 | nd6_llinfo_settimer_locked(struct llentry *ln, time_t xtick) | |
394 | { | 388 | { | |
395 | 389 | |||
396 | CTASSERT(sizeof(time_t) > sizeof(int)); | 390 | CTASSERT(sizeof(time_t) > sizeof(int)); | |
397 | LLE_WLOCK_ASSERT(ln); | 391 | LLE_WLOCK_ASSERT(ln); | |
398 | 392 | |||
399 | if (xtick < 0) { | 393 | if (xtick < 0) { | |
400 | ln->ln_expire = 0; | 394 | ln->ln_expire = 0; | |
401 | ln->ln_ntick = 0; | 395 | ln->ln_ntick = 0; | |
402 | callout_halt(&ln->ln_timer_ch, &ln->lle_lock); | 396 | callout_halt(&ln->ln_timer_ch, &ln->lle_lock); | |
403 | } else { | 397 | } else { | |
404 | ln->ln_expire = time_uptime + xtick / hz; | 398 | ln->ln_expire = time_uptime + xtick / hz; | |
405 | LLE_ADDREF(ln); | 399 | LLE_ADDREF(ln); | |
406 | if (xtick > INT_MAX) { | 400 | if (xtick > INT_MAX) { | |
407 | ln->ln_ntick = xtick - INT_MAX; | 401 | ln->ln_ntick = xtick - INT_MAX; | |
408 | callout_reset(&ln->ln_timer_ch, INT_MAX, | 402 | callout_reset(&ln->ln_timer_ch, INT_MAX, | |
409 | nd6_llinfo_timer, ln); | 403 | nd6_llinfo_timer, ln); | |
410 | } else { | 404 | } else { | |
411 | ln->ln_ntick = 0; | 405 | ln->ln_ntick = 0; | |
412 | callout_reset(&ln->ln_timer_ch, xtick, | 406 | callout_reset(&ln->ln_timer_ch, xtick, | |
413 | nd6_llinfo_timer, ln); | 407 | nd6_llinfo_timer, ln); | |
414 | } | 408 | } | |
415 | } | 409 | } | |
416 | } | 410 | } | |
417 | 411 | |||
418 | void | 412 | void | |
419 | nd6_llinfo_settimer(struct llentry *ln, time_t xtick) | 413 | nd6_llinfo_settimer(struct llentry *ln, time_t xtick) | |
420 | { | 414 | { | |
421 | 415 | |||
422 | LLE_WLOCK(ln); | 416 | LLE_WLOCK(ln); | |
423 | nd6_llinfo_settimer_locked(ln, xtick); | 417 | nd6_llinfo_settimer_locked(ln, xtick); | |
424 | LLE_WUNLOCK(ln); | 418 | LLE_WUNLOCK(ln); | |
425 | } | 419 | } | |
426 | 420 | |||
427 | /* | 421 | /* | |
428 | * Gets source address of the first packet in hold queue | 422 | * Gets source address of the first packet in hold queue | |
429 | * and stores it in @src. | 423 | * and stores it in @src. | |
430 | * Returns pointer to @src (if hold queue is not empty) or NULL. | 424 | * Returns pointer to @src (if hold queue is not empty) or NULL. | |
431 | */ | 425 | */ | |
432 | static struct in6_addr * | 426 | static struct in6_addr * | |
433 | nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src) | 427 | nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src) | |
434 | { | 428 | { | |
435 | struct ip6_hdr *hip6; | 429 | struct ip6_hdr *hip6; | |
436 | 430 | |||
437 | if (ln == NULL || ln->ln_hold == NULL) | 431 | if (ln == NULL || ln->ln_hold == NULL) | |
438 | return NULL; | 432 | return NULL; | |
439 | 433 | |||
440 | /* | 434 | /* | |
441 | * assuming every packet in ln_hold has the same IP header | 435 | * assuming every packet in ln_hold has the same IP header | |
442 | */ | 436 | */ | |
443 | hip6 = mtod(ln->ln_hold, struct ip6_hdr *); | 437 | hip6 = mtod(ln->ln_hold, struct ip6_hdr *); | |
444 | /* XXX pullup? */ | 438 | /* XXX pullup? */ | |
445 | if (sizeof(*hip6) < ln->ln_hold->m_len) | 439 | if (sizeof(*hip6) < ln->ln_hold->m_len) | |
446 | *src = hip6->ip6_src; | 440 | *src = hip6->ip6_src; | |
447 | else | 441 | else | |
448 | src = NULL; | 442 | src = NULL; | |
449 | 443 | |||
450 | return src; | 444 | return src; | |
451 | } | 445 | } | |
452 | 446 | |||
453 | static void | 447 | static void | |
454 | nd6_llinfo_timer(void *arg) | 448 | nd6_llinfo_timer(void *arg) | |
455 | { | 449 | { | |
456 | struct llentry *ln = arg; | 450 | struct llentry *ln = arg; | |
457 | struct rtentry *rt; | 451 | struct rtentry *rt; | |
458 | const struct sockaddr_in6 *dst; | 452 | const struct sockaddr_in6 *dst; | |
459 | struct ifnet *ifp; | 453 | struct ifnet *ifp; | |
460 | struct nd_ifinfo *ndi = NULL; | 454 | struct nd_ifinfo *ndi = NULL; | |
461 | bool send_ns = false; | 455 | bool send_ns = false; | |
462 | const struct in6_addr *daddr6 = NULL; | 456 | const struct in6_addr *daddr6 = NULL; | |
463 | 457 | |||
464 | mutex_enter(softnet_lock); | 458 | mutex_enter(softnet_lock); | |
465 | KERNEL_LOCK(1, NULL); | 459 | KERNEL_LOCK(1, NULL); | |
466 | 460 | |||
467 | LLE_WLOCK(ln); | 461 | LLE_WLOCK(ln); | |
468 | if (ln->ln_ntick > 0) { | 462 | if (ln->ln_ntick > 0) { | |
469 | nd6_llinfo_settimer_locked(ln, ln->ln_ntick); | 463 | nd6_llinfo_settimer_locked(ln, ln->ln_ntick); | |
470 | goto out; | 464 | goto out; | |
471 | } | 465 | } | |
472 | 466 | |||
473 | if (callout_pending(&ln->la_timer)) { | 467 | if (callout_pending(&ln->la_timer)) { | |
474 | /* | 468 | /* | |
475 | * Here we are a bit odd here in the treatment of | 469 | * Here we are a bit odd here in the treatment of | |
476 | * active/pending. If the pending bit is set, it got | 470 | * active/pending. If the pending bit is set, it got | |
477 | * rescheduled before I ran. The active | 471 | * rescheduled before I ran. The active | |
478 | * bit we ignore, since if it was stopped | 472 | * bit we ignore, since if it was stopped | |
479 | * in ll_tablefree() and was currently running | 473 | * in ll_tablefree() and was currently running | |
480 | * it would have return 0 so the code would | 474 | * it would have return 0 so the code would | |
481 | * not have deleted it since the callout could | 475 | * not have deleted it since the callout could | |
482 | * not be stopped so we want to go through | 476 | * not be stopped so we want to go through | |
483 | * with the delete here now. If the callout | 477 | * with the delete here now. If the callout | |
484 | * was restarted, the pending bit will be back on and | 478 | * was restarted, the pending bit will be back on and | |
485 | * we just want to bail since the callout_reset would | 479 | * we just want to bail since the callout_reset would | |
486 | * return 1 and our reference would have been removed | 480 | * return 1 and our reference would have been removed | |
487 | * by nd6_llinfo_settimer_locked above since canceled | 481 | * by nd6_llinfo_settimer_locked above since canceled | |
488 | * would have been 1. | 482 | * would have been 1. | |
489 | */ | 483 | */ | |
490 | goto out; | 484 | goto out; | |
491 | } | 485 | } | |
492 | 486 | |||
493 | ifp = ln->lle_tbl->llt_ifp; | 487 | ifp = ln->lle_tbl->llt_ifp; | |
494 | rt = ln->ln_rt; | 488 | rt = ln->ln_rt; | |
495 | 489 | |||
496 | KASSERT(rt != NULL); | 490 | KASSERT(rt != NULL); | |
497 | KASSERT(ifp != NULL); | 491 | KASSERT(ifp != NULL); | |
498 | 492 | |||
499 | ndi = ND_IFINFO(ifp); | 493 | ndi = ND_IFINFO(ifp); | |
500 | dst = satocsin6(rt_getkey(rt)); | 494 | dst = satocsin6(rt_getkey(rt)); | |
501 | 495 | |||
502 | /* sanity check */ | 496 | /* sanity check */ | |
503 | if (rt->rt_llinfo && (struct llentry *)rt->rt_llinfo != ln) | 497 | if (rt->rt_llinfo && (struct llentry *)rt->rt_llinfo != ln) | |
504 | panic("rt_llinfo(%p) is not equal to ln(%p)", | 498 | panic("rt_llinfo(%p) is not equal to ln(%p)", | |
505 | rt->rt_llinfo, ln); | 499 | rt->rt_llinfo, ln); | |
506 | if (!dst) | 500 | if (!dst) | |
507 | panic("dst=0 in nd6_timer(ln=%p)", ln); | 501 | panic("dst=0 in nd6_timer(ln=%p)", ln); | |
508 | 502 | |||
509 | switch (ln->ln_state) { | 503 | switch (ln->ln_state) { | |
510 | case ND6_LLINFO_INCOMPLETE: | 504 | case ND6_LLINFO_INCOMPLETE: | |
511 | if (ln->ln_asked < nd6_mmaxtries) { | 505 | if (ln->ln_asked < nd6_mmaxtries) { | |
512 | ln->ln_asked++; | 506 | ln->ln_asked++; | |
513 | send_ns = true; | 507 | send_ns = true; | |
514 | } else { | 508 | } else { | |
515 | struct mbuf *m = ln->ln_hold; | 509 | struct mbuf *m = ln->ln_hold; | |
516 | if (m) { | 510 | if (m) { | |
517 | struct mbuf *m0; | 511 | struct mbuf *m0; | |
518 | 512 | |||
519 | /* | 513 | /* | |
520 | * assuming every packet in ln_hold has | 514 | * assuming every packet in ln_hold has | |
521 | * the same IP header | 515 | * the same IP header | |
522 | */ | 516 | */ | |
523 | m0 = m->m_nextpkt; | 517 | m0 = m->m_nextpkt; | |
524 | m->m_nextpkt = NULL; | 518 | m->m_nextpkt = NULL; | |
525 | ln->ln_hold = m0; | 519 | ln->ln_hold = m0; | |
526 | clear_llinfo_pqueue(ln); | 520 | clear_llinfo_pqueue(ln); | |
527 | } | 521 | } | |
528 | nd6_free(rt, ln, 0); | 522 | nd6_free(rt, ln, 0); | |
529 | ln = NULL; | 523 | ln = NULL; | |
530 | if (m != NULL) | 524 | if (m != NULL) | |
531 | icmp6_error2(m, ICMP6_DST_UNREACH, | 525 | icmp6_error2(m, ICMP6_DST_UNREACH, | |
532 | ICMP6_DST_UNREACH_ADDR, 0, ifp); | 526 | ICMP6_DST_UNREACH_ADDR, 0, ifp); | |
533 | } | 527 | } | |
534 | break; | 528 | break; | |
535 | case ND6_LLINFO_REACHABLE: | 529 | case ND6_LLINFO_REACHABLE: | |
536 | if (!ND6_LLINFO_PERMANENT(ln)) { | 530 | if (!ND6_LLINFO_PERMANENT(ln)) { | |
537 | ln->ln_state = ND6_LLINFO_STALE; | 531 | ln->ln_state = ND6_LLINFO_STALE; | |
538 | nd6_llinfo_settimer_locked(ln, nd6_gctimer * hz); | 532 | nd6_llinfo_settimer_locked(ln, nd6_gctimer * hz); | |
539 | } | 533 | } | |
540 | break; | 534 | break; | |
541 | 535 | |||
542 | case ND6_LLINFO_PURGE: | 536 | case ND6_LLINFO_PURGE: | |
543 | case ND6_LLINFO_STALE: | 537 | case ND6_LLINFO_STALE: | |
544 | /* Garbage Collection(RFC 2461 5.3) */ | 538 | /* Garbage Collection(RFC 2461 5.3) */ | |
545 | if (!ND6_LLINFO_PERMANENT(ln)) { | 539 | if (!ND6_LLINFO_PERMANENT(ln)) { | |
546 | nd6_free(rt, ln, 1); | 540 | nd6_free(rt, ln, 1); | |
547 | ln = NULL; | 541 | ln = NULL; | |
548 | } | 542 | } | |
549 | break; | 543 | break; | |
550 | 544 | |||
551 | case ND6_LLINFO_DELAY: | 545 | case ND6_LLINFO_DELAY: | |
552 | if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) { | 546 | if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) { | |
553 | /* We need NUD */ | 547 | /* We need NUD */ | |
554 | ln->ln_asked = 1; | 548 | ln->ln_asked = 1; | |
555 | ln->ln_state = ND6_LLINFO_PROBE; | 549 | ln->ln_state = ND6_LLINFO_PROBE; | |
556 | daddr6 = &dst->sin6_addr; | 550 | daddr6 = &dst->sin6_addr; | |
557 | send_ns = true; | 551 | send_ns = true; | |
558 | } else { | 552 | } else { | |
559 | ln->ln_state = ND6_LLINFO_STALE; /* XXX */ | 553 | ln->ln_state = ND6_LLINFO_STALE; /* XXX */ | |
560 | nd6_llinfo_settimer_locked(ln, nd6_gctimer * hz); | 554 | nd6_llinfo_settimer_locked(ln, nd6_gctimer * hz); | |
561 | } | 555 | } | |
562 | break; | 556 | break; | |
563 | case ND6_LLINFO_PROBE: | 557 | case ND6_LLINFO_PROBE: | |
564 | if (ln->ln_asked < nd6_umaxtries) { | 558 | if (ln->ln_asked < nd6_umaxtries) { | |
565 | ln->ln_asked++; | 559 | ln->ln_asked++; | |
566 | daddr6 = &dst->sin6_addr; | 560 | daddr6 = &dst->sin6_addr; | |
567 | send_ns = true; | 561 | send_ns = true; | |
568 | } else { | 562 | } else { | |
569 | nd6_free(rt, ln, 0); | 563 | nd6_free(rt, ln, 0); | |
570 | ln = NULL; | 564 | ln = NULL; | |
571 | } | 565 | } | |
572 | break; | 566 | break; | |
573 | } | 567 | } | |
574 | 568 | |||
575 | if (send_ns) { | 569 | if (send_ns) { | |
576 | struct in6_addr src, *psrc; | 570 | struct in6_addr src, *psrc; | |
577 | 571 | |||
578 | nd6_llinfo_settimer_locked(ln, ndi->retrans * hz / 1000); | 572 | nd6_llinfo_settimer_locked(ln, ndi->retrans * hz / 1000); | |
579 | psrc = nd6_llinfo_get_holdsrc(ln, &src); | 573 | psrc = nd6_llinfo_get_holdsrc(ln, &src); | |
580 | LLE_FREE_LOCKED(ln); | 574 | LLE_FREE_LOCKED(ln); | |
581 | ln = NULL; | 575 | ln = NULL; | |
582 | nd6_ns_output(ifp, daddr6, &dst->sin6_addr, psrc, 0); | 576 | nd6_ns_output(ifp, daddr6, &dst->sin6_addr, psrc, 0); | |
583 | } | 577 | } | |
584 | 578 | |||
585 | out: | 579 | out: | |
586 | if (ln != NULL) | 580 | if (ln != NULL) | |
587 | LLE_FREE_LOCKED(ln); | 581 | LLE_FREE_LOCKED(ln); | |
588 | KERNEL_UNLOCK_ONE(NULL); | 582 | KERNEL_UNLOCK_ONE(NULL); | |
589 | mutex_exit(softnet_lock); | 583 | mutex_exit(softnet_lock); | |
590 | } | 584 | } | |
591 | 585 | |||
592 | /* | 586 | /* | |
593 | * ND6 timer routine to expire default route list and prefix list | 587 | * ND6 timer routine to expire default route list and prefix list | |
594 | */ | 588 | */ | |
595 | void | 589 | static void | |
596 | nd6_timer(void *ignored_arg) | 590 | nd6_timer(void *ignored_arg) | |
597 | { | 591 | { | |
598 | struct nd_defrouter *next_dr, *dr; | 592 | struct nd_defrouter *next_dr, *dr; | |
599 | struct nd_prefix *next_pr, *pr; | 593 | struct nd_prefix *next_pr, *pr; | |
600 | struct in6_ifaddr *ia6, *nia6; | 594 | struct in6_ifaddr *ia6, *nia6; | |
601 | 595 | |||
602 | callout_reset(&nd6_timer_ch, nd6_prune * hz, | 596 | callout_reset(&nd6_timer_ch, nd6_prune * hz, | |
603 | nd6_timer, NULL); | 597 | nd6_timer, NULL); | |
604 | 598 | |||
605 | mutex_enter(softnet_lock); | 599 | mutex_enter(softnet_lock); | |
606 | KERNEL_LOCK(1, NULL); | 600 | KERNEL_LOCK(1, NULL); | |
607 | 601 | |||
608 | /* expire default router list */ | 602 | /* expire default router list */ | |
609 | 603 | |||
610 | TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, next_dr) { | 604 | TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, next_dr) { | |
611 | if (dr->expire && dr->expire < time_uptime) { | 605 | if (dr->expire && dr->expire < time_uptime) { | |
612 | defrtrlist_del(dr, NULL); | 606 | defrtrlist_del(dr, NULL); | |
613 | } | 607 | } | |
614 | } | 608 | } | |
615 | 609 | |||
616 | /* | 610 | /* | |
617 | * expire interface addresses. | 611 | * expire interface addresses. | |
618 | * in the past the loop was inside prefix expiry processing. | 612 | * in the past the loop was inside prefix expiry processing. | |
619 | * However, from a stricter speci-confrmance standpoint, we should | 613 | * However, from a stricter speci-confrmance standpoint, we should | |
620 | * rather separate address lifetimes and prefix lifetimes. | 614 | * rather separate address lifetimes and prefix lifetimes. | |
621 | */ | 615 | */ | |
622 | addrloop: | 616 | addrloop: | |
623 | for (ia6 = in6_ifaddr; ia6; ia6 = nia6) { | 617 | for (ia6 = in6_ifaddr; ia6; ia6 = nia6) { | |
624 | nia6 = ia6->ia_next; | 618 | nia6 = ia6->ia_next; | |
625 | /* check address lifetime */ | 619 | /* check address lifetime */ | |
626 | if (IFA6_IS_INVALID(ia6)) { | 620 | if (IFA6_IS_INVALID(ia6)) { | |
627 | int regen = 0; | 621 | int regen = 0; | |
628 | 622 | |||
629 | /* | 623 | /* | |
630 | * If the expiring address is temporary, try | 624 | * If the expiring address is temporary, try | |
631 | * regenerating a new one. This would be useful when | 625 | * regenerating a new one. This would be useful when | |
632 | * we suspended a laptop PC, then turned it on after a | 626 | * we suspended a laptop PC, then turned it on after a | |
633 | * period that could invalidate all temporary | 627 | * period that could invalidate all temporary | |
634 | * addresses. Although we may have to restart the | 628 | * addresses. Although we may have to restart the | |
635 | * loop (see below), it must be after purging the | 629 | * loop (see below), it must be after purging the | |
636 | * address. Otherwise, we'd see an infinite loop of | 630 | * address. Otherwise, we'd see an infinite loop of | |
637 | * regeneration. | 631 | * regeneration. | |
638 | */ | 632 | */ | |
639 | if (ip6_use_tempaddr && | 633 | if (ip6_use_tempaddr && | |
640 | (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) { | 634 | (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) { | |
641 | if (regen_tmpaddr(ia6) == 0) | 635 | if (regen_tmpaddr(ia6) == 0) | |
642 | regen = 1; | 636 | regen = 1; | |
643 | } | 637 | } | |
644 | 638 | |||
645 | in6_purgeaddr(&ia6->ia_ifa); | 639 | in6_purgeaddr(&ia6->ia_ifa); | |
646 | 640 | |||
647 | if (regen) | 641 | if (regen) | |
648 | goto addrloop; /* XXX: see below */ | 642 | goto addrloop; /* XXX: see below */ | |
649 | } else if (IFA6_IS_DEPRECATED(ia6)) { | 643 | } else if (IFA6_IS_DEPRECATED(ia6)) { | |
650 | int oldflags = ia6->ia6_flags; | 644 | int oldflags = ia6->ia6_flags; | |
651 | 645 | |||
652 | if ((oldflags & IN6_IFF_DEPRECATED) == 0) { | 646 | if ((oldflags & IN6_IFF_DEPRECATED) == 0) { | |
653 | ia6->ia6_flags |= IN6_IFF_DEPRECATED; | 647 | ia6->ia6_flags |= IN6_IFF_DEPRECATED; | |
654 | rt_newaddrmsg(RTM_NEWADDR, | 648 | rt_newaddrmsg(RTM_NEWADDR, | |
655 | (struct ifaddr *)ia6, 0, NULL); | 649 | (struct ifaddr *)ia6, 0, NULL); | |
656 | } | 650 | } | |
657 | 651 | |||
658 | /* | 652 | /* | |
659 | * If a temporary address has just become deprecated, | 653 | * If a temporary address has just become deprecated, | |
660 | * regenerate a new one if possible. | 654 | * regenerate a new one if possible. | |
661 | */ | 655 | */ | |
662 | if (ip6_use_tempaddr && | 656 | if (ip6_use_tempaddr && | |
663 | (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && | 657 | (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && | |
664 | (oldflags & IN6_IFF_DEPRECATED) == 0) { | 658 | (oldflags & IN6_IFF_DEPRECATED) == 0) { | |
665 | 659 | |||
666 | if (regen_tmpaddr(ia6) == 0) { | 660 | if (regen_tmpaddr(ia6) == 0) { | |
667 | /* | 661 | /* | |
668 | * A new temporary address is | 662 | * A new temporary address is | |
669 | * generated. | 663 | * generated. | |
670 | * XXX: this means the address chain | 664 | * XXX: this means the address chain | |
671 | * has changed while we are still in | 665 | * has changed while we are still in | |
672 | * the loop. Although the change | 666 | * the loop. Although the change | |
673 | * would not cause disaster (because | 667 | * would not cause disaster (because | |
674 | * it's not a deletion, but an | 668 | * it's not a deletion, but an | |
675 | * addition,) we'd rather restart the | 669 | * addition,) we'd rather restart the | |
676 | * loop just for safety. Or does this | 670 | * loop just for safety. Or does this | |
677 | * significantly reduce performance?? | 671 | * significantly reduce performance?? | |
678 | */ | 672 | */ | |
679 | goto addrloop; | 673 | goto addrloop; | |
680 | } | 674 | } | |
681 | } | 675 | } | |
682 | } else { | 676 | } else { | |
683 | /* | 677 | /* | |
684 | * A new RA might have made a deprecated address | 678 | * A new RA might have made a deprecated address | |
685 | * preferred. | 679 | * preferred. | |
686 | */ | 680 | */ | |
687 | if (ia6->ia6_flags & IN6_IFF_DEPRECATED) { | 681 | if (ia6->ia6_flags & IN6_IFF_DEPRECATED) { | |
688 | ia6->ia6_flags &= ~IN6_IFF_DEPRECATED; | 682 | ia6->ia6_flags &= ~IN6_IFF_DEPRECATED; | |
689 | rt_newaddrmsg(RTM_NEWADDR, | 683 | rt_newaddrmsg(RTM_NEWADDR, | |
690 | (struct ifaddr *)ia6, 0, NULL); | 684 | (struct ifaddr *)ia6, 0, NULL); | |
691 | } | 685 | } | |
692 | } | 686 | } | |
693 | } | 687 | } | |
694 | 688 | |||
695 | /* expire prefix list */ | 689 | /* expire prefix list */ | |
696 | LIST_FOREACH_SAFE(pr, &nd_prefix, ndpr_entry, next_pr) { | 690 | LIST_FOREACH_SAFE(pr, &nd_prefix, ndpr_entry, next_pr) { | |
697 | /* | 691 | /* | |
698 | * check prefix lifetime. | 692 | * check prefix lifetime. | |
699 | * since pltime is just for autoconf, pltime processing for | 693 | * since pltime is just for autoconf, pltime processing for | |
700 | * prefix is not necessary. | 694 | * prefix is not necessary. | |
701 | */ | 695 | */ | |
702 | if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME && | 696 | if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME && | |
703 | time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) { | 697 | time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) { | |
704 | 698 | |||
705 | /* | 699 | /* | |
706 | * address expiration and prefix expiration are | 700 | * address expiration and prefix expiration are | |
707 | * separate. NEVER perform in6_purgeaddr here. | 701 | * separate. NEVER perform in6_purgeaddr here. | |
708 | */ | 702 | */ | |
709 | 703 | |||
710 | prelist_remove(pr); | 704 | prelist_remove(pr); | |
711 | } | 705 | } | |
712 | } | 706 | } | |
713 | 707 | |||
714 | KERNEL_UNLOCK_ONE(NULL); | 708 | KERNEL_UNLOCK_ONE(NULL); | |
715 | mutex_exit(softnet_lock); | 709 | mutex_exit(softnet_lock); | |
716 | } | 710 | } | |
717 | 711 | |||
718 | /* ia6: deprecated/invalidated temporary address */ | 712 | /* ia6: deprecated/invalidated temporary address */ | |
719 | static int | 713 | static int | |
720 | regen_tmpaddr(struct in6_ifaddr *ia6) | 714 | regen_tmpaddr(struct in6_ifaddr *ia6) | |
721 | { | 715 | { | |
722 | struct ifaddr *ifa; | 716 | struct ifaddr *ifa; | |
723 | struct ifnet *ifp; | 717 | struct ifnet *ifp; | |
724 | struct in6_ifaddr *public_ifa6 = NULL; | 718 | struct in6_ifaddr *public_ifa6 = NULL; | |
725 | 719 | |||
726 | ifp = ia6->ia_ifa.ifa_ifp; | 720 | ifp = ia6->ia_ifa.ifa_ifp; | |
727 | IFADDR_FOREACH(ifa, ifp) { | 721 | IFADDR_FOREACH(ifa, ifp) { | |
728 | struct in6_ifaddr *it6; | 722 | struct in6_ifaddr *it6; | |
729 | 723 | |||
730 | if (ifa->ifa_addr->sa_family != AF_INET6) | 724 | if (ifa->ifa_addr->sa_family != AF_INET6) | |
731 | continue; | 725 | continue; | |
732 | 726 | |||
733 | it6 = (struct in6_ifaddr *)ifa; | 727 | it6 = (struct in6_ifaddr *)ifa; | |
734 | 728 | |||
735 | /* ignore no autoconf addresses. */ | 729 | /* ignore no autoconf addresses. */ | |
736 | if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0) | 730 | if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0) | |
737 | continue; | 731 | continue; | |
738 | 732 | |||
739 | /* ignore autoconf addresses with different prefixes. */ | 733 | /* ignore autoconf addresses with different prefixes. */ | |
740 | if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr) | 734 | if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr) | |
741 | continue; | 735 | continue; | |
742 | 736 | |||
743 | /* | 737 | /* | |
744 | * Now we are looking at an autoconf address with the same | 738 | * Now we are looking at an autoconf address with the same | |
745 | * prefix as ours. If the address is temporary and is still | 739 | * prefix as ours. If the address is temporary and is still | |
746 | * preferred, do not create another one. It would be rare, but | 740 | * preferred, do not create another one. It would be rare, but | |
747 | * could happen, for example, when we resume a laptop PC after | 741 | * could happen, for example, when we resume a laptop PC after | |
748 | * a long period. | 742 | * a long period. | |
749 | */ | 743 | */ | |
750 | if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && | 744 | if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && | |
751 | !IFA6_IS_DEPRECATED(it6)) { | 745 | !IFA6_IS_DEPRECATED(it6)) { | |
752 | public_ifa6 = NULL; | 746 | public_ifa6 = NULL; | |
753 | break; | 747 | break; | |
754 | } | 748 | } | |
755 | 749 | |||
756 | /* | 750 | /* | |
757 | * This is a public autoconf address that has the same prefix | 751 | * This is a public autoconf address that has the same prefix | |
758 | * as ours. If it is preferred, keep it. We can't break the | 752 | * as ours. If it is preferred, keep it. We can't break the | |
759 | * loop here, because there may be a still-preferred temporary | 753 | * loop here, because there may be a still-preferred temporary | |
760 | * address with the prefix. | 754 | * address with the prefix. | |
761 | */ | 755 | */ | |
762 | if (!IFA6_IS_DEPRECATED(it6)) | 756 | if (!IFA6_IS_DEPRECATED(it6)) | |
763 | public_ifa6 = it6; | 757 | public_ifa6 = it6; | |
764 | } | 758 | } | |
765 | 759 | |||
766 | if (public_ifa6 != NULL) { | 760 | if (public_ifa6 != NULL) { | |
767 | int e; | 761 | int e; | |
768 | 762 | |||
769 | /* | 763 | /* | |
770 | * Random factor is introduced in the preferred lifetime, so | 764 | * Random factor is introduced in the preferred lifetime, so | |
771 | * we do not need additional delay (3rd arg to in6_tmpifadd). | 765 | * we do not need additional delay (3rd arg to in6_tmpifadd). | |
772 | */ | 766 | */ | |
773 | if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) { | 767 | if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) { | |
774 | log(LOG_NOTICE, "regen_tmpaddr: failed to create a new" | 768 | log(LOG_NOTICE, "regen_tmpaddr: failed to create a new" | |
775 | " tmp addr, errno=%d\n", e); | 769 | " tmp addr, errno=%d\n", e); | |
776 | return -1; | 770 | return -1; | |
777 | } | 771 | } | |
778 | return 0; | 772 | return 0; | |
779 | } | 773 | } | |
780 | 774 | |||
781 | return -1; | 775 | return -1; | |
782 | } | 776 | } | |
783 | 777 | |||
784 | bool | 778 | bool | |
785 | nd6_accepts_rtadv(const struct nd_ifinfo *ndi) | 779 | nd6_accepts_rtadv(const struct nd_ifinfo *ndi) | |
786 | { | 780 | { | |
787 | switch (ndi->flags & (ND6_IFF_ACCEPT_RTADV|ND6_IFF_OVERRIDE_RTADV)) { | 781 | switch (ndi->flags & (ND6_IFF_ACCEPT_RTADV|ND6_IFF_OVERRIDE_RTADV)) { | |
788 | case ND6_IFF_OVERRIDE_RTADV|ND6_IFF_ACCEPT_RTADV: | 782 | case ND6_IFF_OVERRIDE_RTADV|ND6_IFF_ACCEPT_RTADV: | |
789 | return true; | 783 | return true; | |
790 | case ND6_IFF_ACCEPT_RTADV: | 784 | case ND6_IFF_ACCEPT_RTADV: | |
791 | return ip6_accept_rtadv != 0; | 785 | return ip6_accept_rtadv != 0; | |
792 | case ND6_IFF_OVERRIDE_RTADV: | 786 | case ND6_IFF_OVERRIDE_RTADV: | |
793 | case 0: | 787 | case 0: | |
794 | default: | 788 | default: | |
795 | return false; | 789 | return false; | |
796 | } | 790 | } | |
797 | } | 791 | } | |
798 | 792 | |||
799 | /* | 793 | /* | |
800 | * Nuke neighbor cache/prefix/default router management table, right before | 794 | * Nuke neighbor cache/prefix/default router management table, right before | |
801 | * ifp goes away. | 795 | * ifp goes away. | |
802 | */ | 796 | */ | |
803 | void | 797 | void | |
804 | nd6_purge(struct ifnet *ifp, struct in6_ifextra *ext) | 798 | nd6_purge(struct ifnet *ifp, struct in6_ifextra *ext) | |
805 | { | 799 | { | |
806 | struct nd_defrouter *dr, *ndr; | 800 | struct nd_defrouter *dr, *ndr; | |
807 | struct nd_prefix *pr, *npr; | 801 | struct nd_prefix *pr, *npr; | |
808 | 802 | |||
809 | /* | 803 | /* | |
810 | * During detach, the ND info might be already removed, but | 804 | * During detach, the ND info might be already removed, but | |
811 | * then is explitly passed as argument. | 805 | * then is explitly passed as argument. | |
812 | * Otherwise get it from ifp->if_afdata. | 806 | * Otherwise get it from ifp->if_afdata. | |
813 | */ | 807 | */ | |
814 | if (ext == NULL) | 808 | if (ext == NULL) | |
815 | ext = ifp->if_afdata[AF_INET6]; | 809 | ext = ifp->if_afdata[AF_INET6]; | |
816 | if (ext == NULL) | 810 | if (ext == NULL) | |
817 | return; | 811 | return; | |
818 | 812 | |||
819 | /* | 813 | /* | |
820 | * Nuke default router list entries toward ifp. | 814 | * Nuke default router list entries toward ifp. | |
821 | * We defer removal of default router list entries that is installed | 815 | * We defer removal of default router list entries that is installed | |
822 | * in the routing table, in order to keep additional side effects as | 816 | * in the routing table, in order to keep additional side effects as | |
823 | * small as possible. | 817 | * small as possible. | |
824 | */ | 818 | */ | |
825 | TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, ndr) { | 819 | TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, ndr) { | |
826 | if (dr->installed) | 820 | if (dr->installed) | |
827 | continue; | 821 | continue; | |
828 | 822 | |||
829 | if (dr->ifp == ifp) { | 823 | if (dr->ifp == ifp) { | |
830 | KASSERT(ext != NULL); | 824 | KASSERT(ext != NULL); | |
831 | defrtrlist_del(dr, ext); | 825 | defrtrlist_del(dr, ext); | |
832 | } | 826 | } | |
833 | } | 827 | } | |
834 | 828 | |||
835 | TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, ndr) { | 829 | TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, ndr) { | |
836 | if (!dr->installed) | 830 | if (!dr->installed) | |
837 | continue; | 831 | continue; | |
838 | 832 | |||
839 | if (dr->ifp == ifp) { | 833 | if (dr->ifp == ifp) { | |
840 | KASSERT(ext != NULL); | 834 | KASSERT(ext != NULL); | |
841 | defrtrlist_del(dr, ext); | 835 | defrtrlist_del(dr, ext); | |
842 | } | 836 | } | |
843 | } | 837 | } | |
844 | 838 | |||
845 | /* Nuke prefix list entries toward ifp */ | 839 | /* Nuke prefix list entries toward ifp */ | |
846 | LIST_FOREACH_SAFE(pr, &nd_prefix, ndpr_entry, npr) { | 840 | LIST_FOREACH_SAFE(pr, &nd_prefix, ndpr_entry, npr) { | |
847 | if (pr->ndpr_ifp == ifp) { | 841 | if (pr->ndpr_ifp == ifp) { | |
848 | /* | 842 | /* | |
849 | * Because if_detach() does *not* release prefixes | 843 | * Because if_detach() does *not* release prefixes | |
850 | * while purging addresses the reference count will | 844 | * while purging addresses the reference count will | |
851 | * still be above zero. We therefore reset it to | 845 | * still be above zero. We therefore reset it to | |
852 | * make sure that the prefix really gets purged. | 846 | * make sure that the prefix really gets purged. | |
853 | */ | 847 | */ | |
854 | pr->ndpr_refcnt = 0; | 848 | pr->ndpr_refcnt = 0; | |
855 | /* | 849 | /* | |
856 | * Previously, pr->ndpr_addr is removed as well, | 850 | * Previously, pr->ndpr_addr is removed as well, | |
857 | * but I strongly believe we don't have to do it. | 851 | * but I strongly believe we don't have to do it. | |
858 | * nd6_purge() is only called from in6_ifdetach(), | 852 | * nd6_purge() is only called from in6_ifdetach(), | |
859 | * which removes all the associated interface addresses | 853 | * which removes all the associated interface addresses | |
860 | * by itself. | 854 | * by itself. | |
861 | * (jinmei@kame.net 20010129) | 855 | * (jinmei@kame.net 20010129) | |
862 | */ | 856 | */ | |
863 | prelist_remove(pr); | 857 | prelist_remove(pr); | |
864 | } | 858 | } | |
865 | } | 859 | } | |
866 | 860 | |||
867 | /* cancel default outgoing interface setting */ | 861 | /* cancel default outgoing interface setting */ | |
868 | if (nd6_defifindex == ifp->if_index) | 862 | if (nd6_defifindex == ifp->if_index) | |
869 | nd6_setdefaultiface(0); | 863 | nd6_setdefaultiface(0); | |
870 | 864 | |||
871 | /* XXX: too restrictive? */ | 865 | /* XXX: too restrictive? */ | |
872 | if (!ip6_forwarding && ifp->if_afdata[AF_INET6]) { | 866 | if (!ip6_forwarding && ifp->if_afdata[AF_INET6]) { | |
873 | struct nd_ifinfo *ndi = ND_IFINFO(ifp); | 867 | struct nd_ifinfo *ndi = ND_IFINFO(ifp); | |
874 | if (ndi && nd6_accepts_rtadv(ndi)) { | 868 | if (ndi && nd6_accepts_rtadv(ndi)) { | |
875 | /* refresh default router list */ | 869 | /* refresh default router list */ | |
876 | defrouter_select(); | 870 | defrouter_select(); | |
877 | } | 871 | } | |
878 | } | 872 | } | |
879 | 873 | |||
880 | /* | 874 | /* | |
881 | * We may not need to nuke the neighbor cache entries here | 875 | * We may not need to nuke the neighbor cache entries here | |
882 | * because the neighbor cache is kept in if_afdata[AF_INET6]. | 876 | * because the neighbor cache is kept in if_afdata[AF_INET6]. | |
883 | * nd6_purge() is invoked by in6_ifdetach() which is called | 877 | * nd6_purge() is invoked by in6_ifdetach() which is called | |
884 | * from if_detach() where everything gets purged. However | 878 | * from if_detach() where everything gets purged. However | |
885 | * in6_ifdetach is directly called from vlan(4), so we still | 879 | * in6_ifdetach is directly called from vlan(4), so we still | |
886 | * need to purge entries here. | 880 | * need to purge entries here. | |
887 | */ | 881 | */ | |
888 | if (ext->lltable != NULL) | 882 | if (ext->lltable != NULL) | |
889 | lltable_purge_entries(ext->lltable); | 883 | lltable_purge_entries(ext->lltable); | |
890 | } | 884 | } | |
891 | 885 | |||
892 | static struct rtentry * | 886 | static struct rtentry * | |
893 | nd6_lookup1(const struct in6_addr *addr6, int create, struct ifnet *ifp, | 887 | nd6_lookup1(const struct in6_addr *addr6, int create, struct ifnet *ifp, | |
894 | int cloning) | 888 | int cloning) | |
895 | { | 889 | { | |
896 | struct rtentry *rt; | 890 | struct rtentry *rt; | |
897 | struct sockaddr_in6 sin6; | 891 | struct sockaddr_in6 sin6; | |
898 | 892 | |||
899 | sockaddr_in6_init(&sin6, addr6, 0, 0, 0); | 893 | sockaddr_in6_init(&sin6, addr6, 0, 0, 0); | |
900 | rt = rtalloc1((struct sockaddr *)&sin6, create); | 894 | rt = rtalloc1((struct sockaddr *)&sin6, create); | |
901 | if (rt != NULL && (rt->rt_flags & RTF_LLINFO) == 0) { | 895 | if (rt != NULL && (rt->rt_flags & RTF_LLINFO) == 0) { | |
902 | /* | 896 | /* | |
903 | * This is the case for the default route. | 897 | * This is the case for the default route. | |
904 | * If we want to create a neighbor cache for the address, we | 898 | * If we want to create a neighbor cache for the address, we | |
905 | * should free the route for the destination and allocate an | 899 | * should free the route for the destination and allocate an | |
906 | * interface route. | 900 | * interface route. | |
907 | */ | 901 | */ | |
908 | if (create) { | 902 | if (create) { | |
909 | rtfree(rt); | 903 | rtfree(rt); | |
910 | rt = NULL; | 904 | rt = NULL; | |
911 | } | 905 | } | |
912 | } | 906 | } | |
913 | if (rt != NULL) | 907 | if (rt != NULL) | |
914 | ; | 908 | ; | |
915 | else if (create && ifp) { | 909 | else if (create && ifp) { | |
916 | int e; | 910 | int e; | |
917 | 911 | |||
918 | /* | 912 | /* | |
919 | * If no route is available and create is set, | 913 | * If no route is available and create is set, | |
920 | * we allocate a host route for the destination | 914 | * we allocate a host route for the destination | |
921 | * and treat it like an interface route. | 915 | * and treat it like an interface route. | |
922 | * This hack is necessary for a neighbor which can't | 916 | * This hack is necessary for a neighbor which can't | |
923 | * be covered by our own prefix. | 917 | * be covered by our own prefix. | |
924 | */ | 918 | */ | |
925 | struct ifaddr *ifa = | 919 | struct ifaddr *ifa = | |
926 | ifaof_ifpforaddr((struct sockaddr *)&sin6, ifp); | 920 | ifaof_ifpforaddr((struct sockaddr *)&sin6, ifp); | |
927 | if (ifa == NULL) | 921 | if (ifa == NULL) | |
928 | return NULL; | 922 | return NULL; | |
929 | 923 | |||
930 | /* | 924 | /* | |
931 | * Create a new route. RTF_LLINFO is necessary | 925 | * Create a new route. RTF_LLINFO is necessary | |
932 | * to create a Neighbor Cache entry for the | 926 | * to create a Neighbor Cache entry for the | |
933 | * destination in nd6_rtrequest which will be | 927 | * destination in nd6_rtrequest which will be | |
934 | * called in rtrequest via ifa->ifa_rtrequest. | 928 | * called in rtrequest via ifa->ifa_rtrequest. | |
935 | */ | 929 | */ | |
936 | if ((e = rtrequest(RTM_ADD, (const struct sockaddr *)&sin6, | 930 | if ((e = rtrequest(RTM_ADD, (const struct sockaddr *)&sin6, | |
937 | ifa->ifa_addr, (const struct sockaddr *)&all1_sa, | 931 | ifa->ifa_addr, (const struct sockaddr *)&all1_sa, | |
938 | (ifa->ifa_flags | RTF_HOST | RTF_LLINFO) & | 932 | (ifa->ifa_flags | RTF_HOST | RTF_LLINFO) & | |
939 | ~RTF_CLONING, &rt)) != 0) { | 933 | ~RTF_CLONING, &rt)) != 0) { | |
940 | #if 0 | 934 | #if 0 | |
941 | log(LOG_ERR, | 935 | log(LOG_ERR, | |
942 | "nd6_lookup: failed to add route for a " | 936 | "nd6_lookup: failed to add route for a " | |
943 | "neighbor(%s), errno=%d\n", | 937 | "neighbor(%s), errno=%d\n", | |
944 | ip6_sprintf(addr6), e); | 938 | ip6_sprintf(addr6), e); | |
945 | #endif | 939 | #endif | |
946 | return NULL; | 940 | return NULL; | |
947 | } | 941 | } | |
948 | if (rt == NULL) | 942 | if (rt == NULL) | |
949 | return NULL; | 943 | return NULL; | |
950 | if (rt->rt_llinfo) { | 944 | if (rt->rt_llinfo) { | |
951 | struct llentry *ln = rt->rt_llinfo; | 945 | struct llentry *ln = rt->rt_llinfo; | |
952 | ln->ln_state = ND6_LLINFO_NOSTATE; | 946 | ln->ln_state = ND6_LLINFO_NOSTATE; | |
953 | } | 947 | } | |
954 | } else | 948 | } else | |
955 | return NULL; | 949 | return NULL; | |
956 | 950 | |||
957 | /* | 951 | /* | |
958 | * Check for a cloning route to match the address. | 952 | * Check for a cloning route to match the address. | |
959 | * This should only be set from in6_is_addr_neighbor so we avoid | 953 | * This should only be set from in6_is_addr_neighbor so we avoid | |
960 | * a potentially expensive second call to rtalloc1. | 954 | * a potentially expensive second call to rtalloc1. | |
961 | */ | 955 | */ | |
962 | if (cloning && | 956 | if (cloning && | |
963 | rt->rt_flags & (RTF_CLONING | RTF_CLONED) && | 957 | rt->rt_flags & (RTF_CLONING | RTF_CLONED) && | |
964 | (rt->rt_ifp == ifp | 958 | (rt->rt_ifp == ifp | |
965 | #if NBRIDGE > 0 | 959 | #if NBRIDGE > 0 | |
966 | || rt->rt_ifp->if_bridge == ifp->if_bridge | 960 | || rt->rt_ifp->if_bridge == ifp->if_bridge | |
967 | #endif | 961 | #endif | |
968 | #if NCARP > 0 | 962 | #if NCARP > 0 | |
969 | || (ifp->if_type == IFT_CARP && rt->rt_ifp == ifp->if_carpdev) || | 963 | || (ifp->if_type == IFT_CARP && rt->rt_ifp == ifp->if_carpdev) || | |
970 | (rt->rt_ifp->if_type == IFT_CARP && rt->rt_ifp->if_carpdev == ifp)|| | 964 | (rt->rt_ifp->if_type == IFT_CARP && rt->rt_ifp->if_carpdev == ifp)|| | |
971 | (ifp->if_type == IFT_CARP && rt->rt_ifp->if_type == IFT_CARP && | 965 | (ifp->if_type == IFT_CARP && rt->rt_ifp->if_type == IFT_CARP && | |
972 | rt->rt_ifp->if_carpdev == ifp->if_carpdev) | 966 | rt->rt_ifp->if_carpdev == ifp->if_carpdev) | |
973 | #endif | 967 | #endif | |
974 | )) | 968 | )) | |
975 | return rt; | 969 | return rt; | |
976 | 970 | |||
977 | /* | 971 | /* | |
978 | * Validation for the entry. | 972 | * Validation for the entry. | |
979 | * Note that the check for rt_llinfo is necessary because a cloned | 973 | * Note that the check for rt_llinfo is necessary because a cloned | |
980 | * route from a parent route that has the L flag (e.g. the default | 974 | * route from a parent route that has the L flag (e.g. the default | |
981 | * route to a p2p interface) may have the flag, too, while the | 975 | * route to a p2p interface) may have the flag, too, while the | |
982 | * destination is not actually a neighbor. | 976 | * destination is not actually a neighbor. | |
983 | * XXX: we can't use rt->rt_ifp to check for the interface, since | 977 | * XXX: we can't use rt->rt_ifp to check for the interface, since | |
984 | * it might be the loopback interface if the entry is for our | 978 | * it might be the loopback interface if the entry is for our | |
985 | * own address on a non-loopback interface. Instead, we should | 979 | * own address on a non-loopback interface. Instead, we should | |
986 | * use rt->rt_ifa->ifa_ifp, which would specify the REAL | 980 | * use rt->rt_ifa->ifa_ifp, which would specify the REAL | |
987 | * interface. | 981 | * interface. | |
988 | * Note also that ifa_ifp and ifp may differ when we connect two | 982 | * Note also that ifa_ifp and ifp may differ when we connect two | |
989 | * interfaces to a same link, install a link prefix to an interface, | 983 | * interfaces to a same link, install a link prefix to an interface, | |
990 | * and try to install a neighbor cache on an interface that does not | 984 | * and try to install a neighbor cache on an interface that does not | |
991 | * have a route to the prefix. | 985 | * have a route to the prefix. | |
992 | */ | 986 | */ | |
993 | if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || | 987 | if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || | |
994 | rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL || | 988 | rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL || | |
995 | (ifp && rt->rt_ifa->ifa_ifp != ifp)) { | 989 | (ifp && rt->rt_ifa->ifa_ifp != ifp)) { | |
996 | if (create) { | 990 | if (create) { | |
997 | nd6log((LOG_DEBUG, | 991 | nd6log((LOG_DEBUG, | |
998 | "nd6_lookup: failed to lookup %s (if = %s)\n", | 992 | "nd6_lookup: failed to lookup %s (if = %s)\n", | |
999 | ip6_sprintf(addr6), | 993 | ip6_sprintf(addr6), | |
1000 | ifp ? if_name(ifp) : "unspec")); | 994 | ifp ? if_name(ifp) : "unspec")); | |
1001 | } | 995 | } | |
1002 | rtfree(rt); | 996 | rtfree(rt); | |
1003 | return NULL; | 997 | return NULL; | |
1004 | } | 998 | } | |
1005 | return rt; | 999 | return rt; | |
1006 | } | 1000 | } | |
1007 | 1001 | |||
1008 | struct rtentry * | 1002 | struct rtentry * | |
1009 | nd6_lookup(const struct in6_addr *addr6, int create, struct ifnet *ifp) | 1003 | nd6_lookup(const struct in6_addr *addr6, int create, struct ifnet *ifp) | |
1010 | { | 1004 | { | |
1011 | 1005 | |||
1012 | return nd6_lookup1(addr6, create, ifp, 0); | 1006 | return nd6_lookup1(addr6, create, ifp, 0); | |
1013 | } | 1007 | } | |
1014 | 1008 | |||
1015 | /* | 1009 | /* | |
1016 | * Detect if a given IPv6 address identifies a neighbor on a given link. | 1010 | * Detect if a given IPv6 address identifies a neighbor on a given link. | |
1017 | * XXX: should take care of the destination of a p2p link? | 1011 | * XXX: should take care of the destination of a p2p link? | |
1018 | */ | 1012 | */ | |
1019 | int | 1013 | int | |
1020 | nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) | 1014 | nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) | |
1021 | { | 1015 | { | |
1022 | struct nd_prefix *pr; | 1016 | struct nd_prefix *pr; | |
1023 | struct rtentry *rt; | 1017 | struct rtentry *rt; | |
1024 | 1018 | |||
1025 | /* | 1019 | /* | |
1026 | * A link-local address is always a neighbor. | 1020 | * A link-local address is always a neighbor. | |
1027 | * XXX: a link does not necessarily specify a single interface. | 1021 | * XXX: a link does not necessarily specify a single interface. | |
1028 | */ | 1022 | */ | |
1029 | if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { | 1023 | if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { | |
1030 | struct sockaddr_in6 sin6_copy; | 1024 | struct sockaddr_in6 sin6_copy; | |
1031 | u_int32_t zone; | 1025 | u_int32_t zone; | |
1032 | 1026 | |||
1033 | /* | 1027 | /* | |
1034 | * We need sin6_copy since sa6_recoverscope() may modify the | 1028 | * We need sin6_copy since sa6_recoverscope() may modify the | |
1035 | * content (XXX). | 1029 | * content (XXX). | |
1036 | */ | 1030 | */ | |
1037 | sin6_copy = *addr; | 1031 | sin6_copy = *addr; | |
1038 | if (sa6_recoverscope(&sin6_copy)) | 1032 | if (sa6_recoverscope(&sin6_copy)) | |
1039 | return 0; /* XXX: should be impossible */ | 1033 | return 0; /* XXX: should be impossible */ | |
1040 | if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone)) | 1034 | if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone)) | |
1041 | return 0; | 1035 | return 0; | |
1042 | if (sin6_copy.sin6_scope_id == zone) | 1036 | if (sin6_copy.sin6_scope_id == zone) | |
1043 | return 1; | 1037 | return 1; | |
1044 | else | 1038 | else | |
1045 | return 0; | 1039 | return 0; | |
1046 | } | 1040 | } | |
1047 | 1041 | |||
1048 | /* | 1042 | /* | |
1049 | * If the address matches one of our on-link prefixes, it should be a | 1043 | * If the address matches one of our on-link prefixes, it should be a | |
1050 | * neighbor. | 1044 | * neighbor. | |
1051 | */ | 1045 | */ | |
1052 | LIST_FOREACH(pr, &nd_prefix, ndpr_entry) { | 1046 | LIST_FOREACH(pr, &nd_prefix, ndpr_entry) { | |
1053 | if (pr->ndpr_ifp != ifp) | 1047 | if (pr->ndpr_ifp != ifp) | |
1054 | continue; | 1048 | continue; | |
1055 | 1049 | |||
1056 | if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) | 1050 | if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) | |
1057 | continue; | 1051 | continue; | |
1058 | 1052 | |||
1059 | if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr, | 1053 | if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr, | |
1060 | &addr->sin6_addr, &pr->ndpr_mask)) | 1054 | &addr->sin6_addr, &pr->ndpr_mask)) | |
1061 | return 1; | 1055 | return 1; | |
1062 | } | 1056 | } | |
1063 | 1057 | |||
1064 | /* | 1058 | /* | |
1065 | * If the default router list is empty, all addresses are regarded | 1059 | * If the default router list is empty, all addresses are regarded | |
1066 | * as on-link, and thus, as a neighbor. | 1060 | * as on-link, and thus, as a neighbor. | |
1067 | * XXX: we restrict the condition to hosts, because routers usually do | 1061 | * XXX: we restrict the condition to hosts, because routers usually do | |
1068 | * not have the "default router list". | 1062 | * not have the "default router list". | |
1069 | */ | 1063 | */ | |
1070 | if (!ip6_forwarding && TAILQ_FIRST(&nd_defrouter) == NULL && | 1064 | if (!ip6_forwarding && TAILQ_FIRST(&nd_defrouter) == NULL && | |
1071 | nd6_defifindex == ifp->if_index) { | 1065 | nd6_defifindex == ifp->if_index) { | |
1072 | return 1; | 1066 | return 1; | |
1073 | } | 1067 | } | |
1074 | 1068 | |||
1075 | /* | 1069 | /* | |
1076 | * Even if the address matches none of our addresses, it might match | 1070 | * Even if the address matches none of our addresses, it might match | |
1077 | * a cloning route or be in the neighbor cache. | 1071 | * a cloning route or be in the neighbor cache. | |
1078 | */ | 1072 | */ | |
1079 | rt = nd6_lookup1(&addr->sin6_addr, 0, ifp, 1); | 1073 | rt = nd6_lookup1(&addr->sin6_addr, 0, ifp, 1); | |
1080 | if (rt != NULL) { | 1074 | if (rt != NULL) { | |
1081 | rtfree(rt); | 1075 | rtfree(rt); | |
1082 | return 1; | 1076 | return 1; | |
1083 | } | 1077 | } | |
1084 | 1078 | |||
1085 | return 0; | 1079 | return 0; | |
1086 | } | 1080 | } | |
1087 | 1081 | |||
1088 | /* | 1082 | /* | |
1089 | * Free an nd6 llinfo entry. | 1083 | * Free an nd6 llinfo entry. | |
1090 | * Since the function would cause significant changes in the kernel, DO NOT | 1084 | * Since the function would cause significant changes in the kernel, DO NOT | |
1091 | * make it global, unless you have a strong reason for the change, and are sure | 1085 | * make it global, unless you have a strong reason for the change, and are sure | |
1092 | * that the change is safe. | 1086 | * that the change is safe. | |
1093 | */ | 1087 | */ | |
1094 | static void | 1088 | static void | |
1095 | nd6_free(struct rtentry *rt, struct llentry *ln, int gc) | 1089 | nd6_free(struct rtentry *rt, struct llentry *ln, int gc) | |
1096 | { | 1090 | { | |
1097 | struct in6_addr in6 = satocsin6(rt_getkey(rt))->sin6_addr; | 1091 | struct in6_addr in6 = satocsin6(rt_getkey(rt))->sin6_addr; | |
1098 | struct nd_defrouter *dr; | 1092 | struct nd_defrouter *dr; | |
1099 | int error; | 1093 | int error; | |
1100 | 1094 | |||
1101 | KASSERT(ln != NULL); | 1095 | KASSERT(ln != NULL); | |
1102 | KASSERT(ln == rt->rt_llinfo); | 1096 | KASSERT(ln == rt->rt_llinfo); | |
1103 | LLE_WLOCK_ASSERT(ln); | 1097 | LLE_WLOCK_ASSERT(ln); | |
1104 | 1098 | |||
1105 | /* | 1099 | /* | |
1106 | * we used to have pfctlinput(PRC_HOSTDEAD) here. | 1100 | * we used to have pfctlinput(PRC_HOSTDEAD) here. | |
1107 | * even though it is not harmful, it was not really necessary. | 1101 | * even though it is not harmful, it was not really necessary. | |
1108 | */ | 1102 | */ | |
1109 | 1103 | |||
1110 | /* cancel timer */ | 1104 | /* cancel timer */ | |
1111 | nd6_llinfo_settimer_locked(ln, -1); | 1105 | nd6_llinfo_settimer_locked(ln, -1); | |
1112 | 1106 | |||
1113 | if (!ip6_forwarding) { | 1107 | if (!ip6_forwarding) { | |
1114 | int s; | 1108 | int s; | |
1115 | s = splsoftnet(); | 1109 | s = splsoftnet(); | |
1116 | dr = defrouter_lookup(&satocsin6(rt_getkey(rt))->sin6_addr, | 1110 | dr = defrouter_lookup(&satocsin6(rt_getkey(rt))->sin6_addr, | |
1117 | rt->rt_ifp); | 1111 | rt->rt_ifp); | |
1118 | 1112 | |||
1119 | if (dr != NULL && dr->expire && | 1113 | if (dr != NULL && dr->expire && | |
1120 | ln->ln_state == ND6_LLINFO_STALE && gc) { | 1114 | ln->ln_state == ND6_LLINFO_STALE && gc) { | |
1121 | /* | 1115 | /* | |
1122 | * If the reason for the deletion is just garbage | 1116 | * If the reason for the deletion is just garbage | |
1123 | * collection, and the neighbor is an active default | 1117 | * collection, and the neighbor is an active default | |
1124 | * router, do not delete it. Instead, reset the GC | 1118 | * router, do not delete it. Instead, reset the GC | |
1125 | * timer using the router's lifetime. | 1119 | * timer using the router's lifetime. | |
1126 | * Simply deleting the entry would affect default | 1120 | * Simply deleting the entry would affect default | |
1127 | * router selection, which is not necessarily a good | 1121 | * router selection, which is not necessarily a good | |
1128 | * thing, especially when we're using router preference | 1122 | * thing, especially when we're using router preference | |
1129 | * values. | 1123 | * values. | |
1130 | * XXX: the check for ln_state would be redundant, | 1124 | * XXX: the check for ln_state would be redundant, | |
1131 | * but we intentionally keep it just in case. | 1125 | * but we intentionally keep it just in case. | |
1132 | */ | 1126 | */ | |
1133 | if (dr->expire > time_uptime) | 1127 | if (dr->expire > time_uptime) | |
1134 | nd6_llinfo_settimer_locked(ln, | 1128 | nd6_llinfo_settimer_locked(ln, | |
1135 | (dr->expire - time_uptime) * hz); | 1129 | (dr->expire - time_uptime) * hz); | |
1136 | else | 1130 | else | |
1137 | nd6_llinfo_settimer_locked(ln, | 1131 | nd6_llinfo_settimer_locked(ln, | |
1138 | nd6_gctimer * hz); | 1132 | nd6_gctimer * hz); | |
1139 | splx(s); | 1133 | splx(s); | |
1140 | LLE_WUNLOCK(ln); | 1134 | LLE_WUNLOCK(ln); | |
1141 | return; | 1135 | return; | |
1142 | } | 1136 | } | |
1143 | 1137 | |||
1144 | if (ln->ln_router || dr) { | 1138 | if (ln->ln_router || dr) { | |
1145 | /* | 1139 | /* | |
1146 | * rt6_flush must be called whether or not the neighbor | 1140 | * rt6_flush must be called whether or not the neighbor | |
1147 | * is in the Default Router List. | 1141 | * is in the Default Router List. | |
1148 | * See a corresponding comment in nd6_na_input(). | 1142 | * See a corresponding comment in nd6_na_input(). | |
1149 | */ | 1143 | */ | |
1150 | rt6_flush(&in6, rt->rt_ifp); | 1144 | rt6_flush(&in6, rt->rt_ifp); | |
1151 | } | 1145 | } | |
1152 | 1146 | |||
1153 | if (dr) { | 1147 | if (dr) { | |
1154 | /* | 1148 | /* | |
1155 | * Unreachablity of a router might affect the default | 1149 | * Unreachablity of a router might affect the default | |
1156 | * router selection and on-link detection of advertised | 1150 | * router selection and on-link detection of advertised | |
1157 | * prefixes. | 1151 | * prefixes. | |
1158 | */ | 1152 | */ | |
1159 | 1153 | |||
1160 | /* | 1154 | /* | |
1161 | * Temporarily fake the state to choose a new default | 1155 | * Temporarily fake the state to choose a new default | |
1162 | * router and to perform on-link determination of | 1156 | * router and to perform on-link determination of | |
1163 | * prefixes correctly. | 1157 | * prefixes correctly. | |
1164 | * Below the state will be set correctly, | 1158 | * Below the state will be set correctly, | |
1165 | * or the entry itself will be deleted. | 1159 | * or the entry itself will be deleted. | |
1166 | */ | 1160 | */ | |
1167 | ln->ln_state = ND6_LLINFO_INCOMPLETE; | 1161 | ln->ln_state = ND6_LLINFO_INCOMPLETE; | |
1168 | 1162 | |||
1169 | /* | 1163 | /* | |
1170 | * Since defrouter_select() does not affect the | 1164 | * Since defrouter_select() does not affect the | |
1171 | * on-link determination and MIP6 needs the check | 1165 | * on-link determination and MIP6 needs the check | |
1172 | * before the default router selection, we perform | 1166 | * before the default router selection, we perform | |
1173 | * the check now. | 1167 | * the check now. | |
1174 | */ | 1168 | */ | |
1175 | pfxlist_onlink_check(); | 1169 | pfxlist_onlink_check(); | |
1176 | 1170 | |||
1177 | /* | 1171 | /* | |
1178 | * refresh default router list | 1172 | * refresh default router list | |
1179 | */ | 1173 | */ | |
1180 | defrouter_select(); | 1174 | defrouter_select(); | |
1181 | } | 1175 | } | |
1182 | splx(s); | 1176 | splx(s); | |
1183 | } | 1177 | } | |
1184 | 1178 | |||
1185 | LLE_WUNLOCK(ln); | 1179 | LLE_WUNLOCK(ln); | |
1186 | /* | 1180 | /* | |
1187 | * Detach the route from the routing tree and the list of neighbor | 1181 | * Detach the route from the routing tree and the list of neighbor | |
1188 | * caches, and disable the route entry not to be used in already | 1182 | * caches, and disable the route entry not to be used in already | |
1189 | * cached routes. | 1183 | * cached routes. | |
1190 | */ | 1184 | */ | |
1191 | error = rtrequest_newmsg(RTM_DELETE, rt_getkey(rt), NULL, | 1185 | error = rtrequest_newmsg(RTM_DELETE, rt_getkey(rt), NULL, | |
1192 | rt_mask(rt), 0); | 1186 | rt_mask(rt), 0); | |
1193 | if (error != 0) { | 1187 | if (error != 0) { | |
1194 | /* XXX need error message? */; | 1188 | /* XXX need error message? */; | |
1195 | } | 1189 | } | |
1196 | } | 1190 | } | |
1197 | 1191 | |||
1198 | /* | 1192 | /* | |
1199 | * Upper-layer reachability hint for Neighbor Unreachability Detection. | 1193 | * Upper-layer reachability hint for Neighbor Unreachability Detection. | |
1200 | * | 1194 | * | |
1201 | * XXX cost-effective methods? | 1195 | * XXX cost-effective methods? | |
1202 | */ | 1196 | */ | |
1203 | void | 1197 | void | |
1204 | nd6_nud_hint(struct rtentry *rt) | 1198 | nd6_nud_hint(struct rtentry *rt) | |
1205 | { | 1199 | { | |
1206 | struct llentry *ln; | 1200 | struct llentry *ln; | |
1207 | 1201 | |||
1208 | if (rt == NULL) | 1202 | if (rt == NULL) | |
1209 | return; | 1203 | return; | |
1210 | 1204 | |||
1211 | if ((rt->rt_flags & RTF_GATEWAY) != 0 || | 1205 | if ((rt->rt_flags & RTF_GATEWAY) != 0 || | |
1212 | (rt->rt_flags & RTF_LLINFO) == 0 || | 1206 | (rt->rt_flags & RTF_LLINFO) == 0 || | |
1213 | !rt->rt_llinfo || !rt->rt_gateway || | 1207 | !rt->rt_llinfo || !rt->rt_gateway || | |
1214 | rt->rt_gateway->sa_family != AF_LINK) { | 1208 | rt->rt_gateway->sa_family != AF_LINK) { | |
1215 | /* This is not a host route. */ | 1209 | /* This is not a host route. */ | |
1216 | return; | 1210 | return; | |
1217 | } | 1211 | } | |
1218 | 1212 | |||
1219 | ln = rt->rt_llinfo; | 1213 | ln = rt->rt_llinfo; | |
1220 | if (ln->ln_state < ND6_LLINFO_REACHABLE) | 1214 | if (ln->ln_state < ND6_LLINFO_REACHABLE) | |
1221 | return; | 1215 | return; | |
1222 | 1216 | |||
1223 | /* | 1217 | /* | |
1224 | * if we get upper-layer reachability confirmation many times, | 1218 | * if we get upper-layer reachability confirmation many times, | |
1225 | * it is possible we have false information. | 1219 | * it is possible we have false information. | |
1226 | */ | 1220 | */ | |
1227 | ln->ln_byhint++; | 1221 | ln->ln_byhint++; | |
1228 | if (ln->ln_byhint > nd6_maxnudhint) | 1222 | if (ln->ln_byhint > nd6_maxnudhint) | |
1229 | return; | 1223 | return; | |
1230 | 1224 | |||
1231 | ln->ln_state = ND6_LLINFO_REACHABLE; | 1225 | ln->ln_state = ND6_LLINFO_REACHABLE; | |
1232 | if (!ND6_LLINFO_PERMANENT(ln)) { | 1226 | if (!ND6_LLINFO_PERMANENT(ln)) { | |
1233 | nd6_llinfo_settimer(ln, | 1227 | nd6_llinfo_settimer(ln, | |
1234 | ND_IFINFO(rt->rt_ifp)->reachable * hz); | 1228 | ND_IFINFO(rt->rt_ifp)->reachable * hz); | |
1235 | } | 1229 | } | |
1236 | 1230 | |||
1237 | return; | 1231 | return; | |
1238 | } | 1232 | } | |
1239 | 1233 | |||
1240 | static int | 1234 | static int | |
1241 | nd6_purge_entry(struct lltable *llt, struct llentry *ln, void *farg) | 1235 | nd6_purge_entry(struct lltable *llt, struct llentry *ln, void *farg) | |
1242 | { | 1236 | { | |
1243 | int *n = farg; | 1237 | int *n = farg; | |
1244 | 1238 | |||
1245 | if (*n <= 0) | 1239 | if (*n <= 0) | |
1246 | return 0; | 1240 | return 0; | |
1247 | 1241 | |||
1248 | if (ND6_LLINFO_PERMANENT(ln)) | 1242 | if (ND6_LLINFO_PERMANENT(ln)) | |
1249 | return 0; | 1243 | return 0; | |
1250 | 1244 | |||
1251 | LLE_WLOCK(ln); | 1245 | LLE_WLOCK(ln); | |
1252 | if (ln->ln_state > ND6_LLINFO_INCOMPLETE) | 1246 | if (ln->ln_state > ND6_LLINFO_INCOMPLETE) | |
1253 | ln->ln_state = ND6_LLINFO_STALE; | 1247 | ln->ln_state = ND6_LLINFO_STALE; | |
1254 | else | 1248 | else | |
1255 | ln->ln_state = ND6_LLINFO_PURGE; | 1249 | ln->ln_state = ND6_LLINFO_PURGE; | |
1256 | nd6_llinfo_settimer_locked(ln, 0); | 1250 | nd6_llinfo_settimer_locked(ln, 0); | |
1257 | LLE_WUNLOCK(ln); | 1251 | LLE_WUNLOCK(ln); | |
1258 | 1252 | |||
1259 | (*n)--; | 1253 | (*n)--; | |
1260 | return 0; | 1254 | return 0; | |
1261 | } | 1255 | } | |
1262 | 1256 | |||
1263 | static void | 1257 | static void | |
1264 | nd6_gc_neighbors(struct lltable *llt) | 1258 | nd6_gc_neighbors(struct lltable *llt) | |
1265 | { | 1259 | { | |
1266 | int max_gc_entries = 10; | 1260 | int max_gc_entries = 10; | |
1267 | 1261 | |||
1268 | if (ip6_neighborgcthresh >= 0 && | 1262 | if (ip6_neighborgcthresh >= 0 && | |
1269 | lltable_get_entry_count(llt) >= ip6_neighborgcthresh) { | 1263 | lltable_get_entry_count(llt) >= ip6_neighborgcthresh) { | |
1270 | /* | 1264 | /* | |
1271 | * XXX entries that are "less recently used" should be | 1265 | * XXX entries that are "less recently used" should be | |
1272 | * freed first. | 1266 | * freed first. | |
1273 | */ | 1267 | */ | |
1274 | lltable_foreach_lle(llt, nd6_purge_entry, &max_gc_entries); | 1268 | lltable_foreach_lle(llt, nd6_purge_entry, &max_gc_entries); | |
1275 | } | 1269 | } | |
1276 | } | 1270 | } | |
1277 | 1271 | |||
1278 | void | 1272 | void | |
1279 | nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info) | 1273 | nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info) | |
1280 | { | 1274 | { | |
1281 | struct sockaddr *gate = rt->rt_gateway; | 1275 | struct sockaddr *gate = rt->rt_gateway; | |
1282 | struct llentry *ln; | 1276 | struct llentry *ln; | |
1283 | struct ifnet *ifp = rt->rt_ifp; | 1277 | struct ifnet *ifp = rt->rt_ifp; | |
1284 | uint8_t namelen = strlen(ifp->if_xname), addrlen = ifp->if_addrlen; | 1278 | uint8_t namelen = strlen(ifp->if_xname), addrlen = ifp->if_addrlen; | |
1285 | struct ifaddr *ifa; | 1279 | struct ifaddr *ifa; | |
1286 | int flags = 0; | 1280 | int flags = 0; | |
1287 | bool use_lo0ifp = false; | 1281 | bool use_lo0ifp = false; | |
1288 | 1282 | |||
1289 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1283 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1290 | 1284 | |||
1291 | if (req == RTM_LLINFO_UPD) { | 1285 | if (req == RTM_LLINFO_UPD) { | |
1292 | int rc; | 1286 | int rc; | |
1293 | struct in6_addr *in6; | 1287 | struct in6_addr *in6; | |
1294 | struct in6_addr in6_all; | 1288 | struct in6_addr in6_all; | |
1295 | int anycast; | 1289 | int anycast; | |
1296 | 1290 | |||
1297 | if ((ifa = info->rti_ifa) == NULL) | 1291 | if ((ifa = info->rti_ifa) == NULL) | |
1298 | return; | 1292 | return; | |
1299 | 1293 | |||
1300 | in6 = &ifatoia6(ifa)->ia_addr.sin6_addr; | 1294 | in6 = &ifatoia6(ifa)->ia_addr.sin6_addr; | |
1301 | anycast = ifatoia6(ifa)->ia6_flags & IN6_IFF_ANYCAST; | 1295 | anycast = ifatoia6(ifa)->ia6_flags & IN6_IFF_ANYCAST; | |
1302 | 1296 | |||
1303 | in6_all = in6addr_linklocal_allnodes; | 1297 | in6_all = in6addr_linklocal_allnodes; | |
1304 | if ((rc = in6_setscope(&in6_all, ifa->ifa_ifp, NULL)) != 0) { | 1298 | if ((rc = in6_setscope(&in6_all, ifa->ifa_ifp, NULL)) != 0) { | |
1305 | log(LOG_ERR, "%s: failed to set scope %s " | 1299 | log(LOG_ERR, "%s: failed to set scope %s " | |
1306 | "(errno=%d)\n", __func__, if_name(ifp), rc); | 1300 | "(errno=%d)\n", __func__, if_name(ifp), rc); | |
1307 | return; | 1301 | return; | |
1308 | } | 1302 | } | |
1309 | 1303 | |||
1310 | /* XXX don't set Override for proxy addresses */ | 1304 | /* XXX don't set Override for proxy addresses */ | |
1311 | nd6_na_output(ifa->ifa_ifp, &in6_all, in6, | 1305 | nd6_na_output(ifa->ifa_ifp, &in6_all, in6, | |
1312 | (anycast ? 0 : ND_NA_FLAG_OVERRIDE) | 1306 | (anycast ? 0 : ND_NA_FLAG_OVERRIDE) | |
1313 | #if 0 | 1307 | #if 0 | |
1314 | | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) | 1308 | | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) | |
1315 | #endif | 1309 | #endif | |
1316 | , 1, NULL); | 1310 | , 1, NULL); | |
1317 | return; | 1311 | return; | |
1318 | } | 1312 | } | |
1319 | 1313 | |||
1320 | if ((rt->rt_flags & RTF_GATEWAY) != 0) | 1314 | if ((rt->rt_flags & RTF_GATEWAY) != 0) | |
1321 | return; | 1315 | return; | |
1322 | 1316 | |||
1323 | if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) { | 1317 | if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) { | |
1324 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1318 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1325 | /* | 1319 | /* | |
1326 | * This is probably an interface direct route for a link | 1320 | * This is probably an interface direct route for a link | |
1327 | * which does not need neighbor caches (e.g. fe80::%lo0/64). | 1321 | * which does not need neighbor caches (e.g. fe80::%lo0/64). | |
1328 | * We do not need special treatment below for such a route. | 1322 | * We do not need special treatment below for such a route. | |
1329 | * Moreover, the RTF_LLINFO flag which would be set below | 1323 | * Moreover, the RTF_LLINFO flag which would be set below | |
1330 | * would annoy the ndp(8) command. | 1324 | * would annoy the ndp(8) command. | |
1331 | */ | 1325 | */ | |
1332 | return; | 1326 | return; | |
1333 | } | 1327 | } | |
1334 | 1328 | |||
1335 | IF_AFDATA_RLOCK(ifp); | 1329 | IF_AFDATA_RLOCK(ifp); | |
1336 | ln = lla_lookup(LLTABLE6(ifp), flags, rt_getkey(rt)); | 1330 | ln = lla_lookup(LLTABLE6(ifp), flags, rt_getkey(rt)); | |
1337 | IF_AFDATA_RUNLOCK(ifp); | 1331 | IF_AFDATA_RUNLOCK(ifp); | |
1338 | 1332 | |||
1339 | if (req == RTM_RESOLVE && | 1333 | if (req == RTM_RESOLVE && | |
1340 | (nd6_need_cache(ifp) == 0 || /* stf case */ | 1334 | (nd6_need_cache(ifp) == 0 || /* stf case */ | |
1341 | !nd6_is_addr_neighbor(satocsin6(rt_getkey(rt)), ifp))) { | 1335 | !nd6_is_addr_neighbor(satocsin6(rt_getkey(rt)), ifp))) { | |
1342 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1336 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1343 | /* | 1337 | /* | |
1344 | * FreeBSD and BSD/OS often make a cloned host route based | 1338 | * FreeBSD and BSD/OS often make a cloned host route based | |
1345 | * on a less-specific route (e.g. the default route). | 1339 | * on a less-specific route (e.g. the default route). | |
1346 | * If the less specific route does not have a "gateway" | 1340 | * If the less specific route does not have a "gateway" | |
1347 | * (this is the case when the route just goes to a p2p or an | 1341 | * (this is the case when the route just goes to a p2p or an | |
1348 | * stf interface), we'll mistakenly make a neighbor cache for | 1342 | * stf interface), we'll mistakenly make a neighbor cache for | |
1349 | * the host route, and will see strange neighbor solicitation | 1343 | * the host route, and will see strange neighbor solicitation | |
1350 | * for the corresponding destination. In order to avoid the | 1344 | * for the corresponding destination. In order to avoid the | |
1351 | * confusion, we check if the destination of the route is | 1345 | * confusion, we check if the destination of the route is | |
1352 | * a neighbor in terms of neighbor discovery, and stop the | 1346 | * a neighbor in terms of neighbor discovery, and stop the | |
1353 | * process if not. Additionally, we remove the LLINFO flag | 1347 | * process if not. Additionally, we remove the LLINFO flag | |
1354 | * so that ndp(8) will not try to get the neighbor information | 1348 | * so that ndp(8) will not try to get the neighbor information | |
1355 | * of the destination. | 1349 | * of the destination. | |
1356 | */ | 1350 | */ | |
1357 | rt->rt_flags &= ~RTF_LLINFO; | 1351 | rt->rt_flags &= ~RTF_LLINFO; | |
1358 | return; | 1352 | return; | |
1359 | } | 1353 | } | |
1360 | 1354 | |||
1361 | switch (req) { | 1355 | switch (req) { | |
1362 | case RTM_ADD: | 1356 | case RTM_ADD: | |
1363 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1357 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1364 | /* | 1358 | /* | |
1365 | * There is no backward compatibility :) | 1359 | * There is no backward compatibility :) | |
1366 | * | 1360 | * | |
1367 | * if ((rt->rt_flags & RTF_HOST) == 0 && | 1361 | * if ((rt->rt_flags & RTF_HOST) == 0 && | |
1368 | * SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) | 1362 | * SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) | |
1369 | * rt->rt_flags |= RTF_CLONING; | 1363 | * rt->rt_flags |= RTF_CLONING; | |
1370 | */ | 1364 | */ | |
1371 | if ((rt->rt_flags & RTF_CLONING) || | 1365 | if ((rt->rt_flags & RTF_CLONING) || | |
1372 | ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && ln == NULL)) { | 1366 | ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && ln == NULL)) { | |
1373 | union { | 1367 | union { | |
1374 | struct sockaddr sa; | 1368 | struct sockaddr sa; | |
1375 | struct sockaddr_dl sdl; | 1369 | struct sockaddr_dl sdl; | |
1376 | struct sockaddr_storage ss; | 1370 | struct sockaddr_storage ss; | |
1377 | } u; | 1371 | } u; | |
1378 | /* | 1372 | /* | |
1379 | * Case 1: This route should come from a route to | 1373 | * Case 1: This route should come from a route to | |
1380 | * interface (RTF_CLONING case) or the route should be | 1374 | * interface (RTF_CLONING case) or the route should be | |
1381 | * treated as on-link but is currently not | 1375 | * treated as on-link but is currently not | |
1382 | * (RTF_LLINFO && ln == NULL case). | 1376 | * (RTF_LLINFO && ln == NULL case). | |
1383 | */ | 1377 | */ | |
1384 | if (sockaddr_dl_init(&u.sdl, sizeof(u.ss), | 1378 | if (sockaddr_dl_init(&u.sdl, sizeof(u.ss), | |
1385 | ifp->if_index, ifp->if_type, | 1379 | ifp->if_index, ifp->if_type, | |
1386 | NULL, namelen, NULL, addrlen) == NULL) { | 1380 | NULL, namelen, NULL, addrlen) == NULL) { | |
1387 | printf("%s.%d: sockaddr_dl_init(, %zu, ) " | 1381 | printf("%s.%d: sockaddr_dl_init(, %zu, ) " | |
1388 | "failed on %s\n", __func__, __LINE__, | 1382 | "failed on %s\n", __func__, __LINE__, | |
1389 | sizeof(u.ss), if_name(ifp)); | 1383 | sizeof(u.ss), if_name(ifp)); | |
1390 | } | 1384 | } | |
1391 | rt_setgate(rt, &u.sa); | 1385 | rt_setgate(rt, &u.sa); | |
1392 | gate = rt->rt_gateway; | 1386 | gate = rt->rt_gateway; | |
1393 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1387 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1394 | if (ln != NULL) | 1388 | if (ln != NULL) | |
1395 | nd6_llinfo_settimer_locked(ln, 0); | 1389 | nd6_llinfo_settimer_locked(ln, 0); | |
1396 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1390 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1397 | if ((rt->rt_flags & RTF_CLONING) != 0) | 1391 | if ((rt->rt_flags & RTF_CLONING) != 0) | |
1398 | break; | 1392 | break; | |
1399 | } | 1393 | } | |
1400 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1394 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1401 | /* | 1395 | /* | |
1402 | * In IPv4 code, we try to annonuce new RTF_ANNOUNCE entry here. | 1396 | * In IPv4 code, we try to annonuce new RTF_ANNOUNCE entry here. | |
1403 | * We don't do that here since llinfo is not ready yet. | 1397 | * We don't do that here since llinfo is not ready yet. | |
1404 | * | 1398 | * | |
1405 | * There are also couple of other things to be discussed: | 1399 | * There are also couple of other things to be discussed: | |
1406 | * - unsolicited NA code needs improvement beforehand | 1400 | * - unsolicited NA code needs improvement beforehand | |
1407 | * - RFC2461 says we MAY send multicast unsolicited NA | 1401 | * - RFC2461 says we MAY send multicast unsolicited NA | |
1408 | * (7.2.6 paragraph 4), however, it also says that we | 1402 | * (7.2.6 paragraph 4), however, it also says that we | |
1409 | * SHOULD provide a mechanism to prevent multicast NA storm. | 1403 | * SHOULD provide a mechanism to prevent multicast NA storm. | |
1410 | * we don't have anything like it right now. | 1404 | * we don't have anything like it right now. | |
1411 | * note that the mechanism needs a mutual agreement | 1405 | * note that the mechanism needs a mutual agreement | |
1412 | * between proxies, which means that we need to implement | 1406 | * between proxies, which means that we need to implement | |
1413 | * a new protocol, or a new kludge. | 1407 | * a new protocol, or a new kludge. | |
1414 | * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA. | 1408 | * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA. | |
1415 | * we need to check ip6forwarding before sending it. | 1409 | * we need to check ip6forwarding before sending it. | |
1416 | * (or should we allow proxy ND configuration only for | 1410 | * (or should we allow proxy ND configuration only for | |
1417 | * routers? there's no mention about proxy ND from hosts) | 1411 | * routers? there's no mention about proxy ND from hosts) | |
1418 | */ | 1412 | */ | |
1419 | #if 0 | 1413 | #if 0 | |
1420 | /* XXX it does not work */ | 1414 | /* XXX it does not work */ | |
1421 | if (rt->rt_flags & RTF_ANNOUNCE) | 1415 | if (rt->rt_flags & RTF_ANNOUNCE) | |
1422 | nd6_na_output(ifp, | 1416 | nd6_na_output(ifp, | |
1423 | &satocsin6(rt_getkey(rt))->sin6_addr, | 1417 | &satocsin6(rt_getkey(rt))->sin6_addr, | |
1424 | &satocsin6(rt_getkey(rt))->sin6_addr, | 1418 | &satocsin6(rt_getkey(rt))->sin6_addr, | |
1425 | ip6_forwarding ? ND_NA_FLAG_ROUTER : 0, | 1419 | ip6_forwarding ? ND_NA_FLAG_ROUTER : 0, | |
1426 | 1, NULL); | 1420 | 1, NULL); | |
1427 | #endif | 1421 | #endif | |
1428 | /* FALLTHROUGH */ | 1422 | /* FALLTHROUGH */ | |
1429 | case RTM_RESOLVE: | 1423 | case RTM_RESOLVE: | |
1430 | if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) { | 1424 | if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) { | |
1431 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1425 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1432 | /* | 1426 | /* | |
1433 | * Address resolution isn't necessary for a point to | 1427 | * Address resolution isn't necessary for a point to | |
1434 | * point link, so we can skip this test for a p2p link. | 1428 | * point link, so we can skip this test for a p2p link. | |
1435 | */ | 1429 | */ | |
1436 | if (gate->sa_family != AF_LINK || | 1430 | if (gate->sa_family != AF_LINK || | |
1437 | gate->sa_len < | 1431 | gate->sa_len < | |
1438 | sockaddr_dl_measure(namelen, addrlen)) { | 1432 | sockaddr_dl_measure(namelen, addrlen)) { | |
1439 | log(LOG_DEBUG, | 1433 | log(LOG_DEBUG, | |
1440 | "nd6_rtrequest: bad gateway value: %s\n", | 1434 | "nd6_rtrequest: bad gateway value: %s\n", | |
1441 | if_name(ifp)); | 1435 | if_name(ifp)); | |
1442 | break; | 1436 | break; | |
1443 | } | 1437 | } | |
1444 | satosdl(gate)->sdl_type = ifp->if_type; | 1438 | satosdl(gate)->sdl_type = ifp->if_type; | |
1445 | satosdl(gate)->sdl_index = ifp->if_index; | 1439 | satosdl(gate)->sdl_index = ifp->if_index; | |
1446 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1440 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1447 | } | 1441 | } | |
1448 | if (ln != NULL) | 1442 | if (ln != NULL) | |
1449 | break; /* This happens on a route change */ | 1443 | break; /* This happens on a route change */ | |
1450 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1444 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1451 | 1445 | |||
1452 | /* Determine to use lo0ifp or not before lla_create */ | 1446 | /* Determine to use lo0ifp or not before lla_create */ | |
1453 | ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, | 1447 | ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, | |
1454 | &satocsin6(rt_getkey(rt))->sin6_addr); | 1448 | &satocsin6(rt_getkey(rt))->sin6_addr); | |
1455 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1449 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1456 | if (ifa != NULL && nd6_useloopback) | 1450 | if (ifa != NULL && nd6_useloopback) | |
1457 | use_lo0ifp = true; | 1451 | use_lo0ifp = true; | |
1458 | 1452 | |||
1459 | /* | 1453 | /* | |
1460 | * Case 2: This route may come from cloning, or a manual route | 1454 | * Case 2: This route may come from cloning, or a manual route | |
1461 | * add with a LL address. | 1455 | * add with a LL address. | |
1462 | */ | 1456 | */ | |
1463 | flags = LLE_EXCLUSIVE; | 1457 | flags = LLE_EXCLUSIVE; | |
1464 | if ((rt->rt_flags & RTF_CLONED) == 0) | 1458 | if ((rt->rt_flags & RTF_CLONED) == 0) | |
1465 | flags |= LLE_IFADDR; | 1459 | flags |= LLE_IFADDR; | |
1466 | 1460 | |||
1467 | #define _IFP() (use_lo0ifp ? lo0ifp : ifp) | 1461 | #define _IFP() (use_lo0ifp ? lo0ifp : ifp) | |
1468 | IF_AFDATA_WLOCK(_IFP()); | 1462 | IF_AFDATA_WLOCK(_IFP()); | |
1469 | ln = lla_create(LLTABLE6(_IFP()), flags, rt_getkey(rt)); | 1463 | ln = lla_create(LLTABLE6(_IFP()), flags, rt_getkey(rt)); | |
1470 | IF_AFDATA_WUNLOCK(_IFP()); | 1464 | IF_AFDATA_WUNLOCK(_IFP()); | |
1471 | 1465 | |||
1472 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1466 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1473 | if (ln == NULL) { | 1467 | if (ln == NULL) { | |
1474 | log(LOG_DEBUG, "nd6_rtrequest: malloc failed\n"); | 1468 | log(LOG_DEBUG, "nd6_rtrequest: malloc failed\n"); | |
1475 | break; | 1469 | break; | |
1476 | } | 1470 | } | |
1477 | 1471 | |||
1478 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1472 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1479 | nd6_inuse++; | 1473 | nd6_inuse++; | |
1480 | nd6_allocated++; | 1474 | nd6_allocated++; | |
1481 | ln->ln_rt = rt; | 1475 | ln->ln_rt = rt; | |
1482 | rt->rt_refcnt++; | 1476 | rt->rt_refcnt++; | |
1483 | rt->rt_llinfo = ln; | 1477 | rt->rt_llinfo = ln; | |
1484 | LLE_ADDREF(ln); | 1478 | LLE_ADDREF(ln); | |
1485 | rt->rt_flags |= RTF_LLINFO; | 1479 | rt->rt_flags |= RTF_LLINFO; | |
1486 | switch (_IFP()->if_type) { | 1480 | switch (_IFP()->if_type) { | |
1487 | #if NTOKEN > 0 | 1481 | #if NTOKEN > 0 | |
1488 | case IFT_ISO88025: | 1482 | case IFT_ISO88025: | |
1489 | ln->la_opaque = kmem_alloc(sizeof(struct token_rif), | 1483 | ln->la_opaque = kmem_alloc(sizeof(struct token_rif), | |
1490 | KM_SLEEP); | 1484 | KM_SLEEP); | |
1491 | break; | 1485 | break; | |
1492 | #endif /* NTOKEN > 0 */ | 1486 | #endif /* NTOKEN > 0 */ | |
1493 | default: | 1487 | default: | |
1494 | break; | 1488 | break; | |
1495 | } | 1489 | } | |
1496 | #undef _IFP | 1490 | #undef _IFP | |
1497 | 1491 | |||
1498 | /* this is required for "ndp" command. - shin */ | 1492 | /* this is required for "ndp" command. - shin */ | |
1499 | if (req == RTM_ADD) { | 1493 | if (req == RTM_ADD) { | |
1500 | /* | 1494 | /* | |
1501 | * gate should have some valid AF_LINK entry, | 1495 | * gate should have some valid AF_LINK entry, | |
1502 | * and ln->ln_expire should have some lifetime | 1496 | * and ln->ln_expire should have some lifetime | |
1503 | * which is specified by ndp command. | 1497 | * which is specified by ndp command. | |
1504 | */ | 1498 | */ | |
1505 | ln->ln_state = ND6_LLINFO_REACHABLE; | 1499 | ln->ln_state = ND6_LLINFO_REACHABLE; | |
1506 | ln->ln_byhint = 0; | 1500 | ln->ln_byhint = 0; | |
1507 | } else { | 1501 | } else { | |
1508 | /* | 1502 | /* | |
1509 | * When req == RTM_RESOLVE, rt is created and | 1503 | * When req == RTM_RESOLVE, rt is created and | |
1510 | * initialized in rtrequest(), so rt_expire is 0. | 1504 | * initialized in rtrequest(), so rt_expire is 0. | |
1511 | */ | 1505 | */ | |
1512 | ln->ln_state = ND6_LLINFO_NOSTATE; | 1506 | ln->ln_state = ND6_LLINFO_NOSTATE; | |
1513 | nd6_llinfo_settimer_locked(ln, 0); | 1507 | nd6_llinfo_settimer_locked(ln, 0); | |
1514 | } | 1508 | } | |
1515 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | 1509 | RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt)); | |
1516 | 1510 | |||
1517 | /* | 1511 | /* | |
1518 | * check if rt_getkey(rt) is an address assigned | 1512 | * check if rt_getkey(rt) is an address assigned | |
1519 | * to the interface. | 1513 | * to the interface. | |
1520 | */ | 1514 | */ | |
1521 | if (ifa != NULL) { | 1515 | if (ifa != NULL) { | |
1522 | const void *mac; | 1516 | const void *mac; | |
1523 | nd6_llinfo_settimer_locked(ln, -1); | 1517 | nd6_llinfo_settimer_locked(ln, -1); | |
1524 | ln->ln_state = ND6_LLINFO_REACHABLE; | 1518 | ln->ln_state = ND6_LLINFO_REACHABLE; | |
1525 | ln->ln_byhint = 0; | 1519 | ln->ln_byhint = 0; | |
1526 | if ((mac = nd6_ifptomac(ifp)) != NULL) { | 1520 | if ((mac = nd6_ifptomac(ifp)) != NULL) { | |
1527 | /* XXX check for error */ | 1521 | /* XXX check for error */ | |
1528 | if (sockaddr_dl_setaddr(satosdl(gate), | 1522 | if (sockaddr_dl_setaddr(satosdl(gate), | |
1529 | gate->sa_len, mac, | 1523 | gate->sa_len, mac, | |
1530 | ifp->if_addrlen) == NULL) { | 1524 | ifp->if_addrlen) == NULL) { | |
1531 | printf("%s.%d: " | 1525 | printf("%s.%d: " | |
1532 | "sockaddr_dl_setaddr(, %d, ) " | 1526 | "sockaddr_dl_setaddr(, %d, ) " | |
1533 | "failed on %s\n", __func__, | 1527 | "failed on %s\n", __func__, | |
1534 | __LINE__, gate->sa_len, | 1528 | __LINE__, gate->sa_len, | |
1535 | if_name(ifp)); | 1529 | if_name(ifp)); | |
1536 | } | 1530 | } | |
1537 | } | 1531 | } | |
1538 | if (nd6_useloopback) { | 1532 | if (nd6_useloopback) { | |
1539 | ifp = rt->rt_ifp = lo0ifp; /* XXX */ | 1533 | ifp = rt->rt_ifp = lo0ifp; /* XXX */ | |
1540 | /* | 1534 | /* | |
1541 | * Make sure rt_ifa be equal to the ifaddr | 1535 | * Make sure rt_ifa be equal to the ifaddr | |
1542 | * corresponding to the address. | 1536 | * corresponding to the address. | |
1543 | * We need this because when we refer | 1537 | * We need this because when we refer | |
1544 | * rt_ifa->ia6_flags in ip6_input, we assume | 1538 | * rt_ifa->ia6_flags in ip6_input, we assume | |
1545 | * that the rt_ifa points to the address instead | 1539 | * that the rt_ifa points to the address instead | |
1546 | * of the loopback address. | 1540 | * of the loopback address. | |
1547 | */ | 1541 | */ | |
1548 | if (ifa != rt->rt_ifa) | 1542 | if (ifa != rt->rt_ifa) | |
1549 | rt_replace_ifa(rt, ifa); | 1543 | rt_replace_ifa(rt, ifa); | |
1550 | rt->rt_rmx.rmx_mtu = 0; | 1544 | rt->rt_rmx.rmx_mtu = 0; | |
1551 | rt->rt_flags &= ~RTF_CLONED; | 1545 | rt->rt_flags &= ~RTF_CLONED; | |
1552 | } | 1546 | } | |
1553 | rt->rt_flags |= RTF_LOCAL; | 1547 | rt->rt_flags |= RTF_LOCAL; | |
1554 | } else if (rt->rt_flags & RTF_ANNOUNCE) { | 1548 | } else if (rt->rt_flags & RTF_ANNOUNCE) { | |
1555 | nd6_llinfo_settimer_locked(ln, -1); | 1549 | nd6_llinfo_settimer_locked(ln, -1); | |
1556 | ln->ln_state = ND6_LLINFO_REACHABLE; | 1550 | ln->ln_state = ND6_LLINFO_REACHABLE; | |
1557 | ln->ln_byhint = 0; | 1551 | ln->ln_byhint = 0; | |
1558 | 1552 | |||
1559 | /* join solicited node multicast for proxy ND */ | 1553 | /* join solicited node multicast for proxy ND */ | |
1560 | if (ifp->if_flags & IFF_MULTICAST) { | 1554 | if (ifp->if_flags & IFF_MULTICAST) { | |
1561 | struct in6_addr llsol; | 1555 | struct in6_addr llsol; | |
1562 | int error; | 1556 | int error; | |
1563 | 1557 | |||
1564 | llsol = satocsin6(rt_getkey(rt))->sin6_addr; | 1558 | llsol = satocsin6(rt_getkey(rt))->sin6_addr; | |
1565 | llsol.s6_addr32[0] = htonl(0xff020000); | 1559 | llsol.s6_addr32[0] = htonl(0xff020000); | |
1566 | llsol.s6_addr32[1] = 0; | 1560 | llsol.s6_addr32[1] = 0; | |
1567 | llsol.s6_addr32[2] = htonl(1); | 1561 | llsol.s6_addr32[2] = htonl(1); | |
1568 | llsol.s6_addr8[12] = 0xff; | 1562 | llsol.s6_addr8[12] = 0xff; | |
1569 | if (in6_setscope(&llsol, ifp, NULL)) | 1563 | if (in6_setscope(&llsol, ifp, NULL)) | |
1570 | break; | 1564 | break; | |
1571 | if (!in6_addmulti(&llsol, ifp, &error, 0)) { | 1565 | if (!in6_addmulti(&llsol, ifp, &error, 0)) { | |
1572 | nd6log((LOG_ERR, "%s: failed to join " | 1566 | nd6log((LOG_ERR, "%s: failed to join " | |
1573 | "%s (errno=%d)\n", if_name(ifp), | 1567 | "%s (errno=%d)\n", if_name(ifp), | |
1574 | ip6_sprintf(&llsol), error)); | 1568 | ip6_sprintf(&llsol), error)); | |
1575 | } | 1569 | } | |
1576 | } | 1570 | } | |
1577 | } | 1571 | } | |
1578 | LLE_WUNLOCK(ln); | 1572 | LLE_WUNLOCK(ln); | |
1579 | /* | 1573 | /* | |
1580 | * If we have too many cache entries, initiate immediate | 1574 | * If we have too many cache entries, initiate immediate | |
1581 | * purging for some entries. | 1575 | * purging for some entries. | |
1582 | */ | 1576 | */ | |
1583 | nd6_gc_neighbors(ln->lle_tbl); | 1577 | nd6_gc_neighbors(ln->lle_tbl); | |
1584 | ln = NULL; | 1578 | ln = NULL; | |
1585 | 1579 | |||
1586 | break; | 1580 | break; | |
1587 | 1581 | |||
1588 | case RTM_DELETE: | 1582 | case RTM_DELETE: | |
1589 | if (ln == NULL) | 1583 | if (ln == NULL) | |
1590 | break; | 1584 | break; | |
1591 | /* leave from solicited node multicast for proxy ND */ | 1585 | /* leave from solicited node multicast for proxy ND */ | |
1592 | if ((rt->rt_flags & RTF_ANNOUNCE) != 0 && | 1586 | if ((rt->rt_flags & RTF_ANNOUNCE) != 0 && | |
1593 | (ifp->if_flags & IFF_MULTICAST) != 0) { | 1587 | (ifp->if_flags & IFF_MULTICAST) != 0) { | |
1594 | struct in6_addr llsol; | 1588 | struct in6_addr llsol; |
--- src/sys/netinet6/nd6.h 2015/12/07 06:19:13 1.69
+++ src/sys/netinet6/nd6.h 2016/04/01 05:11:38 1.70
@@ -1,459 +1,456 @@ | @@ -1,459 +1,456 @@ | |||
1 | /* $NetBSD: nd6.h,v 1.69 2015/12/07 06:19:13 ozaki-r Exp $ */ | 1 | /* $NetBSD: nd6.h,v 1.70 2016/04/01 05:11:38 ozaki-r Exp $ */ | |
2 | /* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */ | 2 | /* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun 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 | #ifndef _NETINET6_ND6_H_ | 33 | #ifndef _NETINET6_ND6_H_ | |
34 | #define _NETINET6_ND6_H_ | 34 | #define _NETINET6_ND6_H_ | |
35 | 35 | |||
36 | #include <sys/queue.h> | 36 | #include <sys/queue.h> | |
37 | #include <sys/callout.h> | 37 | #include <sys/callout.h> | |
38 | 38 | |||
39 | #define ND6_LLINFO_PURGE -3 | 39 | #define ND6_LLINFO_PURGE -3 | |
40 | #define ND6_LLINFO_NOSTATE -2 | 40 | #define ND6_LLINFO_NOSTATE -2 | |
41 | /* | 41 | /* | |
42 | * We don't need the WAITDELETE state any more, but we keep the definition | 42 | * We don't need the WAITDELETE state any more, but we keep the definition | |
43 | * in a comment line instead of removing it. This is necessary to avoid | 43 | * in a comment line instead of removing it. This is necessary to avoid | |
44 | * unintentionally reusing the value for another purpose, which might | 44 | * unintentionally reusing the value for another purpose, which might | |
45 | * affect backward compatibility with old applications. | 45 | * affect backward compatibility with old applications. | |
46 | * (20000711 jinmei@kame.net) | 46 | * (20000711 jinmei@kame.net) | |
47 | */ | 47 | */ | |
48 | /* #define ND6_LLINFO_WAITDELETE -1 */ | 48 | /* #define ND6_LLINFO_WAITDELETE -1 */ | |
49 | #define ND6_LLINFO_INCOMPLETE 0 | 49 | #define ND6_LLINFO_INCOMPLETE 0 | |
50 | #define ND6_LLINFO_REACHABLE 1 | 50 | #define ND6_LLINFO_REACHABLE 1 | |
51 | #define ND6_LLINFO_STALE 2 | 51 | #define ND6_LLINFO_STALE 2 | |
52 | #define ND6_LLINFO_DELAY 3 | 52 | #define ND6_LLINFO_DELAY 3 | |
53 | #define ND6_LLINFO_PROBE 4 | 53 | #define ND6_LLINFO_PROBE 4 | |
54 | 54 | |||
55 | #define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE) | 55 | #define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE) | |
56 | #define ND6_LLINFO_PERMANENT(n) (((n)->ln_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE)) | 56 | #define ND6_LLINFO_PERMANENT(n) (((n)->ln_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE)) | |
57 | 57 | |||
58 | struct nd_ifinfo { | 58 | struct nd_ifinfo { | |
59 | u_int32_t linkmtu; /* LinkMTU */ | 59 | u_int32_t linkmtu; /* LinkMTU */ | |
60 | u_int32_t maxmtu; /* Upper bound of LinkMTU */ | 60 | u_int32_t maxmtu; /* Upper bound of LinkMTU */ | |
61 | u_int32_t basereachable; /* BaseReachableTime */ | 61 | u_int32_t basereachable; /* BaseReachableTime */ | |
62 | u_int32_t reachable; /* Reachable Time */ | 62 | u_int32_t reachable; /* Reachable Time */ | |
63 | u_int32_t retrans; /* Retrans Timer */ | 63 | u_int32_t retrans; /* Retrans Timer */ | |
64 | u_int32_t flags; /* Flags */ | 64 | u_int32_t flags; /* Flags */ | |
65 | int recalctm; /* BaseReacable re-calculation timer */ | 65 | int recalctm; /* BaseReacable re-calculation timer */ | |
66 | u_int8_t chlim; /* CurHopLimit */ | 66 | u_int8_t chlim; /* CurHopLimit */ | |
67 | u_int8_t initialized; /* Flag to see the entry is initialized */ | 67 | u_int8_t initialized; /* Flag to see the entry is initialized */ | |
68 | /* the following 3 members are for privacy extension for addrconf */ | 68 | /* the following 3 members are for privacy extension for addrconf */ | |
69 | u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */ | 69 | u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */ | |
70 | u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */ | 70 | u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */ | |
71 | u_int8_t randomid[8]; /* current random ID */ | 71 | u_int8_t randomid[8]; /* current random ID */ | |
72 | }; | 72 | }; | |
73 | 73 | |||
74 | #define ND6_IFF_PERFORMNUD 0x01 | 74 | #define ND6_IFF_PERFORMNUD 0x01 | |
75 | #define ND6_IFF_ACCEPT_RTADV 0x02 /* See "RTADV Key", below. */ | 75 | #define ND6_IFF_ACCEPT_RTADV 0x02 /* See "RTADV Key", below. */ | |
76 | #define ND6_IFF_PREFER_SOURCE 0x04 /* XXX: not related to ND. */ | 76 | #define ND6_IFF_PREFER_SOURCE 0x04 /* XXX: not related to ND. */ | |
77 | #define ND6_IFF_IFDISABLED 0x08 /* IPv6 operation is disabled due to | 77 | #define ND6_IFF_IFDISABLED 0x08 /* IPv6 operation is disabled due to | |
78 | * DAD failure. (XXX: not ND-specific) | 78 | * DAD failure. (XXX: not ND-specific) | |
79 | */ | 79 | */ | |
80 | #define ND6_IFF_OVERRIDE_RTADV 0x10 /* See "RTADV Key", below. */ | 80 | #define ND6_IFF_OVERRIDE_RTADV 0x10 /* See "RTADV Key", below. */ | |
81 | #define ND6_IFF_AUTO_LINKLOCAL 0x20 | 81 | #define ND6_IFF_AUTO_LINKLOCAL 0x20 | |
82 | 82 | |||
83 | /* | 83 | /* | |
84 | * RTADV Key | 84 | * RTADV Key | |
85 | * | 85 | * | |
86 | * The flags ND6_IFF_ACCEPT_RTADV and ND6_IFF_OVERRIDE_RTADV form a | 86 | * The flags ND6_IFF_ACCEPT_RTADV and ND6_IFF_OVERRIDE_RTADV form a | |
87 | * tri-state variable. (There are actually four different states, but | 87 | * tri-state variable. (There are actually four different states, but | |
88 | * two of the states are functionally identical.) | 88 | * two of the states are functionally identical.) | |
89 | * | 89 | * | |
90 | * ND6_IFF_OVERRIDE_RTADV or 0: This interface does not accept | 90 | * ND6_IFF_OVERRIDE_RTADV or 0: This interface does not accept | |
91 | * Router Advertisements. | 91 | * Router Advertisements. | |
92 | * | 92 | * | |
93 | * ND6_IFF_OVERRIDE_RTADV| | 93 | * ND6_IFF_OVERRIDE_RTADV| | |
94 | * ND6_IFF_ACCEPT_RTADV: This interface accepts Router | 94 | * ND6_IFF_ACCEPT_RTADV: This interface accepts Router | |
95 | * Advertisements regardless of the | 95 | * Advertisements regardless of the | |
96 | * global setting, ip6_accept_rtadv. | 96 | * global setting, ip6_accept_rtadv. | |
97 | * | 97 | * | |
98 | * ND6_IFF_ACCEPT_RTADV: This interface follows the global setting, | 98 | * ND6_IFF_ACCEPT_RTADV: This interface follows the global setting, | |
99 | * ip6_accept_rtadv. If ip6_accept_rtadv == 0, | 99 | * ip6_accept_rtadv. If ip6_accept_rtadv == 0, | |
100 | * this interface does not accept Router | 100 | * this interface does not accept Router | |
101 | * Advertisements. If ip6_accept_rtadv != 0, | 101 | * Advertisements. If ip6_accept_rtadv != 0, | |
102 | * this interface does accept them. | 102 | * this interface does accept them. | |
103 | */ | 103 | */ | |
104 | 104 | |||
105 | #ifdef _KERNEL | 105 | #ifdef _KERNEL | |
106 | #define ND_IFINFO(ifp) \ | 106 | #define ND_IFINFO(ifp) \ | |
107 | (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo) | 107 | (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo) | |
108 | #define IN6_LINKMTU(ifp) \ | 108 | #define IN6_LINKMTU(ifp) \ | |
109 | ((ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) \ | 109 | ((ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) \ | |
110 | ? ND_IFINFO(ifp)->linkmtu \ | 110 | ? ND_IFINFO(ifp)->linkmtu \ | |
111 | : ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) \ | 111 | : ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) \ | |
112 | ? ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu)) | 112 | ? ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu)) | |
113 | #endif | 113 | #endif | |
114 | 114 | |||
115 | struct in6_nbrinfo { | 115 | struct in6_nbrinfo { | |
116 | char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */ | 116 | char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */ | |
117 | struct in6_addr addr; /* IPv6 address of the neighbor */ | 117 | struct in6_addr addr; /* IPv6 address of the neighbor */ | |
118 | long asked; /* number of queries already sent for this addr */ | 118 | long asked; /* number of queries already sent for this addr */ | |
119 | int isrouter; /* if it acts as a router */ | 119 | int isrouter; /* if it acts as a router */ | |
120 | int state; /* reachability state */ | 120 | int state; /* reachability state */ | |
121 | int expire; /* lifetime for NDP state transition */ | 121 | int expire; /* lifetime for NDP state transition */ | |
122 | }; | 122 | }; | |
123 | 123 | |||
124 | #define DRLSTSIZ 10 | 124 | #define DRLSTSIZ 10 | |
125 | #define PRLSTSIZ 10 | 125 | #define PRLSTSIZ 10 | |
126 | struct in6_drlist { | 126 | struct in6_drlist { | |
127 | char ifname[IFNAMSIZ]; | 127 | char ifname[IFNAMSIZ]; | |
128 | struct { | 128 | struct { | |
129 | struct in6_addr rtaddr; | 129 | struct in6_addr rtaddr; | |
130 | u_char flags; | 130 | u_char flags; | |
131 | u_short rtlifetime; | 131 | u_short rtlifetime; | |
132 | u_long expire; | 132 | u_long expire; | |
133 | u_short if_index; | 133 | u_short if_index; | |
134 | } defrouter[DRLSTSIZ]; | 134 | } defrouter[DRLSTSIZ]; | |
135 | }; | 135 | }; | |
136 | 136 | |||
137 | struct in6_defrouter { | 137 | struct in6_defrouter { | |
138 | struct sockaddr_in6 rtaddr; | 138 | struct sockaddr_in6 rtaddr; | |
139 | u_char flags; | 139 | u_char flags; | |
140 | u_short rtlifetime; | 140 | u_short rtlifetime; | |
141 | u_long expire; | 141 | u_long expire; | |
142 | u_short if_index; | 142 | u_short if_index; | |
143 | }; | 143 | }; | |
144 | 144 | |||
145 | #ifdef _KERNEL | 145 | #ifdef _KERNEL | |
146 | struct in6_oprlist { | 146 | struct in6_oprlist { | |
147 | char ifname[IFNAMSIZ]; | 147 | char ifname[IFNAMSIZ]; | |
148 | struct { | 148 | struct { | |
149 | struct in6_addr prefix; | 149 | struct in6_addr prefix; | |
150 | struct prf_ra raflags; | 150 | struct prf_ra raflags; | |
151 | u_char prefixlen; | 151 | u_char prefixlen; | |
152 | u_char origin; | 152 | u_char origin; | |
153 | u_long vltime; | 153 | u_long vltime; | |
154 | u_long pltime; | 154 | u_long pltime; | |
155 | u_long expire; | 155 | u_long expire; | |
156 | u_short if_index; | 156 | u_short if_index; | |
157 | u_short advrtrs; /* number of advertisement routers */ | 157 | u_short advrtrs; /* number of advertisement routers */ | |
158 | struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ | 158 | struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ | |
159 | } prefix[PRLSTSIZ]; | 159 | } prefix[PRLSTSIZ]; | |
160 | }; | 160 | }; | |
161 | #endif | 161 | #endif | |
162 | 162 | |||
163 | struct in6_prlist { | 163 | struct in6_prlist { | |
164 | char ifname[IFNAMSIZ]; | 164 | char ifname[IFNAMSIZ]; | |
165 | struct { | 165 | struct { | |
166 | struct in6_addr prefix; | 166 | struct in6_addr prefix; | |
167 | struct prf_ra raflags; | 167 | struct prf_ra raflags; | |
168 | u_char prefixlen; | 168 | u_char prefixlen; | |
169 | u_char origin; | 169 | u_char origin; | |
170 | u_int32_t vltime; | 170 | u_int32_t vltime; | |
171 | u_int32_t pltime; | 171 | u_int32_t pltime; | |
172 | time_t expire; | 172 | time_t expire; | |
173 | u_short if_index; | 173 | u_short if_index; | |
174 | u_short advrtrs; /* number of advertisement routers */ | 174 | u_short advrtrs; /* number of advertisement routers */ | |
175 | struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ | 175 | struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ | |
176 | } prefix[PRLSTSIZ]; | 176 | } prefix[PRLSTSIZ]; | |
177 | }; | 177 | }; | |
178 | 178 | |||
179 | struct in6_prefix { | 179 | struct in6_prefix { | |
180 | struct sockaddr_in6 prefix; | 180 | struct sockaddr_in6 prefix; | |
181 | struct prf_ra raflags; | 181 | struct prf_ra raflags; | |
182 | u_char prefixlen; | 182 | u_char prefixlen; | |
183 | u_char origin; | 183 | u_char origin; | |
184 | u_int32_t vltime; | 184 | u_int32_t vltime; | |
185 | u_int32_t pltime; | 185 | u_int32_t pltime; | |
186 | time_t expire; | 186 | time_t expire; | |
187 | u_int32_t flags; | 187 | u_int32_t flags; | |
188 | int refcnt; | 188 | int refcnt; | |
189 | u_short if_index; | 189 | u_short if_index; | |
190 | u_short advrtrs; /* number of advertisement routers */ | 190 | u_short advrtrs; /* number of advertisement routers */ | |
191 | /* struct sockaddr_in6 advrtr[] */ | 191 | /* struct sockaddr_in6 advrtr[] */ | |
192 | }; | 192 | }; | |
193 | 193 | |||
194 | #ifdef _KERNEL | 194 | #ifdef _KERNEL | |
195 | struct in6_ondireq { | 195 | struct in6_ondireq { | |
196 | char ifname[IFNAMSIZ]; | 196 | char ifname[IFNAMSIZ]; | |
197 | struct { | 197 | struct { | |
198 | u_int32_t linkmtu; /* LinkMTU */ | 198 | u_int32_t linkmtu; /* LinkMTU */ | |
199 | u_int32_t maxmtu; /* Upper bound of LinkMTU */ | 199 | u_int32_t maxmtu; /* Upper bound of LinkMTU */ | |
200 | u_int32_t basereachable; /* BaseReachableTime */ | 200 | u_int32_t basereachable; /* BaseReachableTime */ | |
201 | u_int32_t reachable; /* Reachable Time */ | 201 | u_int32_t reachable; /* Reachable Time */ | |
202 | u_int32_t retrans; /* Retrans Timer */ | 202 | u_int32_t retrans; /* Retrans Timer */ | |
203 | u_int32_t flags; /* Flags */ | 203 | u_int32_t flags; /* Flags */ | |
204 | int recalctm; /* BaseReacable re-calculation timer */ | 204 | int recalctm; /* BaseReacable re-calculation timer */ | |
205 | u_int8_t chlim; /* CurHopLimit */ | 205 | u_int8_t chlim; /* CurHopLimit */ | |
206 | u_int8_t receivedra; | 206 | u_int8_t receivedra; | |
207 | } ndi; | 207 | } ndi; | |
208 | }; | 208 | }; | |
209 | #endif | 209 | #endif | |
210 | 210 | |||
211 | struct in6_ndireq { | 211 | struct in6_ndireq { | |
212 | char ifname[IFNAMSIZ]; | 212 | char ifname[IFNAMSIZ]; | |
213 | struct nd_ifinfo ndi; | 213 | struct nd_ifinfo ndi; | |
214 | }; | 214 | }; | |
215 | 215 | |||
216 | struct in6_ndifreq { | 216 | struct in6_ndifreq { | |
217 | char ifname[IFNAMSIZ]; | 217 | char ifname[IFNAMSIZ]; | |
218 | u_long ifindex; | 218 | u_long ifindex; | |
219 | }; | 219 | }; | |
220 | 220 | |||
221 | /* Prefix status */ | 221 | /* Prefix status */ | |
222 | #define NDPRF_ONLINK 0x1 | 222 | #define NDPRF_ONLINK 0x1 | |
223 | #define NDPRF_DETACHED 0x2 | 223 | #define NDPRF_DETACHED 0x2 | |
224 | #define NDPRF_HOME 0x4 | 224 | #define NDPRF_HOME 0x4 | |
225 | 225 | |||
226 | /* protocol constants */ | 226 | /* protocol constants */ | |
227 | #define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */ | 227 | #define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */ | |
228 | #define RTR_SOLICITATION_INTERVAL 4 /* 4sec */ | 228 | #define RTR_SOLICITATION_INTERVAL 4 /* 4sec */ | |
229 | #define MAX_RTR_SOLICITATIONS 3 | 229 | #define MAX_RTR_SOLICITATIONS 3 | |
230 | 230 | |||
231 | #define ND6_INFINITE_LIFETIME ((u_int32_t)~0) | 231 | #define ND6_INFINITE_LIFETIME ((u_int32_t)~0) | |
232 | 232 | |||
233 | #ifdef _KERNEL | 233 | #ifdef _KERNEL | |
234 | /* node constants */ | 234 | /* node constants */ | |
235 | #define MAX_REACHABLE_TIME 3600000 /* msec */ | 235 | #define MAX_REACHABLE_TIME 3600000 /* msec */ | |
236 | #define REACHABLE_TIME 30000 /* msec */ | 236 | #define REACHABLE_TIME 30000 /* msec */ | |
237 | #define RETRANS_TIMER 1000 /* msec */ | 237 | #define RETRANS_TIMER 1000 /* msec */ | |
238 | #define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */ | 238 | #define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */ | |
239 | #define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */ | 239 | #define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */ | |
240 | #define DEF_TEMP_VALID_LIFETIME 604800 /* 1 week */ | 240 | #define DEF_TEMP_VALID_LIFETIME 604800 /* 1 week */ | |
241 | #define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */ | 241 | #define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */ | |
242 | #define TEMPADDR_REGEN_ADVANCE 5 /* sec */ | 242 | #define TEMPADDR_REGEN_ADVANCE 5 /* sec */ | |
243 | #define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */ | 243 | #define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */ | |
244 | #define ND_COMPUTE_RTIME(x) \ | 244 | #define ND_COMPUTE_RTIME(x) \ | |
245 | (((MIN_RANDOM_FACTOR * (x >> 10)) + (cprng_fast32() & \ | 245 | (((MIN_RANDOM_FACTOR * (x >> 10)) + (cprng_fast32() & \ | |
246 | ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) | 246 | ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) | |
247 | 247 | |||
248 | TAILQ_HEAD(nd_drhead, nd_defrouter); | 248 | TAILQ_HEAD(nd_drhead, nd_defrouter); | |
249 | struct nd_defrouter { | 249 | struct nd_defrouter { | |
250 | TAILQ_ENTRY(nd_defrouter) dr_entry; | 250 | TAILQ_ENTRY(nd_defrouter) dr_entry; | |
251 | struct in6_addr rtaddr; | 251 | struct in6_addr rtaddr; | |
252 | u_char flags; /* flags on RA message */ | 252 | u_char flags; /* flags on RA message */ | |
253 | u_short rtlifetime; | 253 | u_short rtlifetime; | |
254 | u_long expire; | 254 | u_long expire; | |
255 | struct ifnet *ifp; | 255 | struct ifnet *ifp; | |
256 | int installed; /* is installed into kernel routing table */ | 256 | int installed; /* is installed into kernel routing table */ | |
257 | }; | 257 | }; | |
258 | 258 | |||
259 | struct nd_prefixctl { | 259 | struct nd_prefixctl { | |
260 | struct ifnet *ndprc_ifp; | 260 | struct ifnet *ndprc_ifp; | |
261 | 261 | |||
262 | /* prefix */ | 262 | /* prefix */ | |
263 | struct sockaddr_in6 ndprc_prefix; | 263 | struct sockaddr_in6 ndprc_prefix; | |
264 | u_char ndprc_plen; | 264 | u_char ndprc_plen; | |
265 | 265 | |||
266 | u_int32_t ndprc_vltime; /* advertised valid lifetime */ | 266 | u_int32_t ndprc_vltime; /* advertised valid lifetime */ | |
267 | u_int32_t ndprc_pltime; /* advertised preferred lifetime */ | 267 | u_int32_t ndprc_pltime; /* advertised preferred lifetime */ | |
268 | 268 | |||
269 | struct prf_ra ndprc_flags; | 269 | struct prf_ra ndprc_flags; | |
270 | }; | 270 | }; | |
271 | 271 | |||
272 | #define ndprc_raf ndprc_flags | 272 | #define ndprc_raf ndprc_flags | |
273 | #define ndprc_raf_onlink ndprc_flags.onlink | 273 | #define ndprc_raf_onlink ndprc_flags.onlink | |
274 | #define ndprc_raf_auto ndprc_flags.autonomous | 274 | #define ndprc_raf_auto ndprc_flags.autonomous | |
275 | #define ndprc_raf_router ndprc_flags.router | 275 | #define ndprc_raf_router ndprc_flags.router | |
276 | 276 | |||
277 | struct nd_prefix { | 277 | struct nd_prefix { | |
278 | struct ifnet *ndpr_ifp; | 278 | struct ifnet *ndpr_ifp; | |
279 | LIST_ENTRY(nd_prefix) ndpr_entry; | 279 | LIST_ENTRY(nd_prefix) ndpr_entry; | |
280 | struct sockaddr_in6 ndpr_prefix; /* prefix */ | 280 | struct sockaddr_in6 ndpr_prefix; /* prefix */ | |
281 | struct in6_addr ndpr_mask; /* netmask derived from the prefix */ | 281 | struct in6_addr ndpr_mask; /* netmask derived from the prefix */ | |
282 | 282 | |||
283 | u_int32_t ndpr_vltime; /* advertised valid lifetime */ | 283 | u_int32_t ndpr_vltime; /* advertised valid lifetime */ | |
284 | u_int32_t ndpr_pltime; /* advertised preferred lifetime */ | 284 | u_int32_t ndpr_pltime; /* advertised preferred lifetime */ | |
285 | 285 | |||
286 | time_t ndpr_expire; /* expiration time of the prefix */ | 286 | time_t ndpr_expire; /* expiration time of the prefix */ | |
287 | time_t ndpr_preferred; /* preferred time of the prefix */ | 287 | time_t ndpr_preferred; /* preferred time of the prefix */ | |
288 | time_t ndpr_lastupdate; /* reception time of last advertisement */ | 288 | time_t ndpr_lastupdate; /* reception time of last advertisement */ | |
289 | 289 | |||
290 | struct prf_ra ndpr_flags; | 290 | struct prf_ra ndpr_flags; | |
291 | u_int32_t ndpr_stateflags; /* actual state flags */ | 291 | u_int32_t ndpr_stateflags; /* actual state flags */ | |
292 | /* list of routers that advertise the prefix: */ | 292 | /* list of routers that advertise the prefix: */ | |
293 | LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs; | 293 | LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs; | |
294 | u_char ndpr_plen; | 294 | u_char ndpr_plen; | |
295 | int ndpr_refcnt; /* reference couter from addresses */ | 295 | int ndpr_refcnt; /* reference couter from addresses */ | |
296 | }; | 296 | }; | |
297 | 297 | |||
298 | #define ndpr_next ndpr_entry.le_next | 298 | #define ndpr_next ndpr_entry.le_next | |
299 | 299 | |||
300 | #define ndpr_raf ndpr_flags | 300 | #define ndpr_raf ndpr_flags | |
301 | #define ndpr_raf_onlink ndpr_flags.onlink | 301 | #define ndpr_raf_onlink ndpr_flags.onlink | |
302 | #define ndpr_raf_auto ndpr_flags.autonomous | 302 | #define ndpr_raf_auto ndpr_flags.autonomous | |
303 | #define ndpr_raf_router ndpr_flags.router | 303 | #define ndpr_raf_router ndpr_flags.router | |
304 | 304 | |||
305 | /* | 305 | /* | |
306 | * Message format for use in obtaining information about prefixes | 306 | * Message format for use in obtaining information about prefixes | |
307 | * from inet6 sysctl function | 307 | * from inet6 sysctl function | |
308 | */ | 308 | */ | |
309 | struct inet6_ndpr_msghdr { | 309 | struct inet6_ndpr_msghdr { | |
310 | u_short inpm_msglen; /* to skip over non-understood messages */ | 310 | u_short inpm_msglen; /* to skip over non-understood messages */ | |
311 | u_char inpm_version; /* future binary compatibility */ | 311 | u_char inpm_version; /* future binary compatibility */ | |
312 | u_char inpm_type; /* message type */ | 312 | u_char inpm_type; /* message type */ | |
313 | struct in6_addr inpm_prefix; | 313 | struct in6_addr inpm_prefix; | |
314 | u_long prm_vltim; | 314 | u_long prm_vltim; | |
315 | u_long prm_pltime; | 315 | u_long prm_pltime; | |
316 | u_long prm_expire; | 316 | u_long prm_expire; | |
317 | u_long prm_preferred; | 317 | u_long prm_preferred; | |
318 | struct in6_prflags prm_flags; | 318 | struct in6_prflags prm_flags; | |
319 | u_short prm_index; /* index for associated ifp */ | 319 | u_short prm_index; /* index for associated ifp */ | |
320 | u_char prm_plen; /* length of prefix in bits */ | 320 | u_char prm_plen; /* length of prefix in bits */ | |
321 | }; | 321 | }; | |
322 | 322 | |||
323 | #define prm_raf_onlink prm_flags.prf_ra.onlink | 323 | #define prm_raf_onlink prm_flags.prf_ra.onlink | |
324 | #define prm_raf_auto prm_flags.prf_ra.autonomous | 324 | #define prm_raf_auto prm_flags.prf_ra.autonomous | |
325 | 325 | |||
326 | #define prm_statef_onlink prm_flags.prf_state.onlink | 326 | #define prm_statef_onlink prm_flags.prf_state.onlink | |
327 | 327 | |||
328 | #define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid | 328 | #define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid | |
329 | #define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd | 329 | #define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd | |
330 | 330 | |||
331 | struct nd_pfxrouter { | 331 | struct nd_pfxrouter { | |
332 | LIST_ENTRY(nd_pfxrouter) pfr_entry; | 332 | LIST_ENTRY(nd_pfxrouter) pfr_entry; | |
333 | struct nd_defrouter *router; | 333 | struct nd_defrouter *router; | |
334 | }; | 334 | }; | |
335 | 335 | |||
336 | LIST_HEAD(nd_prhead, nd_prefix); | 336 | LIST_HEAD(nd_prhead, nd_prefix); | |
337 | 337 | |||
338 | #include <sys/mallocvar.h> | 338 | #include <sys/mallocvar.h> | |
339 | MALLOC_DECLARE(M_IP6NDP); | 339 | MALLOC_DECLARE(M_IP6NDP); | |
340 | 340 | |||
341 | /* nd6.c */ | 341 | /* nd6.c */ | |
342 | extern int nd6_prune; | 342 | extern int nd6_prune; | |
343 | extern int nd6_delay; | 343 | extern int nd6_delay; | |
344 | extern int nd6_umaxtries; | 344 | extern int nd6_umaxtries; | |
345 | extern int nd6_mmaxtries; | 345 | extern int nd6_mmaxtries; | |
346 | extern int nd6_useloopback; | 346 | extern int nd6_useloopback; | |
347 | extern int nd6_maxnudhint; | 347 | extern int nd6_maxnudhint; | |
348 | extern int nd6_gctimer; | 348 | extern int nd6_gctimer; | |
349 | extern struct nd_drhead nd_defrouter; | 349 | extern struct nd_drhead nd_defrouter; | |
350 | extern struct nd_prhead nd_prefix; | 350 | extern struct nd_prhead nd_prefix; | |
351 | extern int nd6_debug; | 351 | extern int nd6_debug; | |
352 | 352 | |||
353 | #define nd6log(x) do { if (nd6_debug) log x; } while (/*CONSTCOND*/ 0) | 353 | #define nd6log(x) do { if (nd6_debug) log x; } while (/*CONSTCOND*/ 0) | |
354 | 354 | |||
355 | extern struct callout nd6_timer_ch; | |||
356 | ||||
357 | /* nd6_rtr.c */ | 355 | /* nd6_rtr.c */ | |
358 | extern int nd6_defifindex; | 356 | extern int nd6_defifindex; | |
359 | extern int ip6_desync_factor; /* seconds */ | 357 | extern int ip6_desync_factor; /* seconds */ | |
360 | extern u_int32_t ip6_temp_preferred_lifetime; /* seconds */ | 358 | extern u_int32_t ip6_temp_preferred_lifetime; /* seconds */ | |
361 | extern u_int32_t ip6_temp_valid_lifetime; /* seconds */ | 359 | extern u_int32_t ip6_temp_valid_lifetime; /* seconds */ | |
362 | extern int ip6_temp_regen_advance; /* seconds */ | 360 | extern int ip6_temp_regen_advance; /* seconds */ | |
363 | extern int nd6_numroutes; | 361 | extern int nd6_numroutes; | |
364 | 362 | |||
365 | union nd_opts { | 363 | union nd_opts { | |
366 | struct nd_opt_hdr *nd_opt_array[8]; | 364 | struct nd_opt_hdr *nd_opt_array[8]; | |
367 | struct { | 365 | struct { | |
368 | struct nd_opt_hdr *zero; | 366 | struct nd_opt_hdr *zero; | |
369 | struct nd_opt_hdr *src_lladdr; | 367 | struct nd_opt_hdr *src_lladdr; | |
370 | struct nd_opt_hdr *tgt_lladdr; | 368 | struct nd_opt_hdr *tgt_lladdr; | |
371 | struct nd_opt_prefix_info *pi_beg; /* multiple opts, start */ | 369 | struct nd_opt_prefix_info *pi_beg; /* multiple opts, start */ | |
372 | struct nd_opt_rd_hdr *rh; | 370 | struct nd_opt_rd_hdr *rh; | |
373 | struct nd_opt_mtu *mtu; | 371 | struct nd_opt_mtu *mtu; | |
374 | struct nd_opt_hdr *search; /* multiple opts */ | 372 | struct nd_opt_hdr *search; /* multiple opts */ | |
375 | struct nd_opt_hdr *last; /* multiple opts */ | 373 | struct nd_opt_hdr *last; /* multiple opts */ | |
376 | int done; | 374 | int done; | |
377 | struct nd_opt_prefix_info *pi_end;/* multiple opts, end */ | 375 | struct nd_opt_prefix_info *pi_end;/* multiple opts, end */ | |
378 | } nd_opt_each; | 376 | } nd_opt_each; | |
379 | }; | 377 | }; | |
380 | #define nd_opts_src_lladdr nd_opt_each.src_lladdr | 378 | #define nd_opts_src_lladdr nd_opt_each.src_lladdr | |
381 | #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr | 379 | #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr | |
382 | #define nd_opts_pi nd_opt_each.pi_beg | 380 | #define nd_opts_pi nd_opt_each.pi_beg | |
383 | #define nd_opts_pi_end nd_opt_each.pi_end | 381 | #define nd_opts_pi_end nd_opt_each.pi_end | |
384 | #define nd_opts_rh nd_opt_each.rh | 382 | #define nd_opts_rh nd_opt_each.rh | |
385 | #define nd_opts_mtu nd_opt_each.mtu | 383 | #define nd_opts_mtu nd_opt_each.mtu | |
386 | #define nd_opts_search nd_opt_each.search | 384 | #define nd_opts_search nd_opt_each.search | |
387 | #define nd_opts_last nd_opt_each.last | 385 | #define nd_opts_last nd_opt_each.last | |
388 | #define nd_opts_done nd_opt_each.done | 386 | #define nd_opts_done nd_opt_each.done | |
389 | 387 | |||
390 | #include <net/if_llatbl.h> | 388 | #include <net/if_llatbl.h> | |
391 | 389 | |||
392 | /* XXX: need nd6_var.h?? */ | 390 | /* XXX: need nd6_var.h?? */ | |
393 | /* nd6.c */ | 391 | /* nd6.c */ | |
394 | void nd6_init(void); | 392 | void nd6_init(void); | |
395 | struct nd_ifinfo *nd6_ifattach(struct ifnet *); | 393 | struct nd_ifinfo *nd6_ifattach(struct ifnet *); | |
396 | void nd6_ifdetach(struct ifnet *, struct in6_ifextra *); | 394 | void nd6_ifdetach(struct ifnet *, struct in6_ifextra *); | |
397 | int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *); | 395 | int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *); | |
398 | void nd6_option_init(void *, int, union nd_opts *); | 396 | void nd6_option_init(void *, int, union nd_opts *); | |
399 | struct nd_opt_hdr *nd6_option(union nd_opts *); | 397 | struct nd_opt_hdr *nd6_option(union nd_opts *); | |
400 | int nd6_options(union nd_opts *); | 398 | int nd6_options(union nd_opts *); | |
401 | struct rtentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *); | 399 | struct rtentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *); | |
402 | void nd6_setmtu(struct ifnet *); | 400 | void nd6_setmtu(struct ifnet *); | |
403 | void nd6_llinfo_settimer(struct llentry *, time_t); | 401 | void nd6_llinfo_settimer(struct llentry *, time_t); | |
404 | void nd6_llinfo_settimer_locked(struct llentry *, time_t); | 402 | void nd6_llinfo_settimer_locked(struct llentry *, time_t); | |
405 | void nd6_timer(void *); | |||
406 | void nd6_purge(struct ifnet *, struct in6_ifextra *); | 403 | void nd6_purge(struct ifnet *, struct in6_ifextra *); | |
407 | void nd6_nud_hint(struct rtentry *); | 404 | void nd6_nud_hint(struct rtentry *); | |
408 | int nd6_resolve(struct ifnet *, struct rtentry *, | 405 | int nd6_resolve(struct ifnet *, struct rtentry *, | |
409 | struct mbuf *, struct sockaddr *, u_char *); | 406 | struct mbuf *, struct sockaddr *, u_char *); | |
410 | void nd6_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); | 407 | void nd6_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); | |
411 | int nd6_ioctl(u_long, void *, struct ifnet *); | 408 | int nd6_ioctl(u_long, void *, struct ifnet *); | |
412 | void nd6_cache_lladdr(struct ifnet *, struct in6_addr *, | 409 | void nd6_cache_lladdr(struct ifnet *, struct in6_addr *, | |
413 | char *, int, int, int); | 410 | char *, int, int, int); | |
414 | int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *, | 411 | int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *, | |
415 | const struct sockaddr_in6 *, struct rtentry *); | 412 | const struct sockaddr_in6 *, struct rtentry *); | |
416 | int nd6_storelladdr(const struct ifnet *, const struct rtentry *, struct mbuf *, | 413 | int nd6_storelladdr(const struct ifnet *, const struct rtentry *, struct mbuf *, | |
417 | const struct sockaddr *, uint8_t *, size_t); | 414 | const struct sockaddr *, uint8_t *, size_t); | |
418 | int nd6_sysctl(int, void *, size_t *, void *, size_t); | 415 | int nd6_sysctl(int, void *, size_t *, void *, size_t); | |
419 | int nd6_need_cache(struct ifnet *); | 416 | int nd6_need_cache(struct ifnet *); | |
420 | void nd6_llinfo_release_pkts(struct llentry *, struct ifnet *, | 417 | void nd6_llinfo_release_pkts(struct llentry *, struct ifnet *, | |
421 | struct rtentry *); | 418 | struct rtentry *); | |
422 | 419 | |||
423 | /* nd6_nbr.c */ | 420 | /* nd6_nbr.c */ | |
424 | void nd6_na_input(struct mbuf *, int, int); | 421 | void nd6_na_input(struct mbuf *, int, int); | |
425 | void nd6_na_output(struct ifnet *, const struct in6_addr *, | 422 | void nd6_na_output(struct ifnet *, const struct in6_addr *, | |
426 | const struct in6_addr *, u_long, int, const struct sockaddr *); | 423 | const struct in6_addr *, u_long, int, const struct sockaddr *); | |
427 | void nd6_ns_input(struct mbuf *, int, int); | 424 | void nd6_ns_input(struct mbuf *, int, int); | |
428 | void nd6_ns_output(struct ifnet *, const struct in6_addr *, | 425 | void nd6_ns_output(struct ifnet *, const struct in6_addr *, | |
429 | const struct in6_addr *, struct in6_addr *, int); | 426 | const struct in6_addr *, struct in6_addr *, int); | |
430 | const void *nd6_ifptomac(const struct ifnet *); | 427 | const void *nd6_ifptomac(const struct ifnet *); | |
431 | void nd6_dad_start(struct ifaddr *, int); | 428 | void nd6_dad_start(struct ifaddr *, int); | |
432 | void nd6_dad_stop(struct ifaddr *); | 429 | void nd6_dad_stop(struct ifaddr *); | |
433 | void nd6_dad_duplicated(struct ifaddr *); | 430 | void nd6_dad_duplicated(struct ifaddr *); | |
434 | 431 | |||
435 | /* nd6_rtr.c */ | 432 | /* nd6_rtr.c */ | |
436 | void nd6_rs_input(struct mbuf *, int, int); | 433 | void nd6_rs_input(struct mbuf *, int, int); | |
437 | void nd6_ra_input(struct mbuf *, int, int); | 434 | void nd6_ra_input(struct mbuf *, int, int); | |
438 | void prelist_del(struct nd_prefix *); | 435 | void prelist_del(struct nd_prefix *); | |
439 | void defrouter_addreq(struct nd_defrouter *); | 436 | void defrouter_addreq(struct nd_defrouter *); | |
440 | void defrouter_reset(void); | 437 | void defrouter_reset(void); | |
441 | void defrouter_select(void); | 438 | void defrouter_select(void); | |
442 | void defrtrlist_del(struct nd_defrouter *, struct in6_ifextra *); | 439 | void defrtrlist_del(struct nd_defrouter *, struct in6_ifextra *); | |
443 | void prelist_remove(struct nd_prefix *); | 440 | void prelist_remove(struct nd_prefix *); | |
444 | int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *, | 441 | int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *, | |
445 | struct nd_prefix **); | 442 | struct nd_prefix **); | |
446 | int nd6_prefix_onlink(struct nd_prefix *); | 443 | int nd6_prefix_onlink(struct nd_prefix *); | |
447 | int nd6_prefix_offlink(struct nd_prefix *); | 444 | int nd6_prefix_offlink(struct nd_prefix *); | |
448 | void pfxlist_onlink_check(void); | 445 | void pfxlist_onlink_check(void); | |
449 | struct nd_defrouter *defrouter_lookup(const struct in6_addr *, struct ifnet *); | 446 | struct nd_defrouter *defrouter_lookup(const struct in6_addr *, struct ifnet *); | |
450 | struct nd_prefix *nd6_prefix_lookup(struct nd_prefixctl *); | 447 | struct nd_prefix *nd6_prefix_lookup(struct nd_prefixctl *); | |
451 | int in6_ifdel(struct ifnet *, struct in6_addr *); | 448 | int in6_ifdel(struct ifnet *, struct in6_addr *); | |
452 | void rt6_flush(struct in6_addr *, struct ifnet *); | 449 | void rt6_flush(struct in6_addr *, struct ifnet *); | |
453 | int nd6_setdefaultiface(int); | 450 | int nd6_setdefaultiface(int); | |
454 | int in6_tmpifadd(const struct in6_ifaddr *, int, int); | 451 | int in6_tmpifadd(const struct in6_ifaddr *, int, int); | |
455 | bool nd6_accepts_rtadv(const struct nd_ifinfo *); | 452 | bool nd6_accepts_rtadv(const struct nd_ifinfo *); | |
456 | 453 | |||
457 | #endif /* _KERNEL */ | 454 | #endif /* _KERNEL */ | |
458 | 455 | |||
459 | #endif /* !_NETINET6_ND6_H_ */ | 456 | #endif /* !_NETINET6_ND6_H_ */ |