bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * CDDL HEADER START
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The contents of this file are subject to the terms of the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Common Development and Distribution License (the "License").
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * You may not use this file except in compliance with the License.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * See the License for the specific language governing permissions
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * and limitations under the License.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When distributing Covered Code, include this CDDL HEADER in each
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If applicable, add the following below this CDDL HEADER, with the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * fields enclosed by brackets "[]" replaced with your own identifying
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * information: Portions Copyright [yyyy] [name of copyright owner]
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * CDDL HEADER END
9e3469d3db608feb0e43d9955cbf406c22025463Erik Nordmark * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Use is subject to license terms.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* Copyright (c) 1990 Mentat Inc. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_output_simple_v6(mblk_t *mp, ip_xmit_attr_t *ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark in6_addr_t dst; /* End of source route, or ip6_dst if none */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_pktlen = ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &ixa->ixa_ip_hdr_length,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Malformed packet */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsHCOutRequests);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards", mp, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Assumes that source routed packets have already been massaged by
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the ULP (ip_massage_options_v6) and as a result ip6_dst is the next
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * hop in the source route. The final destination is used for IPsec
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * policy and DCE lookup.
44b099c4d944a196d124a02c7403ad891223139eSowmini Varadhan ire = ip_select_route_v6(&firsthop, ip6h->ip6_src, ixa, NULL, &setsrc,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(ire != NULL); /* IRE_NOROUTE if none found */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsHCOutRequests);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards", mp, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ire->ire_flags & (RTF_BLACKHOLE|RTF_REJECT)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* ire_ill might be NULL hence need to skip some code */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsHCOutRequests);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* No dce yet; use default one */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Note that ip6_dst is only used for IRE_MULTICAST */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark nce = ire_to_nce(ire, INADDR_ANY, &ip6h->ip6_dst);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Allocation failure? */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark nce1 = ire_handle_condemned_nce(nce, ire, NULL, ip6h, B_TRUE);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Try finding a better IRE */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Tried twice - drop packet */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * For multicast with multirt we have a flag passed back from
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_lookup_multi_ill_v6 since we don't have an IRE for each
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * possible multicast address.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We also need a flag for multicast since we can't check
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * whether RTF_MULTIRT is set in ixa_ire for multicast.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Check for a dce_t with a path mtu.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ifindex = nce->nce_common->ncec_ill->ill_phyint->phyint_ifindex;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = dce_lookup_v6(&dst, ifindex, ipst, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * To avoid a periodic timer to increase the path MTU we
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * look at dce_last_change_time each time we send a packet.
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (TICK_TO_SEC(now) - dce->dce_last_change_time >
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Older than 20 minutes. Drop the path MTU information.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_flags &= ~(DCEF_PMTU|DCEF_TOO_SMALL_PMTU);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_fragsize = ip_get_base_mtu(nce->nce_ill, ire);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark fragsize = ip_get_base_mtu(nce->nce_ill, ire);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_fragsize = ip_get_base_mtu(nce->nce_ill, ire);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We use use ire_nexthop_ill (and not ncec_ill) to avoid the under ipmp
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * interface for source address selection.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We use the final destination to get
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * correct selection for source routed packets
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* If unreachable we have no ill but need some source */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark error = ip_select_source_v6(ill, &setsrc, &dst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCOutRequests);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards - no source",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Check if the IP source is assigned to the host. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Don't send a packet with a source that isn't ours */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsHCOutRequests);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards - invalid source",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Check against global IPsec policy to set the AH/ESP attributes.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * IPsec will set IXAF_IPSEC_* and ixa_ipsec_* as appropriate.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!(ixaflags & (IXAF_NO_IPSEC|IXAF_IPSEC_SECURE))) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mp = ip_output_attach_policy(mp, NULL, ip6h, NULL, ixa);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* MIB and ip_drop_packet already done */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (EHOSTUNREACH); /* IPsec policy failure */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCOutRequests);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsHCOutRequests);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We update the statistics on the most specific IRE i.e., the first
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * one we found.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We don't have an IRE when we fragment, hence ire_ob_pkt_count
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * can only count the use prior to fragmentation. However the MIB
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * counters on the ill will be incremented in post fragmentation.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Based on ire_type and ire_flags call one of:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_send_local_v6 - for IRE_LOCAL and IRE_LOOPBACK
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_send_multirt_v6 - if RTF_MULTIRT
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_send_noroute_v6 - if RTF_REJECT or RTF_BLACHOLE
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_send_multicast_v6 - for IRE_MULTICAST
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_send_wire_v6 - for the rest.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark error = (ire->ire_sendfn)(ire, mp, ip6h, ixa, &dce->dce_ident);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_sendfn() functions.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * These functions use the following xmit_attr:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - ixa_fragsize - read to determine whether or not to fragment
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IXAF_IPSEC_SECURE - to determine whether or not to invoke IPsec
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - ixa_ipsec_* are used inside IPsec
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IXAF_LOOPBACK_COPY - for multicast
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_sendfn for IRE_LOCAL and IRE_LOOPBACK
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The checks for restrict_interzone_loopback are done in ire_route_recursive.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* ARGSUSED4 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkire_send_local_v6(ire_t *ire, mblk_t *mp, void *iph_arg,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_recv_attr_t iras; /* NOTE: No bzero for performance */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * No fragmentation, no nce, and no application of IPsec.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note different order between IP provider and FW_HOOKS than in
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * send_wire case.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * DTrace this as ip:::send. A packet blocked by FW_HOOKS will fire the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * send probe, but not the receive probe.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark DTRACE_IP7(send, mblk_t *, mp, conn_t *, NULL, void_ip_t *,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip6h, __dtrace_ipsr_ill_t *, ill, ipha_t *, NULL, ip6_t *, ip6h,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark DTRACE_PROBE1(ip6__loopback__out__end, mblk_t *, mp);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Even if the destination was changed by the filter we use the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * forwarding decision that was made based on the address
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Length could be different */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark pktlen = ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If a callback is enabled then we need to know the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * source and destination zoneids for the packet. We already
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * have those handy.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Shared-IP zone */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipobs_hook(mp, IPOBS_HOOK_LOCAL, szone, dzone, ill, ipst);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Handle lo0 stats */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Update output mib stats. Note that we can't move into the icmp
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * sender (icmp_output etc) since they don't know the ill and the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * stats are per ill.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark icmp6 = (icmp6_t *)((uchar_t *)ip6h + ixa->ixa_ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark DTRACE_PROBE1(ip6__loopback__in__end, mblk_t *, mp);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Even if the destination was changed by the filter we use the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * forwarding decision that was made based on the address
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Length could be different */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark pktlen = ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark DTRACE_IP7(receive, mblk_t *, mp, conn_t *, NULL, void_ip_t *,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip6h, __dtrace_ipsr_ill_t *, ill, ipha_t *, NULL, ip6_t *, ip6h,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Map ixa to ira including IPsec policies */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInReceives);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark UPDATE_MIB(ill->ill_ip_mib, ipIfStatsHCInOctets, pktlen);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Destined to ire_zoneid - use that for fanout */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This updates ira_cred, ira_tsl and ira_free_flags based
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * on the label. We don't expect this to ever fail for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * loopback packets, so we silently drop the packet should it
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!tsol_get_pkt_label(mp, IPV6_VERSION, &iras)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* tsol_get_pkt_label sometimes does pullupmsg */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We moved any IPsec refs from ixa to iras */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkmultirt_check_v6(ire_t *ire, ip6_t *ip6h, ip_xmit_attr_t *ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Limit the TTL on multirt packets. Do this even if IPV6_HOPLIMIT */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip2dbg(("ire_send_multirt_v6: forcing multicast "
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark "multirt TTL to 1 (was %d)\n", ip6h->ip6_hops));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (ip6h->ip6_hops > ipst->ips_ip_multirt_ttl)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Need to ensure we don't increase the ttl should we go through
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_send_multicast.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* For IPv6 this also needs to insert a fragment header */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_sendfn for IRE_MULTICAST
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that we do path MTU discovery by default for IPv6 multicast. But
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * since unconnected UDP and RAW sockets don't set IXAF_PMTU_DISCOVERY
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * only connected sockets get this by default.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkire_send_multicast_v6(ire_t *ire, mblk_t *mp, void *iph_arg,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The IRE_MULTICAST is the same whether or not multirt is in use.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Hence we need special-case code.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Check if anything in ip_input_v6 wants a copy of the transmitted
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * packet (after IPsec and fragmentation)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * 1. Multicast routers always need a copy unless SO_DONTROUTE is set
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * RSVP and the rsvp daemon is an example of a
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * protocol and user level process that
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * handles it's own routing. Hence, it uses the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * SO_DONTROUTE option to accomplish this.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * 2. If the sender has set IP_MULTICAST_LOOP, then we just
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * check whether there are any receivers for the group on the ill
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * (ignoring the zoneid).
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * 3. If IP_MULTICAST_LOOP is not set, then we check if there are
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * any members in other shared-IP zones.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If such members exist, then we indicate that the sending zone
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * shouldn't get a loopback copy to preserve the IP_MULTICAST_LOOP
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When we loopback we skip hardware checksum to make sure loopback
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * copy is checksumed.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that ire_ill is the upper in the case of IPMP.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_flags &= ~(IXAF_LOOPBACK_COPY | IXAF_NO_HW_CKSUM);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ipst->ips_ip_g_mrouter && ill->ill_mrouter_cnt > 0 &&
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_flags |= IXAF_LOOPBACK_COPY | IXAF_NO_HW_CKSUM;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If this zone or any other zone has members then loopback
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_flags |= IXAF_LOOPBACK_COPY | IXAF_NO_HW_CKSUM;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else if (ipst->ips_netstack->netstack_numzones > 1) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This zone should not have a copy. But there are some other
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * zones which might have members.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ill_hasmembers_otherzones_v6(ill, &ip6h->ip6_dst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_flags |= IXAF_LOOPBACK_COPY | IXAF_NO_HW_CKSUM;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Unless IPV6_HOPLIMIT or ire_send_multirt_v6 already set a ttl,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * force the ttl to the IP_MULTICAST_TTL value
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ire_send_wire_v6(ire, mp, ip6h, ixa, identp));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_sendfn for IREs with RTF_MULTIRT
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkire_send_multirt_v6(ire_t *ire, mblk_t *mp, void *iph_arg,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ire_send_multicast_v6(ire, mp, ip6h, ixa, identp));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ire_send_wire_v6(ire, mp, ip6h, ixa, identp));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_sendfn for IREs with RTF_REJECT/RTF_BLACKHOLE, including IRE_NOROUTE
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* ARGSUSED4 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkire_send_noroute_v6(ire_t *ire, mblk_t *mp, void *iph_arg,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutNoRoutes);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* A lack of a route as opposed to RTF_REJECT|BLACKHOLE */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_rts_change_v6(RTM_MISS, &ip6h->ip6_dst, 0, 0, 0, 0, 0, 0,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutNoRoutes RTF_BLACKHOLE", mp, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* No error even for local senders - silent blackhole */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutNoRoutes RTF_REJECT", mp, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We need an ill_t for the ip_recv_attr_t even though this packet
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * was never received and icmp_unreachable doesn't currently use
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark !(ixa->ixa_flags & IRAF_IS_IPV4), &dummy, ipst);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Map ixa to ira including IPsec policies */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark icmp_unreachable_v6(mp, ICMP6_DST_UNREACH_NOROUTE, B_FALSE, &iras);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We moved any IPsec refs from ixa to iras */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Calculate a checksum ignoring any hardware capabilities
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns B_FALSE if the packet was too short for the checksum. Caller
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * should free and do stats.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_output_sw_cksum_v6(mblk_t *mp, ip6_t *ip6h, ip_xmit_attr_t *ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint16_t ip_hdr_length = ixa->ixa_ip_hdr_length;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Just in case it contained garbage */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Calculate ULP checksum
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = IPH_TCPH_CHECKSUMP(ip6h, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = IPH_UDPH_CHECKSUMP(ip6h, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(MBLKL(mp) >= (ip_hdr_length + sizeof (*sctph)));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sctph = (sctp_hdr_t *)(mp->b_rptr + ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Zero out the checksum field to ensure proper
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * checksum calculation.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sctph->sh_chksum = sctp_cksum(mp, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else if (ixa->ixa_flags & IXAF_SET_RAW_CKSUM) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * icmp has placed length and routing
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * header adjustment in the checksum field.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = (uint16_t *)(((uint8_t *)ip6h) + ip_hdr_length +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = IPH_ICMPV6_CHECKSUMP(ip6h, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksum = IP_ICMPV6_CSUM_COMP; /* Pseudo-header cksum */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* ULP puts the checksum field is in the first mblk */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(((uchar_t *)cksump) + sizeof (uint16_t) <= mp->b_wptr);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We accumulate the pseudo header checksum in cksum.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This is pretty hairy code, so watch close. One
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * thing to keep in mind is that UDP and TCP have
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * stored their respective datagram lengths in their
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * checksum fields. This lines things up real nice.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksum += iphs[4] + iphs[5] + iphs[6] + iphs[7] +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * For UDP/IPv6 a zero UDP checksum is not allowed.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Change to 0xffff
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IP6_STAT_UPDATE(ipst, ip6_out_sw_cksum_bytes, pktlen);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* No IP header checksum for IPv6 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* There are drivers that can't do partial checksum for ICMPv6 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Calculate the ULP checksum - try to use hardware.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * In the case of MULTIRT or multicast the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * IXAF_NO_HW_CKSUM is set in which case we use software.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns B_FALSE if the packet was too short for the checksum. Caller
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * should free and do stats.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_output_cksum_v6(iaflags_t ixaflags, mblk_t *mp, ip6_t *ip6h,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint16_t ip_hdr_length = ixa->ixa_ip_hdr_length;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((ixaflags & IXAF_NO_HW_CKSUM) || !ILL_HCKSUM_CAPABLE(ill) ||
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ip_output_sw_cksum_v6(mp, ip6h, ixa));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Calculate ULP checksum. Note that we don't use cksump and cksum
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * if the ill has FULL support.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = IPH_TCPH_CHECKSUMP(ip6h, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksum = IP_TCP_CSUM_COMP; /* Pseudo-header cksum */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = IPH_UDPH_CHECKSUMP(ip6h, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksum = IP_UDP_CSUM_COMP; /* Pseudo-header cksum */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(MBLKL(mp) >= (ip_hdr_length + sizeof (*sctph)));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sctph = (sctp_hdr_t *)(mp->b_rptr + ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Zero out the checksum field to ensure proper
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * checksum calculation.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sctph->sh_chksum = sctp_cksum(mp, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else if (ixa->ixa_flags & IXAF_SET_RAW_CKSUM) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * icmp has placed length and routing
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * header adjustment in the checksum field.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = (uint16_t *)(((uint8_t *)ip6h) + ip_hdr_length +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksump = IPH_ICMPV6_CHECKSUMP(ip6h, ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksum = IP_ICMPV6_CSUM_COMP; /* Pseudo-header cksum */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* No IP header checksum for IPv6 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* ULP puts the checksum field is in the first mblk */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(((uchar_t *)cksump) + sizeof (uint16_t) <= mp->b_wptr);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Underlying interface supports hardware checksum offload for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the payload; leave the payload checksum for the hardware to
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * calculate. N.B: We only need to set up checksum info on the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * first mblk.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark hck_flags = ill->ill_hcksum_capab->ill_hcksum_txflags;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Hardware calculates pseudo-header, header and the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * payload checksums, so clear the checksum field in
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the protocol header.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (protocol != IPPROTO_ICMPV6 || !nxge_cksum_workaround)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Partial checksum offload has been enabled. Fill
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the checksum field in the protocol header with the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * pseudo-header checksum value.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We accumulate the pseudo header checksum in cksum.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This is pretty hairy code, so watch close. One
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * thing to keep in mind is that UDP and TCP have
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * stored their respective datagram lengths in their
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * checksum fields. This lines things up real nice.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cksum += iphs[4] + iphs[5] + iphs[6] + iphs[7] +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Offsets are relative to beginning of IP header.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark DB_CKSUMSTUFF(mp) = (uint8_t *)cksump - (uint8_t *)ip6h;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Hardware capabilities include neither full nor partial IPv6 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ip_output_sw_cksum_v6(mp, ip6h, ixa));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_sendfn for offlink and onlink destinations.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Also called from the multicast, and multirt send functions.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Assumes that the caller has a hold on the ire.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This function doesn't care if the IRE just became condemned since that
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * can happen at any time.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* ARGSUSED */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkire_send_wire_v6(ire_t *ire, mblk_t *mp, void *iph_arg,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Update output mib stats. Note that we can't move into the icmp
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * sender (icmp_output etc) since they don't know the ill and the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * stats are per ill.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * With IPMP we record the stats on the upper ill.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark icmp6 = (icmp6_t *)((uchar_t *)ip6h + ixa->ixa_ip_hdr_length);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark icmp_update_out_mib_v6(ixa->ixa_nce->nce_common->ncec_ill,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This might set b_band, thus the IPsec and fragmentation
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * code in IP ensures that b_band is updated in the first mblk.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* ip_process translates an IS_UNDER_IPMP */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* ip_drop_packet and MIB done */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (0); /* Might just be delayed */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * To handle IPsec/iptun's labeling needs we need to tag packets
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * while we still have ixa_tsl
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (is_system_labeled() && ixa->ixa_tsl != NULL &&
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (ill->ill_mactype == DL_6TO4 || ill->ill_mactype == DL_IPV4 ||
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark newcr = copycred_from_tslabel(ixa->ixa_cred, ixa->ixa_tsl,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards - newcr",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark crfree(newcr); /* mblk_setcred did its own crhold */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * IXAF_IPV6_ADD_FRAGHDR is set for CGTP so that we will add a
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * fragment header without fragmenting. CGTP on the receiver will
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * filter duplicates on the ident field.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (ixaflags & (IXAF_IPSEC_SECURE|IXAF_IPV6_ADD_FRAGHDR))) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Compute ULP checksum using software
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards", mp, ill);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Avoid checksum again below if we only add fraghdr */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If we need a fragment header, pick the ident and insert
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the header before IPsec to we have a place to store
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the ident value.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If this packet would generate a icmp_frag_needed
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * message, we need to handle it before we do the IPsec
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * processing. Otherwise, we need to strip the IPsec
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * headers before we send up the message to the ULPs
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * which becomes messy and difficult.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Generate ICMP and return error */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Map ixa to ira including IPsec policies */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark icmp_pkt2big_v6(mp, ixa->ixa_fragsize, B_TRUE,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We moved any IPsec refs from ixa to iras */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark DTRACE_PROBE4(ip6__fragsize__ok, uint_t, pktlen,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t, ixa->ixa_fragsize, uint_t, ixa->ixa_pktlen,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Assign an ident value for this packet. There could
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * be other threads targeting the same destination, so
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * we have to arrange for a atomic increment.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Normally ixa_extra_ident is 0, but in the case of
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * LSO it will be the number of TCP segments that the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * driver/hardware will extraly construct.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that cl_inet_ipident has only been used for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * IPv4. We don't use it here.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ident = atomic_add_32_nv(identp, ixa->ixa_extra_ident +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ident = ident; /* In case we do IPsec */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Pass in sufficient information so that
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * IPsec can determine whether to fragment, and
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * which function to call after fragmentation.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* MIB and ip_drop_output already done */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ip_fragment_v6(mp, ixa->ixa_nce, ixaflags,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Compute ULP checksum and IP header checksum */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* An IS_UNDER_IPMP ill is ok here */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!ip_output_cksum_v6(ixaflags, mp, ip6h, ixa, ill)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards", mp, ill);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return ((ixa->ixa_postfragfn)(mp, ixa->ixa_nce, ixaflags,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Post fragmentation function for RTF_MULTIRT routes.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since IRE_MULTICASTs might have RTF_MULTIRT, this function
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * checks IXAF_LOOPBACK_COPY.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If no packet is sent due to failures then we return an errno, but if at
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * least one succeeded we return zero.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_postfrag_multirt_v6(mblk_t *mp, nce_t *nce, iaflags_t ixaflags,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t pkt_len, uint32_t xmit_hint, zoneid_t szone, zoneid_t nolzid,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Check for IXAF_LOOPBACK_COPY */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Failed to deliver the loopback copy. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards", mp, ill);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_postfrag_loopback(mp1, nce, ixaflags, pkt_len,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Loop over RTF_MULTIRT for ip6_dst in the same bucket. Send
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * a copy to each one.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Use the nce (nexthop) and ip6_dst to find the ire.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * MULTIRT is not designed to work with shared-IP zones thus we don't
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * need to pass a zoneid or a label to the IRE lookup.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (IN6_ARE_ADDR_EQUAL(&nce->nce_addr, &ip6h->ip6_dst)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Broadcast and multicast case */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_ftable_lookup_v6(&ip6h->ip6_dst, 0, 0, 0, NULL,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ALL_ZONES, NULL, MATCH_IRE_DSTONLY, 0, ipst, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Unicast case */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_ftable_lookup_v6(&ip6h->ip6_dst, 0, &nce->nce_addr,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark 0, NULL, ALL_ZONES, NULL, MATCH_IRE_GW, 0, ipst, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) ||
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ip_postfrag_multirt didn't find route",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (ire1 = irb->irb_ire; ire1 != NULL; ire1 = ire1->ire_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Note: When IPv6 uses radix tree we don't need this check */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!IN6_ARE_ADDR_EQUAL(&ire->ire_addr_v6, &ire1->ire_addr_v6))
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Do the ire argument one after the loop */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This ire might not have been picked by
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_route_recursive, in which case ire_dep might
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * not have been setup yet.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We kick ire_route_recursive to try to resolve
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * starting at ire1.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark &ire1->ire_addr_v6, ire1->ire_type, ire1->ire_ill,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards - no ill",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Pick the addr and type to use for ndp_nce_init */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (nce->nce_common->ncec_flags & NCE_F_MCAST) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_type = ire1->ire_type; /* Doesn't matter */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* If IPMP meta or under, then we just drop */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill1->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark nce1 = ndp_nce_init(ill1, &nexthop, ire_type);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill1->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards - no nce",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(ill1->ill_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("ipIfStatsOutDiscards", mp, ill1);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Preserve HW checksum for this copy */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark err = ip_xmit(mp1, nce1, ixaflags, pkt_len, xmit_hint, szone,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Finally, the main one */