Home | History | Annotate | Download | only in ip
      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);