| 1 | /* $NetBSD: ip6_input.c,v 1.170 2016/11/01 10:32:57 ozaki-r Exp $ */ |
| 2 | /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ |
| 3 | |
| 4 | /* |
| 5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions |
| 10 | * are met: |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 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 |
| 18 | * without specific prior written permission. |
| 19 | * |
| 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 |
| 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
| 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 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 |
| 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 |
| 30 | * SUCH DAMAGE. |
| 31 | */ |
| 32 | |
| 33 | /* |
| 34 | * Copyright (c) 1982, 1986, 1988, 1993 |
| 35 | * The Regents of the University of California. All rights reserved. |
| 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without |
| 38 | * modification, are permitted provided that the following conditions |
| 39 | * are met: |
| 40 | * 1. Redistributions of source code must retain the above copyright |
| 41 | * notice, this list of conditions and the following disclaimer. |
| 42 | * 2. Redistributions in binary form must reproduce the above copyright |
| 43 | * notice, this list of conditions and the following disclaimer in the |
| 44 | * documentation and/or other materials provided with the distribution. |
| 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 |
| 47 | * without specific prior written permission. |
| 48 | * |
| 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 |
| 51 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 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 |
| 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 |
| 59 | * SUCH DAMAGE. |
| 60 | * |
| 61 | * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 |
| 62 | */ |
| 63 | |
| 64 | #include <sys/cdefs.h> |
| 65 | __KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.170 2016/11/01 10:32:57 ozaki-r Exp $" ); |
| 66 | |
| 67 | #ifdef _KERNEL_OPT |
| 68 | #include "opt_gateway.h" |
| 69 | #include "opt_inet.h" |
| 70 | #include "opt_inet6.h" |
| 71 | #include "opt_ipsec.h" |
| 72 | #include "opt_compat_netbsd.h" |
| 73 | #include "opt_net_mpsafe.h" |
| 74 | #endif |
| 75 | |
| 76 | #include <sys/param.h> |
| 77 | #include <sys/systm.h> |
| 78 | #include <sys/malloc.h> |
| 79 | #include <sys/mbuf.h> |
| 80 | #include <sys/domain.h> |
| 81 | #include <sys/protosw.h> |
| 82 | #include <sys/socket.h> |
| 83 | #include <sys/socketvar.h> |
| 84 | #include <sys/errno.h> |
| 85 | #include <sys/time.h> |
| 86 | #include <sys/kernel.h> |
| 87 | #include <sys/syslog.h> |
| 88 | #include <sys/proc.h> |
| 89 | #include <sys/sysctl.h> |
| 90 | #include <sys/cprng.h> |
| 91 | #include <sys/percpu.h> |
| 92 | |
| 93 | #include <net/if.h> |
| 94 | #include <net/if_types.h> |
| 95 | #include <net/if_dl.h> |
| 96 | #include <net/route.h> |
| 97 | #include <net/pktqueue.h> |
| 98 | #include <net/pfil.h> |
| 99 | |
| 100 | #include <netinet/in.h> |
| 101 | #include <netinet/in_systm.h> |
| 102 | #ifdef INET |
| 103 | #include <netinet/ip.h> |
| 104 | #include <netinet/ip_var.h> |
| 105 | #include <netinet/ip_icmp.h> |
| 106 | #endif /* INET */ |
| 107 | #include <netinet/ip6.h> |
| 108 | #include <netinet/portalgo.h> |
| 109 | #include <netinet6/in6_var.h> |
| 110 | #include <netinet6/ip6_var.h> |
| 111 | #include <netinet6/ip6_private.h> |
| 112 | #include <netinet6/in6_pcb.h> |
| 113 | #include <netinet/icmp6.h> |
| 114 | #include <netinet6/scope6_var.h> |
| 115 | #include <netinet6/in6_ifattach.h> |
| 116 | #include <netinet6/nd6.h> |
| 117 | |
| 118 | #ifdef IPSEC |
| 119 | #include <netipsec/ipsec.h> |
| 120 | #include <netipsec/ipsec6.h> |
| 121 | #include <netipsec/key.h> |
| 122 | #endif /* IPSEC */ |
| 123 | |
| 124 | #ifdef COMPAT_50 |
| 125 | #include <compat/sys/time.h> |
| 126 | #include <compat/sys/socket.h> |
| 127 | #endif |
| 128 | |
| 129 | #include <netinet6/ip6protosw.h> |
| 130 | |
| 131 | #include "faith.h" |
| 132 | |
| 133 | #include <net/net_osdep.h> |
| 134 | |
| 135 | extern struct domain inet6domain; |
| 136 | |
| 137 | u_char ip6_protox[IPPROTO_MAX]; |
| 138 | pktqueue_t *ip6_pktq __read_mostly; |
| 139 | |
| 140 | int ip6_forward_srcrt; /* XXX */ |
| 141 | int ip6_sourcecheck; /* XXX */ |
| 142 | int ip6_sourcecheck_interval; /* XXX */ |
| 143 | |
| 144 | pfil_head_t *inet6_pfil_hook; |
| 145 | |
| 146 | percpu_t *ip6stat_percpu; |
| 147 | |
| 148 | percpu_t *ip6_forward_rt_percpu __cacheline_aligned; |
| 149 | |
| 150 | static void ip6_init2(void); |
| 151 | static void ip6intr(void *); |
| 152 | static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); |
| 153 | |
| 154 | static int ip6_process_hopopts(struct mbuf *, u_int8_t *, int, u_int32_t *, |
| 155 | u_int32_t *); |
| 156 | static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); |
| 157 | static void sysctl_net_inet6_ip6_setup(struct sysctllog **); |
| 158 | |
| 159 | #ifdef NET_MPSAFE |
| 160 | #define SOFTNET_LOCK() mutex_enter(softnet_lock) |
| 161 | #define SOFTNET_UNLOCK() mutex_exit(softnet_lock) |
| 162 | #else |
| 163 | #define SOFTNET_LOCK() KASSERT(mutex_owned(softnet_lock)) |
| 164 | #define SOFTNET_UNLOCK() KASSERT(mutex_owned(softnet_lock)) |
| 165 | #endif |
| 166 | |
| 167 | /* |
| 168 | * IP6 initialization: fill in IP6 protocol switch table. |
| 169 | * All protocols not implemented in kernel go to raw IP6 protocol handler. |
| 170 | */ |
| 171 | void |
| 172 | ip6_init(void) |
| 173 | { |
| 174 | const struct ip6protosw *pr; |
| 175 | int i; |
| 176 | |
| 177 | in6_init(); |
| 178 | |
| 179 | sysctl_net_inet6_ip6_setup(NULL); |
| 180 | pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); |
| 181 | if (pr == 0) |
| 182 | panic("ip6_init" ); |
| 183 | for (i = 0; i < IPPROTO_MAX; i++) |
| 184 | ip6_protox[i] = pr - inet6sw; |
| 185 | for (pr = (const struct ip6protosw *)inet6domain.dom_protosw; |
| 186 | pr < (const struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) |
| 187 | if (pr->pr_domain->dom_family == PF_INET6 && |
| 188 | pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) |
| 189 | ip6_protox[pr->pr_protocol] = pr - inet6sw; |
| 190 | |
| 191 | ip6_pktq = pktq_create(IFQ_MAXLEN, ip6intr, NULL); |
| 192 | KASSERT(ip6_pktq != NULL); |
| 193 | |
| 194 | scope6_init(); |
| 195 | addrsel_policy_init(); |
| 196 | nd6_init(); |
| 197 | frag6_init(); |
| 198 | ip6_desync_factor = cprng_fast32() % MAX_TEMP_DESYNC_FACTOR; |
| 199 | |
| 200 | ip6_init2(); |
| 201 | #ifdef GATEWAY |
| 202 | ip6flow_init(ip6_hashsize); |
| 203 | #endif |
| 204 | /* Register our Packet Filter hook. */ |
| 205 | inet6_pfil_hook = pfil_head_create(PFIL_TYPE_AF, (void *)AF_INET6); |
| 206 | KASSERT(inet6_pfil_hook != NULL); |
| 207 | |
| 208 | ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); |
| 209 | |
| 210 | ip6_forward_rt_percpu = percpu_alloc(sizeof(struct route)); |
| 211 | if (ip6_forward_rt_percpu == NULL) |
| 212 | panic("failed to alllocate ip6_forward_rt_percpu" ); |
| 213 | } |
| 214 | |
| 215 | static void |
| 216 | ip6_init2(void) |
| 217 | { |
| 218 | |
| 219 | /* timer for regeneranation of temporary addresses randomize ID */ |
| 220 | callout_init(&in6_tmpaddrtimer_ch, CALLOUT_MPSAFE); |
| 221 | callout_reset(&in6_tmpaddrtimer_ch, |
| 222 | (ip6_temp_preferred_lifetime - ip6_desync_factor - |
| 223 | ip6_temp_regen_advance) * hz, |
| 224 | in6_tmpaddrtimer, NULL); |
| 225 | } |
| 226 | |
| 227 | /* |
| 228 | * IP6 input interrupt handling. Just pass the packet to ip6_input. |
| 229 | */ |
| 230 | static void |
| 231 | ip6intr(void *arg __unused) |
| 232 | { |
| 233 | struct mbuf *m; |
| 234 | |
| 235 | #ifndef NET_MPSAFE |
| 236 | mutex_enter(softnet_lock); |
| 237 | #endif |
| 238 | while ((m = pktq_dequeue(ip6_pktq)) != NULL) { |
| 239 | struct psref psref; |
| 240 | struct ifnet *rcvif = m_get_rcvif_psref(m, &psref); |
| 241 | |
| 242 | if (rcvif == NULL) { |
| 243 | m_freem(m); |
| 244 | continue; |
| 245 | } |
| 246 | /* |
| 247 | * Drop the packet if IPv6 is disabled on the interface. |
| 248 | */ |
| 249 | if ((ND_IFINFO(rcvif)->flags & ND6_IFF_IFDISABLED)) { |
| 250 | m_put_rcvif_psref(rcvif, &psref); |
| 251 | m_freem(m); |
| 252 | continue; |
| 253 | } |
| 254 | ip6_input(m, rcvif); |
| 255 | m_put_rcvif_psref(rcvif, &psref); |
| 256 | } |
| 257 | #ifndef NET_MPSAFE |
| 258 | mutex_exit(softnet_lock); |
| 259 | #endif |
| 260 | } |
| 261 | |
| 262 | void |
| 263 | ip6_input(struct mbuf *m, struct ifnet *rcvif) |
| 264 | { |
| 265 | struct ip6_hdr *ip6; |
| 266 | int hit, off = sizeof(struct ip6_hdr), nest; |
| 267 | u_int32_t plen; |
| 268 | u_int32_t rtalert = ~0; |
| 269 | int nxt, ours = 0, rh_present = 0; |
| 270 | struct ifnet *deliverifp = NULL; |
| 271 | int srcrt = 0; |
| 272 | const struct rtentry *rt; |
| 273 | union { |
| 274 | struct sockaddr dst; |
| 275 | struct sockaddr_in6 dst6; |
| 276 | } u; |
| 277 | struct route *ro; |
| 278 | |
| 279 | /* |
| 280 | * make sure we don't have onion peering information into m_tag. |
| 281 | */ |
| 282 | ip6_delaux(m); |
| 283 | |
| 284 | /* |
| 285 | * mbuf statistics |
| 286 | */ |
| 287 | if (m->m_flags & M_EXT) { |
| 288 | if (m->m_next) |
| 289 | IP6_STATINC(IP6_STAT_MEXT2M); |
| 290 | else |
| 291 | IP6_STATINC(IP6_STAT_MEXT1); |
| 292 | } else { |
| 293 | #define M2MMAX 32 |
| 294 | if (m->m_next) { |
| 295 | if (m->m_flags & M_LOOP) |
| 296 | /*XXX*/ IP6_STATINC(IP6_STAT_M2M + lo0ifp->if_index); |
| 297 | else if (rcvif->if_index < M2MMAX) |
| 298 | IP6_STATINC(IP6_STAT_M2M + rcvif->if_index); |
| 299 | else |
| 300 | IP6_STATINC(IP6_STAT_M2M); |
| 301 | } else |
| 302 | IP6_STATINC(IP6_STAT_M1); |
| 303 | #undef M2MMAX |
| 304 | } |
| 305 | |
| 306 | in6_ifstat_inc(rcvif, ifs6_in_receive); |
| 307 | IP6_STATINC(IP6_STAT_TOTAL); |
| 308 | |
| 309 | /* |
| 310 | * If the IPv6 header is not aligned, slurp it up into a new |
| 311 | * mbuf with space for link headers, in the event we forward |
| 312 | * it. Otherwise, if it is aligned, make sure the entire base |
| 313 | * IPv6 header is in the first mbuf of the chain. |
| 314 | */ |
| 315 | if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) { |
| 316 | if ((m = m_copyup(m, sizeof(struct ip6_hdr), |
| 317 | (max_linkhdr + 3) & ~3)) == NULL) { |
| 318 | /* XXXJRT new stat, please */ |
| 319 | IP6_STATINC(IP6_STAT_TOOSMALL); |
| 320 | in6_ifstat_inc(rcvif, ifs6_in_hdrerr); |
| 321 | return; |
| 322 | } |
| 323 | } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) { |
| 324 | if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { |
| 325 | IP6_STATINC(IP6_STAT_TOOSMALL); |
| 326 | in6_ifstat_inc(rcvif, ifs6_in_hdrerr); |
| 327 | return; |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | ip6 = mtod(m, struct ip6_hdr *); |
| 332 | |
| 333 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { |
| 334 | IP6_STATINC(IP6_STAT_BADVERS); |
| 335 | in6_ifstat_inc(rcvif, ifs6_in_hdrerr); |
| 336 | goto bad; |
| 337 | } |
| 338 | |
| 339 | /* |
| 340 | * Assume that we can create a fast-forward IP flow entry |
| 341 | * based on this packet. |
| 342 | */ |
| 343 | m->m_flags |= M_CANFASTFWD; |
| 344 | |
| 345 | /* |
| 346 | * Run through list of hooks for input packets. If there are any |
| 347 | * filters which require that additional packets in the flow are |
| 348 | * not fast-forwarded, they must clear the M_CANFASTFWD flag. |
| 349 | * Note that filters must _never_ set this flag, as another filter |
| 350 | * in the list may have previously cleared it. |
| 351 | */ |
| 352 | /* |
| 353 | * let ipfilter look at packet on the wire, |
| 354 | * not the decapsulated packet. |
| 355 | */ |
| 356 | #if defined(IPSEC) |
| 357 | if (!ipsec_used || !ipsec_indone(m)) |
| 358 | #else |
| 359 | if (1) |
| 360 | #endif |
| 361 | { |
| 362 | struct in6_addr odst; |
| 363 | |
| 364 | odst = ip6->ip6_dst; |
| 365 | if (pfil_run_hooks(inet6_pfil_hook, &m, rcvif, PFIL_IN) != 0) |
| 366 | return; |
| 367 | if (m == NULL) |
| 368 | return; |
| 369 | ip6 = mtod(m, struct ip6_hdr *); |
| 370 | srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); |
| 371 | } |
| 372 | |
| 373 | IP6_STATINC(IP6_STAT_NXTHIST + ip6->ip6_nxt); |
| 374 | |
| 375 | #ifdef ALTQ |
| 376 | if (altq_input != NULL) { |
| 377 | SOFTNET_LOCK(); |
| 378 | if ((*altq_input)(m, AF_INET6) == 0) { |
| 379 | SOFTNET_UNLOCK(); |
| 380 | /* packet is dropped by traffic conditioner */ |
| 381 | return; |
| 382 | } |
| 383 | SOFTNET_UNLOCK(); |
| 384 | } |
| 385 | #endif |
| 386 | |
| 387 | /* |
| 388 | * Check against address spoofing/corruption. |
| 389 | */ |
| 390 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || |
| 391 | IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { |
| 392 | /* |
| 393 | * XXX: "badscope" is not very suitable for a multicast source. |
| 394 | */ |
| 395 | IP6_STATINC(IP6_STAT_BADSCOPE); |
| 396 | in6_ifstat_inc(rcvif, ifs6_in_addrerr); |
| 397 | goto bad; |
| 398 | } |
| 399 | /* |
| 400 | * The following check is not documented in specs. A malicious |
| 401 | * party may be able to use IPv4 mapped addr to confuse tcp/udp stack |
| 402 | * and bypass security checks (act as if it was from 127.0.0.1 by using |
| 403 | * IPv6 src ::ffff:127.0.0.1). Be cautious. |
| 404 | * |
| 405 | * This check chokes if we are in an SIIT cloud. As none of BSDs |
| 406 | * support IPv4-less kernel compilation, we cannot support SIIT |
| 407 | * environment at all. So, it makes more sense for us to reject any |
| 408 | * malicious packets for non-SIIT environment, than try to do a |
| 409 | * partial support for SIIT environment. |
| 410 | */ |
| 411 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || |
| 412 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { |
| 413 | IP6_STATINC(IP6_STAT_BADSCOPE); |
| 414 | in6_ifstat_inc(rcvif, ifs6_in_addrerr); |
| 415 | goto bad; |
| 416 | } |
| 417 | #if 0 |
| 418 | /* |
| 419 | * Reject packets with IPv4 compatible addresses (auto tunnel). |
| 420 | * |
| 421 | * The code forbids auto tunnel relay case in RFC1933 (the check is |
| 422 | * stronger than RFC1933). We may want to re-enable it if mech-xx |
| 423 | * is revised to forbid relaying case. |
| 424 | */ |
| 425 | if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || |
| 426 | IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { |
| 427 | IP6_STATINC(IP6_STAT_BADSCOPE); |
| 428 | in6_ifstat_inc(rcvif, ifs6_in_addrerr); |
| 429 | goto bad; |
| 430 | } |
| 431 | #endif |
| 432 | |
| 433 | /* |
| 434 | * Disambiguate address scope zones (if there is ambiguity). |
| 435 | * We first make sure that the original source or destination address |
| 436 | * is not in our internal form for scoped addresses. Such addresses |
| 437 | * are not necessarily invalid spec-wise, but we cannot accept them due |
| 438 | * to the usage conflict. |
| 439 | * in6_setscope() then also checks and rejects the cases where src or |
| 440 | * dst are the loopback address and the receiving interface |
| 441 | * is not loopback. |
| 442 | */ |
| 443 | if (__predict_false( |
| 444 | m_makewritable(&m, 0, sizeof(struct ip6_hdr), M_DONTWAIT))) |
| 445 | goto bad; |
| 446 | ip6 = mtod(m, struct ip6_hdr *); |
| 447 | if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) { |
| 448 | IP6_STATINC(IP6_STAT_BADSCOPE); /* XXX */ |
| 449 | goto bad; |
| 450 | } |
| 451 | if (in6_setscope(&ip6->ip6_src, rcvif, NULL) || |
| 452 | in6_setscope(&ip6->ip6_dst, rcvif, NULL)) { |
| 453 | IP6_STATINC(IP6_STAT_BADSCOPE); |
| 454 | goto bad; |
| 455 | } |
| 456 | |
| 457 | /* |
| 458 | * Multicast check |
| 459 | */ |
| 460 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
| 461 | struct in6_multi *in6m = 0; |
| 462 | |
| 463 | in6_ifstat_inc(rcvif, ifs6_in_mcast); |
| 464 | /* |
| 465 | * See if we belong to the destination multicast group on the |
| 466 | * arrival interface. |
| 467 | */ |
| 468 | IN6_LOOKUP_MULTI(ip6->ip6_dst, rcvif, in6m); |
| 469 | if (in6m) |
| 470 | ours = 1; |
| 471 | else if (!ip6_mrouter) { |
| 472 | uint64_t *ip6s = IP6_STAT_GETREF(); |
| 473 | ip6s[IP6_STAT_NOTMEMBER]++; |
| 474 | ip6s[IP6_STAT_CANTFORWARD]++; |
| 475 | IP6_STAT_PUTREF(); |
| 476 | in6_ifstat_inc(rcvif, ifs6_in_discard); |
| 477 | goto bad; |
| 478 | } |
| 479 | deliverifp = rcvif; |
| 480 | goto hbhcheck; |
| 481 | } |
| 482 | |
| 483 | sockaddr_in6_init(&u.dst6, &ip6->ip6_dst, 0, 0, 0); |
| 484 | |
| 485 | /* |
| 486 | * Unicast check |
| 487 | */ |
| 488 | ro = percpu_getref(ip6_forward_rt_percpu); |
| 489 | rt = rtcache_lookup2(ro, &u.dst, 1, &hit); |
| 490 | percpu_putref(ip6_forward_rt_percpu); |
| 491 | if (hit) |
| 492 | IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); |
| 493 | else |
| 494 | IP6_STATINC(IP6_STAT_FORWARD_CACHEMISS); |
| 495 | |
| 496 | #define rt6_getkey(__rt) satocsin6(rt_getkey(__rt)) |
| 497 | |
| 498 | /* |
| 499 | * Accept the packet if the forwarding interface to the destination |
| 500 | * according to the routing table is the loopback interface, |
| 501 | * unless the associated route has a gateway. |
| 502 | * Note that this approach causes to accept a packet if there is a |
| 503 | * route to the loopback interface for the destination of the packet. |
| 504 | * But we think it's even useful in some situations, e.g. when using |
| 505 | * a special daemon which wants to intercept the packet. |
| 506 | */ |
| 507 | if (rt != NULL && |
| 508 | (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST && |
| 509 | #if 0 |
| 510 | /* |
| 511 | * The check below is redundant since the comparison of |
| 512 | * the destination and the key of the rtentry has |
| 513 | * already done through looking up the routing table. |
| 514 | */ |
| 515 | IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &rt6_getkey(rt)->sin6_addr) && |
| 516 | #endif |
| 517 | rt->rt_ifp->if_type == IFT_LOOP) { |
| 518 | struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa; |
| 519 | if (ia6->ia6_flags & IN6_IFF_ANYCAST) |
| 520 | m->m_flags |= M_ANYCAST6; |
| 521 | /* |
| 522 | * packets to a tentative, duplicated, or somehow invalid |
| 523 | * address must not be accepted. |
| 524 | */ |
| 525 | if (!(ia6->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED))) { |
| 526 | /* this address is ready */ |
| 527 | ours = 1; |
| 528 | deliverifp = ia6->ia_ifp; /* correct? */ |
| 529 | goto hbhcheck; |
| 530 | } else { |
| 531 | /* address is not ready, so discard the packet. */ |
| 532 | nd6log(LOG_INFO, "packet to an unready address %s->%s\n" , |
| 533 | ip6_sprintf(&ip6->ip6_src), |
| 534 | ip6_sprintf(&ip6->ip6_dst)); |
| 535 | |
| 536 | goto bad; |
| 537 | } |
| 538 | } |
| 539 | |
| 540 | /* |
| 541 | * FAITH (Firewall Aided Internet Translator) |
| 542 | */ |
| 543 | #if defined(NFAITH) && 0 < NFAITH |
| 544 | if (ip6_keepfaith) { |
| 545 | if (rt != NULL && rt->rt_ifp != NULL && |
| 546 | rt->rt_ifp->if_type == IFT_FAITH) { |
| 547 | /* XXX do we need more sanity checks? */ |
| 548 | ours = 1; |
| 549 | deliverifp = rt->rt_ifp; /* faith */ |
| 550 | goto hbhcheck; |
| 551 | } |
| 552 | } |
| 553 | #endif |
| 554 | |
| 555 | #if 0 |
| 556 | { |
| 557 | /* |
| 558 | * Last resort: check in6_ifaddr for incoming interface. |
| 559 | * The code is here until I update the "goto ours hack" code above |
| 560 | * working right. |
| 561 | */ |
| 562 | struct ifaddr *ifa; |
| 563 | IFADDR_READER_FOREACH(ifa, rcvif) { |
| 564 | if (ifa->ifa_addr->sa_family != AF_INET6) |
| 565 | continue; |
| 566 | if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { |
| 567 | ours = 1; |
| 568 | deliverifp = ifa->ifa_ifp; |
| 569 | goto hbhcheck; |
| 570 | } |
| 571 | } |
| 572 | } |
| 573 | #endif |
| 574 | |
| 575 | /* |
| 576 | * Now there is no reason to process the packet if it's not our own |
| 577 | * and we're not a router. |
| 578 | */ |
| 579 | if (!ip6_forwarding) { |
| 580 | IP6_STATINC(IP6_STAT_CANTFORWARD); |
| 581 | in6_ifstat_inc(rcvif, ifs6_in_discard); |
| 582 | goto bad; |
| 583 | } |
| 584 | |
| 585 | hbhcheck: |
| 586 | /* |
| 587 | * record address information into m_tag, if we don't have one yet. |
| 588 | * note that we are unable to record it, if the address is not listed |
| 589 | * as our interface address (e.g. multicast addresses, addresses |
| 590 | * within FAITH prefixes and such). |
| 591 | */ |
| 592 | if (deliverifp && ip6_getdstifaddr(m) == NULL) { |
| 593 | struct in6_ifaddr *ia6; |
| 594 | int s = pserialize_read_enter(); |
| 595 | |
| 596 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
| 597 | /* Depends on ip6_setdstifaddr never sleep */ |
| 598 | if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) { |
| 599 | /* |
| 600 | * XXX maybe we should drop the packet here, |
| 601 | * as we could not provide enough information |
| 602 | * to the upper layers. |
| 603 | */ |
| 604 | } |
| 605 | pserialize_read_exit(s); |
| 606 | } |
| 607 | |
| 608 | /* |
| 609 | * Process Hop-by-Hop options header if it's contained. |
| 610 | * m may be modified in ip6_hopopts_input(). |
| 611 | * If a JumboPayload option is included, plen will also be modified. |
| 612 | */ |
| 613 | plen = (u_int32_t)ntohs(ip6->ip6_plen); |
| 614 | if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { |
| 615 | struct ip6_hbh *hbh; |
| 616 | |
| 617 | if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { |
| 618 | #if 0 /*touches NULL pointer*/ |
| 619 | in6_ifstat_inc(rcvif, ifs6_in_discard); |
| 620 | #endif |
| 621 | return; /* m have already been freed */ |
| 622 | } |
| 623 | |
| 624 | /* adjust pointer */ |
| 625 | ip6 = mtod(m, struct ip6_hdr *); |
| 626 | |
| 627 | /* |
| 628 | * if the payload length field is 0 and the next header field |
| 629 | * indicates Hop-by-Hop Options header, then a Jumbo Payload |
| 630 | * option MUST be included. |
| 631 | */ |
| 632 | if (ip6->ip6_plen == 0 && plen == 0) { |
| 633 | /* |
| 634 | * Note that if a valid jumbo payload option is |
| 635 | * contained, ip6_hopopts_input() must set a valid |
| 636 | * (non-zero) payload length to the variable plen. |
| 637 | */ |
| 638 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
| 639 | in6_ifstat_inc(rcvif, ifs6_in_discard); |
| 640 | in6_ifstat_inc(rcvif, ifs6_in_hdrerr); |
| 641 | icmp6_error(m, ICMP6_PARAM_PROB, |
| 642 | ICMP6_PARAMPROB_HEADER, |
| 643 | (char *)&ip6->ip6_plen - (char *)ip6); |
| 644 | return; |
| 645 | } |
| 646 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), |
| 647 | sizeof(struct ip6_hbh)); |
| 648 | if (hbh == NULL) { |
| 649 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 650 | return; |
| 651 | } |
| 652 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); |
| 653 | nxt = hbh->ip6h_nxt; |
| 654 | |
| 655 | /* |
| 656 | * accept the packet if a router alert option is included |
| 657 | * and we act as an IPv6 router. |
| 658 | */ |
| 659 | if (rtalert != ~0 && ip6_forwarding) |
| 660 | ours = 1; |
| 661 | } else |
| 662 | nxt = ip6->ip6_nxt; |
| 663 | |
| 664 | /* |
| 665 | * Check that the amount of data in the buffers |
| 666 | * is as at least much as the IPv6 header would have us expect. |
| 667 | * Trim mbufs if longer than we expect. |
| 668 | * Drop packet if shorter than we expect. |
| 669 | */ |
| 670 | if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { |
| 671 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 672 | in6_ifstat_inc(rcvif, ifs6_in_truncated); |
| 673 | goto bad; |
| 674 | } |
| 675 | if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { |
| 676 | if (m->m_len == m->m_pkthdr.len) { |
| 677 | m->m_len = sizeof(struct ip6_hdr) + plen; |
| 678 | m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; |
| 679 | } else |
| 680 | m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); |
| 681 | } |
| 682 | |
| 683 | /* |
| 684 | * Forward if desirable. |
| 685 | */ |
| 686 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
| 687 | /* |
| 688 | * If we are acting as a multicast router, all |
| 689 | * incoming multicast packets are passed to the |
| 690 | * kernel-level multicast forwarding function. |
| 691 | * The packet is returned (relatively) intact; if |
| 692 | * ip6_mforward() returns a non-zero value, the packet |
| 693 | * must be discarded, else it may be accepted below. |
| 694 | */ |
| 695 | if (ip6_mrouter != NULL) { |
| 696 | int error; |
| 697 | |
| 698 | SOFTNET_LOCK(); |
| 699 | error = ip6_mforward(ip6, rcvif, m); |
| 700 | SOFTNET_UNLOCK(); |
| 701 | |
| 702 | if (error != 0) { |
| 703 | IP6_STATINC(IP6_STAT_CANTFORWARD); |
| 704 | goto bad; |
| 705 | } |
| 706 | } |
| 707 | if (!ours) |
| 708 | goto bad; |
| 709 | } else if (!ours) { |
| 710 | ip6_forward(m, srcrt); |
| 711 | return; |
| 712 | } |
| 713 | |
| 714 | ip6 = mtod(m, struct ip6_hdr *); |
| 715 | |
| 716 | /* |
| 717 | * Malicious party may be able to use IPv4 mapped addr to confuse |
| 718 | * tcp/udp stack and bypass security checks (act as if it was from |
| 719 | * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious. |
| 720 | * |
| 721 | * For SIIT end node behavior, you may want to disable the check. |
| 722 | * However, you will become vulnerable to attacks using IPv4 mapped |
| 723 | * source. |
| 724 | */ |
| 725 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || |
| 726 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { |
| 727 | IP6_STATINC(IP6_STAT_BADSCOPE); |
| 728 | in6_ifstat_inc(rcvif, ifs6_in_addrerr); |
| 729 | goto bad; |
| 730 | } |
| 731 | |
| 732 | /* |
| 733 | * Tell launch routine the next header |
| 734 | */ |
| 735 | #ifdef IFA_STATS |
| 736 | if (deliverifp != NULL) { |
| 737 | struct in6_ifaddr *ia6; |
| 738 | int s = pserialize_read_enter(); |
| 739 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
| 740 | if (ia6) |
| 741 | ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; |
| 742 | pserialize_read_exit(s); |
| 743 | } |
| 744 | #endif |
| 745 | IP6_STATINC(IP6_STAT_DELIVERED); |
| 746 | in6_ifstat_inc(deliverifp, ifs6_in_deliver); |
| 747 | nest = 0; |
| 748 | |
| 749 | rh_present = 0; |
| 750 | while (nxt != IPPROTO_DONE) { |
| 751 | if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { |
| 752 | IP6_STATINC(IP6_STAT_TOOMANYHDR); |
| 753 | in6_ifstat_inc(rcvif, ifs6_in_hdrerr); |
| 754 | goto bad; |
| 755 | } |
| 756 | |
| 757 | /* |
| 758 | * protection against faulty packet - there should be |
| 759 | * more sanity checks in header chain processing. |
| 760 | */ |
| 761 | if (m->m_pkthdr.len < off) { |
| 762 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 763 | in6_ifstat_inc(rcvif, ifs6_in_truncated); |
| 764 | goto bad; |
| 765 | } |
| 766 | |
| 767 | if (nxt == IPPROTO_ROUTING) { |
| 768 | if (rh_present++) { |
| 769 | in6_ifstat_inc(rcvif, ifs6_in_hdrerr); |
| 770 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
| 771 | goto bad; |
| 772 | } |
| 773 | } |
| 774 | |
| 775 | #ifdef IPSEC |
| 776 | if (ipsec_used) { |
| 777 | /* |
| 778 | * enforce IPsec policy checking if we are seeing last |
| 779 | * header. note that we do not visit this with |
| 780 | * protocols with pcb layer code - like udp/tcp/raw ip. |
| 781 | */ |
| 782 | if ((inet6sw[ip_protox[nxt]].pr_flags |
| 783 | & PR_LASTHDR) != 0) { |
| 784 | int error; |
| 785 | |
| 786 | SOFTNET_LOCK(); |
| 787 | error = ipsec6_input(m); |
| 788 | SOFTNET_UNLOCK(); |
| 789 | if (error) |
| 790 | goto bad; |
| 791 | } |
| 792 | } |
| 793 | #endif /* IPSEC */ |
| 794 | |
| 795 | SOFTNET_LOCK(); |
| 796 | nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); |
| 797 | SOFTNET_UNLOCK(); |
| 798 | } |
| 799 | return; |
| 800 | bad: |
| 801 | m_freem(m); |
| 802 | } |
| 803 | |
| 804 | /* |
| 805 | * set/grab in6_ifaddr correspond to IPv6 destination address. |
| 806 | */ |
| 807 | static struct m_tag * |
| 808 | ip6_setdstifaddr(struct mbuf *m, const struct in6_ifaddr *ia) |
| 809 | { |
| 810 | struct m_tag *mtag; |
| 811 | struct ip6aux *ip6a; |
| 812 | |
| 813 | mtag = ip6_addaux(m); |
| 814 | if (mtag == NULL) |
| 815 | return NULL; |
| 816 | |
| 817 | ip6a = (struct ip6aux *)(mtag + 1); |
| 818 | if (in6_setscope(&ip6a->ip6a_src, ia->ia_ifp, &ip6a->ip6a_scope_id)) { |
| 819 | IP6_STATINC(IP6_STAT_BADSCOPE); |
| 820 | return NULL; |
| 821 | } |
| 822 | |
| 823 | ip6a->ip6a_src = ia->ia_addr.sin6_addr; |
| 824 | ip6a->ip6a_flags = ia->ia6_flags; |
| 825 | return mtag; |
| 826 | } |
| 827 | |
| 828 | const struct ip6aux * |
| 829 | ip6_getdstifaddr(struct mbuf *m) |
| 830 | { |
| 831 | struct m_tag *mtag; |
| 832 | |
| 833 | mtag = ip6_findaux(m); |
| 834 | if (mtag != NULL) |
| 835 | return (struct ip6aux *)(mtag + 1); |
| 836 | else |
| 837 | return NULL; |
| 838 | } |
| 839 | |
| 840 | /* |
| 841 | * Hop-by-Hop options header processing. If a valid jumbo payload option is |
| 842 | * included, the real payload length will be stored in plenp. |
| 843 | * |
| 844 | * rtalertp - XXX: should be stored more smart way |
| 845 | */ |
| 846 | int |
| 847 | ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp, |
| 848 | struct mbuf **mp, int *offp) |
| 849 | { |
| 850 | struct mbuf *m = *mp; |
| 851 | int off = *offp, hbhlen; |
| 852 | struct ip6_hbh *hbh; |
| 853 | |
| 854 | /* validation of the length of the header */ |
| 855 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, |
| 856 | sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); |
| 857 | if (hbh == NULL) { |
| 858 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 859 | return -1; |
| 860 | } |
| 861 | hbhlen = (hbh->ip6h_len + 1) << 3; |
| 862 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), |
| 863 | hbhlen); |
| 864 | if (hbh == NULL) { |
| 865 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 866 | return -1; |
| 867 | } |
| 868 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); |
| 869 | off += hbhlen; |
| 870 | hbhlen -= sizeof(struct ip6_hbh); |
| 871 | |
| 872 | if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), |
| 873 | hbhlen, rtalertp, plenp) < 0) |
| 874 | return (-1); |
| 875 | |
| 876 | *offp = off; |
| 877 | *mp = m; |
| 878 | return (0); |
| 879 | } |
| 880 | |
| 881 | /* |
| 882 | * Search header for all Hop-by-hop options and process each option. |
| 883 | * This function is separate from ip6_hopopts_input() in order to |
| 884 | * handle a case where the sending node itself process its hop-by-hop |
| 885 | * options header. In such a case, the function is called from ip6_output(). |
| 886 | * |
| 887 | * The function assumes that hbh header is located right after the IPv6 header |
| 888 | * (RFC2460 p7), opthead is pointer into data content in m, and opthead to |
| 889 | * opthead + hbhlen is located in continuous memory region. |
| 890 | */ |
| 891 | static int |
| 892 | ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen, |
| 893 | u_int32_t *rtalertp, u_int32_t *plenp) |
| 894 | { |
| 895 | struct ip6_hdr *ip6; |
| 896 | int optlen = 0; |
| 897 | u_int8_t *opt = opthead; |
| 898 | u_int16_t rtalert_val; |
| 899 | u_int32_t jumboplen; |
| 900 | const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); |
| 901 | |
| 902 | for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { |
| 903 | switch (*opt) { |
| 904 | case IP6OPT_PAD1: |
| 905 | optlen = 1; |
| 906 | break; |
| 907 | case IP6OPT_PADN: |
| 908 | if (hbhlen < IP6OPT_MINLEN) { |
| 909 | IP6_STATINC(IP6_STAT_TOOSMALL); |
| 910 | goto bad; |
| 911 | } |
| 912 | optlen = *(opt + 1) + 2; |
| 913 | break; |
| 914 | case IP6OPT_RTALERT: |
| 915 | /* XXX may need check for alignment */ |
| 916 | if (hbhlen < IP6OPT_RTALERT_LEN) { |
| 917 | IP6_STATINC(IP6_STAT_TOOSMALL); |
| 918 | goto bad; |
| 919 | } |
| 920 | if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { |
| 921 | /* XXX stat */ |
| 922 | icmp6_error(m, ICMP6_PARAM_PROB, |
| 923 | ICMP6_PARAMPROB_HEADER, |
| 924 | erroff + opt + 1 - opthead); |
| 925 | return (-1); |
| 926 | } |
| 927 | optlen = IP6OPT_RTALERT_LEN; |
| 928 | memcpy((void *)&rtalert_val, (void *)(opt + 2), 2); |
| 929 | *rtalertp = ntohs(rtalert_val); |
| 930 | break; |
| 931 | case IP6OPT_JUMBO: |
| 932 | /* XXX may need check for alignment */ |
| 933 | if (hbhlen < IP6OPT_JUMBO_LEN) { |
| 934 | IP6_STATINC(IP6_STAT_TOOSMALL); |
| 935 | goto bad; |
| 936 | } |
| 937 | if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { |
| 938 | /* XXX stat */ |
| 939 | icmp6_error(m, ICMP6_PARAM_PROB, |
| 940 | ICMP6_PARAMPROB_HEADER, |
| 941 | erroff + opt + 1 - opthead); |
| 942 | return (-1); |
| 943 | } |
| 944 | optlen = IP6OPT_JUMBO_LEN; |
| 945 | |
| 946 | /* |
| 947 | * IPv6 packets that have non 0 payload length |
| 948 | * must not contain a jumbo payload option. |
| 949 | */ |
| 950 | ip6 = mtod(m, struct ip6_hdr *); |
| 951 | if (ip6->ip6_plen) { |
| 952 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
| 953 | icmp6_error(m, ICMP6_PARAM_PROB, |
| 954 | ICMP6_PARAMPROB_HEADER, |
| 955 | erroff + opt - opthead); |
| 956 | return (-1); |
| 957 | } |
| 958 | |
| 959 | /* |
| 960 | * We may see jumbolen in unaligned location, so |
| 961 | * we'd need to perform bcopy(). |
| 962 | */ |
| 963 | memcpy(&jumboplen, opt + 2, sizeof(jumboplen)); |
| 964 | jumboplen = (u_int32_t)htonl(jumboplen); |
| 965 | |
| 966 | #if 1 |
| 967 | /* |
| 968 | * if there are multiple jumbo payload options, |
| 969 | * *plenp will be non-zero and the packet will be |
| 970 | * rejected. |
| 971 | * the behavior may need some debate in ipngwg - |
| 972 | * multiple options does not make sense, however, |
| 973 | * there's no explicit mention in specification. |
| 974 | */ |
| 975 | if (*plenp != 0) { |
| 976 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
| 977 | icmp6_error(m, ICMP6_PARAM_PROB, |
| 978 | ICMP6_PARAMPROB_HEADER, |
| 979 | erroff + opt + 2 - opthead); |
| 980 | return (-1); |
| 981 | } |
| 982 | #endif |
| 983 | |
| 984 | /* |
| 985 | * jumbo payload length must be larger than 65535. |
| 986 | */ |
| 987 | if (jumboplen <= IPV6_MAXPACKET) { |
| 988 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
| 989 | icmp6_error(m, ICMP6_PARAM_PROB, |
| 990 | ICMP6_PARAMPROB_HEADER, |
| 991 | erroff + opt + 2 - opthead); |
| 992 | return (-1); |
| 993 | } |
| 994 | *plenp = jumboplen; |
| 995 | |
| 996 | break; |
| 997 | default: /* unknown option */ |
| 998 | if (hbhlen < IP6OPT_MINLEN) { |
| 999 | IP6_STATINC(IP6_STAT_TOOSMALL); |
| 1000 | goto bad; |
| 1001 | } |
| 1002 | optlen = ip6_unknown_opt(opt, m, |
| 1003 | erroff + opt - opthead); |
| 1004 | if (optlen == -1) |
| 1005 | return (-1); |
| 1006 | optlen += 2; |
| 1007 | break; |
| 1008 | } |
| 1009 | } |
| 1010 | |
| 1011 | return (0); |
| 1012 | |
| 1013 | bad: |
| 1014 | m_freem(m); |
| 1015 | return (-1); |
| 1016 | } |
| 1017 | |
| 1018 | /* |
| 1019 | * Unknown option processing. |
| 1020 | * The third argument `off' is the offset from the IPv6 header to the option, |
| 1021 | * which is necessary if the IPv6 header the and option header and IPv6 header |
| 1022 | * is not continuous in order to return an ICMPv6 error. |
| 1023 | */ |
| 1024 | int |
| 1025 | ip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off) |
| 1026 | { |
| 1027 | struct ip6_hdr *ip6; |
| 1028 | |
| 1029 | switch (IP6OPT_TYPE(*optp)) { |
| 1030 | case IP6OPT_TYPE_SKIP: /* ignore the option */ |
| 1031 | return ((int)*(optp + 1)); |
| 1032 | case IP6OPT_TYPE_DISCARD: /* silently discard */ |
| 1033 | m_freem(m); |
| 1034 | return (-1); |
| 1035 | case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ |
| 1036 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
| 1037 | icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); |
| 1038 | return (-1); |
| 1039 | case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ |
| 1040 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
| 1041 | ip6 = mtod(m, struct ip6_hdr *); |
| 1042 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || |
| 1043 | (m->m_flags & (M_BCAST|M_MCAST))) |
| 1044 | m_freem(m); |
| 1045 | else |
| 1046 | icmp6_error(m, ICMP6_PARAM_PROB, |
| 1047 | ICMP6_PARAMPROB_OPTION, off); |
| 1048 | return (-1); |
| 1049 | } |
| 1050 | |
| 1051 | m_freem(m); /* XXX: NOTREACHED */ |
| 1052 | return (-1); |
| 1053 | } |
| 1054 | |
| 1055 | /* |
| 1056 | * Create the "control" list for this pcb. |
| 1057 | * |
| 1058 | * The routine will be called from upper layer handlers like tcp6_input(). |
| 1059 | * Thus the routine assumes that the caller (tcp6_input) have already |
| 1060 | * called IP6_EXTHDR_CHECK() and all the extension headers are located in the |
| 1061 | * very first mbuf on the mbuf chain. |
| 1062 | * We may want to add some infinite loop prevention or sanity checks for safety. |
| 1063 | * (This applies only when you are using KAME mbuf chain restriction, i.e. |
| 1064 | * you are using IP6_EXTHDR_CHECK() not m_pulldown()) |
| 1065 | */ |
| 1066 | void |
| 1067 | ip6_savecontrol(struct in6pcb *in6p, struct mbuf **mp, |
| 1068 | struct ip6_hdr *ip6, struct mbuf *m) |
| 1069 | { |
| 1070 | #ifdef RFC2292 |
| 1071 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) |
| 1072 | #else |
| 1073 | #define IS2292(x, y) (y) |
| 1074 | #endif |
| 1075 | |
| 1076 | if (in6p->in6p_socket->so_options & SO_TIMESTAMP |
| 1077 | #ifdef SO_OTIMESTAMP |
| 1078 | || in6p->in6p_socket->so_options & SO_OTIMESTAMP |
| 1079 | #endif |
| 1080 | ) { |
| 1081 | struct timeval tv; |
| 1082 | |
| 1083 | microtime(&tv); |
| 1084 | #ifdef SO_OTIMESTAMP |
| 1085 | if (in6p->in6p_socket->so_options & SO_OTIMESTAMP) { |
| 1086 | struct timeval50 tv50; |
| 1087 | timeval_to_timeval50(&tv, &tv50); |
| 1088 | *mp = sbcreatecontrol((void *) &tv50, sizeof(tv50), |
| 1089 | SCM_OTIMESTAMP, SOL_SOCKET); |
| 1090 | } else |
| 1091 | #endif |
| 1092 | *mp = sbcreatecontrol((void *) &tv, sizeof(tv), |
| 1093 | SCM_TIMESTAMP, SOL_SOCKET); |
| 1094 | if (*mp) |
| 1095 | mp = &(*mp)->m_next; |
| 1096 | } |
| 1097 | |
| 1098 | /* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */ |
| 1099 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) |
| 1100 | return; |
| 1101 | |
| 1102 | /* RFC 2292 sec. 5 */ |
| 1103 | if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) { |
| 1104 | struct in6_pktinfo pi6; |
| 1105 | |
| 1106 | memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr)); |
| 1107 | in6_clearscope(&pi6.ipi6_addr); /* XXX */ |
| 1108 | pi6.ipi6_ifindex = m->m_pkthdr.rcvif_index; |
| 1109 | *mp = sbcreatecontrol((void *) &pi6, |
| 1110 | sizeof(struct in6_pktinfo), |
| 1111 | IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6); |
| 1112 | if (*mp) |
| 1113 | mp = &(*mp)->m_next; |
| 1114 | } |
| 1115 | |
| 1116 | if (in6p->in6p_flags & IN6P_HOPLIMIT) { |
| 1117 | int hlim = ip6->ip6_hlim & 0xff; |
| 1118 | |
| 1119 | *mp = sbcreatecontrol((void *) &hlim, sizeof(int), |
| 1120 | IS2292(IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), IPPROTO_IPV6); |
| 1121 | if (*mp) |
| 1122 | mp = &(*mp)->m_next; |
| 1123 | } |
| 1124 | |
| 1125 | if ((in6p->in6p_flags & IN6P_TCLASS) != 0) { |
| 1126 | u_int32_t flowinfo; |
| 1127 | int tclass; |
| 1128 | |
| 1129 | flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); |
| 1130 | flowinfo >>= 20; |
| 1131 | |
| 1132 | tclass = flowinfo & 0xff; |
| 1133 | *mp = sbcreatecontrol((void *)&tclass, sizeof(tclass), |
| 1134 | IPV6_TCLASS, IPPROTO_IPV6); |
| 1135 | |
| 1136 | if (*mp) |
| 1137 | mp = &(*mp)->m_next; |
| 1138 | } |
| 1139 | |
| 1140 | /* |
| 1141 | * IPV6_HOPOPTS socket option. Recall that we required super-user |
| 1142 | * privilege for the option (see ip6_ctloutput), but it might be too |
| 1143 | * strict, since there might be some hop-by-hop options which can be |
| 1144 | * returned to normal user. |
| 1145 | * See also RFC3542 section 8 (or RFC2292 section 6). |
| 1146 | */ |
| 1147 | if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) { |
| 1148 | /* |
| 1149 | * Check if a hop-by-hop options header is contatined in the |
| 1150 | * received packet, and if so, store the options as ancillary |
| 1151 | * data. Note that a hop-by-hop options header must be |
| 1152 | * just after the IPv6 header, which fact is assured through |
| 1153 | * the IPv6 input processing. |
| 1154 | */ |
| 1155 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); |
| 1156 | if (xip6->ip6_nxt == IPPROTO_HOPOPTS) { |
| 1157 | struct ip6_hbh *hbh; |
| 1158 | int hbhlen; |
| 1159 | struct mbuf *ext; |
| 1160 | |
| 1161 | ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr), |
| 1162 | xip6->ip6_nxt); |
| 1163 | if (ext == NULL) { |
| 1164 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 1165 | return; |
| 1166 | } |
| 1167 | hbh = mtod(ext, struct ip6_hbh *); |
| 1168 | hbhlen = (hbh->ip6h_len + 1) << 3; |
| 1169 | if (hbhlen != ext->m_len) { |
| 1170 | m_freem(ext); |
| 1171 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 1172 | return; |
| 1173 | } |
| 1174 | |
| 1175 | /* |
| 1176 | * XXX: We copy whole the header even if a jumbo |
| 1177 | * payload option is included, which option is to |
| 1178 | * be removed before returning in the RFC 2292. |
| 1179 | * Note: this constraint is removed in RFC3542. |
| 1180 | */ |
| 1181 | *mp = sbcreatecontrol((void *)hbh, hbhlen, |
| 1182 | IS2292(IPV6_2292HOPOPTS, IPV6_HOPOPTS), |
| 1183 | IPPROTO_IPV6); |
| 1184 | if (*mp) |
| 1185 | mp = &(*mp)->m_next; |
| 1186 | m_freem(ext); |
| 1187 | } |
| 1188 | } |
| 1189 | |
| 1190 | /* IPV6_DSTOPTS and IPV6_RTHDR socket options */ |
| 1191 | if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) { |
| 1192 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); |
| 1193 | int nxt = xip6->ip6_nxt, off = sizeof(struct ip6_hdr); |
| 1194 | |
| 1195 | /* |
| 1196 | * Search for destination options headers or routing |
| 1197 | * header(s) through the header chain, and stores each |
| 1198 | * header as ancillary data. |
| 1199 | * Note that the order of the headers remains in |
| 1200 | * the chain of ancillary data. |
| 1201 | */ |
| 1202 | for (;;) { /* is explicit loop prevention necessary? */ |
| 1203 | struct ip6_ext *ip6e = NULL; |
| 1204 | int elen; |
| 1205 | struct mbuf *ext = NULL; |
| 1206 | |
| 1207 | /* |
| 1208 | * if it is not an extension header, don't try to |
| 1209 | * pull it from the chain. |
| 1210 | */ |
| 1211 | switch (nxt) { |
| 1212 | case IPPROTO_DSTOPTS: |
| 1213 | case IPPROTO_ROUTING: |
| 1214 | case IPPROTO_HOPOPTS: |
| 1215 | case IPPROTO_AH: /* is it possible? */ |
| 1216 | break; |
| 1217 | default: |
| 1218 | goto loopend; |
| 1219 | } |
| 1220 | |
| 1221 | ext = ip6_pullexthdr(m, off, nxt); |
| 1222 | if (ext == NULL) { |
| 1223 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 1224 | return; |
| 1225 | } |
| 1226 | ip6e = mtod(ext, struct ip6_ext *); |
| 1227 | if (nxt == IPPROTO_AH) |
| 1228 | elen = (ip6e->ip6e_len + 2) << 2; |
| 1229 | else |
| 1230 | elen = (ip6e->ip6e_len + 1) << 3; |
| 1231 | if (elen != ext->m_len) { |
| 1232 | m_freem(ext); |
| 1233 | IP6_STATINC(IP6_STAT_TOOSHORT); |
| 1234 | return; |
| 1235 | } |
| 1236 | KASSERT(IP6_HDR_ALIGNED_P(ip6e)); |
| 1237 | |
| 1238 | switch (nxt) { |
| 1239 | case IPPROTO_DSTOPTS: |
| 1240 | if (!(in6p->in6p_flags & IN6P_DSTOPTS)) |
| 1241 | break; |
| 1242 | |
| 1243 | *mp = sbcreatecontrol((void *)ip6e, elen, |
| 1244 | IS2292(IPV6_2292DSTOPTS, IPV6_DSTOPTS), |
| 1245 | IPPROTO_IPV6); |
| 1246 | if (*mp) |
| 1247 | mp = &(*mp)->m_next; |
| 1248 | break; |
| 1249 | |
| 1250 | case IPPROTO_ROUTING: |
| 1251 | if (!(in6p->in6p_flags & IN6P_RTHDR)) |
| 1252 | break; |
| 1253 | |
| 1254 | *mp = sbcreatecontrol((void *)ip6e, elen, |
| 1255 | IS2292(IPV6_2292RTHDR, IPV6_RTHDR), |
| 1256 | IPPROTO_IPV6); |
| 1257 | if (*mp) |
| 1258 | mp = &(*mp)->m_next; |
| 1259 | break; |
| 1260 | |
| 1261 | case IPPROTO_HOPOPTS: |
| 1262 | case IPPROTO_AH: /* is it possible? */ |
| 1263 | break; |
| 1264 | |
| 1265 | default: |
| 1266 | /* |
| 1267 | * other cases have been filtered in the above. |
| 1268 | * none will visit this case. here we supply |
| 1269 | * the code just in case (nxt overwritten or |
| 1270 | * other cases). |
| 1271 | */ |
| 1272 | m_freem(ext); |
| 1273 | goto loopend; |
| 1274 | |
| 1275 | } |
| 1276 | |
| 1277 | /* proceed with the next header. */ |
| 1278 | off += elen; |
| 1279 | nxt = ip6e->ip6e_nxt; |
| 1280 | ip6e = NULL; |
| 1281 | m_freem(ext); |
| 1282 | ext = NULL; |
| 1283 | } |
| 1284 | loopend: |
| 1285 | ; |
| 1286 | } |
| 1287 | } |
| 1288 | #undef IS2292 |
| 1289 | |
| 1290 | |
| 1291 | void |
| 1292 | ip6_notify_pmtu(struct in6pcb *in6p, const struct sockaddr_in6 *dst, |
| 1293 | uint32_t *mtu) |
| 1294 | { |
| 1295 | struct socket *so; |
| 1296 | struct mbuf *m_mtu; |
| 1297 | struct ip6_mtuinfo mtuctl; |
| 1298 | |
| 1299 | so = in6p->in6p_socket; |
| 1300 | |
| 1301 | if (mtu == NULL) |
| 1302 | return; |
| 1303 | |
| 1304 | #ifdef DIAGNOSTIC |
| 1305 | if (so == NULL) /* I believe this is impossible */ |
| 1306 | panic("ip6_notify_pmtu: socket is NULL" ); |
| 1307 | #endif |
| 1308 | |
| 1309 | memset(&mtuctl, 0, sizeof(mtuctl)); /* zero-clear for safety */ |
| 1310 | mtuctl.ip6m_mtu = *mtu; |
| 1311 | mtuctl.ip6m_addr = *dst; |
| 1312 | if (sa6_recoverscope(&mtuctl.ip6m_addr)) |
| 1313 | return; |
| 1314 | |
| 1315 | if ((m_mtu = sbcreatecontrol((void *)&mtuctl, sizeof(mtuctl), |
| 1316 | IPV6_PATHMTU, IPPROTO_IPV6)) == NULL) |
| 1317 | return; |
| 1318 | |
| 1319 | if (sbappendaddr(&so->so_rcv, (const struct sockaddr *)dst, NULL, m_mtu) |
| 1320 | == 0) { |
| 1321 | m_freem(m_mtu); |
| 1322 | /* XXX: should count statistics */ |
| 1323 | } else |
| 1324 | sorwakeup(so); |
| 1325 | |
| 1326 | return; |
| 1327 | } |
| 1328 | |
| 1329 | /* |
| 1330 | * pull single extension header from mbuf chain. returns single mbuf that |
| 1331 | * contains the result, or NULL on error. |
| 1332 | */ |
| 1333 | static struct mbuf * |
| 1334 | ip6_pullexthdr(struct mbuf *m, size_t off, int nxt) |
| 1335 | { |
| 1336 | struct ip6_ext ip6e; |
| 1337 | size_t elen; |
| 1338 | struct mbuf *n; |
| 1339 | |
| 1340 | #ifdef DIAGNOSTIC |
| 1341 | switch (nxt) { |
| 1342 | case IPPROTO_DSTOPTS: |
| 1343 | case IPPROTO_ROUTING: |
| 1344 | case IPPROTO_HOPOPTS: |
| 1345 | case IPPROTO_AH: /* is it possible? */ |
| 1346 | break; |
| 1347 | default: |
| 1348 | printf("ip6_pullexthdr: invalid nxt=%d\n" , nxt); |
| 1349 | } |
| 1350 | #endif |
| 1351 | |
| 1352 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); |
| 1353 | if (nxt == IPPROTO_AH) |
| 1354 | elen = (ip6e.ip6e_len + 2) << 2; |
| 1355 | else |
| 1356 | elen = (ip6e.ip6e_len + 1) << 3; |
| 1357 | |
| 1358 | MGET(n, M_DONTWAIT, MT_DATA); |
| 1359 | if (n && elen >= MLEN) { |
| 1360 | MCLGET(n, M_DONTWAIT); |
| 1361 | if ((n->m_flags & M_EXT) == 0) { |
| 1362 | m_free(n); |
| 1363 | n = NULL; |
| 1364 | } |
| 1365 | } |
| 1366 | if (!n) |
| 1367 | return NULL; |
| 1368 | |
| 1369 | n->m_len = 0; |
| 1370 | if (elen >= M_TRAILINGSPACE(n)) { |
| 1371 | m_free(n); |
| 1372 | return NULL; |
| 1373 | } |
| 1374 | |
| 1375 | m_copydata(m, off, elen, mtod(n, void *)); |
| 1376 | n->m_len = elen; |
| 1377 | return n; |
| 1378 | } |
| 1379 | |
| 1380 | /* |
| 1381 | * Get pointer to the previous header followed by the header |
| 1382 | * currently processed. |
| 1383 | * XXX: This function supposes that |
| 1384 | * M includes all headers, |
| 1385 | * the next header field and the header length field of each header |
| 1386 | * are valid, and |
| 1387 | * the sum of each header length equals to OFF. |
| 1388 | * Because of these assumptions, this function must be called very |
| 1389 | * carefully. Moreover, it will not be used in the near future when |
| 1390 | * we develop `neater' mechanism to process extension headers. |
| 1391 | */ |
| 1392 | u_int8_t * |
| 1393 | ip6_get_prevhdr(struct mbuf *m, int off) |
| 1394 | { |
| 1395 | struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); |
| 1396 | |
| 1397 | if (off == sizeof(struct ip6_hdr)) |
| 1398 | return (&ip6->ip6_nxt); |
| 1399 | else { |
| 1400 | int len, nxt; |
| 1401 | struct ip6_ext *ip6e = NULL; |
| 1402 | |
| 1403 | nxt = ip6->ip6_nxt; |
| 1404 | len = sizeof(struct ip6_hdr); |
| 1405 | while (len < off) { |
| 1406 | ip6e = (struct ip6_ext *)(mtod(m, char *) + len); |
| 1407 | |
| 1408 | switch (nxt) { |
| 1409 | case IPPROTO_FRAGMENT: |
| 1410 | len += sizeof(struct ip6_frag); |
| 1411 | break; |
| 1412 | case IPPROTO_AH: |
| 1413 | len += (ip6e->ip6e_len + 2) << 2; |
| 1414 | break; |
| 1415 | default: |
| 1416 | len += (ip6e->ip6e_len + 1) << 3; |
| 1417 | break; |
| 1418 | } |
| 1419 | nxt = ip6e->ip6e_nxt; |
| 1420 | } |
| 1421 | if (ip6e) |
| 1422 | return (&ip6e->ip6e_nxt); |
| 1423 | else |
| 1424 | return NULL; |
| 1425 | } |
| 1426 | } |
| 1427 | |
| 1428 | /* |
| 1429 | * get next header offset. m will be retained. |
| 1430 | */ |
| 1431 | int |
| 1432 | ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp) |
| 1433 | { |
| 1434 | struct ip6_hdr ip6; |
| 1435 | struct ip6_ext ip6e; |
| 1436 | struct ip6_frag fh; |
| 1437 | |
| 1438 | /* just in case */ |
| 1439 | if (m == NULL) |
| 1440 | panic("ip6_nexthdr: m == NULL" ); |
| 1441 | if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off) |
| 1442 | return -1; |
| 1443 | |
| 1444 | switch (proto) { |
| 1445 | case IPPROTO_IPV6: |
| 1446 | /* do not chase beyond intermediate IPv6 headers */ |
| 1447 | if (off != 0) |
| 1448 | return -1; |
| 1449 | if (m->m_pkthdr.len < off + sizeof(ip6)) |
| 1450 | return -1; |
| 1451 | m_copydata(m, off, sizeof(ip6), (void *)&ip6); |
| 1452 | if (nxtp) |
| 1453 | *nxtp = ip6.ip6_nxt; |
| 1454 | off += sizeof(ip6); |
| 1455 | return off; |
| 1456 | |
| 1457 | case IPPROTO_FRAGMENT: |
| 1458 | /* |
| 1459 | * terminate parsing if it is not the first fragment, |
| 1460 | * it does not make sense to parse through it. |
| 1461 | */ |
| 1462 | if (m->m_pkthdr.len < off + sizeof(fh)) |
| 1463 | return -1; |
| 1464 | m_copydata(m, off, sizeof(fh), (void *)&fh); |
| 1465 | if ((fh.ip6f_offlg & IP6F_OFF_MASK) != 0) |
| 1466 | return -1; |
| 1467 | if (nxtp) |
| 1468 | *nxtp = fh.ip6f_nxt; |
| 1469 | off += sizeof(struct ip6_frag); |
| 1470 | return off; |
| 1471 | |
| 1472 | case IPPROTO_AH: |
| 1473 | if (m->m_pkthdr.len < off + sizeof(ip6e)) |
| 1474 | return -1; |
| 1475 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); |
| 1476 | if (nxtp) |
| 1477 | *nxtp = ip6e.ip6e_nxt; |
| 1478 | off += (ip6e.ip6e_len + 2) << 2; |
| 1479 | if (m->m_pkthdr.len < off) |
| 1480 | return -1; |
| 1481 | return off; |
| 1482 | |
| 1483 | case IPPROTO_HOPOPTS: |
| 1484 | case IPPROTO_ROUTING: |
| 1485 | case IPPROTO_DSTOPTS: |
| 1486 | if (m->m_pkthdr.len < off + sizeof(ip6e)) |
| 1487 | return -1; |
| 1488 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); |
| 1489 | if (nxtp) |
| 1490 | *nxtp = ip6e.ip6e_nxt; |
| 1491 | off += (ip6e.ip6e_len + 1) << 3; |
| 1492 | if (m->m_pkthdr.len < off) |
| 1493 | return -1; |
| 1494 | return off; |
| 1495 | |
| 1496 | case IPPROTO_NONE: |
| 1497 | case IPPROTO_ESP: |
| 1498 | case IPPROTO_IPCOMP: |
| 1499 | /* give up */ |
| 1500 | return -1; |
| 1501 | |
| 1502 | default: |
| 1503 | return -1; |
| 1504 | } |
| 1505 | } |
| 1506 | |
| 1507 | /* |
| 1508 | * get offset for the last header in the chain. m will be kept untainted. |
| 1509 | */ |
| 1510 | int |
| 1511 | ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp) |
| 1512 | { |
| 1513 | int newoff; |
| 1514 | int nxt; |
| 1515 | |
| 1516 | if (!nxtp) { |
| 1517 | nxt = -1; |
| 1518 | nxtp = &nxt; |
| 1519 | } |
| 1520 | for (;;) { |
| 1521 | newoff = ip6_nexthdr(m, off, proto, nxtp); |
| 1522 | if (newoff < 0) |
| 1523 | return off; |
| 1524 | else if (newoff < off) |
| 1525 | return -1; /* invalid */ |
| 1526 | else if (newoff == off) |
| 1527 | return newoff; |
| 1528 | |
| 1529 | off = newoff; |
| 1530 | proto = *nxtp; |
| 1531 | } |
| 1532 | } |
| 1533 | |
| 1534 | struct m_tag * |
| 1535 | ip6_addaux(struct mbuf *m) |
| 1536 | { |
| 1537 | struct m_tag *mtag; |
| 1538 | |
| 1539 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); |
| 1540 | if (!mtag) { |
| 1541 | mtag = m_tag_get(PACKET_TAG_INET6, sizeof(struct ip6aux), |
| 1542 | M_NOWAIT); |
| 1543 | if (mtag) { |
| 1544 | m_tag_prepend(m, mtag); |
| 1545 | memset(mtag + 1, 0, sizeof(struct ip6aux)); |
| 1546 | } |
| 1547 | } |
| 1548 | return mtag; |
| 1549 | } |
| 1550 | |
| 1551 | struct m_tag * |
| 1552 | ip6_findaux(struct mbuf *m) |
| 1553 | { |
| 1554 | struct m_tag *mtag; |
| 1555 | |
| 1556 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); |
| 1557 | return mtag; |
| 1558 | } |
| 1559 | |
| 1560 | void |
| 1561 | ip6_delaux(struct mbuf *m) |
| 1562 | { |
| 1563 | struct m_tag *mtag; |
| 1564 | |
| 1565 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); |
| 1566 | if (mtag) |
| 1567 | m_tag_delete(m, mtag); |
| 1568 | } |
| 1569 | |
| 1570 | /* |
| 1571 | * System control for IP6 |
| 1572 | */ |
| 1573 | |
| 1574 | const u_char inet6ctlerrmap[PRC_NCMDS] = { |
| 1575 | 0, 0, 0, 0, |
| 1576 | 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, |
| 1577 | EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, |
| 1578 | EMSGSIZE, EHOSTUNREACH, 0, 0, |
| 1579 | 0, 0, 0, 0, |
| 1580 | ENOPROTOOPT |
| 1581 | }; |
| 1582 | |
| 1583 | extern int sysctl_net_inet6_addrctlpolicy(SYSCTLFN_ARGS); |
| 1584 | |
| 1585 | static int |
| 1586 | sysctl_net_inet6_ip6_stats(SYSCTLFN_ARGS) |
| 1587 | { |
| 1588 | |
| 1589 | return (NETSTAT_SYSCTL(ip6stat_percpu, IP6_NSTATS)); |
| 1590 | } |
| 1591 | |
| 1592 | static void |
| 1593 | sysctl_net_inet6_ip6_setup(struct sysctllog **clog) |
| 1594 | { |
| 1595 | #ifdef RFC2292 |
| 1596 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) |
| 1597 | #else |
| 1598 | #define IS2292(x, y) (y) |
| 1599 | #endif |
| 1600 | |
| 1601 | sysctl_createv(clog, 0, NULL, NULL, |
| 1602 | CTLFLAG_PERMANENT, |
| 1603 | CTLTYPE_NODE, "inet6" , |
| 1604 | SYSCTL_DESCR("PF_INET6 related settings" ), |
| 1605 | NULL, 0, NULL, 0, |
| 1606 | CTL_NET, PF_INET6, CTL_EOL); |
| 1607 | sysctl_createv(clog, 0, NULL, NULL, |
| 1608 | CTLFLAG_PERMANENT, |
| 1609 | CTLTYPE_NODE, "ip6" , |
| 1610 | SYSCTL_DESCR("IPv6 related settings" ), |
| 1611 | NULL, 0, NULL, 0, |
| 1612 | CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_EOL); |
| 1613 | |
| 1614 | sysctl_createv(clog, 0, NULL, NULL, |
| 1615 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1616 | CTLTYPE_INT, "forwarding" , |
| 1617 | SYSCTL_DESCR("Enable forwarding of INET6 datagrams" ), |
| 1618 | NULL, 0, &ip6_forwarding, 0, |
| 1619 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1620 | IPV6CTL_FORWARDING, CTL_EOL); |
| 1621 | sysctl_createv(clog, 0, NULL, NULL, |
| 1622 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1623 | CTLTYPE_INT, "redirect" , |
| 1624 | SYSCTL_DESCR("Enable sending of ICMPv6 redirect messages" ), |
| 1625 | NULL, 0, &ip6_sendredirects, 0, |
| 1626 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1627 | IPV6CTL_SENDREDIRECTS, CTL_EOL); |
| 1628 | sysctl_createv(clog, 0, NULL, NULL, |
| 1629 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1630 | CTLTYPE_INT, "hlim" , |
| 1631 | SYSCTL_DESCR("Hop limit for an INET6 datagram" ), |
| 1632 | NULL, 0, &ip6_defhlim, 0, |
| 1633 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1634 | IPV6CTL_DEFHLIM, CTL_EOL); |
| 1635 | #ifdef notyet |
| 1636 | sysctl_createv(clog, 0, NULL, NULL, |
| 1637 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1638 | CTLTYPE_INT, "mtu" , NULL, |
| 1639 | NULL, 0, &, 0, |
| 1640 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1641 | IPV6CTL_DEFMTU, CTL_EOL); |
| 1642 | #endif |
| 1643 | #ifdef __no_idea__ |
| 1644 | sysctl_createv(clog, 0, NULL, NULL, |
| 1645 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1646 | CTLTYPE_INT, "forwsrcrt" , NULL, |
| 1647 | NULL, 0, &?, 0, |
| 1648 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1649 | IPV6CTL_FORWSRCRT, CTL_EOL); |
| 1650 | sysctl_createv(clog, 0, NULL, NULL, |
| 1651 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1652 | CTLTYPE_STRUCT, "mrtstats" , NULL, |
| 1653 | NULL, 0, &?, sizeof(?), |
| 1654 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1655 | IPV6CTL_MRTSTATS, CTL_EOL); |
| 1656 | sysctl_createv(clog, 0, NULL, NULL, |
| 1657 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1658 | CTLTYPE_?, "mrtproto" , NULL, |
| 1659 | NULL, 0, &?, sizeof(?), |
| 1660 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1661 | IPV6CTL_MRTPROTO, CTL_EOL); |
| 1662 | #endif |
| 1663 | sysctl_createv(clog, 0, NULL, NULL, |
| 1664 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1665 | CTLTYPE_INT, "maxfragpackets" , |
| 1666 | SYSCTL_DESCR("Maximum number of fragments to buffer " |
| 1667 | "for reassembly" ), |
| 1668 | NULL, 0, &ip6_maxfragpackets, 0, |
| 1669 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1670 | IPV6CTL_MAXFRAGPACKETS, CTL_EOL); |
| 1671 | #ifdef __no_idea__ |
| 1672 | sysctl_createv(clog, 0, NULL, NULL, |
| 1673 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1674 | CTLTYPE_INT, "sourcecheck" , NULL, |
| 1675 | NULL, 0, &?, 0, |
| 1676 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1677 | IPV6CTL_SOURCECHECK, CTL_EOL); |
| 1678 | sysctl_createv(clog, 0, NULL, NULL, |
| 1679 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1680 | CTLTYPE_INT, "sourcecheck_logint" , NULL, |
| 1681 | NULL, 0, &?, 0, |
| 1682 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1683 | IPV6CTL_SOURCECHECK_LOGINT, CTL_EOL); |
| 1684 | #endif |
| 1685 | sysctl_createv(clog, 0, NULL, NULL, |
| 1686 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1687 | CTLTYPE_INT, "accept_rtadv" , |
| 1688 | SYSCTL_DESCR("Accept router advertisements" ), |
| 1689 | NULL, 0, &ip6_accept_rtadv, 0, |
| 1690 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1691 | IPV6CTL_ACCEPT_RTADV, CTL_EOL); |
| 1692 | sysctl_createv(clog, 0, NULL, NULL, |
| 1693 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1694 | CTLTYPE_INT, "rtadv_maxroutes" , |
| 1695 | SYSCTL_DESCR("Maximum number of routes accepted via router advertisements" ), |
| 1696 | NULL, 0, &ip6_rtadv_maxroutes, 0, |
| 1697 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1698 | IPV6CTL_RTADV_MAXROUTES, CTL_EOL); |
| 1699 | sysctl_createv(clog, 0, NULL, NULL, |
| 1700 | CTLFLAG_PERMANENT, |
| 1701 | CTLTYPE_INT, "rtadv_numroutes" , |
| 1702 | SYSCTL_DESCR("Current number of routes accepted via router advertisements" ), |
| 1703 | NULL, 0, &nd6_numroutes, 0, |
| 1704 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1705 | IPV6CTL_RTADV_NUMROUTES, CTL_EOL); |
| 1706 | sysctl_createv(clog, 0, NULL, NULL, |
| 1707 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1708 | CTLTYPE_INT, "keepfaith" , |
| 1709 | SYSCTL_DESCR("Activate faith interface" ), |
| 1710 | NULL, 0, &ip6_keepfaith, 0, |
| 1711 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1712 | IPV6CTL_KEEPFAITH, CTL_EOL); |
| 1713 | sysctl_createv(clog, 0, NULL, NULL, |
| 1714 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1715 | CTLTYPE_INT, "log_interval" , |
| 1716 | SYSCTL_DESCR("Minumum interval between logging " |
| 1717 | "unroutable packets" ), |
| 1718 | NULL, 0, &ip6_log_interval, 0, |
| 1719 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1720 | IPV6CTL_LOG_INTERVAL, CTL_EOL); |
| 1721 | sysctl_createv(clog, 0, NULL, NULL, |
| 1722 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1723 | CTLTYPE_INT, "hdrnestlimit" , |
| 1724 | SYSCTL_DESCR("Maximum number of nested IPv6 headers" ), |
| 1725 | NULL, 0, &ip6_hdrnestlimit, 0, |
| 1726 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1727 | IPV6CTL_HDRNESTLIMIT, CTL_EOL); |
| 1728 | sysctl_createv(clog, 0, NULL, NULL, |
| 1729 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1730 | CTLTYPE_INT, "dad_count" , |
| 1731 | SYSCTL_DESCR("Number of Duplicate Address Detection " |
| 1732 | "probes to send" ), |
| 1733 | NULL, 0, &ip6_dad_count, 0, |
| 1734 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1735 | IPV6CTL_DAD_COUNT, CTL_EOL); |
| 1736 | sysctl_createv(clog, 0, NULL, NULL, |
| 1737 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1738 | CTLTYPE_INT, "auto_flowlabel" , |
| 1739 | SYSCTL_DESCR("Assign random IPv6 flow labels" ), |
| 1740 | NULL, 0, &ip6_auto_flowlabel, 0, |
| 1741 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1742 | IPV6CTL_AUTO_FLOWLABEL, CTL_EOL); |
| 1743 | sysctl_createv(clog, 0, NULL, NULL, |
| 1744 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1745 | CTLTYPE_INT, "defmcasthlim" , |
| 1746 | SYSCTL_DESCR("Default multicast hop limit" ), |
| 1747 | NULL, 0, &ip6_defmcasthlim, 0, |
| 1748 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1749 | IPV6CTL_DEFMCASTHLIM, CTL_EOL); |
| 1750 | sysctl_createv(clog, 0, NULL, NULL, |
| 1751 | CTLFLAG_PERMANENT, |
| 1752 | CTLTYPE_STRING, "kame_version" , |
| 1753 | SYSCTL_DESCR("KAME Version" ), |
| 1754 | NULL, 0, __UNCONST(__KAME_VERSION), 0, |
| 1755 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1756 | IPV6CTL_KAME_VERSION, CTL_EOL); |
| 1757 | sysctl_createv(clog, 0, NULL, NULL, |
| 1758 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1759 | CTLTYPE_INT, "use_deprecated" , |
| 1760 | SYSCTL_DESCR("Allow use of deprecated addresses as " |
| 1761 | "source addresses" ), |
| 1762 | NULL, 0, &ip6_use_deprecated, 0, |
| 1763 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1764 | IPV6CTL_USE_DEPRECATED, CTL_EOL); |
| 1765 | sysctl_createv(clog, 0, NULL, NULL, |
| 1766 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1767 | CTLTYPE_INT, "rr_prune" , NULL, |
| 1768 | NULL, 0, &ip6_rr_prune, 0, |
| 1769 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1770 | IPV6CTL_RR_PRUNE, CTL_EOL); |
| 1771 | sysctl_createv(clog, 0, NULL, NULL, |
| 1772 | CTLFLAG_PERMANENT |
| 1773 | #ifndef INET6_BINDV6ONLY |
| 1774 | |CTLFLAG_READWRITE, |
| 1775 | #endif |
| 1776 | CTLTYPE_INT, "v6only" , |
| 1777 | SYSCTL_DESCR("Disallow PF_INET6 sockets from connecting " |
| 1778 | "to PF_INET sockets" ), |
| 1779 | NULL, 0, &ip6_v6only, 0, |
| 1780 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1781 | IPV6CTL_V6ONLY, CTL_EOL); |
| 1782 | sysctl_createv(clog, 0, NULL, NULL, |
| 1783 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1784 | CTLTYPE_INT, "anonportmin" , |
| 1785 | SYSCTL_DESCR("Lowest ephemeral port number to assign" ), |
| 1786 | sysctl_net_inet_ip_ports, 0, &ip6_anonportmin, 0, |
| 1787 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1788 | IPV6CTL_ANONPORTMIN, CTL_EOL); |
| 1789 | sysctl_createv(clog, 0, NULL, NULL, |
| 1790 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1791 | CTLTYPE_INT, "anonportmax" , |
| 1792 | SYSCTL_DESCR("Highest ephemeral port number to assign" ), |
| 1793 | sysctl_net_inet_ip_ports, 0, &ip6_anonportmax, 0, |
| 1794 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1795 | IPV6CTL_ANONPORTMAX, CTL_EOL); |
| 1796 | #ifndef IPNOPRIVPORTS |
| 1797 | sysctl_createv(clog, 0, NULL, NULL, |
| 1798 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1799 | CTLTYPE_INT, "lowportmin" , |
| 1800 | SYSCTL_DESCR("Lowest privileged ephemeral port number " |
| 1801 | "to assign" ), |
| 1802 | sysctl_net_inet_ip_ports, 0, &ip6_lowportmin, 0, |
| 1803 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1804 | IPV6CTL_LOWPORTMIN, CTL_EOL); |
| 1805 | sysctl_createv(clog, 0, NULL, NULL, |
| 1806 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1807 | CTLTYPE_INT, "lowportmax" , |
| 1808 | SYSCTL_DESCR("Highest privileged ephemeral port number " |
| 1809 | "to assign" ), |
| 1810 | sysctl_net_inet_ip_ports, 0, &ip6_lowportmax, 0, |
| 1811 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1812 | IPV6CTL_LOWPORTMAX, CTL_EOL); |
| 1813 | #endif /* IPNOPRIVPORTS */ |
| 1814 | sysctl_createv(clog, 0, NULL, NULL, |
| 1815 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1816 | CTLTYPE_INT, "auto_linklocal" , |
| 1817 | SYSCTL_DESCR("Default value of per-interface flag for " |
| 1818 | "adding an IPv6 link-local address to " |
| 1819 | "interfaces when attached" ), |
| 1820 | NULL, 0, &ip6_auto_linklocal, 0, |
| 1821 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1822 | IPV6CTL_AUTO_LINKLOCAL, CTL_EOL); |
| 1823 | sysctl_createv(clog, 0, NULL, NULL, |
| 1824 | CTLFLAG_PERMANENT|CTLFLAG_READONLY, |
| 1825 | CTLTYPE_STRUCT, "addctlpolicy" , |
| 1826 | SYSCTL_DESCR("Return the current address control" |
| 1827 | " policy" ), |
| 1828 | sysctl_net_inet6_addrctlpolicy, 0, NULL, 0, |
| 1829 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1830 | IPV6CTL_ADDRCTLPOLICY, CTL_EOL); |
| 1831 | sysctl_createv(clog, 0, NULL, NULL, |
| 1832 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1833 | CTLTYPE_INT, "use_tempaddr" , |
| 1834 | SYSCTL_DESCR("Use temporary address" ), |
| 1835 | NULL, 0, &ip6_use_tempaddr, 0, |
| 1836 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1837 | CTL_CREATE, CTL_EOL); |
| 1838 | sysctl_createv(clog, 0, NULL, NULL, |
| 1839 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1840 | CTLTYPE_INT, "prefer_tempaddr" , |
| 1841 | SYSCTL_DESCR("Prefer temporary address as source " |
| 1842 | "address" ), |
| 1843 | NULL, 0, &ip6_prefer_tempaddr, 0, |
| 1844 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1845 | CTL_CREATE, CTL_EOL); |
| 1846 | sysctl_createv(clog, 0, NULL, NULL, |
| 1847 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1848 | CTLTYPE_INT, "temppltime" , |
| 1849 | SYSCTL_DESCR("preferred lifetime of a temporary address" ), |
| 1850 | NULL, 0, &ip6_temp_preferred_lifetime, 0, |
| 1851 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1852 | CTL_CREATE, CTL_EOL); |
| 1853 | sysctl_createv(clog, 0, NULL, NULL, |
| 1854 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1855 | CTLTYPE_INT, "tempvltime" , |
| 1856 | SYSCTL_DESCR("valid lifetime of a temporary address" ), |
| 1857 | NULL, 0, &ip6_temp_valid_lifetime, 0, |
| 1858 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1859 | CTL_CREATE, CTL_EOL); |
| 1860 | sysctl_createv(clog, 0, NULL, NULL, |
| 1861 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1862 | CTLTYPE_INT, "maxfrags" , |
| 1863 | SYSCTL_DESCR("Maximum fragments in reassembly queue" ), |
| 1864 | NULL, 0, &ip6_maxfrags, 0, |
| 1865 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1866 | IPV6CTL_MAXFRAGS, CTL_EOL); |
| 1867 | sysctl_createv(clog, 0, NULL, NULL, |
| 1868 | CTLFLAG_PERMANENT, |
| 1869 | CTLTYPE_STRUCT, "stats" , |
| 1870 | SYSCTL_DESCR("IPv6 statistics" ), |
| 1871 | sysctl_net_inet6_ip6_stats, 0, NULL, 0, |
| 1872 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1873 | IPV6CTL_STATS, CTL_EOL); |
| 1874 | sysctl_createv(clog, 0, NULL, NULL, |
| 1875 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1876 | CTLTYPE_INT, "use_defaultzone" , |
| 1877 | SYSCTL_DESCR("Whether to use the default scope zones" ), |
| 1878 | NULL, 0, &ip6_use_defzone, 0, |
| 1879 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1880 | IPV6CTL_USE_DEFAULTZONE, CTL_EOL); |
| 1881 | sysctl_createv(clog, 0, NULL, NULL, |
| 1882 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1883 | CTLTYPE_INT, "mcast_pmtu" , |
| 1884 | SYSCTL_DESCR("Enable pMTU discovery for multicast packet" ), |
| 1885 | NULL, 0, &ip6_mcast_pmtu, 0, |
| 1886 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1887 | CTL_CREATE, CTL_EOL); |
| 1888 | /* anonportalgo RFC6056 subtree */ |
| 1889 | const struct sysctlnode *portalgo_node; |
| 1890 | sysctl_createv(clog, 0, NULL, &portalgo_node, |
| 1891 | CTLFLAG_PERMANENT, |
| 1892 | CTLTYPE_NODE, "anonportalgo" , |
| 1893 | SYSCTL_DESCR("Anonymous port algorithm selection (RFC 6056)" ), |
| 1894 | NULL, 0, NULL, 0, |
| 1895 | CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_CREATE, CTL_EOL); |
| 1896 | sysctl_createv(clog, 0, &portalgo_node, NULL, |
| 1897 | CTLFLAG_PERMANENT, |
| 1898 | CTLTYPE_STRING, "available" , |
| 1899 | SYSCTL_DESCR("available algorithms" ), |
| 1900 | sysctl_portalgo_available, 0, NULL, PORTALGO_MAXLEN, |
| 1901 | CTL_CREATE, CTL_EOL); |
| 1902 | sysctl_createv(clog, 0, &portalgo_node, NULL, |
| 1903 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1904 | CTLTYPE_STRING, "selected" , |
| 1905 | SYSCTL_DESCR("selected algorithm" ), |
| 1906 | sysctl_portalgo_selected6, 0, NULL, PORTALGO_MAXLEN, |
| 1907 | CTL_CREATE, CTL_EOL); |
| 1908 | sysctl_createv(clog, 0, &portalgo_node, NULL, |
| 1909 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1910 | CTLTYPE_STRUCT, "reserve" , |
| 1911 | SYSCTL_DESCR("bitmap of reserved ports" ), |
| 1912 | sysctl_portalgo_reserve6, 0, NULL, 0, |
| 1913 | CTL_CREATE, CTL_EOL); |
| 1914 | sysctl_createv(clog, 0, NULL, NULL, |
| 1915 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1916 | CTLTYPE_INT, "neighborgcthresh" , |
| 1917 | SYSCTL_DESCR("Maximum number of entries in neighbor" |
| 1918 | " cache" ), |
| 1919 | NULL, 1, &ip6_neighborgcthresh, 0, |
| 1920 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1921 | CTL_CREATE, CTL_EOL); |
| 1922 | sysctl_createv(clog, 0, NULL, NULL, |
| 1923 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1924 | CTLTYPE_INT, "maxifprefixes" , |
| 1925 | SYSCTL_DESCR("Maximum number of prefixes created by" |
| 1926 | " route advertisement per interface" ), |
| 1927 | NULL, 1, &ip6_maxifprefixes, 0, |
| 1928 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1929 | CTL_CREATE, CTL_EOL); |
| 1930 | sysctl_createv(clog, 0, NULL, NULL, |
| 1931 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1932 | CTLTYPE_INT, "maxifdefrouters" , |
| 1933 | SYSCTL_DESCR("Maximum number of default routers created" |
| 1934 | " by route advertisement per interface" ), |
| 1935 | NULL, 1, &ip6_maxifdefrouters, 0, |
| 1936 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1937 | CTL_CREATE, CTL_EOL); |
| 1938 | sysctl_createv(clog, 0, NULL, NULL, |
| 1939 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| 1940 | CTLTYPE_INT, "maxdynroutes" , |
| 1941 | SYSCTL_DESCR("Maximum number of routes created via" |
| 1942 | " redirect" ), |
| 1943 | NULL, 1, &ip6_maxdynroutes, 0, |
| 1944 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
| 1945 | CTL_CREATE, CTL_EOL); |
| 1946 | } |
| 1947 | |
| 1948 | void |
| 1949 | ip6_statinc(u_int stat) |
| 1950 | { |
| 1951 | |
| 1952 | KASSERT(stat < IP6_NSTATS); |
| 1953 | IP6_STATINC(stat); |
| 1954 | } |
| 1955 | |