ip_attr.c revision 3344d7501f5a54d4cb5703f67648ea334c1cec6a
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * CDDL HEADER START
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * The contents of this file are subject to the terms of the
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Common Development and Distribution License (the "License").
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * You may not use this file except in compliance with the License.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * or http://www.opensolaris.org/os/licensing.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * See the License for the specific language governing permissions
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * and limitations under the License.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * When distributing Covered Code, include this CDDL HEADER in each
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * If applicable, add the following below this CDDL HEADER, with the
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * fields enclosed by brackets "[]" replaced with your own identifying
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * information: Portions Copyright [yyyy] [name of copyright owner]
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * CDDL HEADER END
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Use is subject to license terms.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/* Copyright (c) 1990 Mentat Inc. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/types.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/stream.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/strsun.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/zone.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/ddi.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/sunddi.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/cmn_err.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/debug.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/atomic.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/systm.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/param.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/kmem.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/sdt.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/socket.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/mac.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <net/if.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <net/if_arp.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <net/route.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/sockio.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <netinet/in.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <net/if_dl.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/common.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/mi.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/mib2.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/nd.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/arp.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/snmpcom.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/kstatcom.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <netinet/igmp_var.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <netinet/ip6.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <netinet/icmp6.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <netinet/sctp.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_impl.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip6.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip6_asp.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/tcp.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_multi.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_if.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_ire.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_ftable.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_rts.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/optcom.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_ndp.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_listutils.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <netinet/igmp.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <netinet/ip_mroute.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ipp_common.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <net/pfkeyv2.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/sadb.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ipsec_impl.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ipdrop.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ip_netinfo.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/squeue_impl.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/squeue.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/ipclassifier.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/sctp_ip.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/sctp/sctp_impl.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <inet/udp_impl.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/sunddi.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/tsol/label.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#include <sys/tsol/tnet.h>
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Release a reference on ip_xmit_attr.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * The reference is acquired by conn_get_ixa()
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#define IXA_REFRELE(ixa) \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{ \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (atomic_add_32_nv(&(ixa)->ixa_refcnt, -1) == 0) \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa_inactive(ixa); \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#define IXA_REFHOLD(ixa) \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{ \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT((ixa)->ixa_refcnt != 0); \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw atomic_add_32(&(ixa)->ixa_refcnt, 1); \
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * When we need to handle a transmit side asynchronous operation, then we need
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * to save sufficient information so that we can call the fragment and postfrag
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * functions. That information is captured in an mblk containing this structure.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Since this is currently only used for IPsec, we include information for
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * the kernel crypto framework.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwtypedef struct ixamblk_s {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw boolean_t ixm_inbound; /* B_FALSE */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iaflags_t ixm_flags; /* ixa_flags */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstackid_t ixm_stackid; /* Verify it didn't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint_t ixm_ifindex; /* Used to find the nce */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw in6_addr_t ixm_nceaddr_v6; /* Used to find nce */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#define ixm_nceaddr_v4 V4_PART_OF_V6(ixm_nceaddr_v6)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint32_t ixm_fragsize;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint_t ixm_pktlen;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint16_t ixm_ip_hdr_length; /* Points to ULP header */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_protocol; /* Protocol number for ULP cksum */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw pfirepostfrag_t ixm_postfragfn;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw zoneid_t ixm_zoneid; /* Needed for ipobs */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw zoneid_t ixm_no_loop_zoneid; /* IXAF_NO_LOOP_ZONEID_SET */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint_t ixm_scopeid; /* For IPv6 link-locals */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint32_t ixm_ident; /* For IPv6 fragment header */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint32_t ixm_xmit_hint;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw cred_t *ixm_cred; /* For getpeerucred - refhold if set */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw pid_t ixm_cpid; /* For getpeerucred */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ts_label_t *ixm_tsl; /* Refhold if set. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * When the pointers below are set they have a refhold on the struct.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ipsec_latch_t *ixm_ipsec_latch;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsa_s *ixm_ipsec_ah_sa; /* SA for AH */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsa_s *ixm_ipsec_esp_sa; /* SA for ESP */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsec_policy_s *ixm_ipsec_policy; /* why are we here? */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsec_action_s *ixm_ipsec_action; /* For reflected packets */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ipsa_ref_t ixm_ipsec_ref[2]; /* Soft reference to SA */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Need these while waiting for SA */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint16_t ixm_ipsec_src_port; /* Source port number of d-gram. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint16_t ixm_ipsec_dst_port; /* Destination port number of d-gram. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_ipsec_icmp_type; /* ICMP type of d-gram */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_ipsec_icmp_code; /* ICMP code of d-gram */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw sa_family_t ixm_ipsec_inaf; /* Inner address family */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint32_t ixm_ipsec_insrc[IXA_MAX_ADDRLEN]; /* Inner src address */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint32_t ixm_ipsec_indst[IXA_MAX_ADDRLEN]; /* Inner dest address */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_ipsec_insrcpfx; /* Inner source prefix */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_ipsec_indstpfx; /* Inner destination prefix */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_ipsec_proto; /* IP protocol number for d-gram. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw} ixamblk_t;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * When we need to handle a receive side asynchronous operation, then we need
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * to save sufficient information so that we can call ip_fanout.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * That information is captured in an mblk containing this structure.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Since this is currently only used for IPsec, we include information for
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * the kernel crypto framework.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwtypedef struct iramblk_s {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw boolean_t irm_inbound; /* B_TRUE */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iaflags_t irm_flags; /* ira_flags */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstackid_t irm_stackid; /* Verify it didn't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint_t irm_ifindex; /* To find ira_ill */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint_t irm_rifindex; /* ira_rifindex */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint_t irm_ruifindex; /* ira_ruifindex */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint_t irm_pktlen;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint16_t irm_ip_hdr_length; /* Points to ULP header */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t irm_protocol; /* Protocol number for ULP cksum */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw zoneid_t irm_zoneid; /* ALL_ZONES unless local delivery */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw squeue_t *irm_sqp;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill_rx_ring_t *irm_ring;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ipaddr_t irm_mroute_tunnel; /* IRAF_MROUTE_TUNNEL_SET */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw zoneid_t irm_no_loop_zoneid; /* IRAF_NO_LOOP_ZONEID_SET */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint32_t irm_esp_udp_ports; /* IRAF_ESP_UDP_PORTS */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw char irm_l2src[IRA_L2SRC_SIZE]; /* If IRAF_L2SRC_SET */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw cred_t *irm_cred; /* For getpeerucred - refhold if set */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw pid_t irm_cpid; /* For getpeerucred */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ts_label_t *irm_tsl; /* Refhold if set. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * When set these correspond to a refhold on the object.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsa_s *irm_ipsec_ah_sa; /* SA for AH */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsa_s *irm_ipsec_esp_sa; /* SA for ESP */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsec_action_s *irm_ipsec_action; /* For reflected packets */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw} iramblk_t;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Take the information in ip_xmit_attr_t and stick it in an mblk
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * that can later be passed to ip_xmit_attr_from_mblk to recreate the
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * ip_xmit_attr_t.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns NULL on memory allocation failure.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwmblk_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_to_mblk(ip_xmit_attr_t *ixa)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mblk_t *ixamp;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixamblk_t *ixm;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw nce_t *nce = ixa->ixa_nce;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(nce != NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixamp = allocb(sizeof (*ixm), BPRI_MED);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixamp == NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixamp->b_datap->db_type = M_BREAK;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixamp->b_wptr += sizeof (*ixm);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm = (ixamblk_t *)ixamp->b_rptr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bzero(ixm, sizeof (*ixm));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_inbound = B_FALSE;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_flags = ixa->ixa_flags;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_stackid = ixa->ixa_ipst->ips_netstack->netstack_stackid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ifindex = nce->nce_ill->ill_phyint->phyint_ifindex;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_nceaddr_v6 = nce->nce_addr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_fragsize = ixa->ixa_fragsize;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_pktlen = ixa->ixa_pktlen;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ip_hdr_length = ixa->ixa_ip_hdr_length;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_protocol = ixa->ixa_protocol;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_postfragfn = ixa->ixa_postfragfn;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_zoneid = ixa->ixa_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_no_loop_zoneid = ixa->ixa_no_loop_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_scopeid = ixa->ixa_scopeid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ident = ixa->ixa_ident;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_xmit_hint = ixa->ixa_xmit_hint;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_tsl != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_tsl = ixa->ixa_tsl;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_hold(ixm->ixm_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_cred != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_cred = ixa->ixa_cred;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw crhold(ixa->ixa_cred);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_cpid = ixa->ixa_cpid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_flags & IXAF_IPSEC_SECURE) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_ah_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_ah_sa = ixa->ixa_ipsec_ah_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFHOLD(ixa->ixa_ipsec_ah_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_esp_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_esp_sa = ixa->ixa_ipsec_esp_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFHOLD(ixa->ixa_ipsec_esp_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_policy != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_policy = ixa->ixa_ipsec_policy;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPPOL_REFHOLD(ixa->ixa_ipsec_policy);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_action != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_action = ixa->ixa_ipsec_action;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPACT_REFHOLD(ixa->ixa_ipsec_action);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_latch != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_latch = ixa->ixa_ipsec_latch;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPLATCH_REFHOLD(ixa->ixa_ipsec_latch);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_ref[0] = ixa->ixa_ipsec_ref[0];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_ref[1] = ixa->ixa_ipsec_ref[1];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_src_port = ixa->ixa_ipsec_src_port;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_dst_port = ixa->ixa_ipsec_dst_port;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_icmp_type = ixa->ixa_ipsec_icmp_type;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_icmp_code = ixa->ixa_ipsec_icmp_code;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_inaf = ixa->ixa_ipsec_inaf;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_insrc[0] = ixa->ixa_ipsec_insrc[0];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_insrc[1] = ixa->ixa_ipsec_insrc[1];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_insrc[2] = ixa->ixa_ipsec_insrc[2];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_insrc[3] = ixa->ixa_ipsec_insrc[3];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_indst[0] = ixa->ixa_ipsec_indst[0];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_indst[1] = ixa->ixa_ipsec_indst[1];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_indst[2] = ixa->ixa_ipsec_indst[2];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_indst[3] = ixa->ixa_ipsec_indst[3];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_insrcpfx = ixa->ixa_ipsec_insrcpfx;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_indstpfx = ixa->ixa_ipsec_indstpfx;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_proto = ixa->ixa_ipsec_proto;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (ixamp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Extract the ip_xmit_attr_t from the mblk, checking that the
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * ip_stack_t, ill_t, and nce_t still exist. Returns B_FALSE if that is
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * not the case.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Otherwise ixa is updated.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Caller needs to release references on the ixa by calling ixa_refrele()
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * which will imediately call ixa_inactive to release the references.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwboolean_t
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_from_mblk(mblk_t *ixamp, ip_xmit_attr_t *ixa)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixamblk_t *ixm;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstack_t *ns;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ip_stack_t *ipst;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill_t *ill;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw nce_t *nce;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We assume the caller hasn't initialized ixa */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bzero(ixa, sizeof (*ixa));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(DB_TYPE(ixamp) == M_BREAK);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ixamp->b_cont == NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm = (ixamblk_t *)ixamp->b_rptr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(!ixm->ixm_inbound);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the netstack is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ns = netstack_find_by_stackid(ixm->ixm_stackid);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ns == NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw (void) ip_xmit_attr_free_mblk(ixamp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ipst = ns->netstack_ip;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the ill is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill = ill_lookup_on_ifindex(ixm->ixm_ifindex,
d0e518695adc90b82233b99af7dffbb3d3f92c00amw !(ixm->ixm_flags & IXAF_IS_IPV4), ipst);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We have the ill, hence the netstack can't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstack_rele(ns);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ill == NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw (void) ip_xmit_attr_free_mblk(ixamp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Find the nce. We don't load-spread (only lookup nce's on the ill)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * because we want to find the same nce as the one we had when
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * ip_xmit_attr_to_mblk was called.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_flags & IXAF_IS_IPV4) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw nce = nce_lookup_v4(ill, &ixm->ixm_nceaddr_v4);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw } else {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw nce = nce_lookup_v6(ill, &ixm->ixm_nceaddr_v6);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We have the nce, hence the ill can't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill_refrele(ill);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (nce == NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Since this is unusual and we don't know what type of
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * nce it was, we drop the packet.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw (void) ip_xmit_attr_free_mblk(ixamp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_flags = ixm->ixm_flags;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_refcnt = 1;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipst = ipst;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_fragsize = ixm->ixm_fragsize;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_pktlen = ixm->ixm_pktlen;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ip_hdr_length = ixm->ixm_ip_hdr_length;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_protocol = ixm->ixm_protocol;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_nce = nce;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_postfragfn = ixm->ixm_postfragfn;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_zoneid = ixm->ixm_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_no_loop_zoneid = ixm->ixm_no_loop_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_scopeid = ixm->ixm_scopeid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ident = ixm->ixm_ident;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_xmit_hint = ixm->ixm_xmit_hint;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_tsl != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_tsl = ixm->ixm_tsl;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_free_flags |= IXA_FREE_TSL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_tsl = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_cred != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_cred = ixm->ixm_cred;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_free_flags |= IXA_FREE_CRED;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_cred = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_cpid = ixm->ixm_cpid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_ah_sa = ixm->ixm_ipsec_ah_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_esp_sa = ixm->ixm_ipsec_esp_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_policy = ixm->ixm_ipsec_policy;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_action = ixm->ixm_ipsec_action;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_latch = ixm->ixm_ipsec_latch;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_ref[0] = ixm->ixm_ipsec_ref[0];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_ref[1] = ixm->ixm_ipsec_ref[1];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_src_port = ixm->ixm_ipsec_src_port;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_dst_port = ixm->ixm_ipsec_dst_port;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_icmp_type = ixm->ixm_ipsec_icmp_type;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_icmp_code = ixm->ixm_ipsec_icmp_code;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_inaf = ixm->ixm_ipsec_inaf;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_insrc[0] = ixm->ixm_ipsec_insrc[0];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_insrc[1] = ixm->ixm_ipsec_insrc[1];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_insrc[2] = ixm->ixm_ipsec_insrc[2];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_insrc[3] = ixm->ixm_ipsec_insrc[3];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_indst[0] = ixm->ixm_ipsec_indst[0];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_indst[1] = ixm->ixm_ipsec_indst[1];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_indst[2] = ixm->ixm_ipsec_indst[2];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_indst[3] = ixm->ixm_ipsec_indst[3];
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_insrcpfx = ixm->ixm_ipsec_insrcpfx;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_indstpfx = ixm->ixm_ipsec_indstpfx;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_proto = ixm->ixm_ipsec_proto;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw freeb(ixamp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_TRUE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Free the ixm mblk and any references it holds
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns b_cont.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwmblk_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_free_mblk(mblk_t *ixamp)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixamblk_t *ixm;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mblk_t *mp;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Consume mp */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(DB_TYPE(ixamp) == M_BREAK);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mp = ixamp->b_cont;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm = (ixamblk_t *)ixamp->b_rptr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(!ixm->ixm_inbound);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_ipsec_ah_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFRELE(ixm->ixm_ipsec_ah_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_ah_sa = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_ipsec_esp_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFRELE(ixm->ixm_ipsec_esp_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_esp_sa = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_ipsec_policy != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPPOL_REFRELE(ixm->ixm_ipsec_policy);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_policy = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_ipsec_action != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPACT_REFRELE(ixm->ixm_ipsec_action);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_action = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_ipsec_latch) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPLATCH_REFRELE(ixm->ixm_ipsec_latch);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ipsec_latch = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_tsl != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_rele(ixm->ixm_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_tsl = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixm->ixm_cred != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw crfree(ixm->ixm_cred);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_cred = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw freeb(ixamp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (mp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Take the information in ip_recv_attr_t and stick it in an mblk
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * that can later be passed to ip_recv_attr_from_mblk to recreate the
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * ip_recv_attr_t.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns NULL on memory allocation failure.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwmblk_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_recv_attr_to_mblk(ip_recv_attr_t *ira)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mblk_t *iramp;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iramblk_t *irm;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill_t *ill = ira->ira_ill;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ira->ira_ill != NULL || ira->ira_ruifindex != 0);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iramp = allocb(sizeof (*irm), BPRI_MED);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (iramp == NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iramp->b_datap->db_type = M_BREAK;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iramp->b_wptr += sizeof (*irm);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm = (iramblk_t *)iramp->b_rptr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bzero(irm, sizeof (*irm));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_inbound = B_TRUE;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_flags = ira->ira_flags;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ill != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Internal to IP - preserve ip_stack_t, ill and rill */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_stackid =
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill->ill_ipst->ips_netstack->netstack_stackid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ifindex = ira->ira_ill->ill_phyint->phyint_ifindex;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ira->ira_rill->ill_phyint->phyint_ifindex ==
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_rifindex);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw } else {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Let ip_recv_attr_from_stackid know there isn't one */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_stackid = -1;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_rifindex = ira->ira_rifindex;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ruifindex = ira->ira_ruifindex;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_pktlen = ira->ira_pktlen;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ip_hdr_length = ira->ira_ip_hdr_length;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_protocol = ira->ira_protocol;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_sqp = ira->ira_sqp;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ring = ira->ira_ring;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_zoneid = ira->ira_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_mroute_tunnel = ira->ira_mroute_tunnel;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_no_loop_zoneid = ira->ira_no_loop_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_esp_udp_ports = ira->ira_esp_udp_ports;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_tsl != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_tsl = ira->ira_tsl;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_hold(irm->irm_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_cred != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_cred = ira->ira_cred;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw crhold(ira->ira_cred);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_cpid = ira->ira_cpid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_flags & IRAF_L2SRC_SET)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bcopy(ira->ira_l2src, irm->irm_l2src, IRA_L2SRC_SIZE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_flags & IRAF_IPSEC_SECURE) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_ipsec_ah_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ipsec_ah_sa = ira->ira_ipsec_ah_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFHOLD(ira->ira_ipsec_ah_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_ipsec_esp_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ipsec_esp_sa = ira->ira_ipsec_esp_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFHOLD(ira->ira_ipsec_esp_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_ipsec_action != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ipsec_action = ira->ira_ipsec_action;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPACT_REFHOLD(ira->ira_ipsec_action);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (iramp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Extract the ip_recv_attr_t from the mblk. If we are used inside IP
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * then irm_stackid is not -1, in which case we check that the
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * ip_stack_t and ill_t still exist. Returns B_FALSE if that is
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * not the case.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * If irm_stackid is zero then we are used by an ULP (e.g., squeue_enter)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * and we just proceed with ira_ill and ira_rill as NULL.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * The caller needs to release any references on the pointers inside the ire
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * by calling ira_cleanup.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwboolean_t
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_recv_attr_from_mblk(mblk_t *iramp, ip_recv_attr_t *ira)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iramblk_t *irm;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstack_t *ns;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ip_stack_t *ipst = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill_t *ill = NULL, *rill = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We assume the caller hasn't initialized ira */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bzero(ira, sizeof (*ira));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(DB_TYPE(iramp) == M_BREAK);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(iramp->b_cont == NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm = (iramblk_t *)iramp->b_rptr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(irm->irm_inbound);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_stackid != -1) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the netstack is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ns = netstack_find_by_stackid(irm->irm_stackid);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ns == NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw (void) ip_recv_attr_free_mblk(iramp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ipst = ns->netstack_ip;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the ill is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill = ill_lookup_on_ifindex(irm->irm_ifindex,
d0e518695adc90b82233b99af7dffbb3d3f92c00amw !(irm->irm_flags & IRAF_IS_IPV4), ipst);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_ifindex == irm->irm_rifindex) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw rill = ill;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw } else {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw rill = ill_lookup_on_ifindex(irm->irm_rifindex,
d0e518695adc90b82233b99af7dffbb3d3f92c00amw !(irm->irm_flags & IRAF_IS_IPV4), ipst);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We have the ill, hence the netstack can't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstack_rele(ns);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ill == NULL || rill == NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ill != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill_refrele(ill);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (rill != NULL && rill != ill)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ill_refrele(rill);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw (void) ip_recv_attr_free_mblk(iramp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_flags = irm->irm_flags;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Caller must ill_refele(ira_ill) by using ira_cleanup() */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_ill = ill;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_rill = rill;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_rifindex = irm->irm_rifindex;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_ruifindex = irm->irm_ruifindex;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_pktlen = irm->irm_pktlen;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_ip_hdr_length = irm->irm_ip_hdr_length;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_protocol = irm->irm_protocol;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_sqp = irm->irm_sqp;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* The rest of IP assumes that the rings never go away. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_ring = irm->irm_ring;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_zoneid = irm->irm_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_mroute_tunnel = irm->irm_mroute_tunnel;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_no_loop_zoneid = irm->irm_no_loop_zoneid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_esp_udp_ports = irm->irm_esp_udp_ports;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_tsl != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_tsl = irm->irm_tsl;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_free_flags |= IRA_FREE_TSL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_tsl = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_cred != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_cred = irm->irm_cred;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_free_flags |= IRA_FREE_CRED;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_cred = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_cpid = irm->irm_cpid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_flags & IRAF_L2SRC_SET)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bcopy(irm->irm_l2src, ira->ira_l2src, IRA_L2SRC_SIZE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_ipsec_ah_sa = irm->irm_ipsec_ah_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_ipsec_esp_sa = irm->irm_ipsec_esp_sa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_ipsec_action = irm->irm_ipsec_action;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw freeb(iramp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_TRUE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Free the irm mblk and any references it holds
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns b_cont.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwmblk_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_recv_attr_free_mblk(mblk_t *iramp)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iramblk_t *irm;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mblk_t *mp;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Consume mp */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(DB_TYPE(iramp) == M_BREAK);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mp = iramp->b_cont;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm = (iramblk_t *)iramp->b_rptr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(irm->irm_inbound);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_ipsec_ah_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFRELE(irm->irm_ipsec_ah_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ipsec_ah_sa = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_ipsec_esp_sa != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFRELE(irm->irm_ipsec_esp_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ipsec_esp_sa = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_ipsec_action != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPACT_REFRELE(irm->irm_ipsec_action);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ipsec_action = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_tsl != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_rele(irm->irm_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_tsl = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (irm->irm_cred != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw crfree(irm->irm_cred);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_cred = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw freeb(iramp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (mp);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns true if the mblk contains an ip_recv_attr_t
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * For now we just check db_type.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwboolean_t
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_recv_attr_is_mblk(mblk_t *mp)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Need to handle the various forms of tcp_timermp which are tagged
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * with b_wptr and might have a NULL b_datap.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (mp->b_wptr == NULL || mp->b_wptr == (uchar_t *)-1)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#ifdef DEBUG
d0e518695adc90b82233b99af7dffbb3d3f92c00amw iramblk_t *irm;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (DB_TYPE(mp) != M_BREAK)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm = (iramblk_t *)mp->b_rptr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(irm->irm_inbound);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_TRUE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#else
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (DB_TYPE(mp) == M_BREAK);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#endif
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amwstatic ip_xmit_attr_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwconn_get_ixa_impl(conn_t *connp, boolean_t replace, int kmflag)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ip_xmit_attr_t *ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ip_xmit_attr_t *oldixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_enter(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa = connp->conn_ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* At least one references for the conn_t */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ixa->ixa_refcnt >= 1);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (atomic_add_32_nv(&ixa->ixa_refcnt, 1) == 2) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* No other thread using conn_ixa */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_exit(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa = kmem_alloc(sizeof (*ixa), kmflag);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa == NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_exit(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa_refrele(connp->conn_ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa_safe_copy(connp->conn_ixa, ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Make sure we drop conn_lock before any refrele */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (replace) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_refcnt++; /* No atomic needed - not visible */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw oldixa = connp->conn_ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw connp->conn_ixa = ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_exit(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IXA_REFRELE(oldixa); /* Undo refcnt from conn_t */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw } else {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw oldixa = connp->conn_ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_exit(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IXA_REFRELE(oldixa); /* Undo above atomic_add_32_nv */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Return an ip_xmit_attr_t to use with a conn_t that ensures that only
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * the caller can access the ip_xmit_attr_t.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * If nobody else is using conn_ixa we return it.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Otherwise we make a "safe" copy of conn_ixa
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * and return it. The "safe" copy has the pointers set to NULL
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * (since the pointers might be changed by another thread using
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * conn_ixa). The caller needs to check for NULL pointers to see
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * if ip_set_destination needs to be called to re-establish the pointers.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * If 'replace' is set then we replace conn_ixa with the new ip_xmit_attr_t.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * That is used when we connect() the ULP.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwconn_get_ixa(conn_t *connp, boolean_t replace)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (conn_get_ixa_impl(connp, replace, KM_NOSLEEP));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Used only when the option is to have the kernel hang due to not
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * cleaning up ixa references on ills etc.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwconn_get_ixa_tryhard(conn_t *connp, boolean_t replace)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (conn_get_ixa_impl(connp, replace, KM_SLEEP));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Replace conn_ixa with the ixa argument.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * The caller must hold conn_lock.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * We return the old ixa; the caller must ixa_refrele that after conn_lock
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * has been dropped.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwconn_replace_ixa(conn_t *connp, ip_xmit_attr_t *ixa)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ip_xmit_attr_t *oldixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(MUTEX_HELD(&connp->conn_lock));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw oldixa = connp->conn_ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IXA_REFHOLD(ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw connp->conn_ixa = ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (oldixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Return a ip_xmit_attr_t to use with a conn_t that is based on but
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * separate from conn_ixa.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw *
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * This "safe" copy has the pointers set to NULL
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * (since the pointers might be changed by another thread using
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * conn_ixa). The caller needs to check for NULL pointers to see
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * if ip_set_destination needs to be called to re-establish the pointers.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwconn_get_ixa_exclusive(conn_t *connp)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ip_xmit_attr_t *ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_enter(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa = connp->conn_ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* At least one references for the conn_t */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ixa->ixa_refcnt >= 1);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Make sure conn_ixa doesn't disappear while we copy it */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw atomic_add_32(&ixa->ixa_refcnt, 1);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa = kmem_alloc(sizeof (*ixa), KM_NOSLEEP);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa == NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_exit(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa_refrele(connp->conn_ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa_safe_copy(connp->conn_ixa, ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw mutex_exit(&connp->conn_lock);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IXA_REFRELE(connp->conn_ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amwvoid
d0e518695adc90b82233b99af7dffbb3d3f92c00amwixa_safe_copy(ip_xmit_attr_t *src, ip_xmit_attr_t *ixa)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bcopy(src, ixa, sizeof (*ixa));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_refcnt = 1;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Clear any pointers that have references and might be changed
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * by ip_set_destination or the ULP
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ire = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_nce = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_dce = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_dce_generation = DCE_GENERATION_VERIFY;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#ifdef DEBUG
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_curthread = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#endif
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Clear all the IPsec pointers and the flag as well. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_flags &= ~IXAF_IPSEC_SECURE;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_latch = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_ah_sa = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_esp_sa = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_policy = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_ipsec_action = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * We leave ixa_tsl unchanged, but if it has a refhold we need
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * to get an extra refhold.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_free_flags & IXA_FREE_TSL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_hold(ixa->ixa_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * We leave ixa_cred unchanged, but if it has a refhold we need
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * to get an extra refhold.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_free_flags & IXA_FREE_CRED)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw crhold(ixa->ixa_cred);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Duplicate an ip_xmit_attr_t.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Assumes that the caller controls the ixa, hence we do not need to use
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * a safe copy. We just have to increase the refcnt on any pointers.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_t *
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_duplicate(ip_xmit_attr_t *src_ixa)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ip_xmit_attr_t *ixa;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa = kmem_alloc(sizeof (*ixa), KM_NOSLEEP);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa == NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw bcopy(src_ixa, ixa, sizeof (*ixa));
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_refcnt = 1;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ire != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ire_refhold_notr(ixa->ixa_ire);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_nce != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw nce_refhold(ixa->ixa_nce);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_dce != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw dce_refhold_notr(ixa->ixa_dce);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#ifdef DEBUG
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_curthread = NULL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw#endif
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_latch != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPLATCH_REFHOLD(ixa->ixa_ipsec_latch);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_ah_sa != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFHOLD(ixa->ixa_ipsec_ah_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_esp_sa != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPSA_REFHOLD(ixa->ixa_ipsec_esp_sa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_policy != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPPOL_REFHOLD(ixa->ixa_ipsec_policy);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_ipsec_action != NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw IPACT_REFHOLD(ixa->ixa_ipsec_action);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_tsl != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_hold(ixa->ixa_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_free_flags |= IXA_FREE_TSL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_cred != NULL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw crhold(ixa->ixa_cred);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_free_flags |= IXA_FREE_CRED;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (ixa);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Used to replace the ixa_label field.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * The caller should have a reference on the label, which we transfer to
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * the attributes so that when the attribute is freed/cleaned up
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * we will release that reference.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwvoid
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_replace_tsl(ip_xmit_attr_t *ixa, ts_label_t *tsl)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(tsl != NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_free_flags & IXA_FREE_TSL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ixa->ixa_tsl != NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_rele(ixa->ixa_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw } else {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_free_flags |= IXA_FREE_TSL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_tsl = tsl;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Replace the ip_recv_attr_t's label.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Due to kernel RPC's use of db_credp we also need to replace ira_cred;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * TCP/UDP uses ira_cred to set db_credp for non-socket users.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * This can fail (and return B_FALSE) due to lack of memory.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwboolean_t
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_recv_attr_replace_label(ip_recv_attr_t *ira, ts_label_t *tsl)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw cred_t *newcr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_free_flags & IRA_FREE_TSL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ira->ira_tsl != NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_rele(ira->ira_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_hold(tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_tsl = tsl;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_free_flags |= IRA_FREE_TSL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Reset zoneid if we have a shared address. That allows
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * ip_fanout_tx_v4/v6 to determine the zoneid again.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_flags & IRAF_TX_SHARED_ADDR)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_zoneid = ALL_ZONES;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We update ira_cred for RPC */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw newcr = copycred_from_tslabel(ira->ira_cred, ira->ira_tsl, KM_NOSLEEP);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (newcr == NULL)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_FALSE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ira->ira_free_flags & IRA_FREE_CRED)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw crfree(ira->ira_cred);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_cred = newcr;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ira->ira_free_flags |= IRA_FREE_CRED;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return (B_TRUE);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/*
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * This needs to be called after ip_set_destination/tsol_check_dest might
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * have changed ixa_tsl to be specific for a destination, and we now want to
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * send to a different destination.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * We have to restart with crgetlabel() since ip_set_destination/
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * tsol_check_dest will start with ixa_tsl.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw */
d0e518695adc90b82233b99af7dffbb3d3f92c00amwvoid
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_restore_tsl(ip_xmit_attr_t *ixa, cred_t *cr)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw{
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (!is_system_labeled())
d0e518695adc90b82233b99af7dffbb3d3f92c00amw return;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw
d0e518695adc90b82233b99af7dffbb3d3f92c00amw if (ixa->ixa_free_flags & IXA_FREE_TSL) {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ixa->ixa_tsl != NULL);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw label_rele(ixa->ixa_tsl);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_free_flags &= ~IXA_FREE_TSL;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw }
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixa->ixa_tsl = crgetlabel(cr);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw}
void
ixa_refrele(ip_xmit_attr_t *ixa)
{
IXA_REFRELE(ixa);
}
void
ixa_inactive(ip_xmit_attr_t *ixa)
{
ASSERT(ixa->ixa_refcnt == 0);
ixa_cleanup(ixa);
kmem_free(ixa, sizeof (*ixa));
}
/*
* Release any references contained in the ixa.
* Also clear any fields that are not controlled by ixa_flags.
*/
void
ixa_cleanup(ip_xmit_attr_t *ixa)
{
if (ixa->ixa_ire != NULL) {
ire_refrele_notr(ixa->ixa_ire);
ixa->ixa_ire = NULL;
}
if (ixa->ixa_dce != NULL) {
dce_refrele_notr(ixa->ixa_dce);
ixa->ixa_dce = NULL;
}
if (ixa->ixa_nce != NULL) {
nce_refrele(ixa->ixa_nce);
ixa->ixa_nce = NULL;
}
ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
ixa->ixa_dce_generation = DCE_GENERATION_VERIFY;
if (ixa->ixa_flags & IXAF_IPSEC_SECURE) {
ipsec_out_release_refs(ixa);
}
if (ixa->ixa_free_flags & IXA_FREE_TSL) {
ASSERT(ixa->ixa_tsl != NULL);
label_rele(ixa->ixa_tsl);
ixa->ixa_free_flags &= ~IXA_FREE_TSL;
}
ixa->ixa_tsl = NULL;
if (ixa->ixa_free_flags & IXA_FREE_CRED) {
ASSERT(ixa->ixa_cred != NULL);
crfree(ixa->ixa_cred);
ixa->ixa_free_flags &= ~IXA_FREE_CRED;
}
ixa->ixa_cred = NULL;
ixa->ixa_src_preferences = 0;
ixa->ixa_ifindex = 0;
ixa->ixa_multicast_ifindex = 0;
ixa->ixa_multicast_ifaddr = INADDR_ANY;
}
/*
* Release any references contained in the ira.
* Callers which use ip_recv_attr_from_mblk() would pass B_TRUE as the second
* argument.
*/
void
ira_cleanup(ip_recv_attr_t *ira, boolean_t refrele_ill)
{
if (ira->ira_ill != NULL) {
if (ira->ira_rill != ira->ira_ill) {
/* Caused by async processing */
ill_refrele(ira->ira_rill);
}
if (refrele_ill)
ill_refrele(ira->ira_ill);
}
if (ira->ira_flags & IRAF_IPSEC_SECURE) {
ipsec_in_release_refs(ira);
}
if (ira->ira_free_flags & IRA_FREE_TSL) {
ASSERT(ira->ira_tsl != NULL);
label_rele(ira->ira_tsl);
ira->ira_free_flags &= ~IRA_FREE_TSL;
}
ira->ira_tsl = NULL;
if (ira->ira_free_flags & IRA_FREE_CRED) {
ASSERT(ira->ira_cred != NULL);
crfree(ira->ira_cred);
ira->ira_free_flags &= ~IRA_FREE_CRED;
}
ira->ira_cred = NULL;
}
/*
* Function to help release any IRE, NCE, or DCEs that
* have been deleted and are marked as condemned.
* The caller is responsible for any serialization which is different
* for TCP, SCTP, and others.
*/
static void
ixa_cleanup_stale(ip_xmit_attr_t *ixa)
{
ire_t *ire;
nce_t *nce;
dce_t *dce;
ire = ixa->ixa_ire;
nce = ixa->ixa_nce;
dce = ixa->ixa_dce;
if (ire != NULL && IRE_IS_CONDEMNED(ire)) {
ire_refrele_notr(ire);
ire = ire_blackhole(ixa->ixa_ipst,
!(ixa->ixa_flags & IXAF_IS_IPV4));
ASSERT(ire != NULL);
#ifdef DEBUG
ire_refhold_notr(ire);
ire_refrele(ire);
#endif
ixa->ixa_ire = ire;
ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
}
if (nce != NULL && nce->nce_is_condemned) {
/* Can make it NULL as long as we set IRE_GENERATION_VERIFY */
nce_refrele(nce);
ixa->ixa_nce = NULL;
ixa->ixa_ire_generation = IRE_GENERATION_VERIFY;
}
if (dce != NULL && DCE_IS_CONDEMNED(dce)) {
dce_refrele_notr(dce);
dce = dce_get_default(ixa->ixa_ipst);
ASSERT(dce != NULL);
#ifdef DEBUG
dce_refhold_notr(dce);
dce_refrele(dce);
#endif
ixa->ixa_dce = dce;
ixa->ixa_dce_generation = DCE_GENERATION_VERIFY;
}
}
/*
* Used to run ixa_cleanup_stale inside the tcp squeue.
* When done we hand the mp back by assigning it to tcps_ixa_cleanup_mp
* and waking up the caller.
*/
/* ARGSUSED2 */
static void
tcp_ixa_cleanup(void *arg, mblk_t *mp, void *arg2,
ip_recv_attr_t *dummy)
{
conn_t *connp = (conn_t *)arg;
tcp_stack_t *tcps;
tcps = connp->conn_netstack->netstack_tcp;
ixa_cleanup_stale(connp->conn_ixa);
mutex_enter(&tcps->tcps_ixa_cleanup_lock);
ASSERT(tcps->tcps_ixa_cleanup_mp == NULL);
tcps->tcps_ixa_cleanup_mp = mp;
cv_signal(&tcps->tcps_ixa_cleanup_cv);
mutex_exit(&tcps->tcps_ixa_cleanup_lock);
}
/*
* ipcl_walk() function to help release any IRE, NCE, or DCEs that
* have been deleted and are marked as condemned.
* Note that we can't cleanup the pointers since there can be threads
* in conn_ip_output() sending while we are called.
*/
void
conn_ixa_cleanup(conn_t *connp, void *arg)
{
boolean_t tryhard = (boolean_t)arg;
if (IPCL_IS_TCP(connp)) {
mblk_t *mp;
tcp_stack_t *tcps;
tcps = connp->conn_netstack->netstack_tcp;
mutex_enter(&tcps->tcps_ixa_cleanup_lock);
while ((mp = tcps->tcps_ixa_cleanup_mp) == NULL) {
/*
* Multiple concurrent cleanups; need to have the last
* one run since it could be an unplumb.
*/
cv_wait(&tcps->tcps_ixa_cleanup_cv,
&tcps->tcps_ixa_cleanup_lock);
}
tcps->tcps_ixa_cleanup_mp = NULL;
mutex_exit(&tcps->tcps_ixa_cleanup_lock);
if (connp->conn_sqp->sq_run == curthread) {
/* Already on squeue */
tcp_ixa_cleanup(connp, mp, NULL, NULL);
} else {
CONN_INC_REF(connp);
SQUEUE_ENTER_ONE(connp->conn_sqp, mp, tcp_ixa_cleanup,
connp, NULL, SQ_PROCESS, SQTAG_TCP_IXA_CLEANUP);
/* Wait until tcp_ixa_cleanup has run */
mutex_enter(&tcps->tcps_ixa_cleanup_lock);
while (tcps->tcps_ixa_cleanup_mp == NULL) {
cv_wait(&tcps->tcps_ixa_cleanup_cv,
&tcps->tcps_ixa_cleanup_lock);
}
mutex_exit(&tcps->tcps_ixa_cleanup_lock);
}
} else if (IPCL_IS_SCTP(connp)) {
sctp_t *sctp;
sctp_faddr_t *fp;
sctp = CONN2SCTP(connp);
RUN_SCTP(sctp);
ixa_cleanup_stale(connp->conn_ixa);
for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next)
ixa_cleanup_stale(fp->ixa);
WAKE_SCTP(sctp);
} else {
ip_xmit_attr_t *ixa;
/*
* If there is a different thread using conn_ixa then we get a
* new copy and cut the old one loose from conn_ixa. Otherwise
* we use conn_ixa and prevent any other thread from
* using/changing it. Anybody using conn_ixa (e.g., a thread in
* conn_ip_output) will do an ixa_refrele which will remove any
* references on the ire etc.
*
* Once we are done other threads can use conn_ixa since the
* refcnt will be back at one.
*
* We are called either because an ill is going away, or
* due to memory reclaim. In the former case we wait for
* memory since we must remove the refcnts on the ill.
*/
if (tryhard) {
ixa = conn_get_ixa_tryhard(connp, B_TRUE);
ASSERT(ixa != NULL);
} else {
ixa = conn_get_ixa(connp, B_TRUE);
if (ixa == NULL) {
/*
* Somebody else was using it and kmem_alloc
* failed! Next memory reclaim will try to
* clean up.
*/
DTRACE_PROBE1(conn__ixa__cleanup__bail,
conn_t *, connp);
return;
}
}
ixa_cleanup_stale(ixa);
ixa_refrele(ixa);
}
}
/*
* ixa needs to be an exclusive copy so that no one changes the cookie
* or the ixa_nce.
*/
boolean_t
ixa_check_drain_insert(conn_t *connp, ip_xmit_attr_t *ixa)
{
uintptr_t cookie = ixa->ixa_cookie;
ill_dld_direct_t *idd;
idl_tx_list_t *idl_txl;
ill_t *ill = ixa->ixa_nce->nce_ill;
boolean_t inserted = B_FALSE;
idd = &(ill)->ill_dld_capab->idc_direct;
idl_txl = &ixa->ixa_ipst->ips_idl_tx_list[IDLHASHINDEX(cookie)];
mutex_enter(&idl_txl->txl_lock);
/*
* If `cookie' is zero, ip_xmit() -> canputnext() failed -- i.e., flow
* control is asserted on an ill that does not support direct calls.
* Jump to insert.
*/
if (cookie == 0)
goto tryinsert;
ASSERT(ILL_DIRECT_CAPABLE(ill));
if (idd->idd_tx_fctl_df(idd->idd_tx_fctl_dh, cookie) == 0) {
DTRACE_PROBE1(ill__tx__not__blocked, uintptr_t, cookie);
} else if (idl_txl->txl_cookie != NULL &&
idl_txl->txl_cookie != ixa->ixa_cookie) {
DTRACE_PROBE2(ill__tx__cookie__collision, uintptr_t, cookie,
uintptr_t, idl_txl->txl_cookie);
/* TODO: bump kstat for cookie collision */
} else {
/*
* Check/set conn_blocked under conn_lock. Note that txl_lock
* will not suffice since two separate UDP threads may be
* racing to send to different destinations that are
* associated with different cookies and thus may not be
* holding the same txl_lock. Further, since a given conn_t
* can only be on a single drain list, the conn_t will be
* enqueued on whichever thread wins this race.
*/
tryinsert: mutex_enter(&connp->conn_lock);
if (connp->conn_blocked) {
DTRACE_PROBE1(ill__tx__conn__already__blocked,
conn_t *, connp);
mutex_exit(&connp->conn_lock);
} else {
connp->conn_blocked = B_TRUE;
mutex_exit(&connp->conn_lock);
idl_txl->txl_cookie = cookie;
conn_drain_insert(connp, idl_txl);
if (!IPCL_IS_NONSTR(connp))
noenable(connp->conn_wq);
inserted = B_TRUE;
}
}
mutex_exit(&idl_txl->txl_lock);
return (inserted);
}