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
9cd928fe5e3ea4e05f64cfb380beb54b2623e7dcAlan Maguire * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* Copyright (c) 1990 Mentat Inc. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Release a reference on ip_xmit_attr.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The reference is acquired by conn_get_ixa()
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek if (atomic_dec_32_nv(&(ixa)->ixa_refcnt) == 0) \
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When we need to handle a transmit side asynchronous operation, then we need
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to save sufficient information so that we can call the fragment and postfrag
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * functions. That information is captured in an mblk containing this structure.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since this is currently only used for IPsec, we include information for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the kernel crypto framework.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark netstackid_t ixm_stackid; /* Verify it didn't go away */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t ixm_ifindex; /* Used to find the nce */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark in6_addr_t ixm_nceaddr_v6; /* Used to find nce */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#define ixm_nceaddr_v4 V4_PART_OF_V6(ixm_nceaddr_v6)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint16_t ixm_ip_hdr_length; /* Points to ULP header */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint8_t ixm_protocol; /* Protocol number for ULP cksum */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark zoneid_t ixm_no_loop_zoneid; /* IXAF_NO_LOOP_ZONEID_SET */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t ixm_scopeid; /* For IPv6 link-locals */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint32_t ixm_ident; /* For IPv6 fragment header */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cred_t *ixm_cred; /* For getpeerucred - refhold if set */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When the pointers below are set they have a refhold on the struct.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct ipsa_s *ixm_ipsec_ah_sa; /* SA for AH */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct ipsa_s *ixm_ipsec_esp_sa; /* SA for ESP */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct ipsec_policy_s *ixm_ipsec_policy; /* why are we here? */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct ipsec_action_s *ixm_ipsec_action; /* For reflected packets */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipsa_ref_t ixm_ipsec_ref[2]; /* Soft reference to SA */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Need these while waiting for SA */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint16_t ixm_ipsec_src_port; /* Source port number of d-gram. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint16_t ixm_ipsec_dst_port; /* Destination port number of d-gram. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint8_t ixm_ipsec_icmp_type; /* ICMP type of d-gram */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint8_t ixm_ipsec_icmp_code; /* ICMP code of d-gram */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sa_family_t ixm_ipsec_inaf; /* Inner address family */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint32_t ixm_ipsec_insrc[IXA_MAX_ADDRLEN]; /* Inner src address */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint32_t ixm_ipsec_indst[IXA_MAX_ADDRLEN]; /* Inner dest address */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint8_t ixm_ipsec_insrcpfx; /* Inner source prefix */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint8_t ixm_ipsec_indstpfx; /* Inner destination prefix */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint8_t ixm_ipsec_proto; /* IP protocol number for d-gram. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When we need to handle a receive side asynchronous operation, then we need
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to save sufficient information so that we can call ip_fanout.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * That information is captured in an mblk containing this structure.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since this is currently only used for IPsec, we include information for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the kernel crypto framework.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark netstackid_t irm_stackid; /* Verify it didn't go away */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint16_t irm_ip_hdr_length; /* Points to ULP header */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint8_t irm_protocol; /* Protocol number for ULP cksum */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark zoneid_t irm_zoneid; /* ALL_ZONES unless local delivery */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipaddr_t irm_mroute_tunnel; /* IRAF_MROUTE_TUNNEL_SET */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark zoneid_t irm_no_loop_zoneid; /* IRAF_NO_LOOP_ZONEID_SET */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint32_t irm_esp_udp_ports; /* IRAF_ESP_UDP_PORTS */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark char irm_l2src[IRA_L2SRC_SIZE]; /* If IRAF_L2SRC_SET */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark cred_t *irm_cred; /* For getpeerucred - refhold if set */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When set these correspond to a refhold on the object.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct ipsa_s *irm_ipsec_ah_sa; /* SA for AH */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct ipsa_s *irm_ipsec_esp_sa; /* SA for ESP */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct ipsec_action_s *irm_ipsec_action; /* For reflected packets */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Take the information in ip_xmit_attr_t and stick it in an mblk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * that can later be passed to ip_xmit_attr_from_mblk to recreate the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_xmit_attr_t.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns NULL on memory allocation failure.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_stackid = ixa->ixa_ipst->ips_netstack->netstack_stackid;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ifindex = nce->nce_ill->ill_phyint->phyint_ifindex;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ip_hdr_length = ixa->ixa_ip_hdr_length;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_no_loop_zoneid = ixa->ixa_no_loop_zoneid;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_esp_sa = ixa->ixa_ipsec_esp_sa;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_policy = ixa->ixa_ipsec_policy;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_action = ixa->ixa_ipsec_action;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_ref[0] = ixa->ixa_ipsec_ref[0];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_ref[1] = ixa->ixa_ipsec_ref[1];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_src_port = ixa->ixa_ipsec_src_port;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_dst_port = ixa->ixa_ipsec_dst_port;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_icmp_type = ixa->ixa_ipsec_icmp_type;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_icmp_code = ixa->ixa_ipsec_icmp_code;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_insrc[0] = ixa->ixa_ipsec_insrc[0];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_insrc[1] = ixa->ixa_ipsec_insrc[1];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_insrc[2] = ixa->ixa_ipsec_insrc[2];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_insrc[3] = ixa->ixa_ipsec_insrc[3];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_indst[0] = ixa->ixa_ipsec_indst[0];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_indst[1] = ixa->ixa_ipsec_indst[1];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_indst[2] = ixa->ixa_ipsec_indst[2];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_indst[3] = ixa->ixa_ipsec_indst[3];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_insrcpfx = ixa->ixa_ipsec_insrcpfx;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixm->ixm_ipsec_indstpfx = ixa->ixa_ipsec_indstpfx;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Extract the ip_xmit_attr_t from the mblk, checking that the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_stack_t, ill_t, and nce_t still exist. Returns B_FALSE if that is
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * not the case.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Otherwise ixa is updated.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Caller needs to release references on the ixa by calling ixa_refrele()
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * which will imediately call ixa_inactive to release the references.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_xmit_attr_from_mblk(mblk_t *ixamp, ip_xmit_attr_t *ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We assume the caller hasn't initialized ixa */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Verify the netstack is still around */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ns = netstack_find_by_stackid(ixm->ixm_stackid);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Disappeared on us */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Verify the ill is still around */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We have the ill, hence the netstack can't go away */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Disappeared on us */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Find the nce. We don't load-spread (only lookup nce's on the ill)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * because we want to find the same nce as the one we had when
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_xmit_attr_to_mblk was called.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark nce = nce_lookup_v4(ill, &ixm->ixm_nceaddr_v4);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark nce = nce_lookup_v6(ill, &ixm->ixm_nceaddr_v6);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We have the nce, hence the ill can't go away */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since this is unusual and we don't know what type of
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * nce it was, we drop the packet.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ip_hdr_length = ixm->ixm_ip_hdr_length;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_no_loop_zoneid = ixm->ixm_no_loop_zoneid;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_esp_sa = ixm->ixm_ipsec_esp_sa;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_policy = ixm->ixm_ipsec_policy;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_action = ixm->ixm_ipsec_action;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_ref[0] = ixm->ixm_ipsec_ref[0];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_ref[1] = ixm->ixm_ipsec_ref[1];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_src_port = ixm->ixm_ipsec_src_port;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_dst_port = ixm->ixm_ipsec_dst_port;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_icmp_type = ixm->ixm_ipsec_icmp_type;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_icmp_code = ixm->ixm_ipsec_icmp_code;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_insrc[0] = ixm->ixm_ipsec_insrc[0];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_insrc[1] = ixm->ixm_ipsec_insrc[1];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_insrc[2] = ixm->ixm_ipsec_insrc[2];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_insrc[3] = ixm->ixm_ipsec_insrc[3];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_indst[0] = ixm->ixm_ipsec_indst[0];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_indst[1] = ixm->ixm_ipsec_indst[1];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_indst[2] = ixm->ixm_ipsec_indst[2];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_indst[3] = ixm->ixm_ipsec_indst[3];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_insrcpfx = ixm->ixm_ipsec_insrcpfx;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ipsec_indstpfx = ixm->ixm_ipsec_indstpfx;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Free the ixm mblk and any references it holds
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns b_cont.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Consume mp */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Take the information in ip_recv_attr_t and stick it in an mblk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * that can later be passed to ip_recv_attr_from_mblk to recreate the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_recv_attr_t.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns NULL on memory allocation failure.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(ira->ira_ill != NULL || ira->ira_ruifindex != 0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Internal to IP - preserve ip_stack_t, ill and rill */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ill->ill_ipst->ips_netstack->netstack_stackid;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark irm->irm_ifindex = ira->ira_ill->ill_phyint->phyint_ifindex;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(ira->ira_rill->ill_phyint->phyint_ifindex ==
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Let ip_recv_attr_from_stackid know there isn't one */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark irm->irm_ip_hdr_length = ira->ira_ip_hdr_length;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark irm->irm_mroute_tunnel = ira->ira_mroute_tunnel;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark irm->irm_no_loop_zoneid = ira->ira_no_loop_zoneid;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark irm->irm_esp_udp_ports = ira->ira_esp_udp_ports;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark bcopy(ira->ira_l2src, irm->irm_l2src, IRA_L2SRC_SIZE);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark irm->irm_ipsec_esp_sa = ira->ira_ipsec_esp_sa;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark irm->irm_ipsec_action = ira->ira_ipsec_action;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Extract the ip_recv_attr_t from the mblk. If we are used inside IP
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * then irm_stackid is not -1, in which case we check that the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_stack_t and ill_t still exist. Returns B_FALSE if that is
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * not the case.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If irm_stackid is zero then we are used by an ULP (e.g., squeue_enter)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * and we just proceed with ira_ill and ira_rill as NULL.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The caller needs to release any references on the pointers inside the ire
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * by calling ira_cleanup.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_recv_attr_from_mblk(mblk_t *iramp, ip_recv_attr_t *ira)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We assume the caller hasn't initialized ira */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Verify the netstack is still around */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ns = netstack_find_by_stackid(irm->irm_stackid);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Disappeared on us */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Verify the ill is still around */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rill = ill_lookup_on_ifindex(irm->irm_rifindex,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We have the ill, hence the netstack can't go away */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Disappeared on us */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Caller must ill_refele(ira_ill) by using ira_cleanup() */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_ip_hdr_length = irm->irm_ip_hdr_length;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* The rest of IP assumes that the rings never go away. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_mroute_tunnel = irm->irm_mroute_tunnel;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_no_loop_zoneid = irm->irm_no_loop_zoneid;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_esp_udp_ports = irm->irm_esp_udp_ports;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark bcopy(irm->irm_l2src, ira->ira_l2src, IRA_L2SRC_SIZE);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_ipsec_esp_sa = irm->irm_ipsec_esp_sa;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_ipsec_action = irm->irm_ipsec_action;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Free the irm mblk and any references it holds
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns b_cont.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Consume mp */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns true if the mblk contains an ip_recv_attr_t
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * For now we just check db_type.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Need to handle the various forms of tcp_timermp which are tagged
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * with b_wptr and might have a NULL b_datap.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (mp->b_wptr == NULL || mp->b_wptr == (uchar_t *)-1)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkconn_get_ixa_impl(conn_t *connp, boolean_t replace, int kmflag)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* At least one references for the conn_t */
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek if (atomic_inc_32_nv(&ixa->ixa_refcnt) == 2) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* No other thread using conn_ixa */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Make sure we drop conn_lock before any refrele */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_refcnt++; /* No atomic needed - not visible */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IXA_REFRELE(oldixa); /* Undo refcnt from conn_t */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IXA_REFRELE(oldixa); /* Undo above atomic_add_32_nv */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Return an ip_xmit_attr_t to use with a conn_t that ensures that only
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the caller can access the ip_xmit_attr_t.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If nobody else is using conn_ixa we return it.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Otherwise we make a "safe" copy of conn_ixa
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * and return it. The "safe" copy has the pointers set to NULL
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * (since the pointers might be changed by another thread using
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * conn_ixa). The caller needs to check for NULL pointers to see
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * if ip_set_destination needs to be called to re-establish the pointers.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If 'replace' is set then we replace conn_ixa with the new ip_xmit_attr_t.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * That is used when we connect() the ULP.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (conn_get_ixa_impl(connp, replace, KM_NOSLEEP));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Used only when the option is to have the kernel hang due to not
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * cleaning up ixa references on ills etc.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkconn_get_ixa_tryhard(conn_t *connp, boolean_t replace)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (conn_get_ixa_impl(connp, replace, KM_SLEEP));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Replace conn_ixa with the ixa argument.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The caller must hold conn_lock.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We return the old ixa; the caller must ixa_refrele that after conn_lock
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * has been dropped.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkconn_replace_ixa(conn_t *connp, ip_xmit_attr_t *ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Return a ip_xmit_attr_t to use with a conn_t that is based on but
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * separate from conn_ixa.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This "safe" copy has the pointers set to NULL
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * (since the pointers might be changed by another thread using
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * conn_ixa). The caller needs to check for NULL pointers to see
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * if ip_set_destination needs to be called to re-establish the pointers.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* At least one references for the conn_t */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Make sure conn_ixa doesn't disappear while we copy it */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkixa_safe_copy(ip_xmit_attr_t *src, ip_xmit_attr_t *ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Clear any pointers that have references and might be changed
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * by ip_set_destination or the ULP
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_dce_generation = DCE_GENERATION_VERIFY;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Clear all the IPsec pointers and the flag as well. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We leave ixa_tsl unchanged, but if it has a refhold we need
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to get an extra refhold.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We leave ixa_cred unchanged, but if it has a refhold we need
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to get an extra refhold.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Duplicate an ip_xmit_attr_t.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Assumes that the caller controls the ixa, hence we do not need to use
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * a safe copy. We just have to increase the refcnt on any pointers.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_xmit_attr_duplicate(ip_xmit_attr_t *src_ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Used to replace the ixa_label field.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The caller should have a reference on the label, which we transfer to
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the attributes so that when the attribute is freed/cleaned up
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * we will release that reference.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_xmit_attr_replace_tsl(ip_xmit_attr_t *ixa, ts_label_t *tsl)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Replace the ip_recv_attr_t's label.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Due to kernel RPC's use of db_credp we also need to replace ira_cred;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * TCP/UDP uses ira_cred to set db_credp for non-socket users.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This can fail (and return B_FALSE) due to lack of memory.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_recv_attr_replace_label(ip_recv_attr_t *ira, ts_label_t *tsl)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Reset zoneid if we have a shared address. That allows
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_fanout_tx_v4/v6 to determine the zoneid again.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We update ira_cred for RPC */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark newcr = copycred_from_tslabel(ira->ira_cred, ira->ira_tsl, KM_NOSLEEP);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This needs to be called after ip_set_destination/tsol_check_dest might
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * have changed ixa_tsl to be specific for a destination, and we now want to
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * send to a different destination.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We have to restart with crgetlabel() since ip_set_destination/
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_check_dest will start with ixa_tsl.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_xmit_attr_restore_tsl(ip_xmit_attr_t *ixa, cred_t *cr)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Release any references contained in the ixa.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Also clear any fields that are not controlled by ixa_flags.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_dce_generation = DCE_GENERATION_VERIFY;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Release any references contained in the ira.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Callers which use ip_recv_attr_from_mblk() would pass B_TRUE as the second
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkira_cleanup(ip_recv_attr_t *ira, boolean_t refrele_ill)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Caused by async processing */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Function to help release any IRE, NCE, or DCEs that
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * have been deleted and are marked as condemned.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The caller is responsible for any serialization which is different
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * for TCP, SCTP, and others.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Can make it NULL as long as we set IRE_GENERATION_VERIFY */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ixa->ixa_dce_generation = DCE_GENERATION_VERIFY;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek tcp_stack_t *tcps = connp->conn_netstack->netstack_tcp;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * It's possible that someone else came in and started cleaning up
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * another connection between the time we verified this one is not being
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * cleaned up and the time we actually get the shared mblk. If that's
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * the case, we've dropped the lock, and some other thread may have
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * cleaned up this connection again, and is still waiting for
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * notification of that cleanup's completion. Therefore we need to
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek while (connp->conn_ixa->ixa_tcpcleanup != IXATC_IDLE) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek while ((mp = tcps->tcps_ixa_cleanup_mp) == NULL) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * Multiple concurrent cleanups; need to have the last
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * one run since it could be an unplumb.
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * We now have the lock and the mblk; now make sure that no one else can
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * try to clean up this connection or enqueue it for cleanup, clear the
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * mblk pointer for this stack, drop the lock, and return the mblk.
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ASSERT(MUTEX_HELD(&tcps->tcps_ixa_cleanup_lock));
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ASSERT(connp->conn_ixa->ixa_tcpcleanup == IXATC_IDLE);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek connp->conn_ixa->ixa_tcpcleanup = IXATC_INPROGRESS;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Used to run ixa_cleanup_stale inside the tcp squeue.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When done we hand the mp back by assigning it to tcps_ixa_cleanup_mp
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * and waking up the caller.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* ARGSUSED2 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktcp_ixa_cleanup(void *arg, mblk_t *mp, void *arg2,
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek connp->conn_ixa->ixa_tcpcleanup = IXATC_COMPLETE;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * It is possible for any number of threads to be waiting for cleanup of
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * different connections. Absent a per-connection (or per-IXA) CV, we
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * need to wake them all up even though only one can be waiting on this
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * particular cleanup.
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek cv_broadcast(&tcps->tcps_ixa_cleanup_done_cv);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek tcp_stack_t *tcps = connp->conn_netstack->netstack_tcp;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ASSERT(connp->conn_ixa->ixa_tcpcleanup != IXATC_IDLE);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek while (connp->conn_ixa->ixa_tcpcleanup == IXATC_INPROGRESS) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ASSERT(connp->conn_ixa->ixa_tcpcleanup == IXATC_COMPLETE);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek cv_broadcast(&tcps->tcps_ixa_cleanup_done_cv);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ipcl_walk() function to help release any IRE, NCE, or DCEs that
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * have been deleted and are marked as condemned.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that we can't cleanup the pointers since there can be threads
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * in conn_ip_output() sending while we are called.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Already on squeue */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark SQUEUE_ENTER_ONE(connp->conn_sqp, mp, tcp_ixa_cleanup,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark connp, NULL, SQ_PROCESS, SQTAG_TCP_IXA_CLEANUP);
6be61d4ea129a94bdfe33533b2bc265d4447f05cchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next)
6be61d4ea129a94bdfe33533b2bc265d4447f05cchandrasekar marimuthu - Sun Microsystems - Bangalore India ixa_cleanup_stale(fp->sf_ixa);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If there is a different thread using conn_ixa then we get a
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * new copy and cut the old one loose from conn_ixa. Otherwise
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * we use conn_ixa and prevent any other thread from
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * using/changing it. Anybody using conn_ixa (e.g., a thread in
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * conn_ip_output) will do an ixa_refrele which will remove any
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * references on the ire etc.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Once we are done other threads can use conn_ixa since the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * refcnt will be back at one.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We are called either because an ill is going away, or
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * due to memory reclaim. In the former case we wait for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * memory since we must remove the refcnts on the ill.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Somebody else was using it and kmem_alloc
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * failed! Next memory reclaim will try to
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ixa needs to be an exclusive copy so that no one changes the cookie
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * or the ixa_nce.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkixa_check_drain_insert(conn_t *connp, ip_xmit_attr_t *ixa)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark idl_txl = &ixa->ixa_ipst->ips_idl_tx_list[IDLHASHINDEX(cookie)];
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * If `cookie' is zero, ip_xmit() -> canputnext() failed -- i.e., flow
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * control is asserted on an ill that does not support direct calls.
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * Jump to insert.
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem if (idd->idd_tx_fctl_df(idd->idd_tx_fctl_dh, cookie) == 0) {
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem DTRACE_PROBE1(ill__tx__not__blocked, uintptr_t, cookie);
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem DTRACE_PROBE2(ill__tx__cookie__collision, uintptr_t, cookie,
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem /* TODO: bump kstat for cookie collision */
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * Check/set conn_blocked under conn_lock. Note that txl_lock
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * will not suffice since two separate UDP threads may be
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * racing to send to different destinations that are
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * associated with different cookies and thus may not be
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * holding the same txl_lock. Further, since a given conn_t
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * can only be on a single drain list, the conn_t will be
3344d7501f5a54d4cb5703f67648ea334c1cec6ameem * enqueued on whichever thread wins this race.