111042SErik.Nordmark@Sun.COM /* 211042SErik.Nordmark@Sun.COM * CDDL HEADER START 311042SErik.Nordmark@Sun.COM * 411042SErik.Nordmark@Sun.COM * The contents of this file are subject to the terms of the 511042SErik.Nordmark@Sun.COM * Common Development and Distribution License (the "License"). 611042SErik.Nordmark@Sun.COM * You may not use this file except in compliance with the License. 711042SErik.Nordmark@Sun.COM * 811042SErik.Nordmark@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 911042SErik.Nordmark@Sun.COM * or http://www.opensolaris.org/os/licensing. 1011042SErik.Nordmark@Sun.COM * See the License for the specific language governing permissions 1111042SErik.Nordmark@Sun.COM * and limitations under the License. 1211042SErik.Nordmark@Sun.COM * 1311042SErik.Nordmark@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 1411042SErik.Nordmark@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1511042SErik.Nordmark@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 1611042SErik.Nordmark@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 1711042SErik.Nordmark@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 1811042SErik.Nordmark@Sun.COM * 1911042SErik.Nordmark@Sun.COM * CDDL HEADER END 2011042SErik.Nordmark@Sun.COM */ 2111042SErik.Nordmark@Sun.COM 2211042SErik.Nordmark@Sun.COM /* 23*12507SAlan.Maguire@Sun.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 2411042SErik.Nordmark@Sun.COM */ 2511042SErik.Nordmark@Sun.COM /* Copyright (c) 1990 Mentat Inc. */ 2611042SErik.Nordmark@Sun.COM 2711042SErik.Nordmark@Sun.COM #include <sys/types.h> 2811042SErik.Nordmark@Sun.COM #include <sys/stream.h> 2911042SErik.Nordmark@Sun.COM #include <sys/strsun.h> 3011042SErik.Nordmark@Sun.COM #include <sys/zone.h> 3111042SErik.Nordmark@Sun.COM #include <sys/ddi.h> 3211042SErik.Nordmark@Sun.COM #include <sys/sunddi.h> 3311042SErik.Nordmark@Sun.COM #include <sys/cmn_err.h> 3411042SErik.Nordmark@Sun.COM #include <sys/debug.h> 3511042SErik.Nordmark@Sun.COM #include <sys/atomic.h> 3611042SErik.Nordmark@Sun.COM 3711042SErik.Nordmark@Sun.COM #include <sys/systm.h> 3811042SErik.Nordmark@Sun.COM #include <sys/param.h> 3911042SErik.Nordmark@Sun.COM #include <sys/kmem.h> 4011042SErik.Nordmark@Sun.COM #include <sys/sdt.h> 4111042SErik.Nordmark@Sun.COM #include <sys/socket.h> 4211042SErik.Nordmark@Sun.COM #include <sys/mac.h> 4311042SErik.Nordmark@Sun.COM #include <net/if.h> 4411042SErik.Nordmark@Sun.COM #include <net/if_arp.h> 4511042SErik.Nordmark@Sun.COM #include <net/route.h> 4611042SErik.Nordmark@Sun.COM #include <sys/sockio.h> 4711042SErik.Nordmark@Sun.COM #include <netinet/in.h> 4811042SErik.Nordmark@Sun.COM #include <net/if_dl.h> 4911042SErik.Nordmark@Sun.COM 5011042SErik.Nordmark@Sun.COM #include <inet/common.h> 5111042SErik.Nordmark@Sun.COM #include <inet/mi.h> 5211042SErik.Nordmark@Sun.COM #include <inet/mib2.h> 5311042SErik.Nordmark@Sun.COM #include <inet/nd.h> 5411042SErik.Nordmark@Sun.COM #include <inet/arp.h> 5511042SErik.Nordmark@Sun.COM #include <inet/snmpcom.h> 5611042SErik.Nordmark@Sun.COM #include <inet/kstatcom.h> 5711042SErik.Nordmark@Sun.COM 5811042SErik.Nordmark@Sun.COM #include <netinet/igmp_var.h> 5911042SErik.Nordmark@Sun.COM #include <netinet/ip6.h> 6011042SErik.Nordmark@Sun.COM #include <netinet/icmp6.h> 6111042SErik.Nordmark@Sun.COM #include <netinet/sctp.h> 6211042SErik.Nordmark@Sun.COM 6311042SErik.Nordmark@Sun.COM #include <inet/ip.h> 6411042SErik.Nordmark@Sun.COM #include <inet/ip_impl.h> 6511042SErik.Nordmark@Sun.COM #include <inet/ip6.h> 6611042SErik.Nordmark@Sun.COM #include <inet/ip6_asp.h> 6711042SErik.Nordmark@Sun.COM #include <inet/tcp.h> 6811042SErik.Nordmark@Sun.COM #include <inet/ip_multi.h> 6911042SErik.Nordmark@Sun.COM #include <inet/ip_if.h> 7011042SErik.Nordmark@Sun.COM #include <inet/ip_ire.h> 7111042SErik.Nordmark@Sun.COM #include <inet/ip_ftable.h> 7211042SErik.Nordmark@Sun.COM #include <inet/ip_rts.h> 7311042SErik.Nordmark@Sun.COM #include <inet/optcom.h> 7411042SErik.Nordmark@Sun.COM #include <inet/ip_ndp.h> 7511042SErik.Nordmark@Sun.COM #include <inet/ip_listutils.h> 7611042SErik.Nordmark@Sun.COM #include <netinet/igmp.h> 7711042SErik.Nordmark@Sun.COM #include <netinet/ip_mroute.h> 7811042SErik.Nordmark@Sun.COM #include <inet/ipp_common.h> 7911042SErik.Nordmark@Sun.COM 8011042SErik.Nordmark@Sun.COM #include <net/pfkeyv2.h> 8111042SErik.Nordmark@Sun.COM #include <inet/sadb.h> 8211042SErik.Nordmark@Sun.COM #include <inet/ipsec_impl.h> 8311042SErik.Nordmark@Sun.COM #include <inet/ipdrop.h> 8411042SErik.Nordmark@Sun.COM #include <inet/ip_netinfo.h> 8511042SErik.Nordmark@Sun.COM #include <sys/squeue_impl.h> 8611042SErik.Nordmark@Sun.COM #include <sys/squeue.h> 8711042SErik.Nordmark@Sun.COM 8811042SErik.Nordmark@Sun.COM #include <inet/ipclassifier.h> 8911042SErik.Nordmark@Sun.COM #include <inet/sctp_ip.h> 9011042SErik.Nordmark@Sun.COM #include <inet/sctp/sctp_impl.h> 9111042SErik.Nordmark@Sun.COM #include <inet/udp_impl.h> 9211042SErik.Nordmark@Sun.COM #include <sys/sunddi.h> 9311042SErik.Nordmark@Sun.COM 9411042SErik.Nordmark@Sun.COM #include <sys/tsol/label.h> 9511042SErik.Nordmark@Sun.COM #include <sys/tsol/tnet.h> 9611042SErik.Nordmark@Sun.COM 9711042SErik.Nordmark@Sun.COM /* 9811042SErik.Nordmark@Sun.COM * Release a reference on ip_xmit_attr. 9911042SErik.Nordmark@Sun.COM * The reference is acquired by conn_get_ixa() 10011042SErik.Nordmark@Sun.COM */ 10111042SErik.Nordmark@Sun.COM #define IXA_REFRELE(ixa) \ 10211042SErik.Nordmark@Sun.COM { \ 10311042SErik.Nordmark@Sun.COM if (atomic_add_32_nv(&(ixa)->ixa_refcnt, -1) == 0) \ 10411042SErik.Nordmark@Sun.COM ixa_inactive(ixa); \ 10511042SErik.Nordmark@Sun.COM } 10611042SErik.Nordmark@Sun.COM 10711042SErik.Nordmark@Sun.COM #define IXA_REFHOLD(ixa) \ 10811042SErik.Nordmark@Sun.COM { \ 10911042SErik.Nordmark@Sun.COM ASSERT((ixa)->ixa_refcnt != 0); \ 11011042SErik.Nordmark@Sun.COM atomic_add_32(&(ixa)->ixa_refcnt, 1); \ 11111042SErik.Nordmark@Sun.COM } 11211042SErik.Nordmark@Sun.COM 11311042SErik.Nordmark@Sun.COM /* 11411042SErik.Nordmark@Sun.COM * When we need to handle a transmit side asynchronous operation, then we need 11511042SErik.Nordmark@Sun.COM * to save sufficient information so that we can call the fragment and postfrag 11611042SErik.Nordmark@Sun.COM * functions. That information is captured in an mblk containing this structure. 11711042SErik.Nordmark@Sun.COM * 11811042SErik.Nordmark@Sun.COM * Since this is currently only used for IPsec, we include information for 11911042SErik.Nordmark@Sun.COM * the kernel crypto framework. 12011042SErik.Nordmark@Sun.COM */ 12111042SErik.Nordmark@Sun.COM typedef struct ixamblk_s { 12211042SErik.Nordmark@Sun.COM boolean_t ixm_inbound; /* B_FALSE */ 12311042SErik.Nordmark@Sun.COM iaflags_t ixm_flags; /* ixa_flags */ 12411042SErik.Nordmark@Sun.COM netstackid_t ixm_stackid; /* Verify it didn't go away */ 12511042SErik.Nordmark@Sun.COM uint_t ixm_ifindex; /* Used to find the nce */ 12611042SErik.Nordmark@Sun.COM in6_addr_t ixm_nceaddr_v6; /* Used to find nce */ 12711042SErik.Nordmark@Sun.COM #define ixm_nceaddr_v4 V4_PART_OF_V6(ixm_nceaddr_v6) 12811042SErik.Nordmark@Sun.COM uint32_t ixm_fragsize; 12911042SErik.Nordmark@Sun.COM uint_t ixm_pktlen; 13011042SErik.Nordmark@Sun.COM uint16_t ixm_ip_hdr_length; /* Points to ULP header */ 13111042SErik.Nordmark@Sun.COM uint8_t ixm_protocol; /* Protocol number for ULP cksum */ 13211042SErik.Nordmark@Sun.COM pfirepostfrag_t ixm_postfragfn; 13311042SErik.Nordmark@Sun.COM 13411042SErik.Nordmark@Sun.COM zoneid_t ixm_zoneid; /* Needed for ipobs */ 13511042SErik.Nordmark@Sun.COM zoneid_t ixm_no_loop_zoneid; /* IXAF_NO_LOOP_ZONEID_SET */ 13611042SErik.Nordmark@Sun.COM 13711042SErik.Nordmark@Sun.COM uint_t ixm_scopeid; /* For IPv6 link-locals */ 13811042SErik.Nordmark@Sun.COM 13911042SErik.Nordmark@Sun.COM uint32_t ixm_ident; /* For IPv6 fragment header */ 14011042SErik.Nordmark@Sun.COM uint32_t ixm_xmit_hint; 14111042SErik.Nordmark@Sun.COM 142*12507SAlan.Maguire@Sun.COM uint64_t ixm_conn_id; /* Used by DTrace */ 14311042SErik.Nordmark@Sun.COM cred_t *ixm_cred; /* For getpeerucred - refhold if set */ 14411042SErik.Nordmark@Sun.COM pid_t ixm_cpid; /* For getpeerucred */ 14511042SErik.Nordmark@Sun.COM 14611042SErik.Nordmark@Sun.COM ts_label_t *ixm_tsl; /* Refhold if set. */ 14711042SErik.Nordmark@Sun.COM 14811042SErik.Nordmark@Sun.COM /* 14911042SErik.Nordmark@Sun.COM * When the pointers below are set they have a refhold on the struct. 15011042SErik.Nordmark@Sun.COM */ 15111042SErik.Nordmark@Sun.COM ipsec_latch_t *ixm_ipsec_latch; 15211042SErik.Nordmark@Sun.COM struct ipsa_s *ixm_ipsec_ah_sa; /* SA for AH */ 15311042SErik.Nordmark@Sun.COM struct ipsa_s *ixm_ipsec_esp_sa; /* SA for ESP */ 15411042SErik.Nordmark@Sun.COM struct ipsec_policy_s *ixm_ipsec_policy; /* why are we here? */ 15511042SErik.Nordmark@Sun.COM struct ipsec_action_s *ixm_ipsec_action; /* For reflected packets */ 15611042SErik.Nordmark@Sun.COM 15711042SErik.Nordmark@Sun.COM ipsa_ref_t ixm_ipsec_ref[2]; /* Soft reference to SA */ 15811042SErik.Nordmark@Sun.COM 15911042SErik.Nordmark@Sun.COM /* Need these while waiting for SA */ 16011042SErik.Nordmark@Sun.COM uint16_t ixm_ipsec_src_port; /* Source port number of d-gram. */ 16111042SErik.Nordmark@Sun.COM uint16_t ixm_ipsec_dst_port; /* Destination port number of d-gram. */ 16211042SErik.Nordmark@Sun.COM uint8_t ixm_ipsec_icmp_type; /* ICMP type of d-gram */ 16311042SErik.Nordmark@Sun.COM uint8_t ixm_ipsec_icmp_code; /* ICMP code of d-gram */ 16411042SErik.Nordmark@Sun.COM 16511042SErik.Nordmark@Sun.COM sa_family_t ixm_ipsec_inaf; /* Inner address family */ 16611042SErik.Nordmark@Sun.COM uint32_t ixm_ipsec_insrc[IXA_MAX_ADDRLEN]; /* Inner src address */ 16711042SErik.Nordmark@Sun.COM uint32_t ixm_ipsec_indst[IXA_MAX_ADDRLEN]; /* Inner dest address */ 16811042SErik.Nordmark@Sun.COM uint8_t ixm_ipsec_insrcpfx; /* Inner source prefix */ 16911042SErik.Nordmark@Sun.COM uint8_t ixm_ipsec_indstpfx; /* Inner destination prefix */ 17011042SErik.Nordmark@Sun.COM 17111042SErik.Nordmark@Sun.COM uint8_t ixm_ipsec_proto; /* IP protocol number for d-gram. */ 17211042SErik.Nordmark@Sun.COM } ixamblk_t; 17311042SErik.Nordmark@Sun.COM 17411042SErik.Nordmark@Sun.COM 17511042SErik.Nordmark@Sun.COM /* 17611042SErik.Nordmark@Sun.COM * When we need to handle a receive side asynchronous operation, then we need 17711042SErik.Nordmark@Sun.COM * to save sufficient information so that we can call ip_fanout. 17811042SErik.Nordmark@Sun.COM * That information is captured in an mblk containing this structure. 17911042SErik.Nordmark@Sun.COM * 18011042SErik.Nordmark@Sun.COM * Since this is currently only used for IPsec, we include information for 18111042SErik.Nordmark@Sun.COM * the kernel crypto framework. 18211042SErik.Nordmark@Sun.COM */ 18311042SErik.Nordmark@Sun.COM typedef struct iramblk_s { 18411042SErik.Nordmark@Sun.COM boolean_t irm_inbound; /* B_TRUE */ 18511042SErik.Nordmark@Sun.COM iaflags_t irm_flags; /* ira_flags */ 18611042SErik.Nordmark@Sun.COM netstackid_t irm_stackid; /* Verify it didn't go away */ 18711042SErik.Nordmark@Sun.COM uint_t irm_ifindex; /* To find ira_ill */ 18811042SErik.Nordmark@Sun.COM 18911042SErik.Nordmark@Sun.COM uint_t irm_rifindex; /* ira_rifindex */ 19011042SErik.Nordmark@Sun.COM uint_t irm_ruifindex; /* ira_ruifindex */ 19111042SErik.Nordmark@Sun.COM uint_t irm_pktlen; 19211042SErik.Nordmark@Sun.COM uint16_t irm_ip_hdr_length; /* Points to ULP header */ 19311042SErik.Nordmark@Sun.COM uint8_t irm_protocol; /* Protocol number for ULP cksum */ 19411042SErik.Nordmark@Sun.COM zoneid_t irm_zoneid; /* ALL_ZONES unless local delivery */ 19511042SErik.Nordmark@Sun.COM 19611042SErik.Nordmark@Sun.COM squeue_t *irm_sqp; 19711042SErik.Nordmark@Sun.COM ill_rx_ring_t *irm_ring; 19811042SErik.Nordmark@Sun.COM 19911042SErik.Nordmark@Sun.COM ipaddr_t irm_mroute_tunnel; /* IRAF_MROUTE_TUNNEL_SET */ 20011042SErik.Nordmark@Sun.COM zoneid_t irm_no_loop_zoneid; /* IRAF_NO_LOOP_ZONEID_SET */ 20111042SErik.Nordmark@Sun.COM uint32_t irm_esp_udp_ports; /* IRAF_ESP_UDP_PORTS */ 20211042SErik.Nordmark@Sun.COM 20311042SErik.Nordmark@Sun.COM char irm_l2src[IRA_L2SRC_SIZE]; /* If IRAF_L2SRC_SET */ 20411042SErik.Nordmark@Sun.COM 20511042SErik.Nordmark@Sun.COM cred_t *irm_cred; /* For getpeerucred - refhold if set */ 20611042SErik.Nordmark@Sun.COM pid_t irm_cpid; /* For getpeerucred */ 20711042SErik.Nordmark@Sun.COM 20811042SErik.Nordmark@Sun.COM ts_label_t *irm_tsl; /* Refhold if set. */ 20911042SErik.Nordmark@Sun.COM 21011042SErik.Nordmark@Sun.COM /* 21111042SErik.Nordmark@Sun.COM * When set these correspond to a refhold on the object. 21211042SErik.Nordmark@Sun.COM */ 21311042SErik.Nordmark@Sun.COM struct ipsa_s *irm_ipsec_ah_sa; /* SA for AH */ 21411042SErik.Nordmark@Sun.COM struct ipsa_s *irm_ipsec_esp_sa; /* SA for ESP */ 21511042SErik.Nordmark@Sun.COM struct ipsec_action_s *irm_ipsec_action; /* For reflected packets */ 21611042SErik.Nordmark@Sun.COM } iramblk_t; 21711042SErik.Nordmark@Sun.COM 21811042SErik.Nordmark@Sun.COM 21911042SErik.Nordmark@Sun.COM /* 22011042SErik.Nordmark@Sun.COM * Take the information in ip_xmit_attr_t and stick it in an mblk 22111042SErik.Nordmark@Sun.COM * that can later be passed to ip_xmit_attr_from_mblk to recreate the 22211042SErik.Nordmark@Sun.COM * ip_xmit_attr_t. 22311042SErik.Nordmark@Sun.COM * 22411042SErik.Nordmark@Sun.COM * Returns NULL on memory allocation failure. 22511042SErik.Nordmark@Sun.COM */ 22611042SErik.Nordmark@Sun.COM mblk_t * 22711042SErik.Nordmark@Sun.COM ip_xmit_attr_to_mblk(ip_xmit_attr_t *ixa) 22811042SErik.Nordmark@Sun.COM { 22911042SErik.Nordmark@Sun.COM mblk_t *ixamp; 23011042SErik.Nordmark@Sun.COM ixamblk_t *ixm; 23111042SErik.Nordmark@Sun.COM nce_t *nce = ixa->ixa_nce; 23211042SErik.Nordmark@Sun.COM 23311042SErik.Nordmark@Sun.COM ASSERT(nce != NULL); 23411042SErik.Nordmark@Sun.COM ixamp = allocb(sizeof (*ixm), BPRI_MED); 23511042SErik.Nordmark@Sun.COM if (ixamp == NULL) 23611042SErik.Nordmark@Sun.COM return (NULL); 23711042SErik.Nordmark@Sun.COM 23811042SErik.Nordmark@Sun.COM ixamp->b_datap->db_type = M_BREAK; 23911042SErik.Nordmark@Sun.COM ixamp->b_wptr += sizeof (*ixm); 24011042SErik.Nordmark@Sun.COM ixm = (ixamblk_t *)ixamp->b_rptr; 24111042SErik.Nordmark@Sun.COM 24211042SErik.Nordmark@Sun.COM bzero(ixm, sizeof (*ixm)); 24311042SErik.Nordmark@Sun.COM ixm->ixm_inbound = B_FALSE; 24411042SErik.Nordmark@Sun.COM ixm->ixm_flags = ixa->ixa_flags; 24511042SErik.Nordmark@Sun.COM ixm->ixm_stackid = ixa->ixa_ipst->ips_netstack->netstack_stackid; 24611042SErik.Nordmark@Sun.COM ixm->ixm_ifindex = nce->nce_ill->ill_phyint->phyint_ifindex; 24711042SErik.Nordmark@Sun.COM ixm->ixm_nceaddr_v6 = nce->nce_addr; 24811042SErik.Nordmark@Sun.COM ixm->ixm_fragsize = ixa->ixa_fragsize; 24911042SErik.Nordmark@Sun.COM ixm->ixm_pktlen = ixa->ixa_pktlen; 25011042SErik.Nordmark@Sun.COM ixm->ixm_ip_hdr_length = ixa->ixa_ip_hdr_length; 25111042SErik.Nordmark@Sun.COM ixm->ixm_protocol = ixa->ixa_protocol; 25211042SErik.Nordmark@Sun.COM ixm->ixm_postfragfn = ixa->ixa_postfragfn; 25311042SErik.Nordmark@Sun.COM ixm->ixm_zoneid = ixa->ixa_zoneid; 25411042SErik.Nordmark@Sun.COM ixm->ixm_no_loop_zoneid = ixa->ixa_no_loop_zoneid; 25511042SErik.Nordmark@Sun.COM ixm->ixm_scopeid = ixa->ixa_scopeid; 25611042SErik.Nordmark@Sun.COM ixm->ixm_ident = ixa->ixa_ident; 25711042SErik.Nordmark@Sun.COM ixm->ixm_xmit_hint = ixa->ixa_xmit_hint; 25811042SErik.Nordmark@Sun.COM 25911042SErik.Nordmark@Sun.COM if (ixa->ixa_tsl != NULL) { 26011042SErik.Nordmark@Sun.COM ixm->ixm_tsl = ixa->ixa_tsl; 26111042SErik.Nordmark@Sun.COM label_hold(ixm->ixm_tsl); 26211042SErik.Nordmark@Sun.COM } 26311042SErik.Nordmark@Sun.COM if (ixa->ixa_cred != NULL) { 26411042SErik.Nordmark@Sun.COM ixm->ixm_cred = ixa->ixa_cred; 26511042SErik.Nordmark@Sun.COM crhold(ixa->ixa_cred); 26611042SErik.Nordmark@Sun.COM } 26711042SErik.Nordmark@Sun.COM ixm->ixm_cpid = ixa->ixa_cpid; 268*12507SAlan.Maguire@Sun.COM ixm->ixm_conn_id = ixa->ixa_conn_id; 26911042SErik.Nordmark@Sun.COM 27011042SErik.Nordmark@Sun.COM if (ixa->ixa_flags & IXAF_IPSEC_SECURE) { 27111042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_ah_sa != NULL) { 27211042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_ah_sa = ixa->ixa_ipsec_ah_sa; 27311042SErik.Nordmark@Sun.COM IPSA_REFHOLD(ixa->ixa_ipsec_ah_sa); 27411042SErik.Nordmark@Sun.COM } 27511042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_esp_sa != NULL) { 27611042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_esp_sa = ixa->ixa_ipsec_esp_sa; 27711042SErik.Nordmark@Sun.COM IPSA_REFHOLD(ixa->ixa_ipsec_esp_sa); 27811042SErik.Nordmark@Sun.COM } 27911042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_policy != NULL) { 28011042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_policy = ixa->ixa_ipsec_policy; 28111042SErik.Nordmark@Sun.COM IPPOL_REFHOLD(ixa->ixa_ipsec_policy); 28211042SErik.Nordmark@Sun.COM } 28311042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_action != NULL) { 28411042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_action = ixa->ixa_ipsec_action; 28511042SErik.Nordmark@Sun.COM IPACT_REFHOLD(ixa->ixa_ipsec_action); 28611042SErik.Nordmark@Sun.COM } 28711042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_latch != NULL) { 28811042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_latch = ixa->ixa_ipsec_latch; 28911042SErik.Nordmark@Sun.COM IPLATCH_REFHOLD(ixa->ixa_ipsec_latch); 29011042SErik.Nordmark@Sun.COM } 29111042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_ref[0] = ixa->ixa_ipsec_ref[0]; 29211042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_ref[1] = ixa->ixa_ipsec_ref[1]; 29311042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_src_port = ixa->ixa_ipsec_src_port; 29411042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_dst_port = ixa->ixa_ipsec_dst_port; 29511042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_icmp_type = ixa->ixa_ipsec_icmp_type; 29611042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_icmp_code = ixa->ixa_ipsec_icmp_code; 29711042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_inaf = ixa->ixa_ipsec_inaf; 29811042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_insrc[0] = ixa->ixa_ipsec_insrc[0]; 29911042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_insrc[1] = ixa->ixa_ipsec_insrc[1]; 30011042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_insrc[2] = ixa->ixa_ipsec_insrc[2]; 30111042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_insrc[3] = ixa->ixa_ipsec_insrc[3]; 30211042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_indst[0] = ixa->ixa_ipsec_indst[0]; 30311042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_indst[1] = ixa->ixa_ipsec_indst[1]; 30411042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_indst[2] = ixa->ixa_ipsec_indst[2]; 30511042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_indst[3] = ixa->ixa_ipsec_indst[3]; 30611042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_insrcpfx = ixa->ixa_ipsec_insrcpfx; 30711042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_indstpfx = ixa->ixa_ipsec_indstpfx; 30811042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_proto = ixa->ixa_ipsec_proto; 30911042SErik.Nordmark@Sun.COM } 31011042SErik.Nordmark@Sun.COM return (ixamp); 31111042SErik.Nordmark@Sun.COM } 31211042SErik.Nordmark@Sun.COM 31311042SErik.Nordmark@Sun.COM /* 31411042SErik.Nordmark@Sun.COM * Extract the ip_xmit_attr_t from the mblk, checking that the 31511042SErik.Nordmark@Sun.COM * ip_stack_t, ill_t, and nce_t still exist. Returns B_FALSE if that is 31611042SErik.Nordmark@Sun.COM * not the case. 31711042SErik.Nordmark@Sun.COM * 31811042SErik.Nordmark@Sun.COM * Otherwise ixa is updated. 31911042SErik.Nordmark@Sun.COM * Caller needs to release references on the ixa by calling ixa_refrele() 32011042SErik.Nordmark@Sun.COM * which will imediately call ixa_inactive to release the references. 32111042SErik.Nordmark@Sun.COM */ 32211042SErik.Nordmark@Sun.COM boolean_t 32311042SErik.Nordmark@Sun.COM ip_xmit_attr_from_mblk(mblk_t *ixamp, ip_xmit_attr_t *ixa) 32411042SErik.Nordmark@Sun.COM { 32511042SErik.Nordmark@Sun.COM ixamblk_t *ixm; 32611042SErik.Nordmark@Sun.COM netstack_t *ns; 32711042SErik.Nordmark@Sun.COM ip_stack_t *ipst; 32811042SErik.Nordmark@Sun.COM ill_t *ill; 32911042SErik.Nordmark@Sun.COM nce_t *nce; 33011042SErik.Nordmark@Sun.COM 33111042SErik.Nordmark@Sun.COM /* We assume the caller hasn't initialized ixa */ 33211042SErik.Nordmark@Sun.COM bzero(ixa, sizeof (*ixa)); 33311042SErik.Nordmark@Sun.COM 33411042SErik.Nordmark@Sun.COM ASSERT(DB_TYPE(ixamp) == M_BREAK); 33511042SErik.Nordmark@Sun.COM ASSERT(ixamp->b_cont == NULL); 33611042SErik.Nordmark@Sun.COM 33711042SErik.Nordmark@Sun.COM ixm = (ixamblk_t *)ixamp->b_rptr; 33811042SErik.Nordmark@Sun.COM ASSERT(!ixm->ixm_inbound); 33911042SErik.Nordmark@Sun.COM 34011042SErik.Nordmark@Sun.COM /* Verify the netstack is still around */ 34111042SErik.Nordmark@Sun.COM ns = netstack_find_by_stackid(ixm->ixm_stackid); 34211042SErik.Nordmark@Sun.COM if (ns == NULL) { 34311042SErik.Nordmark@Sun.COM /* Disappeared on us */ 34411042SErik.Nordmark@Sun.COM (void) ip_xmit_attr_free_mblk(ixamp); 34511042SErik.Nordmark@Sun.COM return (B_FALSE); 34611042SErik.Nordmark@Sun.COM } 34711042SErik.Nordmark@Sun.COM ipst = ns->netstack_ip; 34811042SErik.Nordmark@Sun.COM 34911042SErik.Nordmark@Sun.COM /* Verify the ill is still around */ 35011042SErik.Nordmark@Sun.COM ill = ill_lookup_on_ifindex(ixm->ixm_ifindex, 35111042SErik.Nordmark@Sun.COM !(ixm->ixm_flags & IXAF_IS_IPV4), ipst); 35211042SErik.Nordmark@Sun.COM 35311042SErik.Nordmark@Sun.COM /* We have the ill, hence the netstack can't go away */ 35411042SErik.Nordmark@Sun.COM netstack_rele(ns); 35511042SErik.Nordmark@Sun.COM if (ill == NULL) { 35611042SErik.Nordmark@Sun.COM /* Disappeared on us */ 35711042SErik.Nordmark@Sun.COM (void) ip_xmit_attr_free_mblk(ixamp); 35811042SErik.Nordmark@Sun.COM return (B_FALSE); 35911042SErik.Nordmark@Sun.COM } 36011042SErik.Nordmark@Sun.COM /* 36111042SErik.Nordmark@Sun.COM * Find the nce. We don't load-spread (only lookup nce's on the ill) 36211042SErik.Nordmark@Sun.COM * because we want to find the same nce as the one we had when 36311042SErik.Nordmark@Sun.COM * ip_xmit_attr_to_mblk was called. 36411042SErik.Nordmark@Sun.COM */ 36511042SErik.Nordmark@Sun.COM if (ixm->ixm_flags & IXAF_IS_IPV4) { 36611042SErik.Nordmark@Sun.COM nce = nce_lookup_v4(ill, &ixm->ixm_nceaddr_v4); 36711042SErik.Nordmark@Sun.COM } else { 36811042SErik.Nordmark@Sun.COM nce = nce_lookup_v6(ill, &ixm->ixm_nceaddr_v6); 36911042SErik.Nordmark@Sun.COM } 37011042SErik.Nordmark@Sun.COM 37111042SErik.Nordmark@Sun.COM /* We have the nce, hence the ill can't go away */ 37211042SErik.Nordmark@Sun.COM ill_refrele(ill); 37311042SErik.Nordmark@Sun.COM if (nce == NULL) { 37411042SErik.Nordmark@Sun.COM /* 37511042SErik.Nordmark@Sun.COM * Since this is unusual and we don't know what type of 37611042SErik.Nordmark@Sun.COM * nce it was, we drop the packet. 37711042SErik.Nordmark@Sun.COM */ 37811042SErik.Nordmark@Sun.COM (void) ip_xmit_attr_free_mblk(ixamp); 37911042SErik.Nordmark@Sun.COM return (B_FALSE); 38011042SErik.Nordmark@Sun.COM } 38111042SErik.Nordmark@Sun.COM 38211042SErik.Nordmark@Sun.COM ixa->ixa_flags = ixm->ixm_flags; 38311042SErik.Nordmark@Sun.COM ixa->ixa_refcnt = 1; 38411042SErik.Nordmark@Sun.COM ixa->ixa_ipst = ipst; 38511042SErik.Nordmark@Sun.COM ixa->ixa_fragsize = ixm->ixm_fragsize; 38611042SErik.Nordmark@Sun.COM ixa->ixa_pktlen = ixm->ixm_pktlen; 38711042SErik.Nordmark@Sun.COM ixa->ixa_ip_hdr_length = ixm->ixm_ip_hdr_length; 38811042SErik.Nordmark@Sun.COM ixa->ixa_protocol = ixm->ixm_protocol; 38911042SErik.Nordmark@Sun.COM ixa->ixa_nce = nce; 39011042SErik.Nordmark@Sun.COM ixa->ixa_postfragfn = ixm->ixm_postfragfn; 39111042SErik.Nordmark@Sun.COM ixa->ixa_zoneid = ixm->ixm_zoneid; 39211042SErik.Nordmark@Sun.COM ixa->ixa_no_loop_zoneid = ixm->ixm_no_loop_zoneid; 39311042SErik.Nordmark@Sun.COM ixa->ixa_scopeid = ixm->ixm_scopeid; 39411042SErik.Nordmark@Sun.COM ixa->ixa_ident = ixm->ixm_ident; 39511042SErik.Nordmark@Sun.COM ixa->ixa_xmit_hint = ixm->ixm_xmit_hint; 39611042SErik.Nordmark@Sun.COM 39711042SErik.Nordmark@Sun.COM if (ixm->ixm_tsl != NULL) { 39811042SErik.Nordmark@Sun.COM ixa->ixa_tsl = ixm->ixm_tsl; 39911042SErik.Nordmark@Sun.COM ixa->ixa_free_flags |= IXA_FREE_TSL; 40011849SErik.Nordmark@Sun.COM ixm->ixm_tsl = NULL; 40111042SErik.Nordmark@Sun.COM } 40211042SErik.Nordmark@Sun.COM if (ixm->ixm_cred != NULL) { 40311042SErik.Nordmark@Sun.COM ixa->ixa_cred = ixm->ixm_cred; 40411042SErik.Nordmark@Sun.COM ixa->ixa_free_flags |= IXA_FREE_CRED; 40511849SErik.Nordmark@Sun.COM ixm->ixm_cred = NULL; 40611042SErik.Nordmark@Sun.COM } 40711042SErik.Nordmark@Sun.COM ixa->ixa_cpid = ixm->ixm_cpid; 408*12507SAlan.Maguire@Sun.COM ixa->ixa_conn_id = ixm->ixm_conn_id; 40911042SErik.Nordmark@Sun.COM 41011042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_ah_sa = ixm->ixm_ipsec_ah_sa; 41111042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_esp_sa = ixm->ixm_ipsec_esp_sa; 41211042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_policy = ixm->ixm_ipsec_policy; 41311042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_action = ixm->ixm_ipsec_action; 41411042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_latch = ixm->ixm_ipsec_latch; 41511042SErik.Nordmark@Sun.COM 41611042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_ref[0] = ixm->ixm_ipsec_ref[0]; 41711042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_ref[1] = ixm->ixm_ipsec_ref[1]; 41811042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_src_port = ixm->ixm_ipsec_src_port; 41911042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_dst_port = ixm->ixm_ipsec_dst_port; 42011042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_icmp_type = ixm->ixm_ipsec_icmp_type; 42111042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_icmp_code = ixm->ixm_ipsec_icmp_code; 42211042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_inaf = ixm->ixm_ipsec_inaf; 42311042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_insrc[0] = ixm->ixm_ipsec_insrc[0]; 42411042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_insrc[1] = ixm->ixm_ipsec_insrc[1]; 42511042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_insrc[2] = ixm->ixm_ipsec_insrc[2]; 42611042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_insrc[3] = ixm->ixm_ipsec_insrc[3]; 42711042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_indst[0] = ixm->ixm_ipsec_indst[0]; 42811042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_indst[1] = ixm->ixm_ipsec_indst[1]; 42911042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_indst[2] = ixm->ixm_ipsec_indst[2]; 43011042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_indst[3] = ixm->ixm_ipsec_indst[3]; 43111042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_insrcpfx = ixm->ixm_ipsec_insrcpfx; 43211042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_indstpfx = ixm->ixm_ipsec_indstpfx; 43311042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_proto = ixm->ixm_ipsec_proto; 43411042SErik.Nordmark@Sun.COM 43511042SErik.Nordmark@Sun.COM freeb(ixamp); 43611042SErik.Nordmark@Sun.COM return (B_TRUE); 43711042SErik.Nordmark@Sun.COM } 43811042SErik.Nordmark@Sun.COM 43911042SErik.Nordmark@Sun.COM /* 44011042SErik.Nordmark@Sun.COM * Free the ixm mblk and any references it holds 44111042SErik.Nordmark@Sun.COM * Returns b_cont. 44211042SErik.Nordmark@Sun.COM */ 44311042SErik.Nordmark@Sun.COM mblk_t * 44411042SErik.Nordmark@Sun.COM ip_xmit_attr_free_mblk(mblk_t *ixamp) 44511042SErik.Nordmark@Sun.COM { 44611042SErik.Nordmark@Sun.COM ixamblk_t *ixm; 44711042SErik.Nordmark@Sun.COM mblk_t *mp; 44811042SErik.Nordmark@Sun.COM 44911042SErik.Nordmark@Sun.COM /* Consume mp */ 45011042SErik.Nordmark@Sun.COM ASSERT(DB_TYPE(ixamp) == M_BREAK); 45111042SErik.Nordmark@Sun.COM mp = ixamp->b_cont; 45211042SErik.Nordmark@Sun.COM 45311042SErik.Nordmark@Sun.COM ixm = (ixamblk_t *)ixamp->b_rptr; 45411042SErik.Nordmark@Sun.COM ASSERT(!ixm->ixm_inbound); 45511042SErik.Nordmark@Sun.COM 45611042SErik.Nordmark@Sun.COM if (ixm->ixm_ipsec_ah_sa != NULL) { 45711042SErik.Nordmark@Sun.COM IPSA_REFRELE(ixm->ixm_ipsec_ah_sa); 45811042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_ah_sa = NULL; 45911042SErik.Nordmark@Sun.COM } 46011042SErik.Nordmark@Sun.COM if (ixm->ixm_ipsec_esp_sa != NULL) { 46111042SErik.Nordmark@Sun.COM IPSA_REFRELE(ixm->ixm_ipsec_esp_sa); 46211042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_esp_sa = NULL; 46311042SErik.Nordmark@Sun.COM } 46411042SErik.Nordmark@Sun.COM if (ixm->ixm_ipsec_policy != NULL) { 46511042SErik.Nordmark@Sun.COM IPPOL_REFRELE(ixm->ixm_ipsec_policy); 46611042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_policy = NULL; 46711042SErik.Nordmark@Sun.COM } 46811042SErik.Nordmark@Sun.COM if (ixm->ixm_ipsec_action != NULL) { 46911042SErik.Nordmark@Sun.COM IPACT_REFRELE(ixm->ixm_ipsec_action); 47011042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_action = NULL; 47111042SErik.Nordmark@Sun.COM } 47211042SErik.Nordmark@Sun.COM if (ixm->ixm_ipsec_latch) { 47311042SErik.Nordmark@Sun.COM IPLATCH_REFRELE(ixm->ixm_ipsec_latch); 47411042SErik.Nordmark@Sun.COM ixm->ixm_ipsec_latch = NULL; 47511042SErik.Nordmark@Sun.COM } 47611042SErik.Nordmark@Sun.COM 47711042SErik.Nordmark@Sun.COM if (ixm->ixm_tsl != NULL) { 47811042SErik.Nordmark@Sun.COM label_rele(ixm->ixm_tsl); 47911042SErik.Nordmark@Sun.COM ixm->ixm_tsl = NULL; 48011042SErik.Nordmark@Sun.COM } 48111042SErik.Nordmark@Sun.COM if (ixm->ixm_cred != NULL) { 48211042SErik.Nordmark@Sun.COM crfree(ixm->ixm_cred); 48311042SErik.Nordmark@Sun.COM ixm->ixm_cred = NULL; 48411042SErik.Nordmark@Sun.COM } 48511042SErik.Nordmark@Sun.COM freeb(ixamp); 48611042SErik.Nordmark@Sun.COM return (mp); 48711042SErik.Nordmark@Sun.COM } 48811042SErik.Nordmark@Sun.COM 48911042SErik.Nordmark@Sun.COM /* 49011042SErik.Nordmark@Sun.COM * Take the information in ip_recv_attr_t and stick it in an mblk 49111042SErik.Nordmark@Sun.COM * that can later be passed to ip_recv_attr_from_mblk to recreate the 49211042SErik.Nordmark@Sun.COM * ip_recv_attr_t. 49311042SErik.Nordmark@Sun.COM * 49411042SErik.Nordmark@Sun.COM * Returns NULL on memory allocation failure. 49511042SErik.Nordmark@Sun.COM */ 49611042SErik.Nordmark@Sun.COM mblk_t * 49711042SErik.Nordmark@Sun.COM ip_recv_attr_to_mblk(ip_recv_attr_t *ira) 49811042SErik.Nordmark@Sun.COM { 49911042SErik.Nordmark@Sun.COM mblk_t *iramp; 50011042SErik.Nordmark@Sun.COM iramblk_t *irm; 50111042SErik.Nordmark@Sun.COM ill_t *ill = ira->ira_ill; 50211042SErik.Nordmark@Sun.COM 50311042SErik.Nordmark@Sun.COM ASSERT(ira->ira_ill != NULL || ira->ira_ruifindex != 0); 50411042SErik.Nordmark@Sun.COM 50511042SErik.Nordmark@Sun.COM iramp = allocb(sizeof (*irm), BPRI_MED); 50611042SErik.Nordmark@Sun.COM if (iramp == NULL) 50711042SErik.Nordmark@Sun.COM return (NULL); 50811042SErik.Nordmark@Sun.COM 50911042SErik.Nordmark@Sun.COM iramp->b_datap->db_type = M_BREAK; 51011042SErik.Nordmark@Sun.COM iramp->b_wptr += sizeof (*irm); 51111042SErik.Nordmark@Sun.COM irm = (iramblk_t *)iramp->b_rptr; 51211042SErik.Nordmark@Sun.COM 51311042SErik.Nordmark@Sun.COM bzero(irm, sizeof (*irm)); 51411042SErik.Nordmark@Sun.COM irm->irm_inbound = B_TRUE; 51511042SErik.Nordmark@Sun.COM irm->irm_flags = ira->ira_flags; 51611042SErik.Nordmark@Sun.COM if (ill != NULL) { 51711042SErik.Nordmark@Sun.COM /* Internal to IP - preserve ip_stack_t, ill and rill */ 51811042SErik.Nordmark@Sun.COM irm->irm_stackid = 51911042SErik.Nordmark@Sun.COM ill->ill_ipst->ips_netstack->netstack_stackid; 52011042SErik.Nordmark@Sun.COM irm->irm_ifindex = ira->ira_ill->ill_phyint->phyint_ifindex; 52111042SErik.Nordmark@Sun.COM ASSERT(ira->ira_rill->ill_phyint->phyint_ifindex == 52211042SErik.Nordmark@Sun.COM ira->ira_rifindex); 52311042SErik.Nordmark@Sun.COM } else { 52411042SErik.Nordmark@Sun.COM /* Let ip_recv_attr_from_stackid know there isn't one */ 52511042SErik.Nordmark@Sun.COM irm->irm_stackid = -1; 52611042SErik.Nordmark@Sun.COM } 52711042SErik.Nordmark@Sun.COM irm->irm_rifindex = ira->ira_rifindex; 52811042SErik.Nordmark@Sun.COM irm->irm_ruifindex = ira->ira_ruifindex; 52911042SErik.Nordmark@Sun.COM irm->irm_pktlen = ira->ira_pktlen; 53011042SErik.Nordmark@Sun.COM irm->irm_ip_hdr_length = ira->ira_ip_hdr_length; 53111042SErik.Nordmark@Sun.COM irm->irm_protocol = ira->ira_protocol; 53211042SErik.Nordmark@Sun.COM 53311042SErik.Nordmark@Sun.COM irm->irm_sqp = ira->ira_sqp; 53411042SErik.Nordmark@Sun.COM irm->irm_ring = ira->ira_ring; 53511042SErik.Nordmark@Sun.COM 53611042SErik.Nordmark@Sun.COM irm->irm_zoneid = ira->ira_zoneid; 53711042SErik.Nordmark@Sun.COM irm->irm_mroute_tunnel = ira->ira_mroute_tunnel; 53811042SErik.Nordmark@Sun.COM irm->irm_no_loop_zoneid = ira->ira_no_loop_zoneid; 53911042SErik.Nordmark@Sun.COM irm->irm_esp_udp_ports = ira->ira_esp_udp_ports; 54011042SErik.Nordmark@Sun.COM 54111042SErik.Nordmark@Sun.COM if (ira->ira_tsl != NULL) { 54211042SErik.Nordmark@Sun.COM irm->irm_tsl = ira->ira_tsl; 54311042SErik.Nordmark@Sun.COM label_hold(irm->irm_tsl); 54411042SErik.Nordmark@Sun.COM } 54511042SErik.Nordmark@Sun.COM if (ira->ira_cred != NULL) { 54611042SErik.Nordmark@Sun.COM irm->irm_cred = ira->ira_cred; 54711042SErik.Nordmark@Sun.COM crhold(ira->ira_cred); 54811042SErik.Nordmark@Sun.COM } 54911042SErik.Nordmark@Sun.COM irm->irm_cpid = ira->ira_cpid; 55011042SErik.Nordmark@Sun.COM 55111042SErik.Nordmark@Sun.COM if (ira->ira_flags & IRAF_L2SRC_SET) 55211042SErik.Nordmark@Sun.COM bcopy(ira->ira_l2src, irm->irm_l2src, IRA_L2SRC_SIZE); 55311042SErik.Nordmark@Sun.COM 55411042SErik.Nordmark@Sun.COM if (ira->ira_flags & IRAF_IPSEC_SECURE) { 55511042SErik.Nordmark@Sun.COM if (ira->ira_ipsec_ah_sa != NULL) { 55611042SErik.Nordmark@Sun.COM irm->irm_ipsec_ah_sa = ira->ira_ipsec_ah_sa; 55711042SErik.Nordmark@Sun.COM IPSA_REFHOLD(ira->ira_ipsec_ah_sa); 55811042SErik.Nordmark@Sun.COM } 55911042SErik.Nordmark@Sun.COM if (ira->ira_ipsec_esp_sa != NULL) { 56011042SErik.Nordmark@Sun.COM irm->irm_ipsec_esp_sa = ira->ira_ipsec_esp_sa; 56111042SErik.Nordmark@Sun.COM IPSA_REFHOLD(ira->ira_ipsec_esp_sa); 56211042SErik.Nordmark@Sun.COM } 56311042SErik.Nordmark@Sun.COM if (ira->ira_ipsec_action != NULL) { 56411042SErik.Nordmark@Sun.COM irm->irm_ipsec_action = ira->ira_ipsec_action; 56511042SErik.Nordmark@Sun.COM IPACT_REFHOLD(ira->ira_ipsec_action); 56611042SErik.Nordmark@Sun.COM } 56711042SErik.Nordmark@Sun.COM } 56811042SErik.Nordmark@Sun.COM return (iramp); 56911042SErik.Nordmark@Sun.COM } 57011042SErik.Nordmark@Sun.COM 57111042SErik.Nordmark@Sun.COM /* 57211042SErik.Nordmark@Sun.COM * Extract the ip_recv_attr_t from the mblk. If we are used inside IP 57311042SErik.Nordmark@Sun.COM * then irm_stackid is not -1, in which case we check that the 57411042SErik.Nordmark@Sun.COM * ip_stack_t and ill_t still exist. Returns B_FALSE if that is 57511042SErik.Nordmark@Sun.COM * not the case. 57611042SErik.Nordmark@Sun.COM * If irm_stackid is zero then we are used by an ULP (e.g., squeue_enter) 57711042SErik.Nordmark@Sun.COM * and we just proceed with ira_ill and ira_rill as NULL. 57811042SErik.Nordmark@Sun.COM * 57911042SErik.Nordmark@Sun.COM * The caller needs to release any references on the pointers inside the ire 58011042SErik.Nordmark@Sun.COM * by calling ira_cleanup. 58111042SErik.Nordmark@Sun.COM */ 58211042SErik.Nordmark@Sun.COM boolean_t 58311042SErik.Nordmark@Sun.COM ip_recv_attr_from_mblk(mblk_t *iramp, ip_recv_attr_t *ira) 58411042SErik.Nordmark@Sun.COM { 58511042SErik.Nordmark@Sun.COM iramblk_t *irm; 58611042SErik.Nordmark@Sun.COM netstack_t *ns; 58711042SErik.Nordmark@Sun.COM ip_stack_t *ipst = NULL; 58811042SErik.Nordmark@Sun.COM ill_t *ill = NULL, *rill = NULL; 58911042SErik.Nordmark@Sun.COM 59011042SErik.Nordmark@Sun.COM /* We assume the caller hasn't initialized ira */ 59111042SErik.Nordmark@Sun.COM bzero(ira, sizeof (*ira)); 59211042SErik.Nordmark@Sun.COM 59311042SErik.Nordmark@Sun.COM ASSERT(DB_TYPE(iramp) == M_BREAK); 59411042SErik.Nordmark@Sun.COM ASSERT(iramp->b_cont == NULL); 59511042SErik.Nordmark@Sun.COM 59611042SErik.Nordmark@Sun.COM irm = (iramblk_t *)iramp->b_rptr; 59711042SErik.Nordmark@Sun.COM ASSERT(irm->irm_inbound); 59811042SErik.Nordmark@Sun.COM 59911042SErik.Nordmark@Sun.COM if (irm->irm_stackid != -1) { 60011042SErik.Nordmark@Sun.COM /* Verify the netstack is still around */ 60111042SErik.Nordmark@Sun.COM ns = netstack_find_by_stackid(irm->irm_stackid); 60211042SErik.Nordmark@Sun.COM if (ns == NULL) { 60311042SErik.Nordmark@Sun.COM /* Disappeared on us */ 60411042SErik.Nordmark@Sun.COM (void) ip_recv_attr_free_mblk(iramp); 60511042SErik.Nordmark@Sun.COM return (B_FALSE); 60611042SErik.Nordmark@Sun.COM } 60711042SErik.Nordmark@Sun.COM ipst = ns->netstack_ip; 60811042SErik.Nordmark@Sun.COM 60911042SErik.Nordmark@Sun.COM /* Verify the ill is still around */ 61011042SErik.Nordmark@Sun.COM ill = ill_lookup_on_ifindex(irm->irm_ifindex, 61111042SErik.Nordmark@Sun.COM !(irm->irm_flags & IRAF_IS_IPV4), ipst); 61211042SErik.Nordmark@Sun.COM 61311042SErik.Nordmark@Sun.COM if (irm->irm_ifindex == irm->irm_rifindex) { 61411042SErik.Nordmark@Sun.COM rill = ill; 61511042SErik.Nordmark@Sun.COM } else { 61611042SErik.Nordmark@Sun.COM rill = ill_lookup_on_ifindex(irm->irm_rifindex, 61711042SErik.Nordmark@Sun.COM !(irm->irm_flags & IRAF_IS_IPV4), ipst); 61811042SErik.Nordmark@Sun.COM } 61911042SErik.Nordmark@Sun.COM 62011042SErik.Nordmark@Sun.COM /* We have the ill, hence the netstack can't go away */ 62111042SErik.Nordmark@Sun.COM netstack_rele(ns); 62211042SErik.Nordmark@Sun.COM if (ill == NULL || rill == NULL) { 62311042SErik.Nordmark@Sun.COM /* Disappeared on us */ 62411042SErik.Nordmark@Sun.COM if (ill != NULL) 62511042SErik.Nordmark@Sun.COM ill_refrele(ill); 62611042SErik.Nordmark@Sun.COM if (rill != NULL && rill != ill) 62711042SErik.Nordmark@Sun.COM ill_refrele(rill); 62811042SErik.Nordmark@Sun.COM (void) ip_recv_attr_free_mblk(iramp); 62911042SErik.Nordmark@Sun.COM return (B_FALSE); 63011042SErik.Nordmark@Sun.COM } 63111042SErik.Nordmark@Sun.COM } 63211042SErik.Nordmark@Sun.COM 63311042SErik.Nordmark@Sun.COM ira->ira_flags = irm->irm_flags; 63411042SErik.Nordmark@Sun.COM /* Caller must ill_refele(ira_ill) by using ira_cleanup() */ 63511042SErik.Nordmark@Sun.COM ira->ira_ill = ill; 63611042SErik.Nordmark@Sun.COM ira->ira_rill = rill; 63711042SErik.Nordmark@Sun.COM 63811042SErik.Nordmark@Sun.COM ira->ira_rifindex = irm->irm_rifindex; 63911042SErik.Nordmark@Sun.COM ira->ira_ruifindex = irm->irm_ruifindex; 64011042SErik.Nordmark@Sun.COM ira->ira_pktlen = irm->irm_pktlen; 64111042SErik.Nordmark@Sun.COM ira->ira_ip_hdr_length = irm->irm_ip_hdr_length; 64211042SErik.Nordmark@Sun.COM ira->ira_protocol = irm->irm_protocol; 64311042SErik.Nordmark@Sun.COM 64411042SErik.Nordmark@Sun.COM ira->ira_sqp = irm->irm_sqp; 64511042SErik.Nordmark@Sun.COM /* The rest of IP assumes that the rings never go away. */ 64611042SErik.Nordmark@Sun.COM ira->ira_ring = irm->irm_ring; 64711042SErik.Nordmark@Sun.COM 64811042SErik.Nordmark@Sun.COM ira->ira_zoneid = irm->irm_zoneid; 64911042SErik.Nordmark@Sun.COM ira->ira_mroute_tunnel = irm->irm_mroute_tunnel; 65011042SErik.Nordmark@Sun.COM ira->ira_no_loop_zoneid = irm->irm_no_loop_zoneid; 65111042SErik.Nordmark@Sun.COM ira->ira_esp_udp_ports = irm->irm_esp_udp_ports; 65211042SErik.Nordmark@Sun.COM 65311042SErik.Nordmark@Sun.COM if (irm->irm_tsl != NULL) { 65411042SErik.Nordmark@Sun.COM ira->ira_tsl = irm->irm_tsl; 65511042SErik.Nordmark@Sun.COM ira->ira_free_flags |= IRA_FREE_TSL; 65611849SErik.Nordmark@Sun.COM irm->irm_tsl = NULL; 65711042SErik.Nordmark@Sun.COM } 65811042SErik.Nordmark@Sun.COM if (irm->irm_cred != NULL) { 65911042SErik.Nordmark@Sun.COM ira->ira_cred = irm->irm_cred; 66011042SErik.Nordmark@Sun.COM ira->ira_free_flags |= IRA_FREE_CRED; 66111849SErik.Nordmark@Sun.COM irm->irm_cred = NULL; 66211042SErik.Nordmark@Sun.COM } 66311042SErik.Nordmark@Sun.COM ira->ira_cpid = irm->irm_cpid; 66411042SErik.Nordmark@Sun.COM 66511042SErik.Nordmark@Sun.COM if (ira->ira_flags & IRAF_L2SRC_SET) 66611042SErik.Nordmark@Sun.COM bcopy(irm->irm_l2src, ira->ira_l2src, IRA_L2SRC_SIZE); 66711042SErik.Nordmark@Sun.COM 66811042SErik.Nordmark@Sun.COM ira->ira_ipsec_ah_sa = irm->irm_ipsec_ah_sa; 66911042SErik.Nordmark@Sun.COM ira->ira_ipsec_esp_sa = irm->irm_ipsec_esp_sa; 67011042SErik.Nordmark@Sun.COM ira->ira_ipsec_action = irm->irm_ipsec_action; 67111042SErik.Nordmark@Sun.COM 67211042SErik.Nordmark@Sun.COM freeb(iramp); 67311042SErik.Nordmark@Sun.COM return (B_TRUE); 67411042SErik.Nordmark@Sun.COM } 67511042SErik.Nordmark@Sun.COM 67611042SErik.Nordmark@Sun.COM /* 67711042SErik.Nordmark@Sun.COM * Free the irm mblk and any references it holds 67811042SErik.Nordmark@Sun.COM * Returns b_cont. 67911042SErik.Nordmark@Sun.COM */ 68011042SErik.Nordmark@Sun.COM mblk_t * 68111042SErik.Nordmark@Sun.COM ip_recv_attr_free_mblk(mblk_t *iramp) 68211042SErik.Nordmark@Sun.COM { 68311042SErik.Nordmark@Sun.COM iramblk_t *irm; 68411042SErik.Nordmark@Sun.COM mblk_t *mp; 68511042SErik.Nordmark@Sun.COM 68611042SErik.Nordmark@Sun.COM /* Consume mp */ 68711042SErik.Nordmark@Sun.COM ASSERT(DB_TYPE(iramp) == M_BREAK); 68811042SErik.Nordmark@Sun.COM mp = iramp->b_cont; 68911042SErik.Nordmark@Sun.COM 69011042SErik.Nordmark@Sun.COM irm = (iramblk_t *)iramp->b_rptr; 69111042SErik.Nordmark@Sun.COM ASSERT(irm->irm_inbound); 69211042SErik.Nordmark@Sun.COM 69311042SErik.Nordmark@Sun.COM if (irm->irm_ipsec_ah_sa != NULL) { 69411042SErik.Nordmark@Sun.COM IPSA_REFRELE(irm->irm_ipsec_ah_sa); 69511042SErik.Nordmark@Sun.COM irm->irm_ipsec_ah_sa = NULL; 69611042SErik.Nordmark@Sun.COM } 69711042SErik.Nordmark@Sun.COM if (irm->irm_ipsec_esp_sa != NULL) { 69811042SErik.Nordmark@Sun.COM IPSA_REFRELE(irm->irm_ipsec_esp_sa); 69911042SErik.Nordmark@Sun.COM irm->irm_ipsec_esp_sa = NULL; 70011042SErik.Nordmark@Sun.COM } 70111042SErik.Nordmark@Sun.COM if (irm->irm_ipsec_action != NULL) { 70211042SErik.Nordmark@Sun.COM IPACT_REFRELE(irm->irm_ipsec_action); 70311042SErik.Nordmark@Sun.COM irm->irm_ipsec_action = NULL; 70411042SErik.Nordmark@Sun.COM } 70511042SErik.Nordmark@Sun.COM if (irm->irm_tsl != NULL) { 70611042SErik.Nordmark@Sun.COM label_rele(irm->irm_tsl); 70711042SErik.Nordmark@Sun.COM irm->irm_tsl = NULL; 70811042SErik.Nordmark@Sun.COM } 70911042SErik.Nordmark@Sun.COM if (irm->irm_cred != NULL) { 71011042SErik.Nordmark@Sun.COM crfree(irm->irm_cred); 71111042SErik.Nordmark@Sun.COM irm->irm_cred = NULL; 71211042SErik.Nordmark@Sun.COM } 71311042SErik.Nordmark@Sun.COM 71411042SErik.Nordmark@Sun.COM freeb(iramp); 71511042SErik.Nordmark@Sun.COM return (mp); 71611042SErik.Nordmark@Sun.COM } 71711042SErik.Nordmark@Sun.COM 71811042SErik.Nordmark@Sun.COM /* 71911042SErik.Nordmark@Sun.COM * Returns true if the mblk contains an ip_recv_attr_t 72011042SErik.Nordmark@Sun.COM * For now we just check db_type. 72111042SErik.Nordmark@Sun.COM */ 72211042SErik.Nordmark@Sun.COM boolean_t 72311042SErik.Nordmark@Sun.COM ip_recv_attr_is_mblk(mblk_t *mp) 72411042SErik.Nordmark@Sun.COM { 72511042SErik.Nordmark@Sun.COM /* 72611042SErik.Nordmark@Sun.COM * Need to handle the various forms of tcp_timermp which are tagged 72711042SErik.Nordmark@Sun.COM * with b_wptr and might have a NULL b_datap. 72811042SErik.Nordmark@Sun.COM */ 72911042SErik.Nordmark@Sun.COM if (mp->b_wptr == NULL || mp->b_wptr == (uchar_t *)-1) 73011042SErik.Nordmark@Sun.COM return (B_FALSE); 73111042SErik.Nordmark@Sun.COM 73211042SErik.Nordmark@Sun.COM #ifdef DEBUG 73311042SErik.Nordmark@Sun.COM iramblk_t *irm; 73411042SErik.Nordmark@Sun.COM 73511042SErik.Nordmark@Sun.COM if (DB_TYPE(mp) != M_BREAK) 73611042SErik.Nordmark@Sun.COM return (B_FALSE); 73711042SErik.Nordmark@Sun.COM 73811042SErik.Nordmark@Sun.COM irm = (iramblk_t *)mp->b_rptr; 73911042SErik.Nordmark@Sun.COM ASSERT(irm->irm_inbound); 74011042SErik.Nordmark@Sun.COM return (B_TRUE); 74111042SErik.Nordmark@Sun.COM #else 74211042SErik.Nordmark@Sun.COM return (DB_TYPE(mp) == M_BREAK); 74311042SErik.Nordmark@Sun.COM #endif 74411042SErik.Nordmark@Sun.COM } 74511042SErik.Nordmark@Sun.COM 74611042SErik.Nordmark@Sun.COM static ip_xmit_attr_t * 74711042SErik.Nordmark@Sun.COM conn_get_ixa_impl(conn_t *connp, boolean_t replace, int kmflag) 74811042SErik.Nordmark@Sun.COM { 74911042SErik.Nordmark@Sun.COM ip_xmit_attr_t *ixa; 75011042SErik.Nordmark@Sun.COM ip_xmit_attr_t *oldixa; 75111042SErik.Nordmark@Sun.COM 75211042SErik.Nordmark@Sun.COM mutex_enter(&connp->conn_lock); 75311042SErik.Nordmark@Sun.COM ixa = connp->conn_ixa; 75411042SErik.Nordmark@Sun.COM 75511042SErik.Nordmark@Sun.COM /* At least one references for the conn_t */ 75611042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_refcnt >= 1); 75711042SErik.Nordmark@Sun.COM if (atomic_add_32_nv(&ixa->ixa_refcnt, 1) == 2) { 75811042SErik.Nordmark@Sun.COM /* No other thread using conn_ixa */ 75911042SErik.Nordmark@Sun.COM mutex_exit(&connp->conn_lock); 76011042SErik.Nordmark@Sun.COM return (ixa); 76111042SErik.Nordmark@Sun.COM } 76211042SErik.Nordmark@Sun.COM ixa = kmem_alloc(sizeof (*ixa), kmflag); 76311042SErik.Nordmark@Sun.COM if (ixa == NULL) { 76411042SErik.Nordmark@Sun.COM mutex_exit(&connp->conn_lock); 76511042SErik.Nordmark@Sun.COM ixa_refrele(connp->conn_ixa); 76611042SErik.Nordmark@Sun.COM return (NULL); 76711042SErik.Nordmark@Sun.COM } 76811042SErik.Nordmark@Sun.COM ixa_safe_copy(connp->conn_ixa, ixa); 76911042SErik.Nordmark@Sun.COM 77011042SErik.Nordmark@Sun.COM /* Make sure we drop conn_lock before any refrele */ 77111042SErik.Nordmark@Sun.COM if (replace) { 77211042SErik.Nordmark@Sun.COM ixa->ixa_refcnt++; /* No atomic needed - not visible */ 77311042SErik.Nordmark@Sun.COM oldixa = connp->conn_ixa; 77411042SErik.Nordmark@Sun.COM connp->conn_ixa = ixa; 77511042SErik.Nordmark@Sun.COM mutex_exit(&connp->conn_lock); 77611042SErik.Nordmark@Sun.COM IXA_REFRELE(oldixa); /* Undo refcnt from conn_t */ 77711042SErik.Nordmark@Sun.COM } else { 77811042SErik.Nordmark@Sun.COM oldixa = connp->conn_ixa; 77911042SErik.Nordmark@Sun.COM mutex_exit(&connp->conn_lock); 78011042SErik.Nordmark@Sun.COM } 78111042SErik.Nordmark@Sun.COM IXA_REFRELE(oldixa); /* Undo above atomic_add_32_nv */ 78211042SErik.Nordmark@Sun.COM 78311042SErik.Nordmark@Sun.COM return (ixa); 78411042SErik.Nordmark@Sun.COM } 78511042SErik.Nordmark@Sun.COM 78611042SErik.Nordmark@Sun.COM /* 78711042SErik.Nordmark@Sun.COM * Return an ip_xmit_attr_t to use with a conn_t that ensures that only 78811042SErik.Nordmark@Sun.COM * the caller can access the ip_xmit_attr_t. 78911042SErik.Nordmark@Sun.COM * 79011042SErik.Nordmark@Sun.COM * If nobody else is using conn_ixa we return it. 79111042SErik.Nordmark@Sun.COM * Otherwise we make a "safe" copy of conn_ixa 79211042SErik.Nordmark@Sun.COM * and return it. The "safe" copy has the pointers set to NULL 79311042SErik.Nordmark@Sun.COM * (since the pointers might be changed by another thread using 79411042SErik.Nordmark@Sun.COM * conn_ixa). The caller needs to check for NULL pointers to see 79511042SErik.Nordmark@Sun.COM * if ip_set_destination needs to be called to re-establish the pointers. 79611042SErik.Nordmark@Sun.COM * 79711042SErik.Nordmark@Sun.COM * If 'replace' is set then we replace conn_ixa with the new ip_xmit_attr_t. 79811042SErik.Nordmark@Sun.COM * That is used when we connect() the ULP. 79911042SErik.Nordmark@Sun.COM */ 80011042SErik.Nordmark@Sun.COM ip_xmit_attr_t * 80111042SErik.Nordmark@Sun.COM conn_get_ixa(conn_t *connp, boolean_t replace) 80211042SErik.Nordmark@Sun.COM { 80311042SErik.Nordmark@Sun.COM return (conn_get_ixa_impl(connp, replace, KM_NOSLEEP)); 80411042SErik.Nordmark@Sun.COM } 80511042SErik.Nordmark@Sun.COM 80611042SErik.Nordmark@Sun.COM /* 80711042SErik.Nordmark@Sun.COM * Used only when the option is to have the kernel hang due to not 80811042SErik.Nordmark@Sun.COM * cleaning up ixa references on ills etc. 80911042SErik.Nordmark@Sun.COM */ 81011042SErik.Nordmark@Sun.COM ip_xmit_attr_t * 81111042SErik.Nordmark@Sun.COM conn_get_ixa_tryhard(conn_t *connp, boolean_t replace) 81211042SErik.Nordmark@Sun.COM { 81311042SErik.Nordmark@Sun.COM return (conn_get_ixa_impl(connp, replace, KM_SLEEP)); 81411042SErik.Nordmark@Sun.COM } 81511042SErik.Nordmark@Sun.COM 81611042SErik.Nordmark@Sun.COM /* 81711042SErik.Nordmark@Sun.COM * Replace conn_ixa with the ixa argument. 81811042SErik.Nordmark@Sun.COM * 81911042SErik.Nordmark@Sun.COM * The caller must hold conn_lock. 82011042SErik.Nordmark@Sun.COM * 82111042SErik.Nordmark@Sun.COM * We return the old ixa; the caller must ixa_refrele that after conn_lock 82211042SErik.Nordmark@Sun.COM * has been dropped. 82311042SErik.Nordmark@Sun.COM */ 82411042SErik.Nordmark@Sun.COM ip_xmit_attr_t * 82511042SErik.Nordmark@Sun.COM conn_replace_ixa(conn_t *connp, ip_xmit_attr_t *ixa) 82611042SErik.Nordmark@Sun.COM { 82711042SErik.Nordmark@Sun.COM ip_xmit_attr_t *oldixa; 82811042SErik.Nordmark@Sun.COM 82911042SErik.Nordmark@Sun.COM ASSERT(MUTEX_HELD(&connp->conn_lock)); 83011042SErik.Nordmark@Sun.COM 83111042SErik.Nordmark@Sun.COM oldixa = connp->conn_ixa; 83211042SErik.Nordmark@Sun.COM IXA_REFHOLD(ixa); 833*12507SAlan.Maguire@Sun.COM ixa->ixa_conn_id = oldixa->ixa_conn_id; 83411042SErik.Nordmark@Sun.COM connp->conn_ixa = ixa; 83511042SErik.Nordmark@Sun.COM return (oldixa); 83611042SErik.Nordmark@Sun.COM } 83711042SErik.Nordmark@Sun.COM 83811042SErik.Nordmark@Sun.COM /* 83911042SErik.Nordmark@Sun.COM * Return a ip_xmit_attr_t to use with a conn_t that is based on but 84011042SErik.Nordmark@Sun.COM * separate from conn_ixa. 84111042SErik.Nordmark@Sun.COM * 84211042SErik.Nordmark@Sun.COM * This "safe" copy has the pointers set to NULL 84311042SErik.Nordmark@Sun.COM * (since the pointers might be changed by another thread using 84411042SErik.Nordmark@Sun.COM * conn_ixa). The caller needs to check for NULL pointers to see 84511042SErik.Nordmark@Sun.COM * if ip_set_destination needs to be called to re-establish the pointers. 84611042SErik.Nordmark@Sun.COM */ 84711042SErik.Nordmark@Sun.COM ip_xmit_attr_t * 84811042SErik.Nordmark@Sun.COM conn_get_ixa_exclusive(conn_t *connp) 84911042SErik.Nordmark@Sun.COM { 85011042SErik.Nordmark@Sun.COM ip_xmit_attr_t *ixa; 85111042SErik.Nordmark@Sun.COM 85211042SErik.Nordmark@Sun.COM mutex_enter(&connp->conn_lock); 85311042SErik.Nordmark@Sun.COM ixa = connp->conn_ixa; 85411042SErik.Nordmark@Sun.COM 85511042SErik.Nordmark@Sun.COM /* At least one references for the conn_t */ 85611042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_refcnt >= 1); 85711042SErik.Nordmark@Sun.COM 85811042SErik.Nordmark@Sun.COM /* Make sure conn_ixa doesn't disappear while we copy it */ 85911042SErik.Nordmark@Sun.COM atomic_add_32(&ixa->ixa_refcnt, 1); 86011042SErik.Nordmark@Sun.COM 86111042SErik.Nordmark@Sun.COM ixa = kmem_alloc(sizeof (*ixa), KM_NOSLEEP); 86211042SErik.Nordmark@Sun.COM if (ixa == NULL) { 86311042SErik.Nordmark@Sun.COM mutex_exit(&connp->conn_lock); 86411042SErik.Nordmark@Sun.COM ixa_refrele(connp->conn_ixa); 86511042SErik.Nordmark@Sun.COM return (NULL); 86611042SErik.Nordmark@Sun.COM } 86711042SErik.Nordmark@Sun.COM ixa_safe_copy(connp->conn_ixa, ixa); 86811042SErik.Nordmark@Sun.COM mutex_exit(&connp->conn_lock); 86911042SErik.Nordmark@Sun.COM IXA_REFRELE(connp->conn_ixa); 87011042SErik.Nordmark@Sun.COM return (ixa); 87111042SErik.Nordmark@Sun.COM } 87211042SErik.Nordmark@Sun.COM 87311042SErik.Nordmark@Sun.COM void 87411042SErik.Nordmark@Sun.COM ixa_safe_copy(ip_xmit_attr_t *src, ip_xmit_attr_t *ixa) 87511042SErik.Nordmark@Sun.COM { 87611042SErik.Nordmark@Sun.COM bcopy(src, ixa, sizeof (*ixa)); 87711042SErik.Nordmark@Sun.COM ixa->ixa_refcnt = 1; 87811042SErik.Nordmark@Sun.COM /* 87911042SErik.Nordmark@Sun.COM * Clear any pointers that have references and might be changed 88011042SErik.Nordmark@Sun.COM * by ip_set_destination or the ULP 88111042SErik.Nordmark@Sun.COM */ 88211042SErik.Nordmark@Sun.COM ixa->ixa_ire = NULL; 88311042SErik.Nordmark@Sun.COM ixa->ixa_nce = NULL; 88411042SErik.Nordmark@Sun.COM ixa->ixa_dce = NULL; 88511042SErik.Nordmark@Sun.COM ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; 88611042SErik.Nordmark@Sun.COM ixa->ixa_dce_generation = DCE_GENERATION_VERIFY; 88711042SErik.Nordmark@Sun.COM #ifdef DEBUG 88811042SErik.Nordmark@Sun.COM ixa->ixa_curthread = NULL; 88911042SErik.Nordmark@Sun.COM #endif 89011042SErik.Nordmark@Sun.COM /* Clear all the IPsec pointers and the flag as well. */ 89111042SErik.Nordmark@Sun.COM ixa->ixa_flags &= ~IXAF_IPSEC_SECURE; 89211042SErik.Nordmark@Sun.COM 89311042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_latch = NULL; 89411042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_ah_sa = NULL; 89511042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_esp_sa = NULL; 89611042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_policy = NULL; 89711042SErik.Nordmark@Sun.COM ixa->ixa_ipsec_action = NULL; 89811042SErik.Nordmark@Sun.COM 89911042SErik.Nordmark@Sun.COM /* 90011042SErik.Nordmark@Sun.COM * We leave ixa_tsl unchanged, but if it has a refhold we need 90111042SErik.Nordmark@Sun.COM * to get an extra refhold. 90211042SErik.Nordmark@Sun.COM */ 90311042SErik.Nordmark@Sun.COM if (ixa->ixa_free_flags & IXA_FREE_TSL) 90411042SErik.Nordmark@Sun.COM label_hold(ixa->ixa_tsl); 90511042SErik.Nordmark@Sun.COM 90611042SErik.Nordmark@Sun.COM /* 90711042SErik.Nordmark@Sun.COM * We leave ixa_cred unchanged, but if it has a refhold we need 90811042SErik.Nordmark@Sun.COM * to get an extra refhold. 90911042SErik.Nordmark@Sun.COM */ 91011042SErik.Nordmark@Sun.COM if (ixa->ixa_free_flags & IXA_FREE_CRED) 91111042SErik.Nordmark@Sun.COM crhold(ixa->ixa_cred); 91211042SErik.Nordmark@Sun.COM } 91311042SErik.Nordmark@Sun.COM 91411042SErik.Nordmark@Sun.COM /* 91511042SErik.Nordmark@Sun.COM * Duplicate an ip_xmit_attr_t. 91611042SErik.Nordmark@Sun.COM * Assumes that the caller controls the ixa, hence we do not need to use 91711042SErik.Nordmark@Sun.COM * a safe copy. We just have to increase the refcnt on any pointers. 91811042SErik.Nordmark@Sun.COM */ 91911042SErik.Nordmark@Sun.COM ip_xmit_attr_t * 92011042SErik.Nordmark@Sun.COM ip_xmit_attr_duplicate(ip_xmit_attr_t *src_ixa) 92111042SErik.Nordmark@Sun.COM { 92211042SErik.Nordmark@Sun.COM ip_xmit_attr_t *ixa; 92311042SErik.Nordmark@Sun.COM 92411042SErik.Nordmark@Sun.COM ixa = kmem_alloc(sizeof (*ixa), KM_NOSLEEP); 92511042SErik.Nordmark@Sun.COM if (ixa == NULL) 92611042SErik.Nordmark@Sun.COM return (NULL); 92711042SErik.Nordmark@Sun.COM bcopy(src_ixa, ixa, sizeof (*ixa)); 92811042SErik.Nordmark@Sun.COM ixa->ixa_refcnt = 1; 92911042SErik.Nordmark@Sun.COM 93011042SErik.Nordmark@Sun.COM if (ixa->ixa_ire != NULL) 93111042SErik.Nordmark@Sun.COM ire_refhold_notr(ixa->ixa_ire); 93211042SErik.Nordmark@Sun.COM if (ixa->ixa_nce != NULL) 93311042SErik.Nordmark@Sun.COM nce_refhold(ixa->ixa_nce); 93411042SErik.Nordmark@Sun.COM if (ixa->ixa_dce != NULL) 93511042SErik.Nordmark@Sun.COM dce_refhold_notr(ixa->ixa_dce); 93611042SErik.Nordmark@Sun.COM 93711042SErik.Nordmark@Sun.COM #ifdef DEBUG 93811042SErik.Nordmark@Sun.COM ixa->ixa_curthread = NULL; 93911042SErik.Nordmark@Sun.COM #endif 94011042SErik.Nordmark@Sun.COM 94111042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_latch != NULL) 94211042SErik.Nordmark@Sun.COM IPLATCH_REFHOLD(ixa->ixa_ipsec_latch); 94311042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_ah_sa != NULL) 94411042SErik.Nordmark@Sun.COM IPSA_REFHOLD(ixa->ixa_ipsec_ah_sa); 94511042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_esp_sa != NULL) 94611042SErik.Nordmark@Sun.COM IPSA_REFHOLD(ixa->ixa_ipsec_esp_sa); 94711042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_policy != NULL) 94811042SErik.Nordmark@Sun.COM IPPOL_REFHOLD(ixa->ixa_ipsec_policy); 94911042SErik.Nordmark@Sun.COM if (ixa->ixa_ipsec_action != NULL) 95011042SErik.Nordmark@Sun.COM IPACT_REFHOLD(ixa->ixa_ipsec_action); 95111042SErik.Nordmark@Sun.COM 95211042SErik.Nordmark@Sun.COM if (ixa->ixa_tsl != NULL) { 95311042SErik.Nordmark@Sun.COM label_hold(ixa->ixa_tsl); 95411042SErik.Nordmark@Sun.COM ixa->ixa_free_flags |= IXA_FREE_TSL; 95511042SErik.Nordmark@Sun.COM } 95611042SErik.Nordmark@Sun.COM if (ixa->ixa_cred != NULL) { 95711042SErik.Nordmark@Sun.COM crhold(ixa->ixa_cred); 95811042SErik.Nordmark@Sun.COM ixa->ixa_free_flags |= IXA_FREE_CRED; 95911042SErik.Nordmark@Sun.COM } 96011042SErik.Nordmark@Sun.COM return (ixa); 96111042SErik.Nordmark@Sun.COM } 96211042SErik.Nordmark@Sun.COM 96311042SErik.Nordmark@Sun.COM /* 96411042SErik.Nordmark@Sun.COM * Used to replace the ixa_label field. 96511042SErik.Nordmark@Sun.COM * The caller should have a reference on the label, which we transfer to 96611042SErik.Nordmark@Sun.COM * the attributes so that when the attribute is freed/cleaned up 96711042SErik.Nordmark@Sun.COM * we will release that reference. 96811042SErik.Nordmark@Sun.COM */ 96911042SErik.Nordmark@Sun.COM void 97011042SErik.Nordmark@Sun.COM ip_xmit_attr_replace_tsl(ip_xmit_attr_t *ixa, ts_label_t *tsl) 97111042SErik.Nordmark@Sun.COM { 97211042SErik.Nordmark@Sun.COM ASSERT(tsl != NULL); 97311042SErik.Nordmark@Sun.COM 97411042SErik.Nordmark@Sun.COM if (ixa->ixa_free_flags & IXA_FREE_TSL) { 97511042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_tsl != NULL); 97611042SErik.Nordmark@Sun.COM label_rele(ixa->ixa_tsl); 97711042SErik.Nordmark@Sun.COM } else { 97811042SErik.Nordmark@Sun.COM ixa->ixa_free_flags |= IXA_FREE_TSL; 97911042SErik.Nordmark@Sun.COM } 98011042SErik.Nordmark@Sun.COM ixa->ixa_tsl = tsl; 98111042SErik.Nordmark@Sun.COM } 98211042SErik.Nordmark@Sun.COM 98311042SErik.Nordmark@Sun.COM /* 98411042SErik.Nordmark@Sun.COM * Replace the ip_recv_attr_t's label. 98511042SErik.Nordmark@Sun.COM * Due to kernel RPC's use of db_credp we also need to replace ira_cred; 98611042SErik.Nordmark@Sun.COM * TCP/UDP uses ira_cred to set db_credp for non-socket users. 98711042SErik.Nordmark@Sun.COM * This can fail (and return B_FALSE) due to lack of memory. 98811042SErik.Nordmark@Sun.COM */ 98911042SErik.Nordmark@Sun.COM boolean_t 99011042SErik.Nordmark@Sun.COM ip_recv_attr_replace_label(ip_recv_attr_t *ira, ts_label_t *tsl) 99111042SErik.Nordmark@Sun.COM { 99211042SErik.Nordmark@Sun.COM cred_t *newcr; 99311042SErik.Nordmark@Sun.COM 99411042SErik.Nordmark@Sun.COM if (ira->ira_free_flags & IRA_FREE_TSL) { 99511042SErik.Nordmark@Sun.COM ASSERT(ira->ira_tsl != NULL); 99611042SErik.Nordmark@Sun.COM label_rele(ira->ira_tsl); 99711042SErik.Nordmark@Sun.COM } 99811042SErik.Nordmark@Sun.COM label_hold(tsl); 99911042SErik.Nordmark@Sun.COM ira->ira_tsl = tsl; 100011042SErik.Nordmark@Sun.COM ira->ira_free_flags |= IRA_FREE_TSL; 100111042SErik.Nordmark@Sun.COM 100211042SErik.Nordmark@Sun.COM /* 100311042SErik.Nordmark@Sun.COM * Reset zoneid if we have a shared address. That allows 100411042SErik.Nordmark@Sun.COM * ip_fanout_tx_v4/v6 to determine the zoneid again. 100511042SErik.Nordmark@Sun.COM */ 100611042SErik.Nordmark@Sun.COM if (ira->ira_flags & IRAF_TX_SHARED_ADDR) 100711042SErik.Nordmark@Sun.COM ira->ira_zoneid = ALL_ZONES; 100811042SErik.Nordmark@Sun.COM 100911042SErik.Nordmark@Sun.COM /* We update ira_cred for RPC */ 101011042SErik.Nordmark@Sun.COM newcr = copycred_from_tslabel(ira->ira_cred, ira->ira_tsl, KM_NOSLEEP); 101111042SErik.Nordmark@Sun.COM if (newcr == NULL) 101211042SErik.Nordmark@Sun.COM return (B_FALSE); 101311042SErik.Nordmark@Sun.COM if (ira->ira_free_flags & IRA_FREE_CRED) 101411042SErik.Nordmark@Sun.COM crfree(ira->ira_cred); 101511042SErik.Nordmark@Sun.COM ira->ira_cred = newcr; 101611042SErik.Nordmark@Sun.COM ira->ira_free_flags |= IRA_FREE_CRED; 101711042SErik.Nordmark@Sun.COM return (B_TRUE); 101811042SErik.Nordmark@Sun.COM } 101911042SErik.Nordmark@Sun.COM 102011042SErik.Nordmark@Sun.COM /* 102111042SErik.Nordmark@Sun.COM * This needs to be called after ip_set_destination/tsol_check_dest might 102211042SErik.Nordmark@Sun.COM * have changed ixa_tsl to be specific for a destination, and we now want to 102311042SErik.Nordmark@Sun.COM * send to a different destination. 102411042SErik.Nordmark@Sun.COM * We have to restart with crgetlabel() since ip_set_destination/ 102511042SErik.Nordmark@Sun.COM * tsol_check_dest will start with ixa_tsl. 102611042SErik.Nordmark@Sun.COM */ 102711042SErik.Nordmark@Sun.COM void 102811042SErik.Nordmark@Sun.COM ip_xmit_attr_restore_tsl(ip_xmit_attr_t *ixa, cred_t *cr) 102911042SErik.Nordmark@Sun.COM { 103011042SErik.Nordmark@Sun.COM if (!is_system_labeled()) 103111042SErik.Nordmark@Sun.COM return; 103211042SErik.Nordmark@Sun.COM 103311042SErik.Nordmark@Sun.COM if (ixa->ixa_free_flags & IXA_FREE_TSL) { 103411042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_tsl != NULL); 103511042SErik.Nordmark@Sun.COM label_rele(ixa->ixa_tsl); 103611042SErik.Nordmark@Sun.COM ixa->ixa_free_flags &= ~IXA_FREE_TSL; 103711042SErik.Nordmark@Sun.COM } 103811042SErik.Nordmark@Sun.COM ixa->ixa_tsl = crgetlabel(cr); 103911042SErik.Nordmark@Sun.COM } 104011042SErik.Nordmark@Sun.COM 104111042SErik.Nordmark@Sun.COM void 104211042SErik.Nordmark@Sun.COM ixa_refrele(ip_xmit_attr_t *ixa) 104311042SErik.Nordmark@Sun.COM { 104411042SErik.Nordmark@Sun.COM IXA_REFRELE(ixa); 104511042SErik.Nordmark@Sun.COM } 104611042SErik.Nordmark@Sun.COM 104711042SErik.Nordmark@Sun.COM void 104811042SErik.Nordmark@Sun.COM ixa_inactive(ip_xmit_attr_t *ixa) 104911042SErik.Nordmark@Sun.COM { 105011042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_refcnt == 0); 105111042SErik.Nordmark@Sun.COM 105211042SErik.Nordmark@Sun.COM ixa_cleanup(ixa); 105311042SErik.Nordmark@Sun.COM kmem_free(ixa, sizeof (*ixa)); 105411042SErik.Nordmark@Sun.COM } 105511042SErik.Nordmark@Sun.COM 105611042SErik.Nordmark@Sun.COM /* 105711042SErik.Nordmark@Sun.COM * Release any references contained in the ixa. 105811042SErik.Nordmark@Sun.COM * Also clear any fields that are not controlled by ixa_flags. 105911042SErik.Nordmark@Sun.COM */ 106011042SErik.Nordmark@Sun.COM void 106111042SErik.Nordmark@Sun.COM ixa_cleanup(ip_xmit_attr_t *ixa) 106211042SErik.Nordmark@Sun.COM { 106311042SErik.Nordmark@Sun.COM if (ixa->ixa_ire != NULL) { 106411042SErik.Nordmark@Sun.COM ire_refrele_notr(ixa->ixa_ire); 106511042SErik.Nordmark@Sun.COM ixa->ixa_ire = NULL; 106611042SErik.Nordmark@Sun.COM } 106711042SErik.Nordmark@Sun.COM if (ixa->ixa_dce != NULL) { 106811042SErik.Nordmark@Sun.COM dce_refrele_notr(ixa->ixa_dce); 106911042SErik.Nordmark@Sun.COM ixa->ixa_dce = NULL; 107011042SErik.Nordmark@Sun.COM } 107111042SErik.Nordmark@Sun.COM if (ixa->ixa_nce != NULL) { 107211042SErik.Nordmark@Sun.COM nce_refrele(ixa->ixa_nce); 107311042SErik.Nordmark@Sun.COM ixa->ixa_nce = NULL; 107411042SErik.Nordmark@Sun.COM } 107511042SErik.Nordmark@Sun.COM ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; 107611042SErik.Nordmark@Sun.COM ixa->ixa_dce_generation = DCE_GENERATION_VERIFY; 107711042SErik.Nordmark@Sun.COM if (ixa->ixa_flags & IXAF_IPSEC_SECURE) { 107811042SErik.Nordmark@Sun.COM ipsec_out_release_refs(ixa); 107911042SErik.Nordmark@Sun.COM } 108011042SErik.Nordmark@Sun.COM if (ixa->ixa_free_flags & IXA_FREE_TSL) { 108111042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_tsl != NULL); 108211042SErik.Nordmark@Sun.COM label_rele(ixa->ixa_tsl); 108311042SErik.Nordmark@Sun.COM ixa->ixa_free_flags &= ~IXA_FREE_TSL; 108411042SErik.Nordmark@Sun.COM } 108511680SErik.Nordmark@Sun.COM ixa->ixa_tsl = NULL; 108611042SErik.Nordmark@Sun.COM if (ixa->ixa_free_flags & IXA_FREE_CRED) { 108711042SErik.Nordmark@Sun.COM ASSERT(ixa->ixa_cred != NULL); 108811042SErik.Nordmark@Sun.COM crfree(ixa->ixa_cred); 108911042SErik.Nordmark@Sun.COM ixa->ixa_free_flags &= ~IXA_FREE_CRED; 109011042SErik.Nordmark@Sun.COM } 109111680SErik.Nordmark@Sun.COM ixa->ixa_cred = NULL; 109211042SErik.Nordmark@Sun.COM ixa->ixa_src_preferences = 0; 109311042SErik.Nordmark@Sun.COM ixa->ixa_ifindex = 0; 109411042SErik.Nordmark@Sun.COM ixa->ixa_multicast_ifindex = 0; 109511042SErik.Nordmark@Sun.COM ixa->ixa_multicast_ifaddr = INADDR_ANY; 109611042SErik.Nordmark@Sun.COM } 109711042SErik.Nordmark@Sun.COM 109811042SErik.Nordmark@Sun.COM /* 109911042SErik.Nordmark@Sun.COM * Release any references contained in the ira. 110011042SErik.Nordmark@Sun.COM * Callers which use ip_recv_attr_from_mblk() would pass B_TRUE as the second 110111042SErik.Nordmark@Sun.COM * argument. 110211042SErik.Nordmark@Sun.COM */ 110311042SErik.Nordmark@Sun.COM void 110411042SErik.Nordmark@Sun.COM ira_cleanup(ip_recv_attr_t *ira, boolean_t refrele_ill) 110511042SErik.Nordmark@Sun.COM { 110611042SErik.Nordmark@Sun.COM if (ira->ira_ill != NULL) { 110711042SErik.Nordmark@Sun.COM if (ira->ira_rill != ira->ira_ill) { 110811042SErik.Nordmark@Sun.COM /* Caused by async processing */ 110911042SErik.Nordmark@Sun.COM ill_refrele(ira->ira_rill); 111011042SErik.Nordmark@Sun.COM } 111111042SErik.Nordmark@Sun.COM if (refrele_ill) 111211042SErik.Nordmark@Sun.COM ill_refrele(ira->ira_ill); 111311042SErik.Nordmark@Sun.COM } 111411042SErik.Nordmark@Sun.COM if (ira->ira_flags & IRAF_IPSEC_SECURE) { 111511042SErik.Nordmark@Sun.COM ipsec_in_release_refs(ira); 111611042SErik.Nordmark@Sun.COM } 111711042SErik.Nordmark@Sun.COM if (ira->ira_free_flags & IRA_FREE_TSL) { 111811042SErik.Nordmark@Sun.COM ASSERT(ira->ira_tsl != NULL); 111911042SErik.Nordmark@Sun.COM label_rele(ira->ira_tsl); 112011042SErik.Nordmark@Sun.COM ira->ira_free_flags &= ~IRA_FREE_TSL; 112111042SErik.Nordmark@Sun.COM } 112211849SErik.Nordmark@Sun.COM ira->ira_tsl = NULL; 112311042SErik.Nordmark@Sun.COM if (ira->ira_free_flags & IRA_FREE_CRED) { 112411042SErik.Nordmark@Sun.COM ASSERT(ira->ira_cred != NULL); 112511042SErik.Nordmark@Sun.COM crfree(ira->ira_cred); 112611042SErik.Nordmark@Sun.COM ira->ira_free_flags &= ~IRA_FREE_CRED; 112711042SErik.Nordmark@Sun.COM } 112811849SErik.Nordmark@Sun.COM ira->ira_cred = NULL; 112911042SErik.Nordmark@Sun.COM } 113011042SErik.Nordmark@Sun.COM 113111042SErik.Nordmark@Sun.COM /* 113211042SErik.Nordmark@Sun.COM * Function to help release any IRE, NCE, or DCEs that 113311042SErik.Nordmark@Sun.COM * have been deleted and are marked as condemned. 113411042SErik.Nordmark@Sun.COM * The caller is responsible for any serialization which is different 113511042SErik.Nordmark@Sun.COM * for TCP, SCTP, and others. 113611042SErik.Nordmark@Sun.COM */ 113711042SErik.Nordmark@Sun.COM static void 113811042SErik.Nordmark@Sun.COM ixa_cleanup_stale(ip_xmit_attr_t *ixa) 113911042SErik.Nordmark@Sun.COM { 114011042SErik.Nordmark@Sun.COM ire_t *ire; 114111042SErik.Nordmark@Sun.COM nce_t *nce; 114211042SErik.Nordmark@Sun.COM dce_t *dce; 114311042SErik.Nordmark@Sun.COM 114411042SErik.Nordmark@Sun.COM ire = ixa->ixa_ire; 114511042SErik.Nordmark@Sun.COM nce = ixa->ixa_nce; 114611042SErik.Nordmark@Sun.COM dce = ixa->ixa_dce; 114711042SErik.Nordmark@Sun.COM 114811042SErik.Nordmark@Sun.COM if (ire != NULL && IRE_IS_CONDEMNED(ire)) { 114911042SErik.Nordmark@Sun.COM ire_refrele_notr(ire); 115011042SErik.Nordmark@Sun.COM ire = ire_blackhole(ixa->ixa_ipst, 115111042SErik.Nordmark@Sun.COM !(ixa->ixa_flags & IXAF_IS_IPV4)); 115211042SErik.Nordmark@Sun.COM ASSERT(ire != NULL); 115311042SErik.Nordmark@Sun.COM #ifdef DEBUG 115411042SErik.Nordmark@Sun.COM ire_refhold_notr(ire); 115511042SErik.Nordmark@Sun.COM ire_refrele(ire); 115611042SErik.Nordmark@Sun.COM #endif 115711042SErik.Nordmark@Sun.COM ixa->ixa_ire = ire; 115811042SErik.Nordmark@Sun.COM ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; 115911042SErik.Nordmark@Sun.COM } 116011042SErik.Nordmark@Sun.COM if (nce != NULL && nce->nce_is_condemned) { 116111042SErik.Nordmark@Sun.COM /* Can make it NULL as long as we set IRE_GENERATION_VERIFY */ 116211042SErik.Nordmark@Sun.COM nce_refrele(nce); 116311042SErik.Nordmark@Sun.COM ixa->ixa_nce = NULL; 116411042SErik.Nordmark@Sun.COM ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; 116511042SErik.Nordmark@Sun.COM } 116611042SErik.Nordmark@Sun.COM if (dce != NULL && DCE_IS_CONDEMNED(dce)) { 116711042SErik.Nordmark@Sun.COM dce_refrele_notr(dce); 116811042SErik.Nordmark@Sun.COM dce = dce_get_default(ixa->ixa_ipst); 116911042SErik.Nordmark@Sun.COM ASSERT(dce != NULL); 117011042SErik.Nordmark@Sun.COM #ifdef DEBUG 117111042SErik.Nordmark@Sun.COM dce_refhold_notr(dce); 117211042SErik.Nordmark@Sun.COM dce_refrele(dce); 117311042SErik.Nordmark@Sun.COM #endif 117411042SErik.Nordmark@Sun.COM ixa->ixa_dce = dce; 117511042SErik.Nordmark@Sun.COM ixa->ixa_dce_generation = DCE_GENERATION_VERIFY; 117611042SErik.Nordmark@Sun.COM } 117711042SErik.Nordmark@Sun.COM } 117811042SErik.Nordmark@Sun.COM 117911042SErik.Nordmark@Sun.COM /* 118011042SErik.Nordmark@Sun.COM * Used to run ixa_cleanup_stale inside the tcp squeue. 118111042SErik.Nordmark@Sun.COM * When done we hand the mp back by assigning it to tcps_ixa_cleanup_mp 118211042SErik.Nordmark@Sun.COM * and waking up the caller. 118311042SErik.Nordmark@Sun.COM */ 118411042SErik.Nordmark@Sun.COM /* ARGSUSED2 */ 118511042SErik.Nordmark@Sun.COM static void 118611042SErik.Nordmark@Sun.COM tcp_ixa_cleanup(void *arg, mblk_t *mp, void *arg2, 118711042SErik.Nordmark@Sun.COM ip_recv_attr_t *dummy) 118811042SErik.Nordmark@Sun.COM { 118911042SErik.Nordmark@Sun.COM conn_t *connp = (conn_t *)arg; 119011042SErik.Nordmark@Sun.COM tcp_stack_t *tcps; 119111042SErik.Nordmark@Sun.COM 119211042SErik.Nordmark@Sun.COM tcps = connp->conn_netstack->netstack_tcp; 119311042SErik.Nordmark@Sun.COM 119411042SErik.Nordmark@Sun.COM ixa_cleanup_stale(connp->conn_ixa); 119511042SErik.Nordmark@Sun.COM 119611042SErik.Nordmark@Sun.COM mutex_enter(&tcps->tcps_ixa_cleanup_lock); 119711042SErik.Nordmark@Sun.COM ASSERT(tcps->tcps_ixa_cleanup_mp == NULL); 119811042SErik.Nordmark@Sun.COM tcps->tcps_ixa_cleanup_mp = mp; 119911042SErik.Nordmark@Sun.COM cv_signal(&tcps->tcps_ixa_cleanup_cv); 120011042SErik.Nordmark@Sun.COM mutex_exit(&tcps->tcps_ixa_cleanup_lock); 120111042SErik.Nordmark@Sun.COM } 120211042SErik.Nordmark@Sun.COM 120311042SErik.Nordmark@Sun.COM 120411042SErik.Nordmark@Sun.COM /* 120511042SErik.Nordmark@Sun.COM * ipcl_walk() function to help release any IRE, NCE, or DCEs that 120611042SErik.Nordmark@Sun.COM * have been deleted and are marked as condemned. 120711042SErik.Nordmark@Sun.COM * Note that we can't cleanup the pointers since there can be threads 120811042SErik.Nordmark@Sun.COM * in conn_ip_output() sending while we are called. 120911042SErik.Nordmark@Sun.COM */ 121011042SErik.Nordmark@Sun.COM void 121111042SErik.Nordmark@Sun.COM conn_ixa_cleanup(conn_t *connp, void *arg) 121211042SErik.Nordmark@Sun.COM { 121311042SErik.Nordmark@Sun.COM boolean_t tryhard = (boolean_t)arg; 121411042SErik.Nordmark@Sun.COM 121511042SErik.Nordmark@Sun.COM if (IPCL_IS_TCP(connp)) { 121611042SErik.Nordmark@Sun.COM mblk_t *mp; 121711042SErik.Nordmark@Sun.COM tcp_stack_t *tcps; 121811042SErik.Nordmark@Sun.COM 121911042SErik.Nordmark@Sun.COM tcps = connp->conn_netstack->netstack_tcp; 122011042SErik.Nordmark@Sun.COM 122111042SErik.Nordmark@Sun.COM mutex_enter(&tcps->tcps_ixa_cleanup_lock); 122211042SErik.Nordmark@Sun.COM while ((mp = tcps->tcps_ixa_cleanup_mp) == NULL) { 122311042SErik.Nordmark@Sun.COM /* 122411042SErik.Nordmark@Sun.COM * Multiple concurrent cleanups; need to have the last 122511042SErik.Nordmark@Sun.COM * one run since it could be an unplumb. 122611042SErik.Nordmark@Sun.COM */ 122711042SErik.Nordmark@Sun.COM cv_wait(&tcps->tcps_ixa_cleanup_cv, 122811042SErik.Nordmark@Sun.COM &tcps->tcps_ixa_cleanup_lock); 122911042SErik.Nordmark@Sun.COM } 123011042SErik.Nordmark@Sun.COM tcps->tcps_ixa_cleanup_mp = NULL; 123111042SErik.Nordmark@Sun.COM mutex_exit(&tcps->tcps_ixa_cleanup_lock); 123211042SErik.Nordmark@Sun.COM 123311042SErik.Nordmark@Sun.COM if (connp->conn_sqp->sq_run == curthread) { 123411042SErik.Nordmark@Sun.COM /* Already on squeue */ 123511042SErik.Nordmark@Sun.COM tcp_ixa_cleanup(connp, mp, NULL, NULL); 123611042SErik.Nordmark@Sun.COM } else { 123711042SErik.Nordmark@Sun.COM CONN_INC_REF(connp); 123811042SErik.Nordmark@Sun.COM SQUEUE_ENTER_ONE(connp->conn_sqp, mp, tcp_ixa_cleanup, 123911042SErik.Nordmark@Sun.COM connp, NULL, SQ_PROCESS, SQTAG_TCP_IXA_CLEANUP); 124011042SErik.Nordmark@Sun.COM 124111042SErik.Nordmark@Sun.COM /* Wait until tcp_ixa_cleanup has run */ 124211042SErik.Nordmark@Sun.COM mutex_enter(&tcps->tcps_ixa_cleanup_lock); 124311042SErik.Nordmark@Sun.COM while (tcps->tcps_ixa_cleanup_mp == NULL) { 124411042SErik.Nordmark@Sun.COM cv_wait(&tcps->tcps_ixa_cleanup_cv, 124511042SErik.Nordmark@Sun.COM &tcps->tcps_ixa_cleanup_lock); 124611042SErik.Nordmark@Sun.COM } 124711042SErik.Nordmark@Sun.COM mutex_exit(&tcps->tcps_ixa_cleanup_lock); 124811042SErik.Nordmark@Sun.COM } 124911042SErik.Nordmark@Sun.COM } else if (IPCL_IS_SCTP(connp)) { 125011042SErik.Nordmark@Sun.COM sctp_t *sctp; 125111042SErik.Nordmark@Sun.COM sctp_faddr_t *fp; 125211042SErik.Nordmark@Sun.COM 125311042SErik.Nordmark@Sun.COM sctp = CONN2SCTP(connp); 125411042SErik.Nordmark@Sun.COM RUN_SCTP(sctp); 125511042SErik.Nordmark@Sun.COM ixa_cleanup_stale(connp->conn_ixa); 125611042SErik.Nordmark@Sun.COM for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) 125711042SErik.Nordmark@Sun.COM ixa_cleanup_stale(fp->ixa); 125811042SErik.Nordmark@Sun.COM WAKE_SCTP(sctp); 125911042SErik.Nordmark@Sun.COM } else { 126011042SErik.Nordmark@Sun.COM ip_xmit_attr_t *ixa; 126111042SErik.Nordmark@Sun.COM 126211042SErik.Nordmark@Sun.COM /* 126311042SErik.Nordmark@Sun.COM * If there is a different thread using conn_ixa then we get a 126411042SErik.Nordmark@Sun.COM * new copy and cut the old one loose from conn_ixa. Otherwise 126511042SErik.Nordmark@Sun.COM * we use conn_ixa and prevent any other thread from 126611042SErik.Nordmark@Sun.COM * using/changing it. Anybody using conn_ixa (e.g., a thread in 126711042SErik.Nordmark@Sun.COM * conn_ip_output) will do an ixa_refrele which will remove any 126811042SErik.Nordmark@Sun.COM * references on the ire etc. 126911042SErik.Nordmark@Sun.COM * 127011042SErik.Nordmark@Sun.COM * Once we are done other threads can use conn_ixa since the 127111042SErik.Nordmark@Sun.COM * refcnt will be back at one. 127211042SErik.Nordmark@Sun.COM * 127311042SErik.Nordmark@Sun.COM * We are called either because an ill is going away, or 127411042SErik.Nordmark@Sun.COM * due to memory reclaim. In the former case we wait for 127511042SErik.Nordmark@Sun.COM * memory since we must remove the refcnts on the ill. 127611042SErik.Nordmark@Sun.COM */ 127711042SErik.Nordmark@Sun.COM if (tryhard) { 127811042SErik.Nordmark@Sun.COM ixa = conn_get_ixa_tryhard(connp, B_TRUE); 127911042SErik.Nordmark@Sun.COM ASSERT(ixa != NULL); 128011042SErik.Nordmark@Sun.COM } else { 128111042SErik.Nordmark@Sun.COM ixa = conn_get_ixa(connp, B_TRUE); 128211042SErik.Nordmark@Sun.COM if (ixa == NULL) { 128311042SErik.Nordmark@Sun.COM /* 128411042SErik.Nordmark@Sun.COM * Somebody else was using it and kmem_alloc 128511042SErik.Nordmark@Sun.COM * failed! Next memory reclaim will try to 128611042SErik.Nordmark@Sun.COM * clean up. 128711042SErik.Nordmark@Sun.COM */ 128811042SErik.Nordmark@Sun.COM DTRACE_PROBE1(conn__ixa__cleanup__bail, 128911042SErik.Nordmark@Sun.COM conn_t *, connp); 129011042SErik.Nordmark@Sun.COM return; 129111042SErik.Nordmark@Sun.COM } 129211042SErik.Nordmark@Sun.COM } 129311042SErik.Nordmark@Sun.COM ixa_cleanup_stale(ixa); 129411042SErik.Nordmark@Sun.COM ixa_refrele(ixa); 129511042SErik.Nordmark@Sun.COM } 129611042SErik.Nordmark@Sun.COM } 129711042SErik.Nordmark@Sun.COM 129811042SErik.Nordmark@Sun.COM /* 129911042SErik.Nordmark@Sun.COM * ixa needs to be an exclusive copy so that no one changes the cookie 130011042SErik.Nordmark@Sun.COM * or the ixa_nce. 130111042SErik.Nordmark@Sun.COM */ 130211042SErik.Nordmark@Sun.COM boolean_t 130311042SErik.Nordmark@Sun.COM ixa_check_drain_insert(conn_t *connp, ip_xmit_attr_t *ixa) 130411042SErik.Nordmark@Sun.COM { 130511042SErik.Nordmark@Sun.COM uintptr_t cookie = ixa->ixa_cookie; 130611042SErik.Nordmark@Sun.COM ill_dld_direct_t *idd; 130711042SErik.Nordmark@Sun.COM idl_tx_list_t *idl_txl; 130811042SErik.Nordmark@Sun.COM ill_t *ill = ixa->ixa_nce->nce_ill; 130911042SErik.Nordmark@Sun.COM boolean_t inserted = B_FALSE; 131011042SErik.Nordmark@Sun.COM 131111042SErik.Nordmark@Sun.COM idd = &(ill)->ill_dld_capab->idc_direct; 131211042SErik.Nordmark@Sun.COM idl_txl = &ixa->ixa_ipst->ips_idl_tx_list[IDLHASHINDEX(cookie)]; 131312020SPeter.Memishian@Sun.COM mutex_enter(&idl_txl->txl_lock); 131412020SPeter.Memishian@Sun.COM 131512020SPeter.Memishian@Sun.COM /* 131612020SPeter.Memishian@Sun.COM * If `cookie' is zero, ip_xmit() -> canputnext() failed -- i.e., flow 131712020SPeter.Memishian@Sun.COM * control is asserted on an ill that does not support direct calls. 131812020SPeter.Memishian@Sun.COM * Jump to insert. 131912020SPeter.Memishian@Sun.COM */ 132012020SPeter.Memishian@Sun.COM if (cookie == 0) 132112020SPeter.Memishian@Sun.COM goto tryinsert; 132212020SPeter.Memishian@Sun.COM 132311042SErik.Nordmark@Sun.COM ASSERT(ILL_DIRECT_CAPABLE(ill)); 132412020SPeter.Memishian@Sun.COM 132512020SPeter.Memishian@Sun.COM if (idd->idd_tx_fctl_df(idd->idd_tx_fctl_dh, cookie) == 0) { 132612020SPeter.Memishian@Sun.COM DTRACE_PROBE1(ill__tx__not__blocked, uintptr_t, cookie); 132711042SErik.Nordmark@Sun.COM } else if (idl_txl->txl_cookie != NULL && 132811042SErik.Nordmark@Sun.COM idl_txl->txl_cookie != ixa->ixa_cookie) { 132912020SPeter.Memishian@Sun.COM DTRACE_PROBE2(ill__tx__cookie__collision, uintptr_t, cookie, 133011042SErik.Nordmark@Sun.COM uintptr_t, idl_txl->txl_cookie); 133112020SPeter.Memishian@Sun.COM /* TODO: bump kstat for cookie collision */ 133211042SErik.Nordmark@Sun.COM } else { 133312020SPeter.Memishian@Sun.COM /* 133412020SPeter.Memishian@Sun.COM * Check/set conn_blocked under conn_lock. Note that txl_lock 133512020SPeter.Memishian@Sun.COM * will not suffice since two separate UDP threads may be 133612020SPeter.Memishian@Sun.COM * racing to send to different destinations that are 133712020SPeter.Memishian@Sun.COM * associated with different cookies and thus may not be 133812020SPeter.Memishian@Sun.COM * holding the same txl_lock. Further, since a given conn_t 133912020SPeter.Memishian@Sun.COM * can only be on a single drain list, the conn_t will be 134012020SPeter.Memishian@Sun.COM * enqueued on whichever thread wins this race. 134112020SPeter.Memishian@Sun.COM */ 134212020SPeter.Memishian@Sun.COM tryinsert: mutex_enter(&connp->conn_lock); 134312020SPeter.Memishian@Sun.COM if (connp->conn_blocked) { 134412020SPeter.Memishian@Sun.COM DTRACE_PROBE1(ill__tx__conn__already__blocked, 134512020SPeter.Memishian@Sun.COM conn_t *, connp); 134612020SPeter.Memishian@Sun.COM mutex_exit(&connp->conn_lock); 134712020SPeter.Memishian@Sun.COM } else { 134812020SPeter.Memishian@Sun.COM connp->conn_blocked = B_TRUE; 134912020SPeter.Memishian@Sun.COM mutex_exit(&connp->conn_lock); 135012020SPeter.Memishian@Sun.COM idl_txl->txl_cookie = cookie; 135112020SPeter.Memishian@Sun.COM conn_drain_insert(connp, idl_txl); 135212020SPeter.Memishian@Sun.COM if (!IPCL_IS_NONSTR(connp)) 135312020SPeter.Memishian@Sun.COM noenable(connp->conn_wq); 135412020SPeter.Memishian@Sun.COM inserted = B_TRUE; 135512020SPeter.Memishian@Sun.COM } 135611042SErik.Nordmark@Sun.COM } 135711042SErik.Nordmark@Sun.COM mutex_exit(&idl_txl->txl_lock); 135811042SErik.Nordmark@Sun.COM return (inserted); 135911042SErik.Nordmark@Sun.COM } 1360