ip_attr.c revision 3344d7501f5a54d4cb5703f67648ea334c1cec6a
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * See the License for the specific language governing permissions
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * and limitations under the License.
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 * CDDL HEADER END
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Use is subject to license terms.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw/* Copyright (c) 1990 Mentat Inc. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Release a reference on ip_xmit_attr.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * The reference is acquired by conn_get_ixa()
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 * Since this is currently only used for IPsec, we include information for
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * the kernel crypto framework.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwtypedef struct ixamblk_s {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstackid_t ixm_stackid; /* Verify it didn't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_protocol; /* Protocol number for ULP cksum */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw zoneid_t ixm_no_loop_zoneid; /* IXAF_NO_LOOP_ZONEID_SET */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw cred_t *ixm_cred; /* For getpeerucred - refhold if set */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * When the pointers below are set they have a refhold on the struct.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsec_policy_s *ixm_ipsec_policy; /* why are we here? */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsec_action_s *ixm_ipsec_action; /* For reflected packets */
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 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_indstpfx; /* Inner destination prefix */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t ixm_ipsec_proto; /* IP protocol number for d-gram. */
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 * Since this is currently only used for IPsec, we include information for
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * the kernel crypto framework.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwtypedef struct iramblk_s {
d0e518695adc90b82233b99af7dffbb3d3f92c00amw netstackid_t irm_stackid; /* Verify it didn't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw uint8_t irm_protocol; /* Protocol number for ULP cksum */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw zoneid_t irm_zoneid; /* ALL_ZONES unless local delivery */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ipaddr_t irm_mroute_tunnel; /* IRAF_MROUTE_TUNNEL_SET */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw zoneid_t irm_no_loop_zoneid; /* IRAF_NO_LOOP_ZONEID_SET */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw cred_t *irm_cred; /* For getpeerucred - refhold if set */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * When set these correspond to a refhold on the object.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw struct ipsec_action_s *irm_ipsec_action; /* For reflected packets */
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 * Returns NULL on memory allocation failure.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_stackid = ixa->ixa_ipst->ips_netstack->netstack_stackid;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ixm->ixm_ifindex = nce->nce_ill->ill_phyint->phyint_ifindex;
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 * 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.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_from_mblk(mblk_t *ixamp, ip_xmit_attr_t *ixa)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We assume the caller hasn't initialized ixa */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the netstack is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the ill is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We have the ill, hence the netstack can't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
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 /* We have the nce, hence the ill can't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Since this is unusual and we don't know what type of
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * nce it was, we drop the packet.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Free the ixm mblk and any references it holds
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns b_cont.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Consume mp */
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 * Returns NULL on memory allocation failure.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw ASSERT(ira->ira_ill != NULL || ira->ira_ruifindex != 0);
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Internal to IP - preserve ip_stack_t, ill and rill */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw irm->irm_ifindex = ira->ira_ill->ill_phyint->phyint_ifindex;
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Let ip_recv_attr_from_stackid know there isn't one */
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 * The caller needs to release any references on the pointers inside the ire
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * by calling ira_cleanup.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_recv_attr_from_mblk(mblk_t *iramp, ip_recv_attr_t *ira)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We assume the caller hasn't initialized ira */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the netstack is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Verify the ill is still around */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We have the ill, hence the netstack can't go away */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Disappeared on us */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Caller must ill_refele(ira_ill) by using ira_cleanup() */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* The rest of IP assumes that the rings never go away. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Free the irm mblk and any references it holds
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns b_cont.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Consume mp */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Returns true if the mblk contains an ip_recv_attr_t
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * For now we just check db_type.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Need to handle the various forms of tcp_timermp which are tagged
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * with b_wptr and might have a NULL b_datap.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwconn_get_ixa_impl(conn_t *connp, boolean_t replace, int kmflag)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* At least one references for the conn_t */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* No other thread using conn_ixa */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Make sure we drop conn_lock before any refrele */
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 * 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 * 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 * Used only when the option is to have the kernel hang due to not
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * cleaning up ixa references on ills etc.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Replace conn_ixa with the ixa argument.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * The caller must hold conn_lock.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * We return the old ixa; the caller must ixa_refrele that after conn_lock
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * has been dropped.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Return a ip_xmit_attr_t to use with a conn_t that is based on but
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * separate from conn_ixa.
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 /* At least one references for the conn_t */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Make sure conn_ixa doesn't disappear while we copy it */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Clear any pointers that have references and might be changed
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * by ip_set_destination or the ULP
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* Clear all the IPsec pointers and the flag as well. */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * We leave ixa_tsl unchanged, but if it has a refhold we need
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * to get an extra refhold.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * We leave ixa_cred unchanged, but if it has a refhold we need
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * to get an extra refhold.
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 * 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.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_replace_tsl(ip_xmit_attr_t *ixa, ts_label_t *tsl)
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.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_recv_attr_replace_label(ip_recv_attr_t *ira, ts_label_t *tsl)
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * Reset zoneid if we have a shared address. That allows
d0e518695adc90b82233b99af7dffbb3d3f92c00amw * ip_fanout_tx_v4/v6 to determine the zoneid again.
d0e518695adc90b82233b99af7dffbb3d3f92c00amw /* We update ira_cred for RPC */
d0e518695adc90b82233b99af7dffbb3d3f92c00amw newcr = copycred_from_tslabel(ira->ira_cred, ira->ira_tsl, KM_NOSLEEP);
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.
d0e518695adc90b82233b99af7dffbb3d3f92c00amwip_xmit_attr_restore_tsl(ip_xmit_attr_t *ixa, cred_t *cr)
if (refrele_ill)
#ifdef DEBUG
#ifdef DEBUG
if (tryhard) {
if (cookie == 0)
goto tryinsert;
return (inserted);