1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1473 ja97890 * Common Development and Distribution License (the "License"). 6 1473 ja97890 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8485 Peter * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel /* 26 0 stevel * Copyright (c) 1990 Mentat Inc. 27 0 stevel */ 28 0 stevel 29 0 stevel #include <sys/types.h> 30 0 stevel #include <sys/stream.h> 31 0 stevel #include <sys/dlpi.h> 32 0 stevel #include <sys/stropts.h> 33 0 stevel #include <sys/sysmacros.h> 34 0 stevel #include <sys/strsun.h> 35 0 stevel #include <sys/strlog.h> 36 0 stevel #include <sys/strsubr.h> 37 0 stevel #define _SUN_TPI_VERSION 2 38 0 stevel #include <sys/tihdr.h> 39 0 stevel #include <sys/ddi.h> 40 0 stevel #include <sys/sunddi.h> 41 0 stevel #include <sys/cmn_err.h> 42 0 stevel #include <sys/debug.h> 43 2958 dr146992 #include <sys/sdt.h> 44 0 stevel #include <sys/kobj.h> 45 0 stevel #include <sys/zone.h> 46 2958 dr146992 #include <sys/neti.h> 47 2958 dr146992 #include <sys/hook.h> 48 0 stevel 49 0 stevel #include <sys/kmem.h> 50 0 stevel #include <sys/systm.h> 51 0 stevel #include <sys/param.h> 52 0 stevel #include <sys/socket.h> 53 0 stevel #include <sys/vtrace.h> 54 0 stevel #include <sys/isa_defs.h> 55 0 stevel #include <sys/atomic.h> 56 0 stevel #include <sys/policy.h> 57 11042 Erik #include <sys/mac.h> 58 0 stevel #include <net/if.h> 59 741 masputra #include <net/if_types.h> 60 0 stevel #include <net/route.h> 61 0 stevel #include <net/if_dl.h> 62 0 stevel #include <sys/sockio.h> 63 0 stevel #include <netinet/in.h> 64 0 stevel #include <netinet/ip6.h> 65 0 stevel #include <netinet/icmp6.h> 66 0 stevel #include <netinet/sctp.h> 67 0 stevel 68 0 stevel #include <inet/common.h> 69 0 stevel #include <inet/mi.h> 70 5240 nordmark #include <inet/optcom.h> 71 0 stevel #include <inet/mib2.h> 72 0 stevel #include <inet/nd.h> 73 0 stevel #include <inet/arp.h> 74 0 stevel 75 0 stevel #include <inet/ip.h> 76 741 masputra #include <inet/ip_impl.h> 77 0 stevel #include <inet/ip6.h> 78 0 stevel #include <inet/ip6_asp.h> 79 0 stevel #include <inet/tcp.h> 80 741 masputra #include <inet/tcp_impl.h> 81 741 masputra #include <inet/udp_impl.h> 82 0 stevel #include <inet/ipp_common.h> 83 0 stevel 84 0 stevel #include <inet/ip_multi.h> 85 0 stevel #include <inet/ip_if.h> 86 0 stevel #include <inet/ip_ire.h> 87 0 stevel #include <inet/ip_rts.h> 88 0 stevel #include <inet/ip_ndp.h> 89 0 stevel #include <net/pfkeyv2.h> 90 0 stevel #include <inet/sadb.h> 91 0 stevel #include <inet/ipsec_impl.h> 92 10616 Sebastien #include <inet/iptun/iptun_impl.h> 93 0 stevel #include <inet/sctp_ip.h> 94 0 stevel #include <sys/pattr.h> 95 0 stevel #include <inet/ipclassifier.h> 96 0 stevel #include <inet/ipsecah.h> 97 5240 nordmark #include <inet/rawip_impl.h> 98 5240 nordmark #include <inet/rts_impl.h> 99 8275 Eric #include <sys/squeue_impl.h> 100 0 stevel #include <sys/squeue.h> 101 1676 jpk 102 1676 jpk #include <sys/tsol/label.h> 103 1676 jpk #include <sys/tsol/tnet.h> 104 2546 carlsonj 105 2546 carlsonj /* Temporary; for CR 6451644 work-around */ 106 2546 carlsonj #include <sys/ethernet.h> 107 0 stevel 108 0 stevel /* 109 0 stevel * Naming conventions: 110 0 stevel * These rules should be judiciously applied 111 0 stevel * if there is a need to identify something as IPv6 versus IPv4 112 0 stevel * IPv6 funcions will end with _v6 in the ip module. 113 0 stevel * IPv6 funcions will end with _ipv6 in the transport modules. 114 0 stevel * IPv6 macros: 115 0 stevel * Some macros end with _V6; e.g. ILL_FRAG_HASH_V6 116 0 stevel * Some macros start with V6_; e.g. V6_OR_V4_INADDR_ANY 117 0 stevel * And then there are ..V4_PART_OF_V6. 118 0 stevel * The intent is that macros in the ip module end with _V6. 119 0 stevel * IPv6 global variables will start with ipv6_ 120 0 stevel * IPv6 structures will start with ipv6 121 0 stevel * IPv6 defined constants should start with IPV6_ 122 0 stevel * (but then there are NDP_DEFAULT_VERS_PRI_AND_FLOW, etc) 123 0 stevel */ 124 0 stevel 125 0 stevel /* 126 1676 jpk * ip6opt_ls is used to enable IPv6 (via /etc/system on TX systems). 127 1676 jpk * We need to do this because we didn't obtain the IP6OPT_LS (0x0a) 128 1676 jpk * from IANA. This mechanism will remain in effect until an official 129 1676 jpk * number is obtained. 130 1676 jpk */ 131 1676 jpk uchar_t ip6opt_ls; 132 0 stevel 133 0 stevel const in6_addr_t ipv6_all_ones = 134 0 stevel { 0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU }; 135 0 stevel const in6_addr_t ipv6_all_zeros = { 0, 0, 0, 0 }; 136 0 stevel 137 0 stevel #ifdef _BIG_ENDIAN 138 0 stevel const in6_addr_t ipv6_unspecified_group = { 0xff000000U, 0, 0, 0 }; 139 0 stevel #else /* _BIG_ENDIAN */ 140 0 stevel const in6_addr_t ipv6_unspecified_group = { 0x000000ffU, 0, 0, 0 }; 141 0 stevel #endif /* _BIG_ENDIAN */ 142 0 stevel 143 0 stevel #ifdef _BIG_ENDIAN 144 0 stevel const in6_addr_t ipv6_loopback = { 0, 0, 0, 0x00000001U }; 145 0 stevel #else /* _BIG_ENDIAN */ 146 0 stevel const in6_addr_t ipv6_loopback = { 0, 0, 0, 0x01000000U }; 147 0 stevel #endif /* _BIG_ENDIAN */ 148 0 stevel 149 0 stevel #ifdef _BIG_ENDIAN 150 0 stevel const in6_addr_t ipv6_all_hosts_mcast = { 0xff020000U, 0, 0, 0x00000001U }; 151 0 stevel #else /* _BIG_ENDIAN */ 152 0 stevel const in6_addr_t ipv6_all_hosts_mcast = { 0x000002ffU, 0, 0, 0x01000000U }; 153 0 stevel #endif /* _BIG_ENDIAN */ 154 0 stevel 155 0 stevel #ifdef _BIG_ENDIAN 156 0 stevel const in6_addr_t ipv6_all_rtrs_mcast = { 0xff020000U, 0, 0, 0x00000002U }; 157 0 stevel #else /* _BIG_ENDIAN */ 158 0 stevel const in6_addr_t ipv6_all_rtrs_mcast = { 0x000002ffU, 0, 0, 0x02000000U }; 159 0 stevel #endif /* _BIG_ENDIAN */ 160 0 stevel 161 0 stevel #ifdef _BIG_ENDIAN 162 0 stevel const in6_addr_t ipv6_all_v2rtrs_mcast = { 0xff020000U, 0, 0, 0x00000016U }; 163 0 stevel #else /* _BIG_ENDIAN */ 164 0 stevel const in6_addr_t ipv6_all_v2rtrs_mcast = { 0x000002ffU, 0, 0, 0x16000000U }; 165 0 stevel #endif /* _BIG_ENDIAN */ 166 0 stevel 167 0 stevel #ifdef _BIG_ENDIAN 168 0 stevel const in6_addr_t ipv6_solicited_node_mcast = 169 0 stevel { 0xff020000U, 0, 0x00000001U, 0xff000000U }; 170 0 stevel #else /* _BIG_ENDIAN */ 171 0 stevel const in6_addr_t ipv6_solicited_node_mcast = 172 0 stevel { 0x000002ffU, 0, 0x01000000U, 0x000000ffU }; 173 0 stevel #endif /* _BIG_ENDIAN */ 174 0 stevel 175 11042 Erik static boolean_t icmp_inbound_verify_v6(mblk_t *, icmp6_t *, ip_recv_attr_t *); 176 11042 Erik static void icmp_inbound_too_big_v6(icmp6_t *, ip_recv_attr_t *); 177 11042 Erik static void icmp_pkt_v6(mblk_t *, void *, size_t, const in6_addr_t *, 178 11042 Erik ip_recv_attr_t *); 179 11042 Erik static void icmp_redirect_v6(mblk_t *, ip6_t *, nd_redirect_t *, 180 11042 Erik ip_recv_attr_t *); 181 11042 Erik static void icmp_send_redirect_v6(mblk_t *, in6_addr_t *, 182 11042 Erik in6_addr_t *, ip_recv_attr_t *); 183 11042 Erik static void icmp_send_reply_v6(mblk_t *, ip6_t *, icmp6_t *, 184 11042 Erik ip_recv_attr_t *); 185 3448 dh155122 static boolean_t ip_source_routed_v6(ip6_t *, mblk_t *, ip_stack_t *); 186 11042 Erik 187 11042 Erik /* 188 11042 Erik * icmp_inbound_v6 deals with ICMP messages that are handled by IP. 189 11042 Erik * If the ICMP message is consumed by IP, i.e., it should not be delivered 190 11042 Erik * to any IPPROTO_ICMP raw sockets, then it returns NULL. 191 11042 Erik * Likewise, if the ICMP error is misformed (too short, etc), then it 192 11042 Erik * returns NULL. The caller uses this to determine whether or not to send 193 11042 Erik * to raw sockets. 194 0 stevel * 195 0 stevel * All error messages are passed to the matching transport stream. 196 0 stevel * 197 11042 Erik * See comment for icmp_inbound_v4() on how IPsec is handled. 198 11042 Erik */ 199 11042 Erik mblk_t * 200 11042 Erik icmp_inbound_v6(mblk_t *mp, ip_recv_attr_t *ira) 201 0 stevel { 202 0 stevel icmp6_t *icmp6; 203 11042 Erik ip6_t *ip6h; /* Outer header */ 204 11042 Erik int ip_hdr_length; /* Outer header length */ 205 0 stevel boolean_t interested; 206 11042 Erik ill_t *ill = ira->ira_ill; 207 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 208 11042 Erik mblk_t *mp_ret = NULL; 209 0 stevel 210 0 stevel ip6h = (ip6_t *)mp->b_rptr; 211 0 stevel 212 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInMsgs); 213 0 stevel 214 11042 Erik /* Make sure ira_l2src is set for ndp_input */ 215 11042 Erik if (!(ira->ira_flags & IRAF_L2SRC_SET)) 216 11042 Erik ip_setl2src(mp, ira, ira->ira_rill); 217 11042 Erik 218 11042 Erik ip_hdr_length = ira->ira_ip_hdr_length; 219 11042 Erik if ((mp->b_wptr - mp->b_rptr) < (ip_hdr_length + ICMP6_MINLEN)) { 220 11042 Erik if (ira->ira_pktlen < (ip_hdr_length + ICMP6_MINLEN)) { 221 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInTruncatedPkts); 222 11042 Erik ip_drop_input("ipIfStatsInTruncatedPkts", mp, ill); 223 11042 Erik freemsg(mp); 224 11042 Erik return (NULL); 225 11042 Erik } 226 11042 Erik ip6h = ip_pullup(mp, ip_hdr_length + ICMP6_MINLEN, ira); 227 11042 Erik if (ip6h == NULL) { 228 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors); 229 11042 Erik freemsg(mp); 230 11042 Erik return (NULL); 231 11042 Erik } 232 11042 Erik } 233 11042 Erik 234 11042 Erik icmp6 = (icmp6_t *)(&mp->b_rptr[ip_hdr_length]); 235 11042 Erik DTRACE_PROBE2(icmp__inbound__v6, ip6_t *, ip6h, icmp6_t *, icmp6); 236 0 stevel ip2dbg(("icmp_inbound_v6: type %d code %d\n", icmp6->icmp6_type, 237 0 stevel icmp6->icmp6_code)); 238 11042 Erik 239 11042 Erik /* 240 11042 Erik * We will set "interested" to "true" if we should pass a copy to 241 11042 Erik * the transport i.e., if it is an error message. 242 11042 Erik */ 243 0 stevel interested = !(icmp6->icmp6_type & ICMP6_INFOMSG_MASK); 244 0 stevel 245 0 stevel switch (icmp6->icmp6_type) { 246 0 stevel case ICMP6_DST_UNREACH: 247 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInDestUnreachs); 248 0 stevel if (icmp6->icmp6_code == ICMP6_DST_UNREACH_ADMIN) 249 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInAdminProhibs); 250 0 stevel break; 251 0 stevel 252 0 stevel case ICMP6_TIME_EXCEEDED: 253 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInTimeExcds); 254 0 stevel break; 255 0 stevel 256 0 stevel case ICMP6_PARAM_PROB: 257 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInParmProblems); 258 0 stevel break; 259 0 stevel 260 0 stevel case ICMP6_PACKET_TOO_BIG: 261 11042 Erik BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInPktTooBigs); 262 11042 Erik break; 263 11042 Erik 264 0 stevel case ICMP6_ECHO_REQUEST: 265 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInEchos); 266 0 stevel if (IN6_IS_ADDR_MULTICAST(&ip6h->ip6_dst) && 267 3448 dh155122 !ipst->ips_ipv6_resp_echo_mcast) 268 0 stevel break; 269 0 stevel 270 0 stevel /* 271 0 stevel * We must have exclusive use of the mblk to convert it to 272 0 stevel * a response. 273 0 stevel * If not, we copy it. 274 0 stevel */ 275 0 stevel if (mp->b_datap->db_ref > 1) { 276 0 stevel mblk_t *mp1; 277 0 stevel 278 0 stevel mp1 = copymsg(mp); 279 0 stevel if (mp1 == NULL) { 280 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 281 11042 Erik ip_drop_input("ipIfStatsInDiscards - copymsg", 282 11042 Erik mp, ill); 283 11042 Erik freemsg(mp); 284 11042 Erik return (NULL); 285 11042 Erik } 286 11042 Erik freemsg(mp); 287 0 stevel mp = mp1; 288 0 stevel ip6h = (ip6_t *)mp->b_rptr; 289 11042 Erik icmp6 = (icmp6_t *)(&mp->b_rptr[ip_hdr_length]); 290 11042 Erik } 291 11042 Erik 292 0 stevel icmp6->icmp6_type = ICMP6_ECHO_REPLY; 293 11042 Erik icmp_send_reply_v6(mp, ip6h, icmp6, ira); 294 11042 Erik return (NULL); 295 0 stevel 296 0 stevel case ICMP6_ECHO_REPLY: 297 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInEchoReplies); 298 0 stevel break; 299 0 stevel 300 0 stevel case ND_ROUTER_SOLICIT: 301 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInRouterSolicits); 302 0 stevel break; 303 0 stevel 304 0 stevel case ND_ROUTER_ADVERT: 305 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInRouterAdvertisements); 306 0 stevel break; 307 0 stevel 308 0 stevel case ND_NEIGHBOR_SOLICIT: 309 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInNeighborSolicits); 310 11042 Erik ndp_input(mp, ira); 311 11042 Erik return (NULL); 312 0 stevel 313 0 stevel case ND_NEIGHBOR_ADVERT: 314 0 stevel BUMP_MIB(ill->ill_icmp6_mib, 315 0 stevel ipv6IfIcmpInNeighborAdvertisements); 316 11042 Erik ndp_input(mp, ira); 317 11042 Erik return (NULL); 318 11042 Erik 319 11042 Erik case ND_REDIRECT: 320 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInRedirects); 321 0 stevel 322 3448 dh155122 if (ipst->ips_ipv6_ignore_redirect) 323 0 stevel break; 324 0 stevel 325 11042 Erik /* We now allow a RAW socket to receive this. */ 326 11042 Erik interested = B_TRUE; 327 11042 Erik break; 328 0 stevel 329 0 stevel /* 330 0 stevel * The next three icmp messages will be handled by MLD. 331 0 stevel * Pass all valid MLD packets up to any process(es) 332 11042 Erik * listening on a raw ICMP socket. 333 0 stevel */ 334 0 stevel case MLD_LISTENER_QUERY: 335 0 stevel case MLD_LISTENER_REPORT: 336 0 stevel case MLD_LISTENER_REDUCTION: 337 11042 Erik mp = mld_input(mp, ira); 338 11042 Erik return (mp); 339 11042 Erik default: 340 11042 Erik break; 341 11042 Erik } 342 11042 Erik /* 343 11042 Erik * See if there is an ICMP client to avoid an extra copymsg/freemsg 344 11042 Erik * if there isn't one. 345 11042 Erik */ 346 11042 Erik if (ipst->ips_ipcl_proto_fanout_v6[IPPROTO_ICMPV6].connf_head != NULL) { 347 11042 Erik /* If there is an ICMP client and we want one too, copy it. */ 348 11042 Erik 349 11042 Erik if (!interested) { 350 11042 Erik /* Caller will deliver to RAW sockets */ 351 11042 Erik return (mp); 352 11042 Erik } 353 11042 Erik mp_ret = copymsg(mp); 354 11042 Erik if (mp_ret == NULL) { 355 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 356 11042 Erik ip_drop_input("ipIfStatsInDiscards - copymsg", mp, ill); 357 11042 Erik } 358 11042 Erik } else if (!interested) { 359 11042 Erik /* Neither we nor raw sockets are interested. Drop packet now */ 360 11042 Erik freemsg(mp); 361 11042 Erik return (NULL); 362 11042 Erik } 363 11042 Erik 364 11042 Erik /* 365 11042 Erik * ICMP error or redirect packet. Make sure we have enough of 366 11042 Erik * the header and that db_ref == 1 since we might end up modifying 367 11042 Erik * the packet. 368 11042 Erik */ 369 11042 Erik if (mp->b_cont != NULL) { 370 11042 Erik if (ip_pullup(mp, -1, ira) == NULL) { 371 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 372 11042 Erik ip_drop_input("ipIfStatsInDiscards - ip_pullup", 373 11042 Erik mp, ill); 374 11042 Erik freemsg(mp); 375 11042 Erik return (mp_ret); 376 11042 Erik } 377 11042 Erik } 378 11042 Erik 379 0 stevel if (mp->b_datap->db_ref > 1) { 380 0 stevel mblk_t *mp1; 381 0 stevel 382 0 stevel mp1 = copymsg(mp); 383 0 stevel if (mp1 == NULL) { 384 3284 apersson BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 385 11042 Erik ip_drop_input("ipIfStatsInDiscards - copymsg", mp, ill); 386 11042 Erik freemsg(mp); 387 11042 Erik return (mp_ret); 388 11042 Erik } 389 11042 Erik freemsg(mp); 390 0 stevel mp = mp1; 391 11042 Erik } 392 11042 Erik 393 11042 Erik /* 394 11042 Erik * In case mp has changed, verify the message before any further 395 11042 Erik * processes. 396 11042 Erik */ 397 11042 Erik ip6h = (ip6_t *)mp->b_rptr; 398 11042 Erik icmp6 = (icmp6_t *)(&mp->b_rptr[ip_hdr_length]); 399 11042 Erik if (!icmp_inbound_verify_v6(mp, icmp6, ira)) { 400 11042 Erik freemsg(mp); 401 11042 Erik return (mp_ret); 402 11042 Erik } 403 11042 Erik 404 11042 Erik switch (icmp6->icmp6_type) { 405 11042 Erik case ND_REDIRECT: 406 11042 Erik icmp_redirect_v6(mp, ip6h, (nd_redirect_t *)icmp6, ira); 407 11042 Erik break; 408 11042 Erik case ICMP6_PACKET_TOO_BIG: 409 11042 Erik /* Update DCE and adjust MTU is icmp header if needed */ 410 11042 Erik icmp_inbound_too_big_v6(icmp6, ira); 411 11042 Erik /* FALLTHRU */ 412 11042 Erik default: 413 11042 Erik icmp_inbound_error_fanout_v6(mp, icmp6, ira); 414 11042 Erik break; 415 11042 Erik } 416 11042 Erik 417 11042 Erik return (mp_ret); 418 11042 Erik } 419 11042 Erik 420 11042 Erik /* 421 11042 Erik * Send an ICMP echo reply. 422 11042 Erik * The caller has already updated the payload part of the packet. 423 11042 Erik * We handle the ICMP checksum, IP source address selection and feed 424 11042 Erik * the packet into ip_output_simple. 425 11042 Erik */ 426 11042 Erik static void 427 11042 Erik icmp_send_reply_v6(mblk_t *mp, ip6_t *ip6h, icmp6_t *icmp6, 428 11042 Erik ip_recv_attr_t *ira) 429 11042 Erik { 430 11042 Erik uint_t ip_hdr_length = ira->ira_ip_hdr_length; 431 11042 Erik ill_t *ill = ira->ira_ill; 432 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 433 11042 Erik ip_xmit_attr_t ixas; 434 11042 Erik in6_addr_t origsrc; 435 11042 Erik 436 11042 Erik /* 437 11042 Erik * Remove any extension headers (do not reverse a source route) 438 11042 Erik * and clear the flow id (keep traffic class for now). 439 11042 Erik */ 440 11042 Erik if (ip_hdr_length != IPV6_HDR_LEN) { 441 11042 Erik int i; 442 11042 Erik 443 11042 Erik for (i = 0; i < IPV6_HDR_LEN; i++) { 444 11042 Erik mp->b_rptr[ip_hdr_length - i - 1] = 445 11042 Erik mp->b_rptr[IPV6_HDR_LEN - i - 1]; 446 11042 Erik } 447 11042 Erik mp->b_rptr += (ip_hdr_length - IPV6_HDR_LEN); 448 11042 Erik ip6h = (ip6_t *)mp->b_rptr; 449 11042 Erik ip6h->ip6_nxt = IPPROTO_ICMPV6; 450 11042 Erik i = ntohs(ip6h->ip6_plen); 451 11042 Erik i -= (ip_hdr_length - IPV6_HDR_LEN); 452 11042 Erik ip6h->ip6_plen = htons(i); 453 11042 Erik ip_hdr_length = IPV6_HDR_LEN; 454 11042 Erik ASSERT(ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN == msgdsize(mp)); 455 11042 Erik } 456 11042 Erik ip6h->ip6_vcf &= ~IPV6_FLOWINFO_FLOWLABEL; 457 11042 Erik 458 11042 Erik /* Reverse the source and destination addresses. */ 459 11042 Erik origsrc = ip6h->ip6_src; 460 11042 Erik ip6h->ip6_src = ip6h->ip6_dst; 461 11042 Erik ip6h->ip6_dst = origsrc; 462 11042 Erik 463 11042 Erik /* set the hop limit */ 464 11042 Erik ip6h->ip6_hops = ipst->ips_ipv6_def_hops; 465 11042 Erik 466 11042 Erik /* 467 11042 Erik * Prepare for checksum by putting icmp length in the icmp 468 11042 Erik * checksum field. The checksum is calculated in ip_output 469 11042 Erik */ 470 11042 Erik icmp6->icmp6_cksum = ip6h->ip6_plen; 471 11042 Erik 472 11042 Erik bzero(&ixas, sizeof (ixas)); 473 11042 Erik ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6; 474 11042 Erik ixas.ixa_zoneid = ira->ira_zoneid; 475 11042 Erik ixas.ixa_cred = kcred; 476 11042 Erik ixas.ixa_cpid = NOPID; 477 11042 Erik ixas.ixa_tsl = ira->ira_tsl; /* Behave as a multi-level responder */ 478 11042 Erik ixas.ixa_ifindex = 0; 479 11042 Erik ixas.ixa_ipst = ipst; 480 11042 Erik ixas.ixa_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; 481 11042 Erik 482 11042 Erik if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) { 483 11042 Erik /* 484 11042 Erik * This packet should go out the same way as it 485 11042 Erik * came in i.e in clear, independent of the IPsec 486 11042 Erik * policy for transmitting packets. 487 11042 Erik */ 488 11042 Erik ixas.ixa_flags |= IXAF_NO_IPSEC; 489 11042 Erik } else { 490 11042 Erik if (!ipsec_in_to_out(ira, &ixas, mp, NULL, ip6h)) { 491 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 492 11042 Erik /* Note: mp already consumed and ip_drop_packet done */ 493 11042 Erik return; 494 11042 Erik } 495 11042 Erik } 496 11042 Erik 497 11042 Erik /* Was the destination (now source) link-local? Send out same group */ 498 11042 Erik if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) { 499 11042 Erik ixas.ixa_flags |= IXAF_SCOPEID_SET; 500 11042 Erik if (IS_UNDER_IPMP(ill)) 501 11042 Erik ixas.ixa_scopeid = ill_get_upper_ifindex(ill); 502 11042 Erik else 503 11042 Erik ixas.ixa_scopeid = ill->ill_phyint->phyint_ifindex; 504 11042 Erik } 505 11042 Erik 506 11042 Erik if (ira->ira_flags & IRAF_MULTIBROADCAST) { 507 11042 Erik /* 508 11042 Erik * Not one or our addresses (IRE_LOCALs), thus we let 509 11042 Erik * ip_output_simple pick the source. 510 11042 Erik */ 511 11042 Erik ip6h->ip6_src = ipv6_all_zeros; 512 11042 Erik ixas.ixa_flags |= IXAF_SET_SOURCE; 513 11042 Erik } 514 11042 Erik 515 11042 Erik /* Should we send using dce_pmtu? */ 516 11042 Erik if (ipst->ips_ipv6_icmp_return_pmtu) 517 11042 Erik ixas.ixa_flags |= IXAF_PMTU_DISCOVERY; 518 11042 Erik 519 11042 Erik (void) ip_output_simple(mp, &ixas); 520 11042 Erik ixa_cleanup(&ixas); 521 11042 Erik 522 11042 Erik } 523 11042 Erik 524 11042 Erik /* 525 11042 Erik * Verify the ICMP messages for either for ICMP error or redirect packet. 526 11042 Erik * The caller should have fully pulled up the message. If it's a redirect 527 11042 Erik * packet, only basic checks on IP header will be done; otherwise, verify 528 11042 Erik * the packet by looking at the included ULP header. 529 11042 Erik * 530 11042 Erik * Called before icmp_inbound_error_fanout_v6 is called. 531 11042 Erik */ 532 11042 Erik static boolean_t 533 11042 Erik icmp_inbound_verify_v6(mblk_t *mp, icmp6_t *icmp6, ip_recv_attr_t *ira) 534 11042 Erik { 535 11042 Erik ill_t *ill = ira->ira_ill; 536 11042 Erik uint16_t hdr_length; 537 11042 Erik uint8_t *nexthdrp; 538 11042 Erik uint8_t nexthdr; 539 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 540 11042 Erik conn_t *connp; 541 11042 Erik ip6_t *ip6h; /* Inner header */ 542 11042 Erik 543 11042 Erik ip6h = (ip6_t *)&icmp6[1]; 544 11042 Erik if ((uchar_t *)ip6h + IPV6_HDR_LEN > mp->b_wptr) 545 11042 Erik goto truncated; 546 11042 Erik 547 11042 Erik if (icmp6->icmp6_type == ND_REDIRECT) { 548 11042 Erik hdr_length = sizeof (nd_redirect_t); 549 11042 Erik } else { 550 11042 Erik if ((IPH_HDR_VERSION(ip6h) != IPV6_VERSION)) 551 11042 Erik goto discard_pkt; 552 0 stevel hdr_length = IPV6_HDR_LEN; 553 11042 Erik } 554 11042 Erik 555 11042 Erik if ((uchar_t *)ip6h + hdr_length > mp->b_wptr) 556 11042 Erik goto truncated; 557 11042 Erik 558 11042 Erik /* 559 11042 Erik * Stop here for ICMP_REDIRECT. 560 11042 Erik */ 561 11042 Erik if (icmp6->icmp6_type == ND_REDIRECT) 562 11042 Erik return (B_TRUE); 563 11042 Erik 564 11042 Erik /* 565 11042 Erik * ICMP errors only. 566 11042 Erik */ 567 11042 Erik if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp)) 568 11042 Erik goto discard_pkt; 569 11042 Erik nexthdr = *nexthdrp; 570 11042 Erik 571 11042 Erik /* Try to pass the ICMP message to clients who need it */ 572 11042 Erik switch (nexthdr) { 573 11042 Erik case IPPROTO_UDP: 574 11042 Erik /* 575 11042 Erik * Verify we have at least ICMP_MIN_TP_HDR_LEN bytes of 576 11042 Erik * transport header. 577 11042 Erik */ 578 11042 Erik if ((uchar_t *)ip6h + hdr_length + ICMP_MIN_TP_HDR_LEN > 579 11042 Erik mp->b_wptr) 580 11042 Erik goto truncated; 581 11042 Erik break; 582 11042 Erik case IPPROTO_TCP: { 583 11042 Erik tcpha_t *tcpha; 584 11042 Erik 585 11042 Erik /* 586 11042 Erik * Verify we have at least ICMP_MIN_TP_HDR_LEN bytes of 587 11042 Erik * transport header. 588 11042 Erik */ 589 11042 Erik if ((uchar_t *)ip6h + hdr_length + ICMP_MIN_TP_HDR_LEN > 590 11042 Erik mp->b_wptr) 591 11042 Erik goto truncated; 592 11042 Erik 593 11042 Erik tcpha = (tcpha_t *)((uchar_t *)ip6h + hdr_length); 594 11042 Erik /* 595 11042 Erik * With IPMP we need to match across group, which we do 596 11042 Erik * since we have the upper ill from ira_ill. 597 11042 Erik */ 598 11042 Erik connp = ipcl_tcp_lookup_reversed_ipv6(ip6h, tcpha, TCPS_LISTEN, 599 11042 Erik ill->ill_phyint->phyint_ifindex, ipst); 600 11042 Erik if (connp == NULL) 601 11042 Erik goto discard_pkt; 602 11042 Erik 603 11042 Erik if ((connp->conn_verifyicmp != NULL) && 604 11042 Erik !connp->conn_verifyicmp(connp, tcpha, NULL, icmp6, ira)) { 605 11042 Erik CONN_DEC_REF(connp); 606 11042 Erik goto discard_pkt; 607 11042 Erik } 608 11042 Erik CONN_DEC_REF(connp); 609 11042 Erik break; 610 11042 Erik } 611 11042 Erik case IPPROTO_SCTP: 612 11042 Erik /* 613 11042 Erik * Verify we have at least ICMP_MIN_TP_HDR_LEN bytes of 614 11042 Erik * transport header. 615 11042 Erik */ 616 11042 Erik if ((uchar_t *)ip6h + hdr_length + ICMP_MIN_TP_HDR_LEN > 617 11042 Erik mp->b_wptr) 618 11042 Erik goto truncated; 619 11042 Erik break; 620 11042 Erik case IPPROTO_ESP: 621 11042 Erik case IPPROTO_AH: 622 11042 Erik break; 623 11042 Erik case IPPROTO_ENCAP: 624 11042 Erik case IPPROTO_IPV6: { 625 11042 Erik /* Look for self-encapsulated packets that caused an error */ 626 11042 Erik ip6_t *in_ip6h; 627 11042 Erik 628 11042 Erik in_ip6h = (ip6_t *)((uint8_t *)ip6h + hdr_length); 629 11042 Erik if ((uint8_t *)in_ip6h + (nexthdr == IPPROTO_ENCAP ? 630 11042 Erik sizeof (ipha_t) : sizeof (ip6_t)) > mp->b_wptr) 631 11042 Erik goto truncated; 632 11042 Erik break; 633 11042 Erik } 634 11042 Erik default: 635 11042 Erik break; 636 11042 Erik } 637 11042 Erik 638 11042 Erik return (B_TRUE); 639 11042 Erik 640 11042 Erik discard_pkt: 641 11042 Erik /* Bogus ICMP error. */ 642 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 643 11042 Erik return (B_FALSE); 644 11042 Erik 645 11042 Erik truncated: 646 11042 Erik /* We pulled up everthing already. Must be truncated */ 647 11042 Erik BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors); 648 11042 Erik return (B_FALSE); 649 11042 Erik } 650 11042 Erik 651 11042 Erik /* 652 11042 Erik * Process received IPv6 ICMP Packet too big. 653 11042 Erik * The caller is responsible for validating the packet before passing it in 654 11042 Erik * and also to fanout the ICMP error to any matching transport conns. Assumes 655 11042 Erik * the message has been fully pulled up. 656 11042 Erik * 657 11042 Erik * Before getting here, the caller has called icmp_inbound_verify_v6() 658 11042 Erik * that should have verified with ULP to prevent undoing the changes we're 659 11042 Erik * going to make to DCE. For example, TCP might have verified that the packet 660 11042 Erik * which generated error is in the send window. 661 11042 Erik * 662 11042 Erik * In some cases modified this MTU in the ICMP header packet; the caller 663 11042 Erik * should pass to the matching ULP after this returns. 664 11042 Erik */ 665 11042 Erik static void 666 11042 Erik icmp_inbound_too_big_v6(icmp6_t *icmp6, ip_recv_attr_t *ira) 667 11042 Erik { 668 11042 Erik uint32_t mtu; 669 11042 Erik dce_t *dce; 670 11042 Erik ill_t *ill = ira->ira_ill; /* Upper ill if IPMP */ 671 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 672 11042 Erik int old_max_frag; 673 11042 Erik in6_addr_t final_dst; 674 11042 Erik ip6_t *ip6h; /* Inner IP header */ 675 11042 Erik 676 11042 Erik /* Caller has already pulled up everything. */ 677 11042 Erik ip6h = (ip6_t *)&icmp6[1]; 678 11042 Erik final_dst = ip_get_dst_v6(ip6h, NULL, NULL); 679 11042 Erik 680 11042 Erik /* 681 11042 Erik * For link local destinations matching simply on address is not 682 0 stevel * sufficient. Same link local addresses for different ILL's is 683 0 stevel * possible. 684 0 stevel */ 685 11042 Erik if (IN6_IS_ADDR_LINKSCOPE(&final_dst)) { 686 11042 Erik dce = dce_lookup_and_add_v6(&final_dst, 687 11042 Erik ill->ill_phyint->phyint_ifindex, ipst); 688 11042 Erik } else { 689 11042 Erik dce = dce_lookup_and_add_v6(&final_dst, 0, ipst); 690 11042 Erik } 691 11042 Erik if (dce == NULL) { 692 11042 Erik /* Couldn't add a unique one - ENOMEM */ 693 11042 Erik if (ip_debug > 2) { 694 11042 Erik /* ip1dbg */ 695 11042 Erik pr_addr_dbg("icmp_inbound_too_big_v6:" 696 11042 Erik "no dce for dst %s\n", AF_INET6, 697 11042 Erik &final_dst); 698 11042 Erik } 699 11042 Erik return; 700 11042 Erik } 701 11042 Erik 702 11042 Erik mtu = ntohl(icmp6->icmp6_mtu); 703 11042 Erik 704 11042 Erik mutex_enter(&dce->dce_lock); 705 11042 Erik if (dce->dce_flags & DCEF_PMTU) 706 11042 Erik old_max_frag = dce->dce_pmtu; 707 11042 Erik else 708 11042 Erik old_max_frag = ill->ill_mtu; 709 11042 Erik 710 11042 Erik if (mtu < IPV6_MIN_MTU) { 711 11042 Erik ip1dbg(("Received mtu less than IPv6 " 712 11042 Erik "min mtu %d: %d\n", IPV6_MIN_MTU, mtu)); 713 11042 Erik mtu = IPV6_MIN_MTU; 714 11042 Erik /* 715 11042 Erik * If an mtu less than IPv6 min mtu is received, 716 11042 Erik * we must include a fragment header in 717 11042 Erik * subsequent packets. 718 11042 Erik */ 719 11042 Erik dce->dce_flags |= DCEF_TOO_SMALL_PMTU; 720 11042 Erik } else { 721 11042 Erik dce->dce_flags &= ~DCEF_TOO_SMALL_PMTU; 722 11042 Erik } 723 11042 Erik ip1dbg(("Received mtu from router: %d\n", mtu)); 724 11042 Erik dce->dce_pmtu = MIN(old_max_frag, mtu); 725 11042 Erik 726 11042 Erik /* Prepare to send the new max frag size for the ULP. */ 727 11042 Erik if (dce->dce_flags & DCEF_TOO_SMALL_PMTU) { 728 11042 Erik /* 729 11042 Erik * If we need a fragment header in every packet 730 11042 Erik * (above case or multirouting), make sure the 731 11042 Erik * ULP takes it into account when computing the 732 11042 Erik * payload size. 733 11042 Erik */ 734 11042 Erik icmp6->icmp6_mtu = htonl(dce->dce_pmtu - sizeof (ip6_frag_t)); 735 11042 Erik } else { 736 11042 Erik icmp6->icmp6_mtu = htonl(dce->dce_pmtu); 737 11042 Erik } 738 11042 Erik /* We now have a PMTU for sure */ 739 11042 Erik dce->dce_flags |= DCEF_PMTU; 740 11066 rafael dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64()); 741 11042 Erik mutex_exit(&dce->dce_lock); 742 11042 Erik /* 743 11042 Erik * After dropping the lock the new value is visible to everyone. 744 11042 Erik * Then we bump the generation number so any cached values reinspect 745 11042 Erik * the dce_t. 746 11042 Erik */ 747 11042 Erik dce_increment_generation(dce); 748 11042 Erik dce_refrele(dce); 749 10616 Sebastien } 750 10616 Sebastien 751 10616 Sebastien /* 752 0 stevel * Fanout received ICMPv6 error packets to the transports. 753 0 stevel * Assumes the IPv6 plus ICMPv6 headers have been pulled up but nothing else. 754 11042 Erik * 755 11042 Erik * The caller must have called icmp_inbound_verify_v6. 756 11042 Erik */ 757 11042 Erik void 758 11042 Erik icmp_inbound_error_fanout_v6(mblk_t *mp, icmp6_t *icmp6, ip_recv_attr_t *ira) 759 11042 Erik { 760 11042 Erik uint16_t *up; /* Pointer to ports in ULP header */ 761 11042 Erik uint32_t ports; /* reversed ports for fanout */ 762 11042 Erik ip6_t rip6h; /* With reversed addresses */ 763 11042 Erik ip6_t *ip6h; /* Inner IP header */ 764 11042 Erik uint16_t hdr_length; /* Inner IP header length */ 765 0 stevel uint8_t *nexthdrp; 766 0 stevel uint8_t nexthdr; 767 11042 Erik tcpha_t *tcpha; 768 11042 Erik conn_t *connp; 769 11042 Erik ill_t *ill = ira->ira_ill; /* Upper in the case of IPMP */ 770 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 771 11042 Erik ipsec_stack_t *ipss = ipst->ips_netstack->netstack_ipsec; 772 11042 Erik 773 11042 Erik /* Caller has already pulled up everything. */ 774 11042 Erik ip6h = (ip6_t *)&icmp6[1]; 775 11042 Erik ASSERT(mp->b_cont == NULL); 776 11042 Erik ASSERT((uchar_t *)&ip6h[1] <= mp->b_wptr); 777 0 stevel 778 0 stevel if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp)) 779 0 stevel goto drop_pkt; 780 0 stevel nexthdr = *nexthdrp; 781 11042 Erik ira->ira_protocol = nexthdr; 782 0 stevel 783 10616 Sebastien /* 784 10616 Sebastien * We need a separate IP header with the source and destination 785 10616 Sebastien * addresses reversed to do fanout/classification because the ip6h in 786 10616 Sebastien * the ICMPv6 error is in the form we sent it out. 787 10616 Sebastien */ 788 10616 Sebastien rip6h.ip6_src = ip6h->ip6_dst; 789 10616 Sebastien rip6h.ip6_dst = ip6h->ip6_src; 790 10616 Sebastien rip6h.ip6_nxt = nexthdr; 791 10616 Sebastien 792 0 stevel /* Try to pass the ICMP message to clients who need it */ 793 0 stevel switch (nexthdr) { 794 0 stevel case IPPROTO_UDP: { 795 10616 Sebastien /* Attempt to find a client stream based on port. */ 796 10616 Sebastien up = (uint16_t *)((uchar_t *)ip6h + hdr_length); 797 11042 Erik 798 11042 Erik /* Note that we send error to all matches. */ 799 11042 Erik ira->ira_flags |= IRAF_ICMP_ERROR; 800 11042 Erik ip_fanout_udp_multi_v6(mp, &rip6h, up[0], up[1], ira); 801 11042 Erik ira->ira_flags &= ~IRAF_ICMP_ERROR; 802 10616 Sebastien return; 803 10616 Sebastien } 804 10616 Sebastien case IPPROTO_TCP: { 805 0 stevel /* 806 0 stevel * Attempt to find a client stream based on port. 807 0 stevel * Note that we do a reverse lookup since the header is 808 0 stevel * in the form we sent it out. 809 10616 Sebastien */ 810 11042 Erik tcpha = (tcpha_t *)((uchar_t *)ip6h + hdr_length); 811 11042 Erik /* 812 11042 Erik * With IPMP we need to match across group, which we do 813 11042 Erik * since we have the upper ill from ira_ill. 814 11042 Erik */ 815 0 stevel connp = ipcl_tcp_lookup_reversed_ipv6(ip6h, tcpha, 816 3448 dh155122 TCPS_LISTEN, ill->ill_phyint->phyint_ifindex, ipst); 817 0 stevel if (connp == NULL) { 818 0 stevel goto drop_pkt; 819 0 stevel } 820 0 stevel 821 11042 Erik if (CONN_INBOUND_POLICY_PRESENT_V6(connp, ipss) || 822 11042 Erik (ira->ira_flags & IRAF_IPSEC_SECURE)) { 823 11042 Erik mp = ipsec_check_inbound_policy(mp, connp, 824 11042 Erik NULL, ip6h, ira); 825 11042 Erik if (mp == NULL) { 826 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 827 11042 Erik /* Note that mp is NULL */ 828 11042 Erik ip_drop_input("ipIfStatsInDiscards", mp, ill); 829 11042 Erik CONN_DEC_REF(connp); 830 11042 Erik return; 831 11042 Erik } 832 11042 Erik } 833 11042 Erik 834 11042 Erik ira->ira_flags |= IRAF_ICMP_ERROR; 835 11042 Erik if (IPCL_IS_TCP(connp)) { 836 11042 Erik SQUEUE_ENTER_ONE(connp->conn_sqp, mp, 837 11042 Erik connp->conn_recvicmp, connp, ira, SQ_FILL, 838 11042 Erik SQTAG_TCP6_INPUT_ICMP_ERR); 839 11042 Erik } else { 840 11042 Erik /* Not TCP; must be SOCK_RAW, IPPROTO_TCP */ 841 11042 Erik ill_t *rill = ira->ira_rill; 842 11042 Erik 843 11042 Erik ira->ira_ill = ira->ira_rill = NULL; 844 11042 Erik (connp->conn_recv)(connp, mp, NULL, ira); 845 11042 Erik CONN_DEC_REF(connp); 846 11042 Erik ira->ira_ill = ill; 847 11042 Erik ira->ira_rill = rill; 848 11042 Erik } 849 11042 Erik ira->ira_flags &= ~IRAF_ICMP_ERROR; 850 0 stevel return; 851 0 stevel 852 0 stevel } 853 0 stevel case IPPROTO_SCTP: 854 0 stevel up = (uint16_t *)((uchar_t *)ip6h + hdr_length); 855 11042 Erik /* Find a SCTP client stream for this packet. */ 856 0 stevel ((uint16_t *)&ports)[0] = up[1]; 857 0 stevel ((uint16_t *)&ports)[1] = up[0]; 858 11042 Erik 859 11042 Erik ira->ira_flags |= IRAF_ICMP_ERROR; 860 11042 Erik ip_fanout_sctp(mp, NULL, &rip6h, ports, ira); 861 11042 Erik ira->ira_flags &= ~IRAF_ICMP_ERROR; 862 11042 Erik return; 863 11042 Erik 864 0 stevel case IPPROTO_ESP: 865 11042 Erik case IPPROTO_AH: 866 3448 dh155122 if (!ipsec_loaded(ipss)) { 867 11042 Erik ip_proto_not_sup(mp, ira); 868 0 stevel return; 869 0 stevel } 870 0 stevel 871 0 stevel if (nexthdr == IPPROTO_ESP) 872 11042 Erik mp = ipsecesp_icmp_error(mp, ira); 873 11042 Erik else 874 11042 Erik mp = ipsecah_icmp_error(mp, ira); 875 11042 Erik if (mp == NULL) 876 11042 Erik return; 877 11042 Erik 878 11042 Erik /* Just in case ipsec didn't preserve the NULL b_cont */ 879 11042 Erik if (mp->b_cont != NULL) { 880 11042 Erik if (!pullupmsg(mp, -1)) 881 11042 Erik goto drop_pkt; 882 11042 Erik } 883 11042 Erik 884 11042 Erik /* 885 11042 Erik * If succesful, the mp has been modified to not include 886 11042 Erik * the ESP/AH header so we can fanout to the ULP's icmp 887 11042 Erik * error handler. 888 11042 Erik */ 889 11042 Erik if (mp->b_wptr - mp->b_rptr < IPV6_HDR_LEN) 890 0 stevel goto drop_pkt; 891 11042 Erik 892 11042 Erik ip6h = (ip6_t *)mp->b_rptr; 893 11042 Erik /* Don't call hdr_length_v6() unless you have to. */ 894 11042 Erik if (ip6h->ip6_nxt != IPPROTO_ICMPV6) 895 11042 Erik hdr_length = ip_hdr_length_v6(mp, ip6h); 896 11042 Erik else 897 11042 Erik hdr_length = IPV6_HDR_LEN; 898 11042 Erik 899 11042 Erik /* Verify the modified message before any further processes. */ 900 11042 Erik icmp6 = (icmp6_t *)(&mp->b_rptr[hdr_length]); 901 11042 Erik if (!icmp_inbound_verify_v6(mp, icmp6, ira)) { 902 11042 Erik freemsg(mp); 903 11042 Erik return; 904 11042 Erik } 905 11042 Erik 906 11042 Erik icmp_inbound_error_fanout_v6(mp, icmp6, ira); 907 11042 Erik return; 908 11042 Erik 909 11042 Erik case IPPROTO_IPV6: { 910 11042 Erik /* Look for self-encapsulated packets that caused an error */ 911 11042 Erik ip6_t *in_ip6h; 912 11042 Erik 913 11042 Erik in_ip6h = (ip6_t *)((uint8_t *)ip6h + hdr_length); 914 11042 Erik 915 11042 Erik if (IN6_ARE_ADDR_EQUAL(&in_ip6h->ip6_src, &ip6h->ip6_src) && 916 11042 Erik IN6_ARE_ADDR_EQUAL(&in_ip6h->ip6_dst, &ip6h->ip6_dst)) { 917 0 stevel /* 918 0 stevel * Self-encapsulated case. As in the ipv4 case, 919 0 stevel * we need to strip the 2nd IP header. Since mp 920 0 stevel * is already pulled-up, we can simply bcopy 921 0 stevel * the 3rd header + data over the 2nd header. 922 0 stevel */ 923 0 stevel uint16_t unused_len; 924 0 stevel 925 0 stevel /* 926 0 stevel * Make sure we don't do recursion more than once. 927 0 stevel */ 928 11042 Erik if (!ip_hdr_length_nexthdr_v6(mp, in_ip6h, 929 0 stevel &unused_len, &nexthdrp) || 930 0 stevel *nexthdrp == IPPROTO_IPV6) { 931 0 stevel goto drop_pkt; 932 0 stevel } 933 0 stevel 934 0 stevel /* 935 0 stevel * Copy the 3rd header + remaining data on top 936 0 stevel * of the 2nd header. 937 0 stevel */ 938 11042 Erik bcopy(in_ip6h, ip6h, mp->b_wptr - (uchar_t *)in_ip6h); 939 0 stevel 940 0 stevel /* 941 0 stevel * Subtract length of the 2nd header. 942 0 stevel */ 943 0 stevel mp->b_wptr -= hdr_length; 944 11042 Erik 945 11042 Erik ip6h = (ip6_t *)mp->b_rptr; 946 11042 Erik /* Don't call hdr_length_v6() unless you have to. */ 947 11042 Erik if (ip6h->ip6_nxt != IPPROTO_ICMPV6) 948 11042 Erik hdr_length = ip_hdr_length_v6(mp, ip6h); 949 11042 Erik else 950 11042 Erik hdr_length = IPV6_HDR_LEN; 951 11042 Erik 952 11042 Erik /* 953 11042 Erik * Verify the modified message before any further 954 11042 Erik * processes. 955 11042 Erik */ 956 11042 Erik icmp6 = (icmp6_t *)(&mp->b_rptr[hdr_length]); 957 11042 Erik if (!icmp_inbound_verify_v6(mp, icmp6, ira)) { 958 11042 Erik freemsg(mp); 959 11042 Erik return; 960 11042 Erik } 961 0 stevel 962 0 stevel /* 963 0 stevel * Now recurse, and see what I _really_ should be 964 0 stevel * doing here. 965 0 stevel */ 966 11042 Erik icmp_inbound_error_fanout_v6(mp, icmp6, ira); 967 11042 Erik return; 968 11042 Erik } 969 0 stevel /* FALLTHRU */ 970 11042 Erik } 971 11042 Erik case IPPROTO_ENCAP: 972 11042 Erik if ((connp = ipcl_iptun_classify_v6(&rip6h.ip6_src, 973 11042 Erik &rip6h.ip6_dst, ipst)) != NULL) { 974 11042 Erik ira->ira_flags |= IRAF_ICMP_ERROR; 975 11042 Erik connp->conn_recvicmp(connp, mp, NULL, ira); 976 11042 Erik CONN_DEC_REF(connp); 977 11042 Erik ira->ira_flags &= ~IRAF_ICMP_ERROR; 978 11042 Erik return; 979 11042 Erik } 980 11042 Erik /* 981 11042 Erik * No IP tunnel is interested, fallthrough and see 982 11042 Erik * if a raw socket will want it. 983 11042 Erik */ 984 11042 Erik /* FALLTHRU */ 985 11042 Erik default: 986 11042 Erik ira->ira_flags |= IRAF_ICMP_ERROR; 987 11042 Erik ASSERT(ira->ira_protocol == nexthdr); 988 11042 Erik ip_fanout_proto_v6(mp, &rip6h, ira); 989 11042 Erik ira->ira_flags &= ~IRAF_ICMP_ERROR; 990 0 stevel return; 991 0 stevel } 992 0 stevel /* NOTREACHED */ 993 0 stevel drop_pkt: 994 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors); 995 0 stevel ip1dbg(("icmp_inbound_error_fanout_v6: drop pkt\n")); 996 11042 Erik freemsg(mp); 997 0 stevel } 998 0 stevel 999 0 stevel /* 1000 0 stevel * Process received IPv6 ICMP Redirect messages. 1001 11042 Erik * Assumes the caller has verified that the headers are in the pulled up mblk. 1002 11042 Erik * Consumes mp. 1003 0 stevel */ 1004 0 stevel /* ARGSUSED */ 1005 0 stevel static void 1006 11042 Erik icmp_redirect_v6(mblk_t *mp, ip6_t *ip6h, nd_redirect_t *rd, 1007 11042 Erik ip_recv_attr_t *ira) 1008 11042 Erik { 1009 11042 Erik ire_t *ire, *nire; 1010 11042 Erik ire_t *prev_ire = NULL; 1011 0 stevel ire_t *redir_ire; 1012 0 stevel in6_addr_t *src, *dst, *gateway; 1013 0 stevel nd_opt_hdr_t *opt; 1014 0 stevel nce_t *nce; 1015 11042 Erik int ncec_flags = 0; 1016 0 stevel int err = 0; 1017 0 stevel boolean_t redirect_to_router = B_FALSE; 1018 0 stevel int len; 1019 3004 dd193516 int optlen; 1020 11042 Erik ill_t *ill = ira->ira_rill; 1021 11042 Erik ill_t *rill = ira->ira_rill; 1022 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 1023 11042 Erik 1024 11042 Erik /* 1025 11042 Erik * Since ira_ill is where the IRE_LOCAL was hosted we use ira_rill 1026 11042 Erik * and make it be the IPMP upper so avoid being confused by a packet 1027 11042 Erik * addressed to a unicast address on a different ill. 1028 11042 Erik */ 1029 11042 Erik if (IS_UNDER_IPMP(rill)) { 1030 11042 Erik rill = ipmp_ill_hold_ipmp_ill(rill); 1031 11042 Erik if (rill == NULL) { 1032 11042 Erik BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects); 1033 11042 Erik ip_drop_input("ipv6IfIcmpInBadRedirects - IPMP ill", 1034 11042 Erik mp, ill); 1035 11042 Erik freemsg(mp); 1036 11042 Erik return; 1037 11042 Erik } 1038 11042 Erik ASSERT(rill != ira->ira_rill); 1039 11042 Erik } 1040 11042 Erik 1041 11042 Erik len = mp->b_wptr - (uchar_t *)rd; 1042 0 stevel src = &ip6h->ip6_src; 1043 0 stevel dst = &rd->nd_rd_dst; 1044 0 stevel gateway = &rd->nd_rd_target; 1045 3004 dd193516 1046 3004 dd193516 /* Verify if it is a valid redirect */ 1047 3004 dd193516 if (!IN6_IS_ADDR_LINKLOCAL(src) || 1048 3004 dd193516 (ip6h->ip6_hops != IPV6_MAX_HOPS) || 1049 3004 dd193516 (rd->nd_rd_code != 0) || 1050 3004 dd193516 (len < sizeof (nd_redirect_t)) || 1051 3004 dd193516 (IN6_IS_ADDR_V4MAPPED(dst)) || 1052 3004 dd193516 (IN6_IS_ADDR_MULTICAST(dst))) { 1053 3004 dd193516 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects); 1054 11042 Erik ip_drop_input("ipv6IfIcmpInBadRedirects - addr/len", mp, ill); 1055 11042 Erik goto fail_redirect; 1056 3004 dd193516 } 1057 3004 dd193516 1058 3004 dd193516 if (!(IN6_IS_ADDR_LINKLOCAL(gateway) || 1059 3004 dd193516 IN6_ARE_ADDR_EQUAL(gateway, dst))) { 1060 3004 dd193516 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects); 1061 11042 Erik ip_drop_input("ipv6IfIcmpInBadRedirects - bad gateway", 1062 11042 Erik mp, ill); 1063 11042 Erik goto fail_redirect; 1064 11042 Erik } 1065 11042 Erik 1066 11042 Erik optlen = len - sizeof (nd_redirect_t); 1067 11042 Erik if (optlen != 0) { 1068 11042 Erik if (!ndp_verify_optlen((nd_opt_hdr_t *)&rd[1], optlen)) { 1069 3004 dd193516 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects); 1070 11042 Erik ip_drop_input("ipv6IfIcmpInBadRedirects - options", 1071 11042 Erik mp, ill); 1072 11042 Erik goto fail_redirect; 1073 3004 dd193516 } 1074 3004 dd193516 } 1075 3004 dd193516 1076 0 stevel if (!IN6_ARE_ADDR_EQUAL(gateway, dst)) { 1077 0 stevel redirect_to_router = B_TRUE; 1078 11042 Erik ncec_flags |= NCE_F_ISROUTER; 1079 11042 Erik } else { 1080 11042 Erik gateway = dst; /* Add nce for dst */ 1081 11042 Erik } 1082 11042 Erik 1083 3004 dd193516 1084 3004 dd193516 /* 1085 3004 dd193516 * Verify that the IP source address of the redirect is 1086 3004 dd193516 * the same as the current first-hop router for the specified 1087 3004 dd193516 * ICMP destination address. 1088 3004 dd193516 * Also, Make sure we had a route for the dest in question and 1089 3004 dd193516 * that route was pointing to the old gateway (the source of the 1090 3004 dd193516 * redirect packet.) 1091 11042 Erik * Note: this merely says that there is some IRE which matches that 1092 11042 Erik * gateway; not that the longest match matches that gateway. 1093 11042 Erik */ 1094 11042 Erik prev_ire = ire_ftable_lookup_v6(dst, 0, src, 0, rill, 1095 11042 Erik ALL_ZONES, NULL, MATCH_IRE_GW | MATCH_IRE_ILL, 0, ipst, NULL); 1096 3004 dd193516 1097 0 stevel /* 1098 0 stevel * Check that 1099 0 stevel * the redirect was not from ourselves 1100 0 stevel * old gateway is still directly reachable 1101 0 stevel */ 1102 0 stevel if (prev_ire == NULL || 1103 11042 Erik (prev_ire->ire_type & (IRE_LOCAL|IRE_LOOPBACK)) || 1104 11042 Erik (prev_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE))) { 1105 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects); 1106 11042 Erik ip_drop_input("ipv6IfIcmpInBadRedirects - ire", mp, ill); 1107 0 stevel goto fail_redirect; 1108 0 stevel } 1109 11042 Erik 1110 11042 Erik ASSERT(prev_ire->ire_ill != NULL); 1111 11042 Erik if (prev_ire->ire_ill->ill_flags & ILLF_NONUD) 1112 11042 Erik ncec_flags |= NCE_F_NONUD; 1113 11042 Erik 1114 0 stevel opt = (nd_opt_hdr_t *)&rd[1]; 1115 3004 dd193516 opt = ndp_get_option(opt, optlen, ND_OPT_TARGET_LINKADDR); 1116 0 stevel if (opt != NULL) { 1117 11042 Erik err = nce_lookup_then_add_v6(rill, 1118 0 stevel (uchar_t *)&opt[1], /* Link layer address */ 1119 11042 Erik rill->ill_phys_addr_length, 1120 11042 Erik gateway, ncec_flags, ND_STALE, &nce); 1121 0 stevel switch (err) { 1122 0 stevel case 0: 1123 11042 Erik nce_refrele(nce); 1124 0 stevel break; 1125 0 stevel case EEXIST: 1126 0 stevel /* 1127 0 stevel * Check to see if link layer address has changed and 1128 11042 Erik * process the ncec_state accordingly. 1129 11042 Erik */ 1130 11042 Erik nce_process(nce->nce_common, 1131 11042 Erik (uchar_t *)&opt[1], 0, B_FALSE); 1132 11042 Erik nce_refrele(nce); 1133 0 stevel break; 1134 0 stevel default: 1135 0 stevel ip1dbg(("icmp_redirect_v6: NCE create failed %d\n", 1136 0 stevel err)); 1137 0 stevel goto fail_redirect; 1138 0 stevel } 1139 0 stevel } 1140 0 stevel if (redirect_to_router) { 1141 0 stevel ASSERT(IN6_IS_ADDR_LINKLOCAL(gateway)); 1142 0 stevel 1143 0 stevel /* 1144 0 stevel * Create a Route Association. This will allow us to remember 1145 0 stevel * a router told us to use the particular gateway. 1146 0 stevel */ 1147 0 stevel ire = ire_create_v6( 1148 0 stevel dst, 1149 0 stevel &ipv6_all_ones, /* mask */ 1150 0 stevel gateway, /* gateway addr */ 1151 3004 dd193516 IRE_HOST, 1152 11042 Erik prev_ire->ire_ill, 1153 11042 Erik ALL_ZONES, 1154 0 stevel (RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST), 1155 3448 dh155122 NULL, 1156 3448 dh155122 ipst); 1157 0 stevel } else { 1158 11042 Erik ipif_t *ipif; 1159 11042 Erik in6_addr_t gw; 1160 3004 dd193516 1161 3004 dd193516 /* 1162 3004 dd193516 * Just create an on link entry, i.e. interface route. 1163 11042 Erik * The gateway field is our link-local on the ill. 1164 11042 Erik */ 1165 11042 Erik mutex_enter(&rill->ill_lock); 1166 11042 Erik for (ipif = rill->ill_ipif; ipif != NULL; 1167 11042 Erik ipif = ipif->ipif_next) { 1168 11042 Erik if (!(ipif->ipif_state_flags & IPIF_CONDEMNED) && 1169 11042 Erik IN6_IS_ADDR_LINKLOCAL(&ipif->ipif_v6lcl_addr)) 1170 11042 Erik break; 1171 11042 Erik } 1172 11042 Erik if (ipif == NULL) { 1173 11042 Erik /* We have no link-local address! */ 1174 11042 Erik mutex_exit(&rill->ill_lock); 1175 11042 Erik goto fail_redirect; 1176 11042 Erik } 1177 11042 Erik gw = ipif->ipif_v6lcl_addr; 1178 11042 Erik mutex_exit(&rill->ill_lock); 1179 11042 Erik 1180 0 stevel ire = ire_create_v6( 1181 0 stevel dst, /* gateway == dst */ 1182 0 stevel &ipv6_all_ones, /* mask */ 1183 11042 Erik &gw, /* gateway addr */ 1184 11042 Erik rill->ill_net_type, /* IF_[NO]RESOLVER */ 1185 11042 Erik prev_ire->ire_ill, 1186 11042 Erik ALL_ZONES, 1187 3004 dd193516 (RTF_DYNAMIC | RTF_HOST), 1188 3448 dh155122 NULL, 1189 3448 dh155122 ipst); 1190 0 stevel } 1191 3004 dd193516 1192 0 stevel if (ire == NULL) 1193 0 stevel goto fail_redirect; 1194 0 stevel 1195 11042 Erik nire = ire_add(ire); 1196 11042 Erik /* Check if it was a duplicate entry */ 1197 11042 Erik if (nire != NULL && nire != ire) { 1198 11042 Erik ASSERT(nire->ire_identical_ref > 1); 1199 11042 Erik ire_delete(nire); 1200 11042 Erik ire_refrele(nire); 1201 11042 Erik nire = NULL; 1202 11042 Erik } 1203 11042 Erik ire = nire; 1204 11042 Erik if (ire != NULL) { 1205 11042 Erik ire_refrele(ire); /* Held in ire_add */ 1206 0 stevel 1207 0 stevel /* tell routing sockets that we received a redirect */ 1208 0 stevel ip_rts_change_v6(RTM_REDIRECT, 1209 0 stevel &rd->nd_rd_dst, 1210 0 stevel &rd->nd_rd_target, 1211 11042 Erik &ipv6_all_ones, 0, src, 1212 0 stevel (RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST), 0, 1213 3448 dh155122 (RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_AUTHOR), ipst); 1214 0 stevel 1215 0 stevel /* 1216 3004 dd193516 * Delete any existing IRE_HOST type ires for this destination. 1217 0 stevel * This together with the added IRE has the effect of 1218 0 stevel * modifying an existing redirect. 1219 0 stevel */ 1220 3004 dd193516 redir_ire = ire_ftable_lookup_v6(dst, 0, src, IRE_HOST, 1221 11042 Erik prev_ire->ire_ill, ALL_ZONES, NULL, 1222 11042 Erik (MATCH_IRE_GW | MATCH_IRE_TYPE | MATCH_IRE_ILL), 0, ipst, 1223 11042 Erik NULL); 1224 0 stevel 1225 0 stevel if (redir_ire != NULL) { 1226 3004 dd193516 if (redir_ire->ire_flags & RTF_DYNAMIC) 1227 3004 dd193516 ire_delete(redir_ire); 1228 0 stevel ire_refrele(redir_ire); 1229 0 stevel } 1230 0 stevel } 1231 0 stevel 1232 0 stevel ire_refrele(prev_ire); 1233 0 stevel prev_ire = NULL; 1234 0 stevel 1235 0 stevel fail_redirect: 1236 0 stevel if (prev_ire != NULL) 1237 0 stevel ire_refrele(prev_ire); 1238 0 stevel freemsg(mp); 1239 11042 Erik if (rill != ira->ira_rill) 1240 11042 Erik ill_refrele(rill); 1241 0 stevel } 1242 0 stevel 1243 0 stevel /* 1244 0 stevel * Build and ship an IPv6 ICMP message using the packet data in mp, 1245 0 stevel * and the ICMP header pointed to by "stuff". (May be called as 1246 0 stevel * writer.) 1247 0 stevel * Note: assumes that icmp_pkt_err_ok_v6 has been called to 1248 0 stevel * verify that an icmp error packet can be sent. 1249 0 stevel * 1250 0 stevel * If v6src_ptr is set use it as a source. Otherwise select a reasonable 1251 0 stevel * source address (see above function). 1252 0 stevel */ 1253 0 stevel static void 1254 11042 Erik icmp_pkt_v6(mblk_t *mp, void *stuff, size_t len, 1255 11042 Erik const in6_addr_t *v6src_ptr, ip_recv_attr_t *ira) 1256 0 stevel { 1257 0 stevel ip6_t *ip6h; 1258 0 stevel in6_addr_t v6dst; 1259 0 stevel size_t len_needed; 1260 0 stevel size_t msg_len; 1261 0 stevel mblk_t *mp1; 1262 0 stevel icmp6_t *icmp6; 1263 0 stevel in6_addr_t v6src; 1264 11042 Erik ill_t *ill = ira->ira_ill; 1265 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 1266 11042 Erik ip_xmit_attr_t ixas; 1267 11042 Erik 1268 11042 Erik ip6h = (ip6_t *)mp->b_rptr; 1269 11042 Erik 1270 11042 Erik bzero(&ixas, sizeof (ixas)); 1271 11042 Erik ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6; 1272 11042 Erik ixas.ixa_zoneid = ira->ira_zoneid; 1273 11042 Erik ixas.ixa_ifindex = 0; 1274 11042 Erik ixas.ixa_ipst = ipst; 1275 11042 Erik ixas.ixa_cred = kcred; 1276 11042 Erik ixas.ixa_cpid = NOPID; 1277 11042 Erik ixas.ixa_tsl = ira->ira_tsl; /* Behave as a multi-level responder */ 1278 11042 Erik ixas.ixa_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; 1279 11042 Erik 1280 11042 Erik /* 1281 11042 Erik * If the source of the original packet was link-local, then 1282 11042 Erik * make sure we send on the same ill (group) as we received it on. 1283 11042 Erik */ 1284 11042 Erik if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) { 1285 11042 Erik ixas.ixa_flags |= IXAF_SCOPEID_SET; 1286 11042 Erik if (IS_UNDER_IPMP(ill)) 1287 11042 Erik ixas.ixa_scopeid = ill_get_upper_ifindex(ill); 1288 11042 Erik else 1289 11042 Erik ixas.ixa_scopeid = ill->ill_phyint->phyint_ifindex; 1290 11042 Erik } 1291 11042 Erik 1292 11042 Erik if (ira->ira_flags & IRAF_IPSEC_SECURE) { 1293 11042 Erik /* 1294 11042 Erik * Apply IPsec based on how IPsec was applied to 1295 11042 Erik * the packet that had the error. 1296 0 stevel * 1297 11042 Erik * If it was an outbound packet that caused the ICMP 1298 11042 Erik * error, then the caller will have setup the IRA 1299 11042 Erik * appropriately. 1300 11042 Erik */ 1301 11042 Erik if (!ipsec_in_to_out(ira, &ixas, mp, NULL, ip6h)) { 1302 11042 Erik BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards); 1303 11042 Erik /* Note: mp already consumed and ip_drop_packet done */ 1304 11042 Erik return; 1305 0 stevel } 1306 0 stevel } else { 1307 0 stevel /* 1308 0 stevel * This is in clear. The icmp message we are building 1309 11042 Erik * here should go out in clear, independent of our policy. 1310 11042 Erik */ 1311 11042 Erik ixas.ixa_flags |= IXAF_NO_IPSEC; 1312 11042 Erik } 1313 11042 Erik 1314 11042 Erik /* 1315 11042 Erik * If the caller specified the source we use that. 1316 11042 Erik * Otherwise, if the packet was for one of our unicast addresses, make 1317 11042 Erik * sure we respond with that as the source. Otherwise 1318 11042 Erik * have ip_output_simple pick the source address. 1319 11042 Erik */ 1320 0 stevel if (v6src_ptr != NULL) { 1321 0 stevel v6src = *v6src_ptr; 1322 0 stevel } else { 1323 11042 Erik ire_t *ire; 1324 11042 Erik uint_t match_flags = MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY; 1325 11042 Erik 1326 11042 Erik if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src) || 1327 11042 Erik IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_dst)) 1328 11042 Erik match_flags |= MATCH_IRE_ILL; 1329 11042 Erik 1330 11042 Erik ire = ire_ftable_lookup_v6(&ip6h->ip6_dst, 0, 0, 1331 11042 Erik (IRE_LOCAL|IRE_LOOPBACK), ill, ira->ira_zoneid, NULL, 1332 11042 Erik match_flags, 0, ipst, NULL); 1333 11042 Erik if (ire != NULL) { 1334 11042 Erik v6src = ip6h->ip6_dst; 1335 11042 Erik ire_refrele(ire); 1336 11042 Erik } else { 1337 11042 Erik v6src = ipv6_all_zeros; 1338 11042 Erik ixas.ixa_flags |= IXAF_SET_SOURCE; 1339 0 stevel } 1340 0 stevel } 1341 0 stevel v6dst = ip6h->ip6_src; 1342 3448 dh155122 len_needed = ipst->ips_ipv6_icmp_return - IPV6_HDR_LEN - len; 1343 0 stevel msg_len = msgdsize(mp); 1344 0 stevel if (msg_len > len_needed) { 1345 0 stevel if (!adjmsg(mp, len_needed - msg_len)) { 1346 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutErrors); 1347 11042 Erik freemsg(mp); 1348 0 stevel return; 1349 0 stevel } 1350 0 stevel msg_len = len_needed; 1351 0 stevel } 1352 11042 Erik mp1 = allocb(IPV6_HDR_LEN + len, BPRI_MED); 1353 0 stevel if (mp1 == NULL) { 1354 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutErrors); 1355 11042 Erik freemsg(mp); 1356 11042 Erik return; 1357 11042 Erik } 1358 0 stevel mp1->b_cont = mp; 1359 0 stevel mp = mp1; 1360 11042 Erik 1361 11042 Erik /* 1362 11042 Erik * Set IXAF_TRUSTED_ICMP so we can let the ICMP messages this 1363 0 stevel * node generates be accepted in peace by all on-host destinations. 1364 0 stevel * If we do NOT assume that all on-host destinations trust 1365 11042 Erik * self-generated ICMP messages, then rework here, ip6.c, and spd.c. 1366 11042 Erik * (Look for IXAF_TRUSTED_ICMP). 1367 11042 Erik */ 1368 11042 Erik ixas.ixa_flags |= IXAF_TRUSTED_ICMP; 1369 0 stevel 1370 0 stevel ip6h = (ip6_t *)mp->b_rptr; 1371 0 stevel mp1->b_wptr = (uchar_t *)ip6h + (IPV6_HDR_LEN + len); 1372 0 stevel 1373 0 stevel ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 1374 0 stevel ip6h->ip6_nxt = IPPROTO_ICMPV6; 1375 3448 dh155122 ip6h->ip6_hops = ipst->ips_ipv6_def_hops; 1376 0 stevel ip6h->ip6_dst = v6dst; 1377 0 stevel ip6h->ip6_src = v6src; 1378 0 stevel msg_len += IPV6_HDR_LEN + len; 1379 0 stevel if (msg_len > IP_MAXPACKET + IPV6_HDR_LEN) { 1380 0 stevel (void) adjmsg(mp, IP_MAXPACKET + IPV6_HDR_LEN - msg_len); 1381 0 stevel msg_len = IP_MAXPACKET + IPV6_HDR_LEN; 1382 0 stevel } 1383 0 stevel ip6h->ip6_plen = htons((uint16_t)(msgdsize(mp) - IPV6_HDR_LEN)); 1384 0 stevel icmp6 = (icmp6_t *)&ip6h[1]; 1385 0 stevel bcopy(stuff, (char *)icmp6, len); 1386 0 stevel /* 1387 0 stevel * Prepare for checksum by putting icmp length in the icmp 1388 11042 Erik * checksum field. The checksum is calculated in ip_output_wire_v6. 1389 0 stevel */ 1390 0 stevel icmp6->icmp6_cksum = ip6h->ip6_plen; 1391 0 stevel if (icmp6->icmp6_type == ND_REDIRECT) { 1392 0 stevel ip6h->ip6_hops = IPV6_MAX_HOPS; 1393 0 stevel } 1394 11042 Erik 1395 11042 Erik (void) ip_output_simple(mp, &ixas); 1396 11042 Erik ixa_cleanup(&ixas); 1397 0 stevel } 1398 0 stevel 1399 0 stevel /* 1400 0 stevel * Update the output mib when ICMPv6 packets are sent. 1401 0 stevel */ 1402 11042 Erik void 1403 0 stevel icmp_update_out_mib_v6(ill_t *ill, icmp6_t *icmp6) 1404 0 stevel { 1405 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutMsgs); 1406 0 stevel 1407 0 stevel switch (icmp6->icmp6_type) { 1408 0 stevel case ICMP6_DST_UNREACH: 1409 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutDestUnreachs); 1410 0 stevel if (icmp6->icmp6_code == ICMP6_DST_UNREACH_ADMIN) 1411 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutAdminProhibs); 1412 0 stevel break; 1413 0 stevel 1414 0 stevel case ICMP6_TIME_EXCEEDED: 1415 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutTimeExcds); 1416 0 stevel break; 1417 0 stevel 1418 0 stevel case ICMP6_PARAM_PROB: 1419 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutParmProblems); 1420 0 stevel break; 1421 0 stevel 1422 0 stevel case ICMP6_PACKET_TOO_BIG: 1423 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutPktTooBigs); 1424 0 stevel break; 1425 0 stevel 1426 0 stevel case ICMP6_ECHO_REQUEST: 1427 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutEchos); 1428 0 stevel break; 1429 0 stevel 1430 0 stevel case ICMP6_ECHO_REPLY: 1431 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutEchoReplies); 1432 0 stevel break; 1433 0 stevel 1434 0 stevel case ND_ROUTER_SOLICIT: 1435 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutRouterSolicits); 1436 0 stevel break; 1437 0 stevel 1438 0 stevel case ND_ROUTER_ADVERT: 1439 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutRouterAdvertisements); 1440 0 stevel break; 1441 0 stevel 1442 0 stevel case ND_NEIGHBOR_SOLICIT: 1443 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutNeighborSolicits); 1444 0 stevel break; 1445 0 stevel 1446 0 stevel case ND_NEIGHBOR_ADVERT: 1447 0 stevel BUMP_MIB(ill->ill_icmp6_mib, 1448 0 stevel ipv6IfIcmpOutNeighborAdvertisements); 1449 0 stevel break; 1450 0 stevel 1451 0 stevel case ND_REDIRECT: 1452 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutRedirects); 1453 0 stevel break; 1454 0 stevel 1455 0 stevel case MLD_LISTENER_QUERY: 1456 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutGroupMembQueries); 1457 0 stevel break; 1458 0 stevel 1459 0 stevel case MLD_LISTENER_REPORT: 1460 0 stevel case MLD_V2_LISTENER_REPORT: 1461 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutGroupMembResponses); 1462 0 stevel break; 1463 0 stevel 1464 0 stevel case MLD_LISTENER_REDUCTION: 1465 0 stevel BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutGroupMembReductions); 1466 0 stevel break; 1467 0 stevel } 1468 0 stevel } 1469 0 stevel 1470 0 stevel /* 1471 0 stevel * Check if it is ok to send an ICMPv6 error packet in 1472 0 stevel * response to the IP packet in mp. 1473 0 stevel * Free the message and return null if no 1474 0 stevel * ICMP error packet should be sent. 1475 0 stevel */ 1476 0 stevel static mblk_t * 1477 11042 Erik icmp_pkt_err_ok_v6(mblk_t *mp, boolean_t mcast_ok, ip_recv_attr_t *ira) 1478 11042 Erik { 1479 11042 Erik ill_t *ill = ira->ira_ill; 1480 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 1481 11042 Erik boolean_t llbcast; 1482 11042 Erik ip6_t *ip6h; 1483 0 stevel 1484 0 stevel if (!mp) 1485 0 stevel return (NULL); 1486 0 stevel 1487 11042 Erik /* We view multicast and broadcast as the same.. */ 1488 11042 Erik llbcast = (ira->ira_flags & 1489 11042 Erik (IRAF_L2DST_MULTICAST|IRAF_L2DST_BROADCAST)) != 0; 1490 0 stevel ip6h = (ip6_t *)mp->b_rptr; 1491 0 stevel 1492 0 stevel /* Check if source address uniquely identifies the host */ 1493 0 stevel 1494 0 stevel if (IN6_IS_ADDR_MULTICAST(&ip6h->ip6_src) || 1495 0 stevel IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_src) || 1496 0 stevel IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src)) { 1497 0 stevel freemsg(mp); 1498 0 stevel return (NULL); 1499 0 stevel } 1500 0 stevel 1501 0 stevel if (ip6h->ip6_nxt == IPPROTO_ICMPV6) { 1502 0 stevel size_t len_needed = IPV6_HDR_LEN + ICMP6_MINLEN; 1503 0 stevel icmp6_t *icmp6; 1504 0 stevel 1505 0 stevel if (mp->b_wptr - mp->b_rptr < len_needed) { 1506 0 stevel if (!pullupmsg(mp, len_needed)) { 1507 11042 Erik BUMP_MIB(ill->ill_icmp6_mib, 1508 11042 Erik ipv6IfIcmpInErrors); 1509 0 stevel freemsg(mp); 1510 0 stevel return (NULL); 1511 0 stevel } 1512 0 stevel ip6h = (ip6_t *)mp->b_rptr; 1513 0 stevel } 1514 0 stevel icmp6 = (icmp6_t *)&ip6h[1]; 1515 0 stevel /* Explicitly do not generate errors in response to redirects */ 1516 0 stevel if (ICMP6_IS_ERROR(icmp6->icmp6_type) || 1517 0 stevel icmp6->icmp6_type == ND_REDIRECT) { 1518 0 stevel freemsg(mp); 1519 0 stevel return (NULL); 1520 0 stevel } 1521 0 stevel } 1522 0 stevel /* 1523 0 stevel * Check that the destination is not multicast and that the packet 1524 0 stevel * was not sent on link layer broadcast or multicast. (Exception 1525 0 stevel * is Packet too big message as per the draft - when mcast_ok is set.) 1526 0 stevel */ 1527 0 stevel if (!mcast_ok && 1528 0 stevel (llbcast || IN6_IS_ADDR_MULTICAST(&ip6h->ip6_dst))) { 1529 0 stevel freemsg(mp); 1530 0 stevel return (NULL); 1531 0 stevel } 1532 11042 Erik /* 1533 11042 Erik * If this is a labeled system, then check to see if we're allowed to 1534 11042 Erik * send a response to this particular sender. If not, then just drop. 1535 11042 Erik */ 1536 11042 Erik if (is_system_labeled() && !tsol_can_reply_error(mp, ira)) { 1537 11042 Erik BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutErrors); 1538 11042 Erik freemsg(mp); 1539 11042 Erik return (NULL); 1540 11042 Erik } 1541 11042 Erik 1542 3448 dh155122 if (icmp_err_rate_limit(ipst)) { 1543 0 stevel /* 1544 0 stevel * Only send ICMP error packets every so often. 1545 0 stevel * This should be done on a per port/source basis, 1546 0 stevel * but for now this will suffice. 1547 0 stevel */ 1548 0 stevel freemsg(mp); 1549 0 stevel return (NULL); 1550 0 stevel } 1551 0 stevel return (mp); 1552 0 stevel } 1553 0 stevel 1554 0 stevel /* 1555 11042 Erik * Called when a packet was sent out the same link that it arrived on. 1556 11042 Erik * Check if it is ok to send a redirect and then send it. 1557 11042 Erik */ 1558 11042 Erik void 1559 11042 Erik ip_send_potential_redirect_v6(mblk_t *mp, ip6_t *ip6h, ire_t *ire, 1560 11042 Erik ip_recv_attr_t *ira) 1561 11042 Erik { 1562 11042 Erik ill_t *ill = ira->ira_ill; 1563 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 1564 11042 Erik in6_addr_t *v6targ; 1565 11042 Erik ire_t *src_ire_v6 = NULL; 1566 11042 Erik mblk_t *mp1; 1567 11042 Erik ire_t *nhop_ire = NULL; 1568 11042 Erik 1569 11042 Erik /* 1570 11042 Erik * Don't send a redirect when forwarding a source 1571 11042 Erik * routed packet. 1572 11042 Erik */ 1573 11042 Erik if (ip_source_routed_v6(ip6h, mp, ipst)) 1574 11042 Erik return; 1575 11042 Erik 1576 11042 Erik if (ire->ire_type & IRE_ONLINK) { 1577 11042 Erik /* Target is directly connected */ 1578 11042 Erik v6targ = &ip6h->ip6_dst; 1579 11042 Erik } else { 1580 11042 Erik /* Determine the most specific IRE used to send the packets */ 1581 11042 Erik nhop_ire = ire_nexthop(ire); 1582 11042 Erik if (nhop_ire == NULL) 1583 11042 Erik return; 1584 11042 Erik 1585 11042 Erik /* 1586 11042 Erik * We won't send redirects to a router 1587 11042 Erik * that doesn't have a link local 1588 11042 Erik * address, but will forward. 1589 11042 Erik */ 1590 11042 Erik if (!IN6_IS_ADDR_LINKLOCAL(&nhop_ire->ire_addr_v6)) { 1591 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInAddrErrors); 1592 11042 Erik ip_drop_input("ipIfStatsInAddrErrors", mp, ill); 1593 11042 Erik ire_refrele(nhop_ire); 1594 11042 Erik return; 1595 11042 Erik } 1596 11042 Erik v6targ = &nhop_ire->ire_addr_v6; 1597 11042 Erik } 1598 11042 Erik src_ire_v6 = ire_ftable_lookup_v6(&ip6h->ip6_src, 1599 11042 Erik NULL, NULL, IRE_INTERFACE, ire->ire_ill, ALL_ZONES, NULL, 1600 11042 Erik MATCH_IRE_ILL | MATCH_IRE_TYPE, 0, ipst, NULL); 1601 11042 Erik 1602 11042 Erik if (src_ire_v6 == NULL) { 1603 11042 Erik if (nhop_ire != NULL) 1604 11042 Erik ire_refrele(nhop_ire); 1605 11042 Erik return; 1606 11042 Erik } 1607 11042 Erik 1608 11042 Erik /* 1609 11042 Erik * The source is directly connected. 1610 11042 Erik */ 1611 11042 Erik mp1 = copymsg(mp); 1612 11042 Erik if (mp1 != NULL) 1613 11042 Erik icmp_send_redirect_v6(mp1, v6targ, &ip6h->ip6_dst, ira); 1614 11042 Erik 1615 11042 Erik if (nhop_ire != NULL) 1616 11042 Erik ire_refrele(nhop_ire); 1617 11042 Erik ire_refrele(src_ire_v6); 1618 11042 Erik } 1619 11042 Erik 1620 11042 Erik /* 1621 0 stevel * Generate an ICMPv6 redirect message. 1622 0 stevel * Include target link layer address option if it exits. 1623 0 stevel * Always include redirect header. 1624 0 stevel */ 1625 0 stevel static void 1626 11042 Erik icmp_send_redirect_v6(mblk_t *mp, in6_addr_t *targetp, in6_addr_t *dest, 1627 11042 Erik ip_recv_attr_t *ira) 1628 0 stevel { 1629 0 stevel nd_redirect_t *rd; 1630 0 stevel nd_opt_rd_hdr_t *rdh; 1631 0 stevel uchar_t *buf; 1632 11042 Erik ncec_t *ncec = NULL; 1633 0 stevel nd_opt_hdr_t *opt; 1634 0 stevel int len; 1635 0 stevel int ll_opt_len = 0; 1636 0 stevel int max_redir_hdr_data_len; 1637 0 stevel int pkt_len; 1638 0 stevel in6_addr_t *srcp; 1639 11042 Erik ill_t *ill; 1640 11042 Erik boolean_t need_refrele; 1641 11042 Erik ip_stack_t *ipst = ira->ira_ill->ill_ipst; 1642 11042 Erik 1643 11042 Erik mp = icmp_pkt_err_ok_v6(mp, B_FALSE, ira); 1644 11042 Erik if (mp == NULL) 1645 11042 Erik return; 1646 11042 Erik 1647 11042 Erik if (IS_UNDER_IPMP(ira->ira_ill)) { 1648 11042 Erik ill = ipmp_ill_hold_ipmp_ill(ira->ira_ill); 1649 11042 Erik if (ill == NULL) { 1650 11042 Erik ill = ira->ira_ill; 1651 11042 Erik BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInBadRedirects); 1652 11042 Erik ip_drop_output("no IPMP ill for sending redirect", 1653 11042 Erik mp, ill); 1654 11042 Erik freemsg(mp); 1655 11042 Erik return; 1656 11042 Erik } 1657 11042 Erik need_refrele = B_TRUE; 1658 11042 Erik } else { 1659 11042 Erik ill = ira->ira_ill; 1660 11042 Erik need_refrele = B_FALSE; 1661 11042 Erik } 1662 11042 Erik 1663 11042 Erik ncec = ncec_lookup_illgrp_v6(ill, targetp); 1664 11042 Erik if (ncec != NULL && ncec->ncec_state != ND_INCOMPLETE && 1665 11042 Erik ncec->ncec_lladdr != NULL) { 1666 0 stevel ll_opt_len = (sizeof (nd_opt_hdr_t) + 1667 0 stevel ill->ill_phys_addr_length + 7)/8 * 8; 1668 0 stevel } 1669 0 stevel len = sizeof (nd_redirect_t) + sizeof (nd_opt_rd_hdr_t) + ll_opt_len; 1670 0 stevel ASSERT(len % 4 == 0); 1671 0 stevel buf = kmem_alloc(len, KM_NOSLEEP); 1672 0 stevel if (buf == NULL) { 1673 11042 Erik if (ncec != NULL) 1674 11042 Erik ncec_refrele(ncec); 1675 11042 Erik if (need_refrele) 1676 11042 Erik ill_refrele(ill); 1677 0 stevel freemsg(mp); 1678 0 stevel return; 1679 0 stevel } 1680 0 stevel 1681 0 stevel rd = (nd_redirect_t *)buf; 1682 0 stevel rd->nd_rd_type = (uint8_t)ND_REDIRECT; 1683 0 stevel rd->nd_rd_code = 0; 1684 0 stevel rd->nd_rd_reserved = 0; 1685 0 stevel rd->nd_rd_target = *targetp; 1686 0 stevel rd->nd_rd_dst = *dest; 1687 0 stevel 1688 0 stevel opt = (nd_opt_hdr_t *)(buf + sizeof (nd_redirect_t)); 1689 11042 Erik if (ncec != NULL && ll_opt_len != 0) { 1690 0 stevel opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; 1691 0 stevel opt->nd_opt_len = ll_opt_len/8; 1692 11042 Erik bcopy((char *)ncec->ncec_lladdr, &opt[1], 1693 0 stevel ill->ill_phys_addr_length); 1694 0 stevel } 1695 11042 Erik if (ncec != NULL) 1696 11042 Erik ncec_refrele(ncec); 1697 0 stevel rdh = (nd_opt_rd_hdr_t *)(buf + sizeof (nd_redirect_t) + ll_opt_len); 1698 0 stevel rdh->nd_opt_rh_type = (uint8_t)ND_OPT_REDIRECTED_HEADER; 1699 0 stevel /* max_redir_hdr_data_len and nd_opt_rh_len must be multiple of 8 */ 1700 3448 dh155122 max_redir_hdr_data_len = 1701 3448 dh155122 (ipst->ips_ipv6_icmp_return - IPV6_HDR_LEN - len)/8*8; 1702 0 stevel pkt_len = msgdsize(mp); 1703 0 stevel /* Make sure mp is 8 byte aligned */ 1704 0 stevel if (pkt_len > max_redir_hdr_data_len) { 1705 0 stevel rdh->nd_opt_rh_len = (max_redir_hdr_data_len + 1706 0 stevel sizeof (nd_opt_rd_hdr_t))/8; 1707 0 stevel (void) adjmsg(mp, max_redir_hdr_data_len - pkt_len); 1708 0 stevel } else { 1709 0 stevel rdh->nd_opt_rh_len = (pkt_len + sizeof (nd_opt_rd_hdr_t))/8; 1710 0 stevel (void) adjmsg(mp, -(pkt_len % 8)); 1711 0 stevel } 1712 0 stevel rdh->nd_opt_rh_reserved1 = 0; 1713 0 stevel rdh->nd_opt_rh_reserved2 = 0; 1714 11042 Erik /* ipif_v6lcl_addr contains the link-local source address */ 1715 11042 Erik srcp = &ill->ill_ipif->ipif_v6lcl_addr; 1716 8485 Peter 1717 2733 nordmark /* Redirects sent by router, and router is global zone */ 1718 11042 Erik ASSERT(ira->ira_zoneid == ALL_ZONES); 1719 11042 Erik ira->ira_zoneid = GLOBAL_ZONEID; 1720 11042 Erik icmp_pkt_v6(mp, buf, len, srcp, ira); 1721 0 stevel kmem_free(buf, len); 1722 11042 Erik if (need_refrele) 1723 11042 Erik ill_refrele(ill); 1724 0 stevel } 1725 0 stevel 1726 0 stevel 1727 0 stevel /* Generate an ICMP time exceeded message. (May be called as writer.) */ 1728 0 stevel void 1729 11042 Erik icmp_time_exceeded_v6(mblk_t *mp, uint8_t code, boolean_t mcast_ok, 1730 11042 Erik ip_recv_attr_t *ira) 1731 0 stevel { 1732 0 stevel icmp6_t icmp6; 1733 11042 Erik 1734 11042 Erik mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira); 1735 11042 Erik if (mp == NULL) 1736 11042 Erik return; 1737 11042 Erik 1738 0 stevel bzero(&icmp6, sizeof (icmp6_t)); 1739 0 stevel icmp6.icmp6_type = ICMP6_TIME_EXCEEDED; 1740 0 stevel icmp6.icmp6_code = code; 1741 11042 Erik icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira); 1742 0 stevel } 1743 0 stevel 1744 0 stevel /* 1745 0 stevel * Generate an ICMP unreachable message. 1746 11042 Erik * When called from ip_output side a minimal ip_recv_attr_t needs to be 1747 11042 Erik * constructed by the caller. 1748 11042 Erik */ 1749 11042 Erik void 1750 11042 Erik icmp_unreachable_v6(mblk_t *mp, uint8_t code, boolean_t mcast_ok, 1751 11042 Erik ip_recv_attr_t *ira) 1752 0 stevel { 1753 0 stevel icmp6_t icmp6; 1754 11042 Erik 1755 11042 Erik mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira); 1756 11042 Erik if (mp == NULL) 1757 11042 Erik return; 1758 11042 Erik 1759 0 stevel bzero(&icmp6, sizeof (icmp6_t)); 1760 0 stevel icmp6.icmp6_type = ICMP6_DST_UNREACH; 1761 0 stevel icmp6.icmp6_code = code; 1762 11042 Erik icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira); 1763 0 stevel } 1764 0 stevel 1765 0 stevel /* 1766 0 stevel * Generate an ICMP pkt too big message. 1767 11042 Erik * When called from ip_output side a minimal ip_recv_attr_t needs to be 1768 11042 Erik * constructed by the caller. 1769 11042 Erik */ 1770 11042 Erik void 1771 11042 Erik icmp_pkt2big_v6(mblk_t *mp, uint32_t mtu, boolean_t mcast_ok, 1772 11042 Erik ip_recv_attr_t *ira) 1773 0 stevel { 1774 0 stevel icmp6_t icmp6; 1775 11042 Erik 1776 11042 Erik mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira); 1777 11042 Erik if (mp == NULL) 1778 11042 Erik return; 1779 11042 Erik 1780 0 stevel bzero(&icmp6, sizeof (icmp6_t)); 1781 0 stevel icmp6.icmp6_type = ICMP6_PACKET_TOO_BIG; 1782 0 stevel icmp6.icmp6_code = 0; 1783 0 stevel icmp6.icmp6_mtu = htonl(mtu); 1784 0 stevel 1785 11042 Erik icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira); 1786 0 stevel } 1787 0 stevel 1788 0 stevel /* 1789 0 stevel * Generate an ICMP parameter problem message. (May be called as writer.) 1790 0 stevel * 'offset' is the offset from the beginning of the packet in error. 1791 11042 Erik * When called from ip_output side a minimal ip_recv_attr_t needs to be 1792 11042 Erik * constructed by the caller. 1793 11042 Erik */ 1794 11042 Erik static void 1795 11042 Erik icmp_param_problem_v6(mblk_t *mp, uint8_t code, uint32_t offset, 1796 11042 Erik boolean_t mcast_ok, ip_recv_attr_t *ira) 1797 0 stevel { 1798 0 stevel icmp6_t icmp6; 1799 11042 Erik 1800 11042 Erik mp = icmp_pkt_err_ok_v6(mp, mcast_ok, ira); 1801 11042 Erik if (mp == NULL) 1802 11042 Erik return; 1803 11042 Erik 1804 0 stevel bzero((char *)&icmp6, sizeof (icmp6_t)); 1805 0 stevel icmp6.icmp6_type = ICMP6_PARAM_PROB; 1806 0 stevel icmp6.icmp6_code = code; 1807 0 stevel icmp6.icmp6_pptr = htonl(offset); 1808 11042 Erik icmp_pkt_v6(mp, &icmp6, sizeof (icmp6_t), NULL, ira); 1809 11042 Erik } 1810 11042 Erik 1811 11042 Erik void 1812 11042 Erik icmp_param_problem_nexthdr_v6(mblk_t *mp, boolean_t mcast_ok, 1813 11042 Erik ip_recv_attr_t *ira) 1814 11042 Erik { 1815 11042 Erik ip6_t *ip6h = (ip6_t *)mp->b_rptr; 1816 11042 Erik uint16_t hdr_length; 1817 11042 Erik uint8_t *nexthdrp; 1818 11042 Erik uint32_t offset; 1819 11042 Erik ill_t *ill = ira->ira_ill; 1820 11042 Erik 1821 11042 Erik /* Determine the offset of the bad nexthdr value */ 1822 11042 Erik if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp)) { 1823 11042 Erik /* Malformed packet */ 1824 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 1825 11042 Erik ip_drop_input("ipIfStatsInDiscards", mp, ill); 1826 11042 Erik freemsg(mp); 1827 11042 Erik return; 1828 11042 Erik } 1829 11042 Erik 1830 11042 Erik offset = nexthdrp - mp->b_rptr; 1831 11042 Erik icmp_param_problem_v6(mp, ICMP6_PARAMPROB_NEXTHEADER, offset, 1832 11042 Erik mcast_ok, ira); 1833 11042 Erik } 1834 11042 Erik 1835 11042 Erik /* 1836 11042 Erik * Verify whether or not the IP address is a valid local address. 1837 11042 Erik * Could be a unicast, including one for a down interface. 1838 11042 Erik * If allow_mcbc then a multicast or broadcast address is also 1839 11042 Erik * acceptable. 1840 11042 Erik * 1841 0 stevel * In the case of a multicast address, however, the 1842 0 stevel * upper protocol is expected to reset the src address 1843 11042 Erik * to zero when we return IPVL_MCAST so that 1844 0 stevel * no packets are emitted with multicast address as 1845 0 stevel * source address. 1846 0 stevel * The addresses valid for bind are: 1847 0 stevel * (1) - in6addr_any 1848 0 stevel * (2) - IP address of an UP interface 1849 0 stevel * (3) - IP address of a DOWN interface 1850 0 stevel * (4) - a multicast address. In this case 1851 0 stevel * the conn will only receive packets destined to 1852 0 stevel * the specified multicast address. Note: the 1853 0 stevel * application still has to issue an 1854 0 stevel * IPV6_JOIN_GROUP socket option. 1855 0 stevel * 1856 0 stevel * In all the above cases, the bound address must be valid in the current zone. 1857 0 stevel * When the address is loopback or multicast, there might be many matching IREs 1858 0 stevel * so bind has to look up based on the zone. 1859 0 stevel */ 1860 11042 Erik ip_laddr_t 1861 11042 Erik ip_laddr_verify_v6(const in6_addr_t *v6src, zoneid_t zoneid, 1862 11042 Erik ip_stack_t *ipst, boolean_t allow_mcbc, uint_t scopeid) 1863 11042 Erik { 1864 11042 Erik ire_t *src_ire; 1865 11042 Erik uint_t match_flags; 1866 11042 Erik ill_t *ill = NULL; 1867 11042 Erik 1868 11042 Erik ASSERT(!IN6_IS_ADDR_V4MAPPED(v6src)); 1869 11042 Erik ASSERT(!IN6_IS_ADDR_UNSPECIFIED(v6src)); 1870 11042 Erik 1871 11042 Erik match_flags = MATCH_IRE_ZONEONLY; 1872 11042 Erik if (scopeid != 0) { 1873 11042 Erik ill = ill_lookup_on_ifindex(scopeid, B_TRUE, ipst); 1874 11042 Erik if (ill == NULL) 1875 11042 Erik return (IPVL_BAD); 1876 11042 Erik match_flags |= MATCH_IRE_ILL; 1877 11042 Erik } 1878 11042 Erik 1879 11042 Erik src_ire = ire_ftable_lookup_v6(v6src, NULL, NULL, 0, 1880 11042 Erik ill, zoneid, NULL, match_flags, 0, ipst, NULL); 1881 11042 Erik if (ill != NULL) 1882 11042 Erik ill_refrele(ill); 1883 11042 Erik 1884 11042 Erik /* 1885 11042 Erik * If an address other than in6addr_any is requested, 1886 11042 Erik * we verify that it is a valid address for bind 1887 11042 Erik * Note: Following code is in if-else-if form for 1888 11042 Erik * readability compared to a condition check. 1889 11042 Erik */ 1890 11042 Erik if (src_ire != NULL && (src_ire->ire_type & (IRE_LOCAL|IRE_LOOPBACK))) { 1891 11042 Erik /* 1892 11042 Erik * (2) Bind to address of local UP interface 1893 11042 Erik */ 1894 11042 Erik ire_refrele(src_ire); 1895 11042 Erik return (IPVL_UNICAST_UP); 1896 11042 Erik } else if (IN6_IS_ADDR_MULTICAST(v6src)) { 1897 11042 Erik /* (4) bind to multicast address. */ 1898 11042 Erik if (src_ire != NULL) 1899 11042 Erik ire_refrele(src_ire); 1900 11042 Erik 1901 11042 Erik /* 1902 11042 Erik * Note: caller should take IPV6_MULTICAST_IF 1903 11042 Erik * into account when selecting a real source address. 1904 11042 Erik */ 1905 11042 Erik if (allow_mcbc) 1906 11042 Erik return (IPVL_MCAST); 1907 11042 Erik else 1908 11042 Erik return (IPVL_BAD); 1909 11042 Erik } else { 1910 11042 Erik ipif_t *ipif; 1911 11042 Erik 1912 11042 Erik /* 1913 11042 Erik * (3) Bind to address of local DOWN interface? 1914 11042 Erik * (ipif_lookup_addr() looks up all interfaces 1915 11042 Erik * but we do not get here for UP interfaces 1916 11042 Erik * - case (2) above) 1917 11042 Erik */ 1918 11042 Erik if (src_ire != NULL) 1919 11042 Erik ire_refrele(src_ire); 1920 11042 Erik 1921 11042 Erik ipif = ipif_lookup_addr_v6(v6src, NULL, zoneid, ipst); 1922 11042 Erik if (ipif == NULL) 1923 11042 Erik return (IPVL_BAD); 1924 11042 Erik 1925 11042 Erik /* Not a useful source? */ 1926 11042 Erik if (ipif->ipif_flags & (IPIF_NOLOCAL | IPIF_ANYCAST)) { 1927 11042 Erik ipif_refrele(ipif); 1928 11042 Erik return (IPVL_BAD); 1929 11042 Erik } 1930 11042 Erik ipif_refrele(ipif); 1931 11042 Erik return (IPVL_UNICAST_DOWN); 1932 11042 Erik } 1933 11042 Erik } 1934 11042 Erik 1935 11042 Erik /* 1936 11042 Erik * Verify that both the source and destination addresses are valid. If 1937 11042 Erik * IPDF_VERIFY_DST is not set, then the destination address may be unreachable, 1938 11042 Erik * i.e. have no route to it. Protocols like TCP want to verify destination 1939 11042 Erik * reachability, while tunnels do not. 1940 11042 Erik * 1941 11042 Erik * Determine the route, the interface, and (optionally) the source address 1942 11042 Erik * to use to reach a given destination. 1943 11042 Erik * Note that we allow connect to broadcast and multicast addresses when 1944 11042 Erik * IPDF_ALLOW_MCBC is set. 1945 11042 Erik * first_hop and dst_addr are normally the same, but if source routing 1946 11042 Erik * they will differ; in that case the first_hop is what we'll use for the 1947 11042 Erik * routing lookup but the dce and label checks will be done on dst_addr, 1948 11042 Erik * 1949 11042 Erik * If uinfo is set, then we fill in the best available information 1950 11042 Erik * we have for the destination. This is based on (in priority order) any 1951 11042 Erik * metrics and path MTU stored in a dce_t, route metrics, and finally the 1952 11042 Erik * ill_mtu. 1953 11042 Erik * 1954 11042 Erik * Tsol note: If we have a source route then dst_addr != firsthop. But we 1955 11042 Erik * always do the label check on dst_addr. 1956 11042 Erik * 1957 11042 Erik * Assumes that the caller has set ixa_scopeid for link-local communication. 1958 11042 Erik */ 1959 11042 Erik int 1960 11042 Erik ip_set_destination_v6(in6_addr_t *src_addrp, const in6_addr_t *dst_addr, 1961 11042 Erik const in6_addr_t *firsthop, ip_xmit_attr_t *ixa, iulp_t *uinfo, 1962 11042 Erik uint32_t flags, uint_t mac_mode) 1963 11042 Erik { 1964 11042 Erik ire_t *ire; 1965 0 stevel int error = 0; 1966 11042 Erik in6_addr_t setsrc; /* RTF_SETSRC */ 1967 11042 Erik zoneid_t zoneid = ixa->ixa_zoneid; /* Honors SO_ALLZONES */ 1968 11042 Erik ip_stack_t *ipst = ixa->ixa_ipst; 1969 11042 Erik dce_t *dce; 1970 11042 Erik uint_t pmtu; 1971 11042 Erik uint_t ifindex; 1972 11042 Erik uint_t generation; 1973 11042 Erik nce_t *nce; 1974 11042 Erik ill_t *ill = NULL; 1975 11042 Erik boolean_t multirt = B_FALSE; 1976 11042 Erik 1977 11042 Erik ASSERT(!IN6_IS_ADDR_V4MAPPED(dst_addr)); 1978 11042 Erik 1979 11042 Erik ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4)); 1980 11042 Erik 1981 11042 Erik /* 1982 11042 Erik * We never send to zero; the ULPs map it to the loopback address. 1983 11042 Erik * We can't allow it since we use zero to mean unitialized in some 1984 11042 Erik * places. 1985 11042 Erik */ 1986 11042 Erik ASSERT(!IN6_IS_ADDR_UNSPECIFIED(dst_addr)); 1987 11042 Erik 1988 11042 Erik if (is_system_labeled()) { 1989 11042 Erik ts_label_t *tsl = NULL; 1990 11042 Erik 1991 11042 Erik error = tsol_check_dest(ixa->ixa_tsl, dst_addr, IPV6_VERSION, 1992 11042 Erik mac_mode, (flags & IPDF_ZONE_IS_GLOBAL) != 0, &tsl); 1993 8348 Eric if (error != 0) 1994 11042 Erik return (error); 1995 11042 Erik if (tsl != NULL) { 1996 11042 Erik /* Update the label */ 1997 11042 Erik ip_xmit_attr_replace_tsl(ixa, tsl); 1998 11042 Erik } 1999 11042 Erik } 2000 11042 Erik 2001 11042 Erik setsrc = ipv6_all_zeros; 2002 11042 Erik /* 2003 11042 Erik * Select a route; For IPMP interfaces, we would only select 2004 11042 Erik * a "hidden" route (i.e., going through a specific under_ill) 2005 11042 Erik * if ixa_ifindex has been specified. 2006 11042 Erik */ 2007 11042 Erik ire = ip_select_route_v6(firsthop, ixa, &generation, &setsrc, &error, 2008 11042 Erik &multirt); 2009 11042 Erik ASSERT(ire != NULL); /* IRE_NOROUTE if none found */ 2010 11042 Erik if (error != 0) 2011 11042 Erik goto bad_addr; 2012 11042 Erik 2013 11042 Erik /* 2014 11042 Erik * ire can't be a broadcast or multicast unless IPDF_ALLOW_MCBC is set. 2015 11042 Erik * If IPDF_VERIFY_DST is set, the destination must be reachable. 2016 11042 Erik * Otherwise the destination needn't be reachable. 2017 9710 Ken * 2018 11042 Erik * If we match on a reject or black hole, then we've got a 2019 11042 Erik * local failure. May as well fail out the connect() attempt, 2020 11042 Erik * since it's never going to succeed. 2021 11042 Erik */ 2022 11042 Erik if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 2023 11042 Erik /* 2024 11042 Erik * If we're verifying destination reachability, we always want 2025 11042 Erik * to complain here. 2026 0 stevel * 2027 11042 Erik * If we're not verifying destination reachability but the 2028 11042 Erik * destination has a route, we still want to fail on the 2029 11042 Erik * temporary address and broadcast address tests. 2030 11042 Erik * 2031 11042 Erik * In both cases do we let the code continue so some reasonable 2032 11042 Erik * information is returned to the caller. That enables the 2033 11042 Erik * caller to use (and even cache) the IRE. conn_ip_ouput will 2034 11042 Erik * use the generation mismatch path to check for the unreachable 2035 11042 Erik * case thereby avoiding any specific check in the main path. 2036 11042 Erik */ 2037 11042 Erik ASSERT(generation == IRE_GENERATION_VERIFY); 2038 11042 Erik if (flags & IPDF_VERIFY_DST) { 2039 11042 Erik /* 2040 11042 Erik * Set errno but continue to set up ixa_ire to be 2041 11042 Erik * the RTF_REJECT|RTF_BLACKHOLE IRE. 2042 11042 Erik * That allows callers to use ip_output to get an 2043 11042 Erik * ICMP error back. 2044 11042 Erik */ 2045 11042 Erik if (!(ire->ire_type & IRE_HOST)) 2046 0 stevel error = ENETUNREACH; 2047 0 stevel else 2048 0 stevel error = EHOSTUNREACH; 2049 11042 Erik } 2050 11042 Erik } 2051 11042 Erik 2052 11042 Erik if ((ire->ire_type & (IRE_BROADCAST|IRE_MULTICAST)) && 2053 11042 Erik !(flags & IPDF_ALLOW_MCBC)) { 2054 11042 Erik ire_refrele(ire); 2055 11042 Erik ire = ire_reject(ipst, B_FALSE); 2056 11042 Erik generation = IRE_GENERATION_VERIFY; 2057 11042 Erik error = ENETUNREACH; 2058 11042 Erik } 2059 11042 Erik 2060 11042 Erik /* Cache things */ 2061 11042 Erik if (ixa->ixa_ire != NULL) 2062 11042 Erik ire_refrele_notr(ixa->ixa_ire); 2063 11042 Erik #ifdef DEBUG 2064 11042 Erik ire_refhold_notr(ire); 2065 11042 Erik ire_refrele(ire); 2066 11042 Erik #endif 2067 11042 Erik ixa->ixa_ire = ire; 2068 11042 Erik ixa->ixa_ire_generation = generation; 2069 11042 Erik 2070 11042 Erik /* 2071 11042 Erik * For multicast with multirt we have a flag passed back from 2072 11042 Erik * ire_lookup_multi_ill_v6 since we don't have an IRE for each 2073 11042 Erik * possible multicast address. 2074 11042 Erik * We also need a flag for multicast since we can't check 2075 11042 Erik * whether RTF_MULTIRT is set in ixa_ire for multicast. 2076 11042 Erik */ 2077 11042 Erik if (multirt) { 2078 11042 Erik ixa->ixa_postfragfn = ip_postfrag_multirt_v6; 2079 11042 Erik ixa->ixa_flags |= IXAF_MULTIRT_MULTICAST; 2080 11042 Erik } else { 2081 11042 Erik ixa->ixa_postfragfn = ire->ire_postfragfn; 2082 11042 Erik ixa->ixa_flags &= ~IXAF_MULTIRT_MULTICAST; 2083 11042 Erik } 2084 11042 Erik if (!(ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE))) { 2085 11042 Erik /* Get an nce to cache. */ 2086 11042 Erik nce = ire_to_nce(ire, NULL, firsthop); 2087 11042 Erik if (nce == NULL) { 2088 11042 Erik /* Allocation failure? */ 2089 11042 Erik ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; 2090 11042 Erik } else { 2091 11042 Erik if (ixa->ixa_nce != NULL) 2092 11042 Erik nce_refrele(ixa->ixa_nce); 2093 11042 Erik ixa->ixa_nce = nce; 2094 11042 Erik } 2095 11042 Erik } 2096 11042 Erik 2097 11042 Erik /* 2098 0 stevel * If the source address is a loopback address, the 2099 0 stevel * destination had best be local or multicast. 2100 11042 Erik * If we are sending to an IRE_LOCAL using a loopback source then 2101 11042 Erik * it had better be the same zoneid. 2102 11042 Erik */ 2103 11042 Erik if (IN6_IS_ADDR_LOOPBACK(src_addrp)) { 2104 11042 Erik if ((ire->ire_type & IRE_LOCAL) && ire->ire_zoneid != zoneid) { 2105 11042 Erik ire = NULL; /* Stored in ixa_ire */ 2106 11042 Erik error = EADDRNOTAVAIL; 2107 0 stevel goto bad_addr; 2108 0 stevel } 2109 11042 Erik if (!(ire->ire_type & (IRE_LOOPBACK|IRE_LOCAL|IRE_MULTICAST))) { 2110 11042 Erik ire = NULL; /* Stored in ixa_ire */ 2111 11042 Erik error = EADDRNOTAVAIL; 2112 0 stevel goto bad_addr; 2113 0 stevel } 2114 0 stevel } 2115 0 stevel 2116 0 stevel /* 2117 11042 Erik * Does the caller want us to pick a source address? 2118 11042 Erik */ 2119 11042 Erik if (flags & IPDF_SELECT_SRC) { 2120 11042 Erik in6_addr_t src_addr; 2121 11131 Erik 2122 11131 Erik /* 2123 11131 Erik * We use use ire_nexthop_ill to avoid the under ipmp 2124 11131 Erik * interface for source address selection. Note that for ipmp 2125 11131 Erik * probe packets, ixa_ifindex would have been specified, and 2126 11131 Erik * the ip_select_route() invocation would have picked an ire 2127 11131 Erik * will ire_ill pointing at an under interface. 2128 11131 Erik */ 2129 11131 Erik ill = ire_nexthop_ill(ire); 2130 11042 Erik 2131 11042 Erik /* If unreachable we have no ill but need some source */ 2132 11042 Erik if (ill == NULL) { 2133 11042 Erik src_addr = ipv6_loopback; 2134 11042 Erik /* Make sure we look for a better source address */ 2135 11042 Erik generation = SRC_GENERATION_VERIFY; 2136 11042 Erik } else { 2137 11042 Erik error = ip_select_source_v6(ill, &setsrc, dst_addr, 2138 11042 Erik zoneid, ipst, B_FALSE, ixa->ixa_src_preferences, 2139 11042 Erik &src_addr, &generation, NULL); 2140 11042 Erik if (error != 0) { 2141 11042 Erik ire = NULL; /* Stored in ixa_ire */ 2142 11042 Erik goto bad_addr; 2143 11042 Erik } 2144 11042 Erik } 2145 11042 Erik 2146 11042 Erik /* 2147 11042 Erik * We allow the source address to to down. 2148 11042 Erik * However, we check that we don't use the loopback address 2149 11042 Erik * as a source when sending out on the wire. 2150 11042 Erik */ 2151 11042 Erik if (IN6_IS_ADDR_LOOPBACK(&src_addr) && 2152 11042 Erik !(ire->ire_type & (IRE_LOCAL|IRE_LOOPBACK|IRE_MULTICAST)) && 2153 11042 Erik !(ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE))) { 2154 11042 Erik ire = NULL; /* Stored in ixa_ire */ 2155 11042 Erik error = EADDRNOTAVAIL; 2156 11042 Erik goto bad_addr; 2157 11042 Erik } 2158 11042 Erik 2159 11042 Erik *src_addrp = src_addr; 2160 11042 Erik ixa->ixa_src_generation = generation; 2161 11042 Erik } 2162 11042 Erik 2163 11042 Erik /* 2164 11042 Erik * Make sure we don't leave an unreachable ixa_nce in place 2165 11042 Erik * since ip_select_route is used when we unplumb i.e., remove 2166 11042 Erik * references on ixa_ire, ixa_nce, and ixa_dce. 2167 11042 Erik */ 2168 11042 Erik nce = ixa->ixa_nce; 2169 11042 Erik if (nce != NULL && nce->nce_is_condemned) { 2170 11042 Erik nce_refrele(nce); 2171 11042 Erik ixa->ixa_nce = NULL; 2172 11042 Erik ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; 2173 11042 Erik } 2174 11042 Erik 2175 11042 Erik 2176 11042 Erik ifindex = 0; 2177 11042 Erik if (IN6_IS_ADDR_LINKSCOPE(dst_addr)) { 2178 11042 Erik /* If we are creating a DCE we'd better have an ifindex */ 2179 11042 Erik if (ill != NULL) 2180 11042 Erik ifindex = ill->ill_phyint->phyint_ifindex; 2181 11042 Erik else 2182 11042 Erik flags &= ~IPDF_UNIQUE_DCE; 2183 11042 Erik } 2184 11042 Erik 2185 11042 Erik if (flags & IPDF_UNIQUE_DCE) { 2186 11042 Erik /* Fallback to the default dce if allocation fails */ 2187 11042 Erik dce = dce_lookup_and_add_v6(dst_addr, ifindex, ipst); 2188 11042 Erik if (dce != NULL) { 2189 11042 Erik generation = dce->dce_generation; 2190 11042 Erik } else { 2191 11042 Erik dce = dce_lookup_v6(dst_addr, ifindex, ipst, 2192 11042 Erik &generation); 2193 11042 Erik } 2194 11042 Erik } else { 2195 11042 Erik dce = dce_lookup_v6(dst_addr, ifindex, ipst, &generation); 2196 11042 Erik } 2197 11042 Erik ASSERT(dce != NULL); 2198 11042 Erik if (ixa->ixa_dce != NULL) 2199 11042 Erik dce_refrele_notr(ixa->ixa_dce); 2200 11042 Erik #ifdef DEBUG 2201 11042 Erik dce_refhold_notr(dce); 2202 11042 Erik dce_refrele(dce); 2203 11042 Erik #endif 2204 11042 Erik ixa->ixa_dce = dce; 2205 11042 Erik ixa->ixa_dce_generation = generation; 2206 11042 Erik 2207 11042 Erik /* 2208 11042 Erik * Note that IPv6 multicast supports PMTU discovery unlike IPv4 2209 11042 Erik * multicast. But pmtu discovery is only enabled for connected 2210 11042 Erik * sockets in general. 2211 11042 Erik */ 2212 11042 Erik 2213 11042 Erik /* 2214 11042 Erik * Set initial value for fragmentation limit. Either conn_ip_output 2215 11042 Erik * or ULP might updates it when there are routing changes. 2216 11042 Erik * Handles a NULL ixa_ire->ire_ill or a NULL ixa_nce for RTF_REJECT. 2217 11042 Erik */ 2218 11042 Erik pmtu = ip_get_pmtu(ixa); 2219 11042 Erik ixa->ixa_fragsize = pmtu; 2220 11042 Erik /* Make sure ixa_fragsize and ixa_pmtu remain identical */ 2221 11042 Erik if (ixa->ixa_flags & IXAF_VERIFY_PMTU) 2222 11042 Erik ixa->ixa_pmtu = pmtu; 2223 11042 Erik 2224 11042 Erik /* 2225 11042 Erik * Extract information useful for some transports. 2226 11042 Erik * First we look for DCE metrics. Then we take what we have in 2227 11042 Erik * the metrics in the route, where the offlink is used if we have 2228 11042 Erik * one. 2229 11042 Erik */ 2230 11042 Erik if (uinfo != NULL) { 2231 11042 Erik bzero(uinfo, sizeof (*uinfo)); 2232 11042 Erik 2233 11042 Erik if (dce->dce_flags & DCEF_UINFO) 2234 11042 Erik *uinfo = dce->dce_uinfo; 2235 11042 Erik 2236 11042 Erik rts_merge_metrics(uinfo, &ire->ire_metrics); 2237 11042 Erik 2238 11042 Erik /* Allow ire_metrics to decrease the path MTU from above */ 2239 11042 Erik if (uinfo->iulp_mtu == 0 || uinfo->iulp_mtu > pmtu) 2240 11042 Erik uinfo->iulp_mtu = pmtu; 2241 11042 Erik 2242 11042 Erik uinfo->iulp_localnet = (ire->ire_type & IRE_ONLINK) != 0; 2243 11042 Erik uinfo->iulp_loopback = (ire->ire_type & IRE_LOOPBACK) != 0; 2244 11042 Erik uinfo->iulp_local = (ire->ire_type & IRE_LOCAL) != 0; 2245 11042 Erik } 2246 11042 Erik 2247 11042 Erik if (ill != NULL) 2248 11042 Erik ill_refrele(ill); 2249 11042 Erik 2250 11042 Erik return (error); 2251 11042 Erik 2252 0 stevel bad_addr: 2253 11042 Erik if (ire != NULL) 2254 11042 Erik ire_refrele(ire); 2255 11042 Erik 2256 11042 Erik if (ill != NULL) 2257 11042 Erik ill_refrele(ill); 2258 11042 Erik 2259 11042 Erik /* 2260 11042 Erik * Make sure we don't leave an unreachable ixa_nce in place 2261 11042 Erik * since ip_select_route is used when we unplumb i.e., remove 2262 11042 Erik * references on ixa_ire, ixa_nce, and ixa_dce. 2263 11042 Erik */ 2264 11042 Erik nce = ixa->ixa_nce; 2265 11042 Erik if (nce != NULL && nce->nce_is_condemned) { 2266 11042 Erik nce_refrele(nce); 2267 11042 Erik ixa->ixa_nce = NULL; 2268 11042 Erik ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; 2269 11042 Erik } 2270 11042 Erik 2271 0 stevel return (error); 2272 0 stevel } 2273 0 stevel 2274 0 stevel /* 2275 0 stevel * Handle protocols with which IP is less intimate. There 2276 0 stevel * can be more than one stream bound to a particular 2277 0 stevel * protocol. When this is the case, normally each one gets a copy 2278 0 stevel * of any incoming packets. 2279 0 stevel * 2280 0 stevel * Zones notes: 2281 11042 Erik * Packets will be distributed to conns in all zones. This is really only 2282 0 stevel * useful for ICMPv6 as only applications in the global zone can create raw 2283 0 stevel * sockets for other protocols. 2284 0 stevel */ 2285 11042 Erik void 2286 11042 Erik ip_fanout_proto_v6(mblk_t *mp, ip6_t *ip6h, ip_recv_attr_t *ira) 2287 11042 Erik { 2288 11042 Erik mblk_t *mp1; 2289 11042 Erik in6_addr_t laddr = ip6h->ip6_dst; 2290 11042 Erik conn_t *connp, *first_connp, *next_connp; 2291 11042 Erik connf_t *connfp; 2292 11042 Erik ill_t *ill = ira->ira_ill; 2293 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 2294 11042 Erik 2295 11042 Erik connfp = &ipst->ips_ipcl_proto_fanout_v6[ira->ira_protocol]; 2296 0 stevel mutex_enter(&connfp->connf_lock); 2297 0 stevel connp = connfp->connf_head; 2298 0 stevel for (connp = connfp->connf_head; connp != NULL; 2299 4459 kcpoon connp = connp->conn_next) { 2300 11042 Erik /* Note: IPCL_PROTO_MATCH_V6 includes conn_wantpacket */ 2301 11042 Erik if (IPCL_PROTO_MATCH_V6(connp, ira, ip6h) && 2302 11042 Erik (!(ira->ira_flags & IRAF_SYSTEM_LABELED) || 2303 11042 Erik tsol_receive_local(mp, &laddr, IPV6_VERSION, ira, connp))) 2304 0 stevel break; 2305 0 stevel } 2306 0 stevel 2307 8348 Eric if (connp == NULL) { 2308 0 stevel /* 2309 0 stevel * No one bound to this port. Is 2310 0 stevel * there a client that wants all 2311 0 stevel * unclaimed datagrams? 2312 0 stevel */ 2313 0 stevel mutex_exit(&connfp->connf_lock); 2314 11042 Erik ip_fanout_send_icmp_v6(mp, ICMP6_PARAM_PROB, 2315 11042 Erik ICMP6_PARAMPROB_NEXTHEADER, ira); 2316 11042 Erik return; 2317 11042 Erik } 2318 11042 Erik 2319 11042 Erik ASSERT(IPCL_IS_NONSTR(connp) || connp->conn_rq != NULL); 2320 0 stevel 2321 0 stevel CONN_INC_REF(connp); 2322 0 stevel first_connp = connp; 2323 0 stevel 2324 0 stevel /* 2325 0 stevel * XXX: Fix the multiple protocol listeners case. We should not 2326 11042 Erik * be walking the conn->conn_next list here. 2327 0 stevel */ 2328 10616 Sebastien connp = connp->conn_next; 2329 0 stevel for (;;) { 2330 0 stevel while (connp != NULL) { 2331 11042 Erik /* Note: IPCL_PROTO_MATCH_V6 includes conn_wantpacket */ 2332 11042 Erik if (IPCL_PROTO_MATCH_V6(connp, ira, ip6h) && 2333 11042 Erik (!(ira->ira_flags & IRAF_SYSTEM_LABELED) || 2334 11042 Erik tsol_receive_local(mp, &laddr, IPV6_VERSION, 2335 11042 Erik ira, connp))) 2336 0 stevel break; 2337 0 stevel connp = connp->conn_next; 2338 0 stevel } 2339 0 stevel 2340 11042 Erik if (connp == NULL) { 2341 11042 Erik /* No more interested clients */ 2342 0 stevel connp = first_connp; 2343 0 stevel break; 2344 0 stevel } 2345 11042 Erik if (((mp1 = dupmsg(mp)) == NULL) && 2346 11042 Erik ((mp1 = copymsg(mp)) == NULL)) { 2347 11042 Erik /* Memory allocation failed */ 2348 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 2349 11042 Erik ip_drop_input("ipIfStatsInDiscards", mp, ill); 2350 11042 Erik connp = first_connp; 2351 11042 Erik break; 2352 11042 Erik } 2353 11042 Erik 2354 0 stevel CONN_INC_REF(connp); 2355 0 stevel mutex_exit(&connfp->connf_lock); 2356 11042 Erik 2357 11042 Erik ip_fanout_proto_conn(connp, mp1, NULL, (ip6_t *)mp1->b_rptr, 2358 11042 Erik ira); 2359 11042 Erik 2360 0 stevel mutex_enter(&connfp->connf_lock); 2361 0 stevel /* Follow the next pointer before releasing the conn. */ 2362 0 stevel next_connp = connp->conn_next; 2363 0 stevel CONN_DEC_REF(connp); 2364 0 stevel connp = next_connp; 2365 0 stevel } 2366 0 stevel 2367 0 stevel /* Last one. Send it upstream. */ 2368 0 stevel mutex_exit(&connfp->connf_lock); 2369 0 stevel 2370 11042 Erik ip_fanout_proto_conn(connp, mp, NULL, ip6h, ira); 2371 11042 Erik 2372 0 stevel CONN_DEC_REF(connp); 2373 0 stevel } 2374 0 stevel 2375 0 stevel /* 2376 11042 Erik * Called when it is conceptually a ULP that would sent the packet 2377 11042 Erik * e.g., port unreachable and nexthdr unknown. Check that the packet 2378 11042 Erik * would have passed the IPsec global policy before sending the error. 2379 11042 Erik * 2380 11042 Erik * Send an ICMP error after patching up the packet appropriately. 2381 11042 Erik * Uses ip_drop_input and bumps the appropriate MIB. 2382 11042 Erik * For ICMP6_PARAMPROB_NEXTHEADER we determine the offset to use. 2383 11042 Erik */ 2384 11042 Erik void 2385 11042 Erik ip_fanout_send_icmp_v6(mblk_t *mp, uint_t icmp_type, uint8_t icmp_code, 2386 11042 Erik ip_recv_attr_t *ira) 2387 11042 Erik { 2388 11042 Erik ip6_t *ip6h; 2389 11042 Erik boolean_t secure; 2390 11042 Erik ill_t *ill = ira->ira_ill; 2391 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 2392 11042 Erik netstack_t *ns = ipst->ips_netstack; 2393 11042 Erik ipsec_stack_t *ipss = ns->netstack_ipsec; 2394 11042 Erik 2395 11042 Erik secure = ira->ira_flags & IRAF_IPSEC_SECURE; 2396 11042 Erik 2397 0 stevel /* 2398 0 stevel * We are generating an icmp error for some inbound packet. 2399 0 stevel * Called from all ip_fanout_(udp, tcp, proto) functions. 2400 0 stevel * Before we generate an error, check with global policy 2401 0 stevel * to see whether this is allowed to enter the system. As 2402 0 stevel * there is no "conn", we are checking with global policy. 2403 0 stevel */ 2404 0 stevel ip6h = (ip6_t *)mp->b_rptr; 2405 3448 dh155122 if (secure || ipss->ipsec_inbound_v6_policy_present) { 2406 11042 Erik mp = ipsec_check_global_policy(mp, NULL, NULL, ip6h, ira, ns); 2407 11042 Erik if (mp == NULL) 2408 11042 Erik return; 2409 11042 Erik } 2410 11042 Erik 2411 11042 Erik /* We never send errors for protocols that we do implement */ 2412 11042 Erik if (ira->ira_protocol == IPPROTO_ICMPV6) { 2413 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 2414 11042 Erik ip_drop_input("ip_fanout_send_icmp_v6", mp, ill); 2415 11042 Erik freemsg(mp); 2416 11042 Erik return; 2417 11042 Erik } 2418 11042 Erik 2419 11042 Erik switch (icmp_type) { 2420 11042 Erik case ICMP6_DST_UNREACH: 2421 11042 Erik ASSERT(icmp_code == ICMP6_DST_UNREACH_NOPORT); 2422 11042 Erik 2423 11042 Erik BUMP_MIB(ill->ill_ip_mib, udpIfStatsNoPorts); 2424 11042 Erik ip_drop_input("ipIfStatsNoPorts", mp, ill); 2425 11042 Erik 2426 11042 Erik icmp_unreachable_v6(mp, icmp_code, B_FALSE, ira); 2427 11042 Erik break; 2428 11042 Erik case ICMP6_PARAM_PROB: 2429 11042 Erik ASSERT(icmp_code == ICMP6_PARAMPROB_NEXTHEADER); 2430 11042 Erik 2431 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInUnknownProtos); 2432 11042 Erik ip_drop_input("ipIfStatsInUnknownProtos", mp, ill); 2433 11042 Erik 2434 11042 Erik /* Let the system determine the offset for this one */ 2435 11042 Erik icmp_param_problem_nexthdr_v6(mp, B_FALSE, ira); 2436 11042 Erik break; 2437 11042 Erik default: 2438 0 stevel #ifdef DEBUG 2439 11042 Erik panic("ip_fanout_send_icmp_v6: wrong type"); 2440 11042 Erik /*NOTREACHED*/ 2441 0 stevel #else 2442 11042 Erik freemsg(mp); 2443 11042 Erik break; 2444 0 stevel #endif 2445 11042 Erik } 2446 11042 Erik } 2447 11042 Erik 2448 11042 Erik /* 2449 11042 Erik * Fanout for UDP packets that are multicast or ICMP errors. 2450 11042 Erik * (Unicast fanout is handled in ip_input_v6.) 2451 11042 Erik * 2452 11042 Erik * If SO_REUSEADDR is set all multicast packets 2453 11042 Erik * will be delivered to all conns bound to the same port. 2454 11042 Erik * 2455 0 stevel * Fanout for UDP packets. 2456 0 stevel * The caller puts <fport, lport> in the ports parameter. 2457 0 stevel * ire_type must be IRE_BROADCAST for multicast and broadcast packets. 2458 0 stevel * 2459 0 stevel * If SO_REUSEADDR is set all multicast and broadcast packets 2460 11042 Erik * will be delivered to all conns bound to the same port. 2461 0 stevel * 2462 0 stevel * Zones notes: 2463 11042 Erik * Earlier in ip_input on a system with multiple shared-IP zones we 2464 11042 Erik * duplicate the multicast and broadcast packets and send them up 2465 11042 Erik * with each explicit zoneid that exists on that ill. 2466 11042 Erik * This means that here we can match the zoneid with SO_ALLZONES being special. 2467 11042 Erik */ 2468 11042 Erik void 2469 11042 Erik ip_fanout_udp_multi_v6(mblk_t *mp, ip6_t *ip6h, uint16_t lport, uint16_t fport, 2470 11042 Erik ip_recv_attr_t *ira) 2471 11042 Erik { 2472 11042 Erik in6_addr_t laddr; 2473 0 stevel conn_t *connp; 2474 0 stevel connf_t *connfp; 2475 11042 Erik in6_addr_t faddr; 2476 11042 Erik ill_t *ill = ira->ira_ill; 2477 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 2478 11042 Erik 2479 11042 Erik ASSERT(ira->ira_flags & (IRAF_MULTIBROADCAST|IRAF_ICMP_ERROR)); 2480 11042 Erik 2481 11042 Erik laddr = ip6h->ip6_dst; 2482 11042 Erik faddr = ip6h->ip6_src; 2483 1676 jpk 2484 0 stevel /* Attempt to find a client stream based on destination port. */ 2485 11042 Erik connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(lport, ipst)]; 2486 0 stevel mutex_enter(&connfp->connf_lock); 2487 0 stevel connp = connfp->connf_head; 2488 11042 Erik while (connp != NULL) { 2489 11042 Erik if ((IPCL_UDP_MATCH_V6(connp, lport, laddr, fport, faddr)) && 2490 11042 Erik conn_wantpacket_v6(connp, ira, ip6h) && 2491 11042 Erik (!(ira->ira_flags & IRAF_SYSTEM_LABELED) || 2492 11042 Erik tsol_receive_local(mp, &laddr, IPV6_VERSION, ira, connp))) 2493 11042 Erik break; 2494 11042 Erik connp = connp->conn_next; 2495 11042 Erik } 2496 11042 Erik 2497 11042 Erik if (connp == NULL) 2498 11042 Erik goto notfound; 2499 11042 Erik 2500 11042 Erik CONN_INC_REF(connp); 2501 11042 Erik 2502 11042 Erik if (connp->conn_reuseaddr) { 2503 11042 Erik conn_t *first_connp = connp; 2504 11042 Erik conn_t *next_connp; 2505 11042 Erik mblk_t *mp1; 2506 11042 Erik 2507 11042 Erik connp = connp->conn_next; 2508 11042 Erik for (;;) { 2509 11042 Erik while (connp != NULL) { 2510 11042 Erik if (IPCL_UDP_MATCH_V6(connp, lport, laddr, 2511 11042 Erik fport, faddr) && 2512 11042 Erik conn_wantpacket_v6(connp, ira, ip6h) && 2513 11042 Erik (!(ira->ira_flags & IRAF_SYSTEM_LABELED) || 2514 11042 Erik tsol_receive_local(mp, &laddr, IPV6_VERSION, 2515 11042 Erik ira, connp))) 2516 11042 Erik break; 2517 11042 Erik connp = connp->conn_next; 2518 11042 Erik } 2519 11042 Erik if (connp == NULL) { 2520 11042 Erik /* No more interested clients */ 2521 11042 Erik connp = first_connp; 2522 11042 Erik break; 2523 11042 Erik } 2524 11042 Erik if (((mp1 = dupmsg(mp)) == NULL) && 2525 11042 Erik ((mp1 = copymsg(mp)) == NULL)) { 2526 11042 Erik /* Memory allocation failed */ 2527 11042 Erik BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 2528 11042 Erik ip_drop_input("ipIfStatsInDiscards", mp, ill); 2529 11042 Erik connp = first_connp; 2530 11042 Erik break; 2531 11042 Erik } 2532 11042 Erik 2533 11042 Erik CONN_INC_REF(connp); 2534 11042 Erik mutex_exit(&connfp->connf_lock); 2535 11042 Erik 2536 11042 Erik IP6_STAT(ipst, ip6_udp_fanmb); 2537 11042 Erik ip_fanout_udp_conn(connp, mp1, NULL, 2538 11042 Erik (ip6_t *)mp1->b_rptr, ira); 2539 11042 Erik 2540 11042 Erik mutex_enter(&connfp->connf_lock); 2541 11042 Erik /* Follow the next pointer before releasing the conn. */ 2542 11042 Erik next_connp = connp->conn_next; 2543 11042 Erik IP6_STAT(ipst, ip6_udp_fanmb); 2544 0 stevel CONN_DEC_REF(connp); 2545 11042 Erik connp = next_connp; 2546 11042 Erik } 2547 0 stevel } 2548 0 stevel 2549 0 stevel /* Last one. Send it upstream. */ 2550 0 stevel mutex_exit(&connfp->connf_lock); 2551 0 stevel 2552 3448 dh155122 IP6_STAT(ipst, ip6_udp_fanmb); 2553 11042 Erik ip_fanout_udp_conn(connp, mp, NULL, ip6h, ira); 2554 0 stevel CONN_DEC_REF(connp); 2555 0 stevel return; 2556 0 stevel 2557 0 stevel notfound: 2558 0 stevel mutex_exit(&connfp->connf_lock); 2559 0 stevel /* 2560 0 stevel * No one bound to this port. Is 2561 0 stevel * there a client that wants all 2562 0 stevel * unclaimed datagrams? 2563 0 stevel */ 2564 3448 dh155122 if (ipst->ips_ipcl_proto_fanout_v6[IPPROTO_UDP].connf_head != NULL) { 2565 11042 Erik ASSERT(ira->ira_protocol == IPPROTO_UDP); 2566 11042 Erik ip_fanout_proto_v6(mp, ip6h, ira); 2567 11042 Erik } else { 2568 11042 Erik ip_fanout_send_icmp_v6(mp, ICMP6_DST_UNREACH, 2569 11042 Erik ICMP6_DST_UNREACH_NOPORT, ira); 2570 0 stevel } 2571 0 stevel } 2572 0 stevel 2573 0 stevel /* 2574 0 stevel * int ip_find_hdr_v6() 2575 0 stevel * 2576 11042 Erik * This routine is used by the upper layer protocols, iptun, and IPsec: 2577 0 stevel * - Set extension header pointers to appropriate locations 2578 0 stevel * - Determine IPv6 header length and return it 2579 0 stevel * - Return a pointer to the last nexthdr value 2580 0 stevel * 2581 0 stevel * The caller must initialize ipp_fields. 2582 11042 Erik * The upper layer protocols normally set label_separate which makes the 2583 11042 Erik * routine put the TX label in ipp_label_v6. If this is not set then 2584 11042 Erik * the hop-by-hop options including the label are placed in ipp_hopopts. 2585 0 stevel * 2586 0 stevel * NOTE: If multiple extension headers of the same type are present, 2587 0 stevel * ip_find_hdr_v6() will set the respective extension header pointers 2588 0 stevel * to the first one that it encounters in the IPv6 header. It also 2589 0 stevel * skips fragment headers. This routine deals with malformed packets 2590 0 stevel * of various sorts in which case the returned length is up to the 2591 0 stevel * malformed part. 2592 0 stevel */ 2593 0 stevel int 2594 11042 Erik ip_find_hdr_v6(mblk_t *mp, ip6_t *ip6h, boolean_t label_separate, ip_pkt_t *ipp, 2595 11042 Erik uint8_t *nexthdrp) 2596 0 stevel { 2597 0 stevel uint_t length, ehdrlen; 2598 0 stevel uint8_t nexthdr; 2599 0 stevel uint8_t *whereptr, *endptr; 2600 0 stevel ip6_dest_t *tmpdstopts; 2601 0 stevel ip6_rthdr_t *tmprthdr; 2602 0 stevel ip6_hbh_t *tmphopopts; 2603 0 stevel ip6_frag_t *tmpfraghdr; 2604 0 stevel 2605 11042 Erik ipp->ipp_fields |= IPPF_HOPLIMIT | IPPF_TCLASS | IPPF_ADDR; 2606 11042 Erik ipp->ipp_hoplimit = ip6h->ip6_hops; 2607 11042 Erik ipp->ipp_tclass = IPV6_FLOW_TCLASS(ip6h->ip6_flow); 2608 11042 Erik ipp->ipp_addr = ip6h->ip6_dst; 2609 11042 Erik 2610 0 stevel length = IPV6_HDR_LEN; 2611 0 stevel whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */ 2612 0 stevel endptr = mp->b_wptr; 2613 0 stevel 2614 0 stevel nexthdr = ip6h->ip6_nxt; 2615 0 stevel while (whereptr < endptr) { 2616 0 stevel /* Is there enough left for len + nexthdr? */ 2617 0 stevel if (whereptr + MIN_EHDR_LEN > endptr) 2618 0 stevel goto done; 2619 0 stevel 2620 0 stevel switch (nexthdr) { 2621 11042 Erik case IPPROTO_HOPOPTS: { 2622 11042 Erik /* We check for any CIPSO */ 2623 11042 Erik uchar_t *secopt; 2624 11042 Erik boolean_t hbh_needed; 2625 11042 Erik uchar_t *after_secopt; 2626 11042 Erik 2627 0 stevel tmphopopts = (ip6_hbh_t *)whereptr; 2628 0 stevel ehdrlen = 8 * (tmphopopts->ip6h_len + 1); 2629 0 stevel if ((uchar_t *)tmphopopts + ehdrlen > endptr) 2630 0 stevel goto done; 2631 0 stevel nexthdr = tmphopopts->ip6h_nxt; 2632 11042 Erik 2633 11042 Erik if (!label_separate) { 2634 11042 Erik secopt = NULL; 2635 11042 Erik after_secopt = whereptr; 2636 11042 Erik } else { 2637 11042 Erik /* 2638 11042 Erik * We have dropped packets with bad options in 2639 11042 Erik * ip6_input. No need to check return value 2640 11042 Erik * here. 2641 11042 Erik */ 2642 11042 Erik (void) tsol_find_secopt_v6(whereptr, ehdrlen, 2643 11042 Erik &secopt, &after_secopt, &hbh_needed); 2644 11042 Erik } 2645 11042 Erik if (secopt != NULL && after_secopt - whereptr > 0) { 2646 11042 Erik ipp->ipp_fields |= IPPF_LABEL_V6; 2647 11042 Erik ipp->ipp_label_v6 = secopt; 2648 11042 Erik ipp->ipp_label_len_v6 = after_secopt - whereptr; 2649 11042 Erik } else { 2650 11042 Erik ipp->ipp_label_len_v6 = 0; 2651 11042 Erik after_secopt = whereptr; 2652 11042 Erik hbh_needed = B_TRUE; 2653 11042 Erik } 2654 0 stevel /* return only 1st hbh */ 2655 11042 Erik if (hbh_needed && !(ipp->ipp_fields & IPPF_HOPOPTS)) { 2656 0 stevel ipp->ipp_fields |= IPPF_HOPOPTS; 2657 11042 Erik ipp->ipp_hopopts = (ip6_hbh_t *)after_secopt; 2658 11042 Erik ipp->ipp_hopoptslen = ehdrlen - 2659 11042 Erik ipp->ipp_label_len_v6; 2660 11042 Erik } 2661 11042 Erik break; 2662 11042 Erik } 2663 0 stevel case IPPROTO_DSTOPTS: 2664 0 stevel tmpdstopts = (ip6_dest_t *)whereptr; 2665 0 stevel ehdrlen = 8 * (tmpdstopts->ip6d_len + 1); 2666 0 stevel if ((uchar_t *)tmpdstopts + ehdrlen > endptr) 2667 0 stevel goto done; 2668 0 stevel nexthdr = tmpdstopts->ip6d_nxt; 2669 0 stevel /* 2670 0 stevel * ipp_dstopts is set to the destination header after a 2671 0 stevel * routing header. 2672 0 stevel * Assume it is a post-rthdr destination header 2673 0 stevel * and adjust when we find an rthdr. 2674 0 stevel */ 2675 0 stevel if (!(ipp->ipp_fields & IPPF_DSTOPTS)) { 2676 0 stevel ipp->ipp_fields |= IPPF_DSTOPTS; 2677 0 stevel ipp->ipp_dstopts = tmpdstopts; 2678 0 stevel ipp->ipp_dstoptslen = ehdrlen; 2679 0 stevel } 2680 0 stevel break; 2681 0 stevel case IPPROTO_ROUTING: 2682 0 stevel tmprthdr = (ip6_rthdr_t *)whereptr; 2683 0 stevel ehdrlen = 8 * (tmprthdr->ip6r_len + 1); 2684 0 stevel if ((uchar_t *)tmprthdr + ehdrlen > endptr) 2685 0 stevel goto done; 2686 0 stevel nexthdr = tmprthdr->ip6r_nxt; 2687 0 stevel /* return only 1st rthdr */ 2688 0 stevel if (!(ipp->ipp_fields & IPPF_RTHDR)) { 2689 0 stevel ipp->ipp_fields |= IPPF_RTHDR; 2690 0 stevel ipp->ipp_rthdr = tmprthdr; 2691 0 stevel ipp->ipp_rthdrlen = ehdrlen; 2692 0 stevel } 2693 0 stevel /* 2694 0 stevel * Make any destination header we've seen be a 2695 0 stevel * pre-rthdr destination header. 2696 0 stevel */ 2697 0 stevel if (ipp->ipp_fields & IPPF_DSTOPTS) { 2698 0 stevel ipp->ipp_fields &= ~IPPF_DSTOPTS; 2699 11042 Erik ipp->ipp_fields |= IPPF_RTHDRDSTOPTS; 2700 11042 Erik ipp->ipp_rthdrdstopts = ipp->ipp_dstopts; 2701 0 stevel ipp->ipp_dstopts = NULL; 2702 11042 Erik ipp->ipp_rthdrdstoptslen = ipp->ipp_dstoptslen; 2703 0 stevel ipp->ipp_dstoptslen = 0; 2704 0 stevel } 2705 0 stevel break; 2706 0 stevel case IPPROTO_FRAGMENT: 2707 0 stevel tmpfraghdr = (ip6_frag_t *)whereptr; 2708 0 stevel ehdrlen = sizeof (ip6_frag_t); 2709 0 stevel if ((uchar_t *)tmpfraghdr + ehdrlen > endptr) 2710 0 stevel goto done; 2711 0 stevel nexthdr = tmpfraghdr->ip6f_nxt; 2712 3055 danmcd if (!(ipp->ipp_fields & IPPF_FRAGHDR)) { 2713 3055 danmcd ipp->ipp_fields |= IPPF_FRAGHDR; 2714 3055 danmcd ipp->ipp_fraghdr = tmpfraghdr; 2715 3055 danmcd ipp->ipp_fraghdrlen = ehdrlen; 2716 3055 danmcd } 2717 0 stevel break; 2718 0 stevel case IPPROTO_NONE: 2719 0 stevel default: 2720 0 stevel goto done; 2721 0 stevel } 2722 0 stevel length += ehdrlen; 2723 0 stevel whereptr += ehdrlen; 2724 0 stevel } 2725 0 stevel done: 2726 0 stevel if (nexthdrp != NULL) 2727 0 stevel *nexthdrp = nexthdr; 2728 0 stevel return (length); 2729 0 stevel } 2730 0 stevel 2731 0 stevel /* 2732 0 stevel * Try to determine where and what are the IPv6 header length and 2733 0 stevel * pointer to nexthdr value for the upper layer protocol (or an 2734 0 stevel * unknown next hdr). 2735 0 stevel * 2736 0 stevel * Parameters returns a pointer to the nexthdr value; 2737 0 stevel * Must handle malformed packets of various sorts. 2738 0 stevel * Function returns failure for malformed cases. 2739 0 stevel */ 2740 0 stevel boolean_t 2741 0 stevel ip_hdr_length_nexthdr_v6(mblk_t *mp, ip6_t *ip6h, uint16_t *hdr_length_ptr, 2742 0 stevel uint8_t **nexthdrpp) 2743 0 stevel { 2744 0 stevel uint16_t length; 2745 0 stevel uint_t ehdrlen; 2746 0 stevel uint8_t *nexthdrp; 2747 0 stevel uint8_t *whereptr; 2748 0 stevel uint8_t *endptr; 2749 0 stevel ip6_dest_t *desthdr; 2750 0 stevel ip6_rthdr_t *rthdr; 2751 0 stevel ip6_frag_t *fraghdr; 2752 0 stevel 2753 11042 Erik ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION); 2754 0 stevel length = IPV6_HDR_LEN; 2755 0 stevel whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */ 2756 0 stevel endptr = mp->b_wptr; 2757 0 stevel 2758 0 stevel nexthdrp = &ip6h->ip6_nxt; 2759 0 stevel while (whereptr < endptr) { 2760 0 stevel /* Is there enough left for len + nexthdr? */ 2761 0 stevel if (whereptr + MIN_EHDR_LEN > endptr) 2762 0 stevel break; 2763 0 stevel 2764 0 stevel switch (*nexthdrp) { 2765 0 stevel case IPPROTO_HOPOPTS: 2766 0 stevel case IPPROTO_DSTOPTS: 2767 0 stevel /* Assumes the headers are identical for hbh and dst */ 2768 0 stevel desthdr = (ip6_dest_t *)whereptr; 2769 0 stevel ehdrlen = 8 * (desthdr->ip6d_len + 1); 2770 0 stevel if ((uchar_t *)desthdr + ehdrlen > endptr) 2771 0 stevel return (B_FALSE); 2772 0 stevel nexthdrp = &desthdr->ip6d_nxt; 2773 0 stevel break; 2774 0 stevel case IPPROTO_ROUTING: 2775 0 stevel rthdr = (ip6_rthdr_t *)whereptr; 2776 0 stevel ehdrlen = 8 * (rthdr->ip6r_len + 1); 2777 0 stevel if ((uchar_t *)rthdr + ehdrlen > endptr) 2778 0 stevel return (B_FALSE); 2779 0 stevel nexthdrp = &rthdr->ip6r_nxt; 2780 0 stevel break; 2781 0 stevel case IPPROTO_FRAGMENT: 2782 0 stevel fraghdr = (ip6_frag_t *)whereptr; 2783 0 stevel ehdrlen = sizeof (ip6_frag_t); 2784 0 stevel if ((uchar_t *)&fraghdr[1] > endptr) 2785 0 stevel return (B_FALSE); 2786 0 stevel nexthdrp = &fraghdr->ip6f_nxt; 2787 0 stevel break; 2788 0 stevel case IPPROTO_NONE: 2789 0 stevel /* No next header means we're finished */ 2790 0 stevel default: 2791 0 stevel *hdr_length_ptr = length; 2792 0 stevel *nexthdrpp = nexthdrp; 2793 0 stevel return (B_TRUE); 2794 0 stevel } 2795 0 stevel length += ehdrlen; 2796 0 stevel whereptr += ehdrlen; 2797 0 stevel *hdr_length_ptr = length; 2798 0 stevel *nexthdrpp = nexthdrp; 2799 0 stevel } 2800 0 stevel switch (*nexthdrp) { 2801 0 stevel case IPPROTO_HOPOPTS: 2802 0 stevel case IPPROTO_DSTOPTS: 2803 0 stevel case IPPROTO_ROUTING: 2804 0 stevel case IPPROTO_FRAGMENT: 2805 0 stevel /* 2806 0 stevel * If any know extension headers are still to be processed, 2807 0 stevel * the packet's malformed (or at least all the IP header(s) are 2808 0 stevel * not in the same mblk - and that should never happen. 2809 0 stevel */ 2810 0 stevel return (B_FALSE); 2811 0 stevel 2812 0 stevel default: 2813 0 stevel /* 2814 0 stevel * If we get here, we know that all of the IP headers were in 2815 0 stevel * the same mblk, even if the ULP header is in the next mblk. 2816 0 stevel */ 2817 0 stevel *hdr_length_ptr = length; 2818 0 stevel *nexthdrpp = nexthdrp; 2819 0 stevel return (B_TRUE); 2820 0 stevel } 2821 0 stevel } 2822 0 stevel 2823 0 stevel /* 2824 0 stevel * Return the length of the IPv6 related headers (including extension headers) 2825 0 stevel * Returns a length even if the packet is malformed. 2826 0 stevel */ 2827 0 stevel int 2828 0 stevel ip_hdr_length_v6(mblk_t *mp, ip6_t *ip6h) 2829 0 stevel { 2830 0 stevel uint16_t hdr_len; 2831 0 stevel uint8_t *nexthdrp; 2832 0 stevel 2833 0 stevel (void) ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_len, &nexthdrp); 2834 0 stevel return (hdr_len); 2835 0 stevel } 2836 0 stevel 2837 0 stevel /* 2838 0 stevel * Parse and process any hop-by-hop or destination options. 2839 0 stevel * 2840 0 stevel * Assumes that q is an ill read queue so that ICMP errors for link-local 2841 0 stevel * destinations are sent out the correct interface. 2842 0 stevel * 2843 0 stevel * Returns -1 if there was an error and mp has been consumed. 2844 0 stevel * Returns 0 if no special action is needed. 2845 0 stevel * Returns 1 if the packet contained a router alert option for this node 2846 0 stevel * which is verified to be "interesting/known" for our implementation. 2847 0 stevel * 2848 0 stevel * XXX Note: In future as more hbh or dest options are defined, 2849 0 stevel * it may be better to have different routines for hbh and dest 2850 0 stevel * options as opt_type fields other than IP6OPT_PAD1 and IP6OPT_PADN 2851 0 stevel * may have same value in different namespaces. Or is it same namespace ?? 2852 0 stevel * Current code checks for each opt_type (other than pads) if it is in 2853 0 stevel * the expected nexthdr (hbh or dest) 2854 0 stevel */ 2855 11042 Erik int 2856 11042 Erik ip_process_options_v6(mblk_t *mp, ip6_t *ip6h, 2857 11042 Erik uint8_t *optptr, uint_t optlen, uint8_t hdr_type, ip_recv_attr_t *ira) 2858 0 stevel { 2859 0 stevel uint8_t opt_type; 2860 0 stevel uint_t optused; 2861 0 stevel int ret = 0; 2862 1676 jpk const char *errtype; 2863 11042 Erik ill_t *ill = ira->ira_ill; 2864 11042 Erik ip_stack_t *ipst = ill->ill_ipst; 2865 0 stevel 2866 0 stevel while (optlen != 0) { 2867 0 stevel opt_type = *optptr; 2868 0 stevel if (opt_type == IP6OPT_PAD1) { 2869 0 stevel optused = 1; 2870 0 stevel } else { 2871 0 stevel if (optlen < 2) 2872 0 stevel goto bad_opt; 2873 1676 jpk errtype = "malformed"; 2874 1676 jpk if (opt_type == ip6opt_ls) { 2875 1676 jpk optused = 2 + optptr[1]; 2876 1676 jpk if (optused > optlen) 2877 1676 jpk goto bad_opt; 2878 1676 jpk } else switch (opt_type) { 2879 0 stevel case IP6OPT_PADN: 2880 0 stevel /* 2881 0 stevel * Note:We don't verify that (N-2) pad octets 2882 0 stevel * are zero as required by spec. Adhere to 2883 0 stevel * "be liberal in what you accept..." part of 2884 0 stevel * implementation philosophy (RFC791,RFC1122) 2885 0 stevel */ 2886 0 stevel optused = 2 + optptr[1]; 2887 0 stevel if (optused > optlen) 2888 0 stevel goto bad_opt; 2889 0 stevel break; 2890 0 stevel 2891 0 stevel case IP6OPT_JUMBO: 2892 0 stevel if (hdr_type != IPPROTO_HOPOPTS) 2893 0 stevel goto opt_error; 2894 0 stevel goto opt_error; /* XXX Not implemented! */ 2895 0 stevel 2896 0 stevel case IP6OPT_ROUTER_ALERT: { 2897 0 stevel struct ip6_opt_router *or; 2898 0 stevel 2899 0 stevel if (hdr_type != IPPROTO_HOPOPTS) 2900 0 stevel goto opt_error; 2901 0 stevel optused = 2 + optptr[1]; 2902 0 stevel if (optused > optlen) 2903 0 stevel goto bad_opt; 2904 0 stevel or = (struct ip6_opt_router *)optptr; 2905 0 stevel /* Check total length and alignment */ 2906 0 stevel if (optused != sizeof (*or) || 2907 0 stevel ((uintptr_t)or->ip6or_value & 0x1) != 0) 2908 0 stevel goto opt_error; 2909 0 stevel /* Check value */ 2910 0 stevel switch (*((uint16_t *)or->ip6or_value)) { 2911 0 stevel case IP6_ALERT_MLD: 2912 0 stevel case IP6_ALERT_RSVP: 2913 0 stevel ret = 1; 2914 0 stevel } 2915 0 stevel break; 2916 0 stevel } 2917 0 stevel case IP6OPT_HOME_ADDRESS: { 2918 0 stevel /* 2919 0 stevel * Minimal support for the home address option 2920 0 stevel * (which is required by all IPv6 nodes). 2921 0 stevel * Implement by just swapping the home address 2922 0 stevel * and source address. 2923 0 stevel * XXX Note: this has IPsec implications since 2924 0 stevel * AH needs to take this into account. 2925 0 stevel * Also, when IPsec is used we need to ensure 2926 0 stevel * that this is only processed once 2927 0 stevel * in the received packet (to avoid swapping 2928 0 stevel * back and forth). 2929 0 stevel * NOTE:This option processing is considered 2930 0 stevel * to be unsafe and prone to a denial of 2931 0 stevel * service attack. 2932 0 stevel * The current processing is not safe even with 2933 0 stevel * IPsec secured IP packets. Since the home 2934 0 stevel * address option processing requirement still 2935 0 stevel * is in the IETF draft and in the process of 2936 0 stevel * being redefined for its usage, it has been 2937 0 stevel * decided to turn off the option by default. 2938 0 stevel * If this section of code needs to be executed, 2939 0 stevel * ndd variable ip6_ignore_home_address_opt 2940 0 stevel * should be set to 0 at the user's own risk. 2941 0 stevel */ 2942 0 stevel struct ip6_opt_home_address *oh; 2943 0 stevel in6_addr_t tmp; 2944 0 stevel 2945 3448 dh155122 if (ipst->ips_ipv6_ignore_home_address_opt) 2946 0 stevel goto opt_error; 2947 0 stevel 2948 0 stevel if (hdr_type != IPPROTO_DSTOPTS) 2949 0 stevel goto opt_error; 2950 0 stevel optused = 2 + optptr[1]; 2951 0 stevel if (optused > optlen) 2952 0 stevel goto bad_opt; 2953 0 stevel 2954 0 stevel /* 2955 0 stevel * We did this dest. opt the first time 2956 0 stevel * around (i.e. before AH processing). 2957 0 stevel * If we've done AH... stop now. 2958 0 stevel */ 2959 11042 Erik if ((ira->ira_flags & IRAF_IPSEC_SECURE) && 2960 11042 Erik ira->ira_ipsec_ah_sa != NULL) 2961 11042 Erik break; 2962 0 stevel 2963 0 stevel oh = (struct ip6_opt_home_address *)optptr; 2964 0 stevel /* Check total length and alignment */ 2965 0 stevel if (optused < sizeof (*oh) || 2966 0 stevel ((uintptr_t)oh->ip6oh_addr & 0x7) != 0) 2967 0 stevel goto opt_error; 2968 0 stevel /* Swap ip6_src and the home address */ 2969 0 stevel tmp = ip6h->ip6_src; 2970 0 stevel /* XXX Note: only 8 byte alignment option */ 2971 0 stevel ip6h->ip6_src = *(in6_addr_t *)oh->ip6oh_addr; 2972 0 stevel *(in6_addr_t *)oh->ip6oh_addr = tmp; 2973 0 stevel break; 2974 0 stevel } 2975 0 stevel 2976 0 stevel case IP6OPT_TUNNEL_LIMIT: 2977 0 stevel if (hdr_type != IPPROTO_DSTOPTS) { 2978 0 stevel goto opt_error; 2979 0 stevel } 2980 0 stevel optused = 2 + optptr[1]; 2981 0 stevel if (optused > optlen) { 2982 0 stevel goto bad_opt; 2983 0 stevel } 2984 0 stevel if (optused != 3) { 2985 0 stevel goto opt_error; 2986 0 stevel } 2987 0 stevel break; 2988 0 stevel 2989 0 stevel default: 2990 1676 jpk errtype = "unknown"; 2991 1676 jpk /* FALLTHROUGH */ 2992 0 stevel opt_error: 2993 2733 nordmark /* Determine which zone should send error */ 2994 0 stevel switch (IP6OPT_TYPE(opt_type)) { 2995 0 stevel case IP6OPT_TYPE_SKIP: 2996 0 stevel optused = 2 + optptr[1]; 2997 0 stevel if (optused > optlen) 2998 0 stevel goto bad_opt; 2999 1676 jpk ip1dbg(("ip_process_options_v6: %s " 3000 1676 jpk "opt 0x%x skipped\n", 3001 1676 jpk errtype, opt_type)); 3002 0 stevel break; 3003 0 stevel case IP6OPT_TYPE_DISCARD: 3004 1676 jpk ip1dbg(("ip_process_options_v6: %s " 3005 1676 jpk "opt 0x%x; packet dropped\n", 3006 1676 jpk errtype, opt_type)); 3007 11042 Erik BUMP_MIB(ill->ill_ip_mib, 3008 11042 Erik ipIfStatsInHdrErrors); 3009 11042 Erik ip_drop_input("ipIfStatsInHdrErrors", 3010 11042 Erik mp, ill); 3011 11042 Erik freemsg(mp); 3012 0 stevel return (-1); 3013 0 stevel case IP6OPT_TYPE_ICMP: 3014 11042 Erik BUMP_MIB(ill->ill_ip_mib, 3015 11042 Erik ipIfStatsInHdrErrors); 3016 11042 Erik ip_drop_input("ipIfStatsInHdrErrors", 3017 11042 Erik mp, ill); 3018 11042 Erik icmp_param_problem_v6(mp, 3019 0 stevel ICMP6_PARAMPROB_OPTION, 3020 0 stevel (uint32_t)(optptr - 3021 0 stevel (uint8_t *)ip6h), 3022 11042 Erik B_FALSE, ira); 3023 0 stevel return (-1); 3024 0 stevel case IP6OPT_TYPE_FORCEICMP: 3025 11042 Erik BUMP_MIB(ill->ill_ip_mib, 3026 11042 Erik ipIfStatsInHdrErrors); 3027 11042 Erik ip_drop_input("ipIfStatsInHdrErrors", 3028 11042 Erik mp, ill); 3029 11042 Erik icmp_param_problem_v6(mp, 3030 0 stevel ICMP6_PARAMPROB_OPTION, 3031 0 stevel (uint32_t)(optptr - 3032 0 stevel (uint8_t *)ip6h), 3033 11042 Erik B_TRUE, ira); 3034 0 stevel return (-1); 3035 1676 jpk default: 3036 1676 jpk ASSERT(0); 3037 0 stevel } 3038 0 stevel } 3039 0 stevel } 3040 0 stevel optlen -= optused; 3041 0 stevel optptr += optused; 3042 0 stevel } 3043 0 stevel return (ret); 3044 0 stevel 3045 0 stevel bad_opt: 3046 2733 nordmark /* Determine which zone should send error */ 3047 11042 Erik ip_drop_input("ICMP_PARAM_PROBLEM", mp, ill); 3048 11042 Erik icmp_param_problem_v6(mp, ICMP6_PARAMPROB_OPTION, 3049 11042 Erik (uint32_t)(optptr - (uint8_t *)ip6h), 3050 11042 Erik B_FALSE, ira); 3051 0 stevel return (-1); 3052 0 stevel } 3053 0 stevel 3054 0 stevel /* 3055 0 stevel * Process a routing header that is not yet empty. 3056 10031 Brian * Because of RFC 5095, we now reject all route headers. 3057 0 stevel */ 3058 11042 Erik void 3059 11042 Erik ip_process_rthdr(mblk_t *mp, ip6_t *ip6h, ip6_rthdr_t *rth, 3060 11042 Erik ip_recv_attr_t *ira) 3061 11042 Erik { 3062 11042 Erik ill_t *ill = ira->ira_ill; 3063 3448 dh155122 ip_stack_t *ipst = ill->ill_ipst; 3064 0 stevel 3065 0 stevel ASSERT(rth->ip6r_segleft != 0); 3066 0 stevel 3067 3448 dh155122 if (!ipst->ips_ipv6_forward_src_routed) { 3068 0 stevel /* XXX Check for source routed out same interface? */ 3069 3284 apersson BUMP_MIB(ill->ill_ip_mib, ipIfStatsForwProhibits); 3070 3284 apersson BUMP_MIB(ill->ill_ip_mib, ipIfStatsInAddrErrors); 3071 11042 Erik ip_drop_input("ipIfStatsInAddrErrors", mp, ill); 3072 11042 Erik freemsg(mp); 3073 11042 Erik return; 3074 11042 Erik } 3075 11042 Erik 3076 11042 Erik ip_drop_input("ICMP_PARAM_PROBLEM", mp, ill);