45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER START
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The contents of this file are subject to the terms of the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Common Development and Distribution License (the "License").
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You may not use this file except in compliance with the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or http://www.opensolaris.org/os/licensing.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * See the License for the specific language governing permissions
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and limitations under the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When distributing Covered Code, include this CDDL HEADER in each
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If applicable, add the following below this CDDL HEADER, with the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * fields enclosed by brackets "[]" replaced with your own identifying
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information: Portions Copyright [yyyy] [name of copyright owner]
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER END
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Use is subject to license terms.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/types.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/stream.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/strsubr.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/stropts.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/sunddi.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/cred.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/debug.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/kmem.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/errno.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/disp.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <netinet/in.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <netinet/in_systm.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <netinet/ip.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <netinet/ip_icmp.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <netinet/tcp.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/common.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ipclassifier.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/mib2.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/nd.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/tcp.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip_rts.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip_ire.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip_if.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/modhash.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/label.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/label_macro.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tnet.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tndb.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/strsun.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* tunable for strict error-reply behavior (TCP RST and ICMP Unreachable) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint tsol_strict_error;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Some notes on the Trusted Solaris IRE gateway security attributes:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When running in Trusted mode, the routing subsystem determines whether or
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * not a packet can be delivered to an off-link host (not directly reachable
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * through an interface) based on the accreditation checks of the packet's
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes against those associated with the next-hop gateway.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The next-hop gateway's security attributes can be derived from two sources
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * (in order of preference): route-related and the host database. A Trusted
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * system must be configured with at least the host database containing an
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * entry for the next-hop gateway, or otherwise no accreditation checks can
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * be performed, which may result in the inability to send packets to any
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * off-link destination host.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The major differences between the two sources are the number and type of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes used for accreditation checks. A host database entry
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * can contain at most one set of security attributes, specific only to the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * next-hop gateway. On contrast, route-related security attributes are made
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * up of a collection of security attributes for the distant networks, and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * are grouped together per next-hop gateway used to reach those networks.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This is the preferred method, and the routing subsystem will fallback to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the host database entry only if there are no route-related attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * associated with the next-hop gateway.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In Trusted mode, all of the IRE entries (except LOCAL/LOOPBACK/BROADCAST/
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * INTERFACE type) are initialized to contain a placeholder to store this
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information. The ire_gw_secattr structure gets allocated, initialized
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and associated with the IRE during the time of the IRE creation. The
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * initialization process also includes resolving the host database entry
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the next-hop gateway for fallback purposes. It does not include any
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * route-related attribute setup, as that process comes separately as part
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the route requests (add/change) made to the routing subsystem.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The underlying logic which involves associating IREs with the gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes are represented by the following data structures:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_gcdb_t, or "gcdb"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - This is a system-wide collection of records containing the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * currently used route-related security attributes, which are fed
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * through the routing socket interface, e.g. "route add/change".
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_gc_t, or "gc"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - This is the gateway credential structure, and it provides for the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * only mechanism to access the contents of gcdb. More than one gc
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * entries may refer to the same gcdb record. gc's in the system are
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * grouped according to the next-hop gateway address.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_gcgrp_t, or "gcgrp"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Group of gateway credentials, and is unique per next-hop gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address. When the group is not empty, i.e. when gcgrp_count is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * greater than zero, it contains one or more gc's, each pointing to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a gcdb record which indicates the gateway security attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * associated with the next-hop gateway.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The fields of the tsol_ire_gw_secattr_t used from within the IRE are:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * igsa_lock
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Lock that protects all fields within tsol_ire_gw_secattr_t.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * igsa_rhc
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Remote host cache database entry of next-hop gateway. This is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * used in the case when there are no route-related attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * configured for the IRE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * igsa_gc
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - A set of route-related attributes that only get set for prefix
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * IREs. If this is non-NULL, the prefix IRE has been associated
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * with a set of gateway security attributes by way of route add/
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * change functionality.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic kmem_cache_t *ire_gw_secattr_cache;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#define GCDB_HASH_SIZE 101
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#define GCGRP_HASH_SIZE 101
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#define GCDB_REFRELE(p) { \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&gcdb_lock); \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT((p)->gcdb_refcnt > 0); \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (--((p)->gcdb_refcnt) == 0) \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb_inactive(p); \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(MUTEX_HELD(&gcdb_lock)); \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&gcdb_lock); \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int gcdb_hash_size = GCDB_HASH_SIZE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int gcgrp_hash_size = GCGRP_HASH_SIZE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic mod_hash_t *gcdb_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic mod_hash_t *gcgrp4_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic mod_hash_t *gcgrp6_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic kmutex_t gcdb_lock;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkmutex_t gcgrp_lock;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic uint_t gcdb_hash_by_secattr(void *, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int gcdb_hash_cmp(mod_hash_key_t, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic tsol_gcdb_t *gcdb_lookup(struct rtsa_s *, boolean_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void gcdb_inactive(tsol_gcdb_t *);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic uint_t gcgrp_hash_by_addr(void *, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int gcgrp_hash_cmp(mod_hash_key_t, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int ire_gw_secattr_constructor(void *, void *, int);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void ire_gw_secattr_destructor(void *, void *);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnet_init(void)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_gw_secattr_cache = kmem_cache_create("ire_gw_secattr_cache",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sizeof (tsol_ire_gw_secattr_t), 64, ire_gw_secattr_constructor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_gw_secattr_destructor, NULL, NULL, NULL, 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb_hash = mod_hash_create_extended("gcdb_hash",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb_hash_by_secattr, NULL, gcdb_hash_cmp, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp4_hash = mod_hash_create_extended("gcgrp4_hash",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp6_hash = mod_hash_create_extended("gcgrp6_hash",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&gcdb_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&gcgrp_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnet_fini(void)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_cache_destroy(ire_gw_secattr_cache);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_destroy_hash(gcdb_hash);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_destroy_hash(gcgrp4_hash);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_destroy_hash(gcgrp6_hash);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_destroy(&gcdb_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_destroy(&gcgrp_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkire_gw_secattr_constructor(void *buf, void *cdrarg, int kmflags)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ire_gw_secattr_t *attrp = buf;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&attrp->igsa_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_rhc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_gc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkire_gw_secattr_destructor(void *buf, void *cdrarg)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ire_gw_secattr_t *attrp = (tsol_ire_gw_secattr_t *)buf;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_destroy(&attrp->igsa_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_ire_gw_secattr_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkire_gw_secattr_alloc(int kmflags)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (kmem_cache_alloc(ire_gw_secattr_cache, kmflags));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkire_gw_secattr_free(tsol_ire_gw_secattr_t *attrp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(MUTEX_NOT_HELD(&attrp->igsa_lock));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (attrp->igsa_rhc != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(attrp->igsa_rhc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_rhc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (attrp->igsa_gc != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk GC_REFRELE(attrp->igsa_gc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_gc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(attrp->igsa_rhc == NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(attrp->igsa_gc == NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_cache_free(ire_gw_secattr_cache, attrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic uint_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcdb_hash_by_secattr(void *hash_data, mod_hash_key_t key)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const struct rtsa_s *rp = (struct rtsa_s *)key;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const uint32_t *up, *ue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int i;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(rp != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* See comments in hash_bylabel in zone.c for details */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hash = rp->rtsa_doi + (rp->rtsa_doi << 1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk up = (const uint32_t *)&rp->rtsa_slrange;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ue = up + sizeof (rp->rtsa_slrange) / sizeof (*up);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk i = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (up < ue) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* using 2^n + 1, 1 <= n <= 16 as source of many primes */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hash += *up + (*up << ((i % 16) + 1));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk up++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk i++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (hash);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcdb_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk struct rtsa_s *rp1 = (struct rtsa_s *)key1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk struct rtsa_s *rp2 = (struct rtsa_s *)key2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(rp1 != NULL && rp2 != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (blequal(&rp1->rtsa_slrange.lower_bound,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &rp2->rtsa_slrange.lower_bound) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk blequal(&rp1->rtsa_slrange.upper_bound,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &rp2->rtsa_slrange.upper_bound) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rp1->rtsa_doi == rp2->rtsa_doi)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* No match; not found */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic uint_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcgrp_hash_by_addr(void *hash_data, mod_hash_key_t key)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_addr_t *ga = (tsol_gcgrp_addr_t *)key;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t idx = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t *ap;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ap = (uint32_t *)&ga->ga_addr.s6_addr32[0];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk idx ^= *ap++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk idx ^= *ap++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk idx ^= *ap++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk idx ^= *ap;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (idx);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcgrp_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_addr_t *ga1 = (tsol_gcgrp_addr_t *)key1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_addr_t *ga2 = (tsol_gcgrp_addr_t *)key2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga1 != NULL && ga2 != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Address family must match */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ga1->ga_af != ga2->ga_af)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ga1->ga_addr.s6_addr32[0] == ga2->ga_addr.s6_addr32[0] &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ga1->ga_addr.s6_addr32[1] == ga2->ga_addr.s6_addr32[1] &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ga1->ga_addr.s6_addr32[2] == ga2->ga_addr.s6_addr32[2] &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ga1->ga_addr.s6_addr32[3] == ga2->ga_addr.s6_addr32[3])
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* No match; not found */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#define RTSAFLAGS "\20\11cipso\3doi\2max_sl\1min_sl"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkrtsa_validate(const struct rtsa_s *rp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t mask = rp->rtsa_mask;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* RTSA_CIPSO must be set, and DOI must not be zero */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((mask & RTSA_CIPSO) == 0 || rp->rtsa_doi == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "rtsa(1) lacks flag or has 0 doi.",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rtsa_s *, rp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * SL range must be specified, and it must have its
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * upper bound dominating its lower bound.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((mask & RTSA_SLRANGE) != RTSA_SLRANGE ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !bldominates(&rp->rtsa_slrange.upper_bound,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &rp->rtsa_slrange.lower_bound)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "rtsa(1) min_sl and max_sl not set or max_sl is "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "not dominating.", rtsa_s *, rp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * A brief explanation of the reference counting scheme:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Apart from dynamic references due to to reference holds done
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * actively by threads, we have the following references:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gcdb_refcnt:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Every tsol_gc_t pointing to a tsol_gcdb_t contributes a reference
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to the gcdb_refcnt.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gc_refcnt:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - A prefix IRE that points to an igsa_gc contributes a reference
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to the gc_refcnt.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gcgrp_refcnt:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a reference to the gcgrp_refcnt.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic tsol_gcdb_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcdb_lookup(struct rtsa_s *rp, boolean_t alloc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcdb_t *gcdb = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rtsa_validate(rp) != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&gcdb_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Find a copy in the cache; otherwise, create one and cache it */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mod_hash_find(gcdb_hash, (mod_hash_key_t)rp,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_val_t *)&gcdb) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb->gcdb_refcnt++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcdb->gcdb_refcnt != 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__lookup, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "gcdb(1) is in gcdb_hash(global)", tsol_gcdb_t *, gcdb);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (alloc) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb = kmem_zalloc(sizeof (*gcdb), KM_NOSLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gcdb != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb->gcdb_refcnt = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb->gcdb_mask = rp->rtsa_mask;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb->gcdb_doi = rp->rtsa_doi;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb->gcdb_slrange = rp->rtsa_slrange;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mod_hash_insert(gcdb_hash,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_key_t)&gcdb->gcdb_attr,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_val_t)gcdb) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&gcdb_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(gcdb, sizeof (*gcdb));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__insert, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "gcdb(1) inserted in gcdb_hash(global)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcdb_t *, gcdb);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&gcdb_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (gcdb);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcdb_inactive(tsol_gcdb_t *gcdb)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(MUTEX_HELD(&gcdb_lock));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcdb != NULL && gcdb->gcdb_refcnt == 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) mod_hash_remove(gcdb_hash, (mod_hash_key_t)&gcdb->gcdb_attr,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_val_t *)&gcdb);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__remove, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "gcdb(1) removed from gcdb_hash(global)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcdb_t *, gcdb);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(gcdb, sizeof (*gcdb));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_gc_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgc_create(struct rtsa_s *rp, tsol_gcgrp_t *gcgrp, boolean_t *gcgrp_xtrarefp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gc_t *gc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcdb_t *gcdb;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *gcgrp_xtrarefp = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&gcgrp->gcgrp_rwlock, RW_WRITER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((gcdb = gcdb_lookup(rp, B_TRUE)) == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&gcgrp->gcgrp_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (gc = gcgrp->gcgrp_head; gc != NULL; gc = gc->gc_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gc->gc_db == gcdb) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gc->gc_grp == gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_refcnt++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gc->gc_refcnt != 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk GCDB_REFRELE(gcdb);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gc__create,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "found gc(1) in gcgrp(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&gcgrp->gcgrp_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (gc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc = kmem_zalloc(sizeof (*gc), KM_NOSLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gc != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gcgrp->gcgrp_head == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_head = gcgrp->gcgrp_tail = gc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_tail->gc_next = gc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_prev = gcgrp->gcgrp_tail;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_tail = gc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_count++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp->gcgrp_count != 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* caller has incremented gcgrp reference for us */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_grp = gcgrp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_db = gcdb;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_refcnt = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gc__create, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "added gc(1) to gcgrp(2)", tsol_gc_t *, gc,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_t *, gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *gcgrp_xtrarefp = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&gcgrp->gcgrp_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (gc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgc_inactive(tsol_gc_t *gc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_t *gcgrp = gc->gc_grp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(RW_WRITE_HELD(&gcgrp->gcgrp_rwlock));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gc->gc_refcnt == 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gc->gc_prev != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_prev->gc_next = gc->gc_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_head = gc->gc_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gc->gc_next != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_next->gc_prev = gc->gc_prev;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_tail = gc->gc_prev;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp->gcgrp_count > 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_count--;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* drop lock before it's destroyed */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&gcgrp->gcgrp_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gc__remove, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "removed inactive gc(1) from gcgrp(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk GCGRP_REFRELE(gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_grp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gc->gc_prev = gc->gc_next = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gc->gc_db != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk GCDB_REFRELE(gc->gc_db);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(gc, sizeof (*gc));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_gcgrp_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcgrp_lookup(tsol_gcgrp_addr_t *ga, boolean_t alloc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_t *gcgrp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_t *hashp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&gcgrp_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mod_hash_find(hashp, (mod_hash_key_t)ga,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_val_t *)&gcgrp) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_refcnt++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp->gcgrp_refcnt != 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__lookup, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "found gcgrp(1) in hash(2)", tsol_gcgrp_t *, gcgrp,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_t *, hashp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (alloc) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp = kmem_zalloc(sizeof (*gcgrp), KM_NOSLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gcgrp != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp->gcgrp_refcnt = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_init(&gcgrp->gcgrp_rwlock, NULL, RW_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(ga, &gcgrp->gcgrp_addr, sizeof (*ga));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mod_hash_insert(hashp,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_key_t)&gcgrp->gcgrp_addr,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_val_t)gcgrp) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&gcgrp_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(gcgrp, sizeof (*gcgrp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__insert,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "inserted gcgrp(1) in hash(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&gcgrp_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcgrp_inactive(tsol_gcgrp_t *gcgrp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_addr_t *ga;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_t *hashp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(MUTEX_HELD(&gcgrp_lock));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp != NULL && gcgrp->gcgrp_refcnt == 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp->gcgrp_head == NULL && gcgrp->gcgrp_count == 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ga = &gcgrp->gcgrp_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) mod_hash_remove(hashp, (mod_hash_key_t)ga,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_val_t *)&gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_destroy(&gcgrp->gcgrp_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__remove, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "removed inactive gcgrp(1) from hash(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(gcgrp, sizeof (*gcgrp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld/*
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * Assign a sensitivity label to inbound traffic which arrived without
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * an explicit on-the-wire label.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld *
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * In the case of CIPSO-type hosts, we assume packets arriving without
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * a label are at the most sensitive label known for the host, most
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * likely involving out-of-band key management traffic (such as IKE,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * etc.,)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld */
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeldstatic boolean_t
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeldtsol_find_unlabeled_label(tsol_tpc_t *rhtp, bslabel_t *sl, uint32_t *doi)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld{
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld *doi = rhtp->tpc_tp.tp_doi;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld switch (rhtp->tpc_tp.host_type) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld case UNLABELED:
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld *sl = rhtp->tpc_tp.tp_def_label;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld break;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld case SUN_CIPSO:
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld *sl = rhtp->tpc_tp.tp_sl_range_cipso.upper_bound;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld break;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld default:
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (B_FALSE);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld setbltype(sl, SUN_SL_ID);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (B_TRUE);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld}
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Converts CIPSO option to sensitivity label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Validity checks based on restrictions defined in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) (draft-ietf-cipso-ipsecurity)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic boolean_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkcipso_to_sl(const uchar_t *option, bslabel_t *sl)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const struct cipso_option *co = (const struct cipso_option *)option;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const struct cipso_tag_type_1 *tt1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1 = (struct cipso_tag_type_1 *)&co->cipso_tag_type[0];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tt1->tag_type != 1 ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_length < TSOL_TT1_MIN_LENGTH ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_length > TSOL_TT1_MAX_LENGTH ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_length + TSOL_CIPSO_TAG_OFFSET > co->cipso_length)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bsllow(sl); /* assumed: sets compartments to all zeroes */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk LCLASS_SET((_bslabel_impl_t *)sl, tt1->tag_sl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(tt1->tag_cat, &((_bslabel_impl_t *)sl)->compartments,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_length - TSOL_TT1_MIN_LENGTH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If present, parse the CIPSO label in the incoming packet and
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * construct a ts_label_t that reflects the CIPSO label and put it in
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the ip_recv_attr_t. Later as the packet flows up through the stack any
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * code that needs to examine the packet label can inspect the label
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * from the ira_tsl. This function is
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * called right in ip_input for all packets, i.e. locally destined and
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to be forwarded packets. The forwarding path needs to examine the label
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to determine how to forward the packet.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * This routine pulls all message text up into the first mblk.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * For IPv4, only the first 20 bytes of the IP header are guaranteed
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * to exist. For IPv6, only the IPv6 header is guaranteed to exist.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkboolean_t
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_get_pkt_label(mblk_t *mp, int version, ip_recv_attr_t *ira)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld tsol_tpc_t *src_rhtp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *opt_ptr = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const ipha_t *ipha;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bslabel_t sl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t doi;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ip_label_t label_type;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld uint32_t label_flags = 0; /* flags to set in label */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const cipso_option_t *co;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const void *src;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const ip6_t *ip6h;
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark cred_t *credp;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld int proto;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(DB_TYPE(mp) == M_DATA);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (mp->b_cont != NULL && !pullupmsg(mp, -1))
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (B_FALSE);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (version == IPV4_VERSION) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ASSERT(MBLKL(mp) >= IP_SIMPLE_HDR_LENGTH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha = (const ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk src = &ipha->ipha_src;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v4(mp, &label_type, &opt_ptr))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ASSERT(MBLKL(mp) >= IPV6_HDR_LEN);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6h = (const ip6_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk src = &ip6h->ip6_src;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v6(mp, &label_type, &opt_ptr))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (label_type) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case OPT_CIPSO:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Convert the CIPSO label to the internal format
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and attach it to the dblk cred.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Validity checks based on restrictions defined in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * (draft-ietf-cipso-ipsecurity)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (version == IPV6_VERSION && ip6opt_ls == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk co = (const struct cipso_option *)opt_ptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((co->cipso_length <
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TSOL_CIPSO_TAG_OFFSET + TSOL_TT1_MIN_LENGTH) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (co->cipso_length > IP_MAX_OPT_LENGTH))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(co->cipso_doi, &doi, sizeof (doi));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk doi = ntohl(doi);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!cipso_to_sl(opt_ptr, &sl))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk setbltype(&sl, SUN_SL_ID);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld /*
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * If the source was unlabeled, then flag as such,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * (since CIPSO routers may add headers)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld */
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (B_FALSE);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (src_rhtp->tpc_tp.host_type == UNLABELED)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld label_flags = TSLF_UNLABELED;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld TPC_RELE(src_rhtp);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case OPT_NONE:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * Handle special cases that may not be labeled, even
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * though the sending system may otherwise be configured as
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * labeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - IGMP
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - IPv4 ICMP Router Discovery
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - IPv6 Neighbor Discovery
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * - IPsec ESP
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (version == IPV4_VERSION) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld proto = ipha->ipha_protocol;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (proto == IPPROTO_IGMP)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (proto == IPPROTO_ICMP) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const struct icmp *icmp = (const struct icmp *)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mp->b_rptr + IPH_HDR_LENGTH(ipha));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if ((uchar_t *)icmp + ICMP_MINLEN > mp->b_wptr)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (icmp->icmp_type == ICMP_ROUTERADVERT ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk icmp->icmp_type == ICMP_ROUTERSOLICIT)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld proto = ip6h->ip6_nxt;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (proto == IPPROTO_ICMPV6) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const icmp6_t *icmp6 = (const icmp6_t *)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mp->b_rptr + IPV6_HDR_LEN);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((uchar_t *)icmp6 + ICMP6_MINLEN >
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem mp->b_wptr)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (icmp6->icmp6_type >= MLD_LISTENER_QUERY &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk icmp6->icmp6_type <= ICMP6_MAX_INFO_TYPE)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Look up the tnrhtp database and get the implicit label
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * that is associated with the sending host and attach
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * it to the packet.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld /*
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * If peer is label-aware, mark as "implicit" rather than
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * "unlabeled" to cause appropriate mac-exempt processing
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * to happen.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld */
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (src_rhtp->tpc_tp.host_type == SUN_CIPSO)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld label_flags = TSLF_IMPLICIT_IN;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld else if (src_rhtp->tpc_tp.host_type == UNLABELED)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld label_flags = TSLF_UNLABELED;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld else {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE2(tx__get__pkt__label, char *,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "template(1) has unknown hosttype",
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld tsol_tpc_t *, src_rhtp);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (!tsol_find_unlabeled_label(src_rhtp, &sl, &doi)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(src_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(src_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ira->ira_cred == NULL) {
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark credp = newcred_from_bslabel(&sl, doi, KM_NOSLEEP);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (credp == NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
0e0e37a8f0c38eb919c913bbb67030114a6b74a9Erik Nordmark credp = copycred_from_bslabel(ira->ira_cred, &sl, doi,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk KM_NOSLEEP);
0e0e37a8f0c38eb919c913bbb67030114a6b74a9Erik Nordmark if (credp == NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (B_FALSE);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ira->ira_free_flags & IRA_FREE_CRED) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark crfree(ira->ira_cred);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_free_flags &= ~IRA_FREE_CRED;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_cred = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Put the label in ira_tsl for convinience, while keeping
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the cred in ira_cred for getpeerucred which is used to get
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * labels with TX.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note: no explicit refcnt/free_flag for ira_tsl. The free_flag
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * for IRA_FREE_CRED is sufficient for both.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_tsl = crgetlabel(credp);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_cred = credp;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_free_flags |= IRA_FREE_CRED;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ira->ira_tsl->tsl_flags |= label_flags;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine determines whether the given packet should be accepted locally.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * It does a range/set check on the packet's label by looking up the given
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address in the remote host database.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkboolean_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_recv_attr_t *ira, const conn_t *connp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const cred_t *credp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *plabel, *conn_plabel;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const bslabel_t *label, *conn_label;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark boolean_t shared_addr = (ira->ira_flags & IRAF_TX_SHARED_ADDR);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_get_pkt_label intentionally avoids the labeling process for:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IPv6 router and neighbor discovery as well as redirects.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - MLD packets. (Anything between ICMPv6 code 130 and 138.)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IGMP packets.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IPv4 router discovery.
0e0e37a8f0c38eb919c913bbb67030114a6b74a9Erik Nordmark * In those cases ira_cred is NULL.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark credp = ira->ira_cred;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (credp == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If this packet is from the inside (not a remote host) and has the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * same zoneid as the selected destination, then no checks are
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * necessary. Membership in the zone is enough proof. This is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * intended to be a hot path through this function.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note: Using crgetzone here is ok since the peer is local.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!crisremote(credp) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk crgetzone(credp) == crgetzone(connp->conn_cred))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark plabel = ira->ira_tsl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk conn_plabel = crgetlabel(connp->conn_cred);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(plabel != NULL && conn_plabel != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label = label2bslabel(plabel);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark conn_label = label2bslabel(conn_plabel);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld /*
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * Implicitly labeled packets from label-aware sources
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * go only to privileged receivers
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld */
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if ((plabel->tsl_flags & TSLF_IMPLICIT_IN) &&
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld (connp->conn_mac_mode != CONN_MAC_IMPLICIT)) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac_impl,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld char *,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "implicitly labeled packet mp(1) for conn(2) "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "which isn't in implicit mac mode",
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld mblk_t *, mp, conn_t *, connp);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (B_FALSE);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * MLPs are always validated using the range and set of the local
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address, even when the remote host is unlabeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (connp->conn_mlp_type == mlptBoth ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED: no consequent */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk connp->conn_mlp_type == (shared_addr ? mlptShared : mlptPrivate)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If this is a packet from an unlabeled sender, then we must apply
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * different rules. If the label is equal to the zone's label, then
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * it's allowed. If it's not equal, but the zone is either the global
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * zone or the label is dominated by the zone's label, then allow it
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * as long as it's in the range configured for the destination.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (plabel->tsl_flags & TSLF_UNLABELED) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (plabel->tsl_doi == conn_plabel->tsl_doi &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk blequal(label, conn_label))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if ((connp->conn_mac_mode == CONN_MAC_DEFAULT) ||
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (!connp->conn_zone_is_global &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (plabel->tsl_doi != conn_plabel->tsl_doi ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !bldominates(conn_label, label)))) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tx__ip__log__drop__receivelocal__mac_unl,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "unlabeled packet mp(1) fails mac for conn(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, conn_t *, connp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * If this is a packet from a labeled sender, verify the
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * label on the packet matches the connection label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
e071b5fba24bf7b3147969da51eb5d194a13dcaakp } else {
e071b5fba24bf7b3147969da51eb5d194a13dcaakp if (plabel->tsl_doi != conn_plabel->tsl_doi ||
e071b5fba24bf7b3147969da51eb5d194a13dcaakp !blequal(label, conn_label)) {
e071b5fba24bf7b3147969da51eb5d194a13dcaakp DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac__slp,
e071b5fba24bf7b3147969da51eb5d194a13dcaakp char *,
e071b5fba24bf7b3147969da51eb5d194a13dcaakp "packet mp(1) failed label match to SLP conn(2)",
e071b5fba24bf7b3147969da51eb5d194a13dcaakp mblk_t *, mp, conn_t *, connp);
e071b5fba24bf7b3147969da51eb5d194a13dcaakp return (B_FALSE);
e071b5fba24bf7b3147969da51eb5d194a13dcaakp }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * No further checks will be needed if this is a zone-
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * specific address because (1) The process for bringing up
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * the interface ensures the zone's label is within the zone-
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * specific address's valid label range; (2) For cases where
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * the conn is bound to the unspecified addresses, ip fanout
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * logic ensures conn's zoneid equals the dest addr's zoneid;
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * (3) Mac-exempt and mlp logic above already handle all
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * cases where the zone label may not be the same as the
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * conn label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
e071b5fba24bf7b3147969da51eb5d194a13dcaakp if (!shared_addr)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tp = find_tpc(addr, version, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__no__tnr,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "dropping mp(1), host(2) lacks entry",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, void *, addr);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The local host address should not be unlabeled at this point. The
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * only way this can happen is that the destination isn't unicast. We
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * assume that the packet should not have had a label, and thus should
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * have been handled by the TSLF_UNLABELED logic above.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp->tpc_tp.host_type == UNLABELED) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__flag, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) unlabeled source, but tp is not unlabeled.",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, tsol_tpc_t *, tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (tp->tpc_tp.host_type != SUN_CIPSO) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__tptype, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "delivering mp(1), found unrecognized tpc(2) type.",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, tsol_tpc_t *, tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) could not be delievered to tp(2), doi mismatch",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, tsol_tpc_t *, tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (!_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blinlset(label, tp->tpc_tp.tp_sl_set_cipso)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) could not be delievered to tp(2), bad mac",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, tsol_tpc_t *, tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkboolean_t
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_can_accept_raw(mblk_t *mp, ip_recv_attr_t *ira, boolean_t check_host)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *plabel = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *src_rhtp, *dst_rhtp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark plabel = ira->ira_tsl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We are bootstrapping or the internal template was never deleted */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (plabel == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha_t *ipha = (ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk src_rhtp = find_tpc(&ipha->ipha_src, IPV4_VERSION,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (src_rhtp == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk dst_rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6_t *ip6h = (ip6_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk src_rhtp = find_tpc(&ip6h->ip6_src, IPV6_VERSION,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (src_rhtp == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk dst_rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (dst_rhtp == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(src_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (label2doi(plabel) != src_rhtp->tpc_tp.tp_doi) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Check that the packet's label is in the correct range for labeled
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * sender, or is equal to the default label for unlabeled sender.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if ((src_rhtp->tpc_tp.host_type != UNLABELED &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !_blinrange(label2bslabel(plabel),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &src_rhtp->tpc_tp.tp_sl_range_cipso) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blinlset(label2bslabel(plabel),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk src_rhtp->tpc_tp.tp_sl_set_cipso)) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (src_rhtp->tpc_tp.host_type == UNLABELED &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blequal(&plabel->tsl_label, &src_rhtp->tpc_tp.tp_def_label))) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (check_host) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Until we have SL range in the Zone structure, pass it
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * when our own address lookup returned an internal entry.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else switch (dst_rhtp->tpc_tp.host_type) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case UNLABELED:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case SUN_CIPSO:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = _blinrange(label2bslabel(plabel),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &dst_rhtp->tpc_tp.tp_sl_range_cipso) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk blinlset(label2bslabel(plabel),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk dst_rhtp->tpc_tp.tp_sl_set_cipso);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(src_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(dst_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine determines whether a response to a failed packet delivery or
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * connection should be sent back. By default, the policy is to allow such
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * messages to be sent at all times, as these messages reveal little useful
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information and are healthy parts of TCP/IP networking.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If tsol_strict_error is set, then we do strict tests: if the packet label is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * within the label range/set of this host/zone, return B_TRUE; otherwise
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * return B_FALSE, which causes the packet to be dropped silently.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note that tsol_get_pkt_label will cause the packet to drop if the sender is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * marked as labeled in the remote host database, but the packet lacks a label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This means that we don't need to do a lookup on the source; the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * TSLF_UNLABELED flag is sufficient.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkboolean_t
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_can_reply_error(const mblk_t *mp, ip_recv_attr_t *ira)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *plabel = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *rhtp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const ipha_t *ipha;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const ip6_t *ip6h;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bslabel_t *pktbs;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Caller must pull up at least the IP header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(MBLKL(mp) >= (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ?
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sizeof (*ipha) : sizeof (*ip6h)));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!tsol_strict_error)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark plabel = ira->ira_tsl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We are bootstrapping or the internal template was never deleted */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (plabel == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (plabel->tsl_flags & TSLF_IMPLICIT_IN) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(tx__ip__log__drop__replyerror__unresolved__label,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld char *,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "cannot send error report for packet mp(1) with "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "unresolved security label sl(2)",
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld mblk_t *, mp, ts_label_t *, plabel);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (B_FALSE);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha = (const ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6h = (const ip6_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rhtp == NULL || label2doi(plabel) != rhtp->tpc_tp.tp_doi) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we're in the midst of forwarding, then the destination
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address might not be labeled. In that case, allow unlabeled
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * packets through only if the default label is the same, and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * labeled ones if they dominate.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pktbs = label2bslabel(plabel);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (rhtp->tpc_tp.host_type) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case UNLABELED:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (plabel->tsl_flags & TSLF_UNLABELED) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = blequal(pktbs,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &rhtp->tpc_tp.tp_def_label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = bldominates(pktbs,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &rhtp->tpc_tp.tp_def_label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case SUN_CIPSO:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = _blinrange(pktbs,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &rhtp->tpc_tp.tp_sl_range_cipso) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk blinlset(pktbs, rhtp->tpc_tp.tp_sl_set_cipso);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rhtp != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Finds the zone associated with the receive attributes. Returns GLOBAL_ZONEID
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * if the zone cannot be located.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This is used by the classifier when the packet matches an ALL_ZONES IRE, and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * there's no MLP defined.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh *
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note that we assume that this is only invoked in the ALL_ZONES case.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Handling other cases would require handling exclusive IP zones where either
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * this routine or the callers would have to map from
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * the zoneid (zone->zone_id) to what IP uses in conn_zoneid etc.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkzoneid_t
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_attr_to_zoneid(const ip_recv_attr_t *ira)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((label = ira->ira_tsl) != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark zone = zone_find_by_label(label);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (zone != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark zoneid_t zoneid = zone->zone_id;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark zone_rele(zone);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (zoneid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (GLOBAL_ZONEID);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int error = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ire_gw_secattr_t *attrp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *gw_rhc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_t *gcgrp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gc_t *gc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk in_addr_t ga_addr4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk void *paddr = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Not in Trusted mode or IRE is local/loopback/broadcast/interface */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!is_system_labeled() ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST |
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IRE_IF_ALL | IRE_MULTICAST | IRE_NOROUTE)))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto done;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we don't have a label to compare with, or the IRE does not
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * contain any gateway security attributes, there's not much that
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * we can do. We let the former case pass, and the latter fail,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * since the IRE doesn't qualify for a match due to the lack of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsl == NULL || ire->ire_gw_secattr == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsl != NULL) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld tx__ip__log__drop__irematch__nogwsec, char *,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "ire(1) lacks ire_gw_secattr when matching "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "label(2)", ire_t *, ire, ts_label_t *, tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = EACCES;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto done;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp = ire->ire_gw_secattr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The possible lock order scenarios related to the tsol gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * attribute locks are documented at the beginning of ip.c in the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * lock order scenario section.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&attrp->igsa_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We seek the group
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * structure which contains all security credentials of the gateway.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * An offline IRE is associated with at most one gateway credential.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((gc = attrp->igsa_gc) != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp = gc->gc_grp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk GCGRP_REFHOLD(gcgrp);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((gw_rhc = attrp->igsa_rhc) != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If our cached entry has grown stale, then discard it so we
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * can get a new one.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gw_rhc->rhc_invalid || gw_rhc->rhc_tpc->tpc_invalid) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(gw_rhc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_rhc = gw_rhc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_HOLD(gw_rhc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Last attempt at loading the template had failed; try again */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gw_rhc == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gcgrp != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ire->ire_ipversion == IPV4_VERSION) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga->ga_af == AF_INET);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk paddr = &ga_addr4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga->ga_af == AF_INET6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk paddr = &ga->ga_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else if (ire->ire_type & IRE_OFFLINK) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ire->ire_ipversion == IPV6_VERSION)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark paddr = &ire->ire_gateway_addr_v6;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else if (ire->ire_ipversion == IPV4_VERSION)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark paddr = &ire->ire_gateway_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We've found a gateway address to do the template lookup */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (paddr != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gw_rhc == NULL);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp gw_rhc = find_rhc(paddr, ire->ire_ipversion, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gw_rhc != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note that if the lookup above returned an
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * internal template, we'll use it for the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * time being, and do another lookup next
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * time around.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Another thread has loaded the template? */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (attrp->igsa_rhc != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(gw_rhc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* reload, it could be different */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gw_rhc = attrp->igsa_rhc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_rhc = gw_rhc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Hold an extra reference just like we did
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * above prior to dropping the igsa_lock.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_HOLD(gw_rhc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&attrp->igsa_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Gateway template not found */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gw_rhc == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If destination address is directly reachable through an
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * interface rather than through a learned route, pass it.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (paddr != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tx__ip__log__drop__irematch__nogwtmpl, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "ire(1), label(2) off-link with no gw_rhc",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_t *, ire, ts_label_t *, tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = EINVAL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto done;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gc != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcdb_t *gcdb;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In the case of IRE_CACHE we've got one or more gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security credentials to compare against the passed in label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Perform label range comparison against each security
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * credential of the gateway. In the case of a prefix ire
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * we need to match against the security attributes of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * just the route itself, so the loop is executed only once.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp != NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark gcdb = gc->gc_db;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (tsl->tsl_doi != gcdb->gcdb_doi ||
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark !_blinrange(&tsl->tsl_label, &gcdb->gcdb_slrange)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tx__ip__log__drop__irematch__nogcmatched,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "ire(1), tsl(2): all gc failed match",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_t *, ire, ts_label_t *, tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = EACCES;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We didn't find any gateway credentials in the IRE
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * attributes; fall back to the gateway's template for
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * label range checks, if we are required to do so.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gw_rhc != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (gw_rhc->rhc_tpc->tpc_tp.host_type) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case SUN_CIPSO:
222c5bce8762079550e5ccd485a12de1fff5a82ekp if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (!_blinrange(&tsl->tsl_label,
222c5bce8762079550e5ccd485a12de1fff5a82ekp &gw_rhc->rhc_tpc->tpc_tp.tp_sl_range_cipso) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blinlset(&tsl->tsl_label,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gw_rhc->rhc_tpc->tpc_tp.tp_sl_set_cipso))) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = EACCES;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE4(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tx__ip__log__drop__irematch__deftmpl,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "ire(1), tsl(2), gw_rhc(3) "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "failed match (cipso gw)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_t *, ire, ts_label_t *, tsl,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *, gw_rhc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case UNLABELED:
222c5bce8762079550e5ccd485a12de1fff5a82ekp if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (!_blinrange(&tsl->tsl_label,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_range) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blinlset(&tsl->tsl_label,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_set))) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = EACCES;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE4(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tx__ip__log__drop__irematch__deftmpl,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "ire(1), tsl(2), gw_rhc(3) "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "failed match (unlabeled gw)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_t *, ire, ts_label_t *, tsl,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *, gw_rhc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkdone:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gcgrp != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&gcgrp->gcgrp_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk GCGRP_REFRELE(gcgrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gw_rhc != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(gw_rhc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (error);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Performs label accreditation checks for packet forwarding.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Add or remove a CIPSO option as needed.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns a pointer to the modified mblk if allowed for forwarding,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or NULL if the packet must be dropped.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkmblk_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_ip_forward(ire_t *ire, mblk_t *mp, const ip_recv_attr_t *ira)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ire_gw_secattr_t *attrp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha_t *ipha;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6_t *ip6h;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const void *pdst;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const void *psrc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t off_link;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *dst_rhtp, *gw_rhtp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ip_label_t label_type;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *opt_ptr = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *tsl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint8_t proto;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int af, adjust;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint16_t iplen;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta boolean_t need_tpc_rele = B_FALSE;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta ipaddr_t *gw;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ip_stack_t *ipst = ire->ire_ipst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark int err;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ts_label_t *effective_tsl = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ire != NULL && mp != NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that the ire is the first one found, i.e., an IRE_OFFLINK if
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the destination is offlink.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk af = (ire->ire_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ire->ire_ipversion == IPV4_VERSION);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha = (ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk psrc = &ipha->ipha_src;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pdst = &ipha->ipha_dst;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk proto = ipha->ipha_protocol;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v4(mp, &label_type, &opt_ptr))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ire->ire_ipversion == IPV6_VERSION);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6h = (ip6_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk psrc = &ip6h->ip6_src;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pdst = &ip6h->ip6_dst;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk proto = ip6h->ip6_nxt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk proto != IPPROTO_ICMPV6) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint8_t *nexthdrp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint16_t hdr_len;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_len,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &nexthdrp)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* malformed packet; drop it */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk proto = *nexthdrp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v6(mp, &label_type, &opt_ptr))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * off_link is TRUE if destination not directly reachable.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark off_link = (ire->ire_type & IRE_OFFLINK);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((tsl = ira->ira_tsl) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (mp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (tsl->tsl_flags & TSLF_IMPLICIT_IN) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(tx__ip__log__drop__forward__unresolved__label,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld char *,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "cannot forward packet mp(1) with unresolved "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "security label sl(2)",
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld mblk_t *, mp, ts_label_t *, tsl);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (NULL);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(psrc != NULL && pdst != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk dst_rhtp = find_tpc(pdst, ire->ire_ipversion, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (dst_rhtp == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Without a template we do not know if forwarding
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * violates MAC
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__forward__nodst, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) dropped, no template for destination ip4|6(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, void *, pdst);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Gateway template must have existed for off-link destinations,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * since tsol_ire_match_gwattr has ensured such condition.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
c793af95640863cd29868fc7c419c5d2496b207bsangeeta if (ire->ire_ipversion == IPV4_VERSION && off_link) {
c793af95640863cd29868fc7c419c5d2496b207bsangeeta /*
c793af95640863cd29868fc7c419c5d2496b207bsangeeta * Surya note: first check if we can get the gw_rhtp from
c793af95640863cd29868fc7c419c5d2496b207bsangeeta * the ire_gw_secattr->igsa_rhc; if this is null, then
c793af95640863cd29868fc7c419c5d2496b207bsangeeta * do a lookup based on the ire_addr (address of gw)
c793af95640863cd29868fc7c419c5d2496b207bsangeeta */
c793af95640863cd29868fc7c419c5d2496b207bsangeeta if (ire->ire_gw_secattr != NULL &&
c793af95640863cd29868fc7c419c5d2496b207bsangeeta ire->ire_gw_secattr->igsa_rhc != NULL) {
c793af95640863cd29868fc7c419c5d2496b207bsangeeta attrp = ire->ire_gw_secattr;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta gw_rhtp = attrp->igsa_rhc->rhc_tpc;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark gw = &ire->ire_gateway_addr;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta gw_rhtp = find_tpc(gw, ire->ire_ipversion, B_FALSE);
c793af95640863cd29868fc7c419c5d2496b207bsangeeta need_tpc_rele = B_TRUE;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta }
c793af95640863cd29868fc7c419c5d2496b207bsangeeta if (gw_rhtp == NULL) {
c793af95640863cd29868fc7c419c5d2496b207bsangeeta DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *,
c793af95640863cd29868fc7c419c5d2496b207bsangeeta "mp(1) dropped, no gateway in ire attributes(2)",
c793af95640863cd29868fc7c419c5d2496b207bsangeeta mblk_t *, mp, tsol_ire_gw_secattr_t *, attrp);
c793af95640863cd29868fc7c419c5d2496b207bsangeeta mp = NULL;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta goto keep_label;
c793af95640863cd29868fc7c419c5d2496b207bsangeeta }
c793af95640863cd29868fc7c419c5d2496b207bsangeeta }
c793af95640863cd29868fc7c419c5d2496b207bsangeeta if (ire->ire_ipversion == IPV6_VERSION &&
c793af95640863cd29868fc7c419c5d2496b207bsangeeta ((attrp = ire->ire_gw_secattr) == NULL || attrp->igsa_rhc == NULL ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (gw_rhtp = attrp->igsa_rhc->rhc_tpc) == NULL) && off_link) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) dropped, no gateway in ire attributes(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, tsol_ire_gw_secattr_t *, attrp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto keep_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Check that the label for the packet is acceptable
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * by destination host; otherwise, drop it.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (dst_rhtp->tpc_tp.host_type) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case SUN_CIPSO:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (!_blinrange(&tsl->tsl_label,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &dst_rhtp->tpc_tp.tp_sl_range_cipso) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blinlset(&tsl->tsl_label,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk dst_rhtp->tpc_tp.tp_sl_set_cipso))) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "labeled packet mp(1) dropped, label(2) fails "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "destination(3) accredation check",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, ts_label_t *, tsl,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *, dst_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto keep_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case UNLABELED:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blequal(&dst_rhtp->tpc_tp.tp_def_label,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &tsl->tsl_label)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "unlabeled packet mp(1) dropped, label(2) fails "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "destination(3) accredation check",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, ts_label_t *, tsl,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *, dst_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto keep_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (label_type == OPT_CIPSO) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We keep the label on any of the following cases:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 1. The destination is labeled (on/off-link).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 2. The unlabeled destination is off-link,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and the next hop gateway is labeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (dst_rhtp->tpc_tp.host_type != UNLABELED ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (off_link &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gw_rhtp->tpc_tp.host_type != UNLABELED))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto keep_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Strip off the CIPSO option from the packet because: the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * unlabeled destination host is directly reachable through
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * an interface (on-link); or, the unlabeled destination host
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * is not directly reachable (off-link), and the next hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gateway is unlabeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk adjust = (af == AF_INET) ? tsol_remove_secopt(ipha, MBLKL(mp)) :
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_remove_secopt_v6(ip6h, MBLKL(mp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(adjust <= 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (adjust != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* adjust is negative */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT((mp->b_wptr + adjust) >= mp->b_rptr);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mp->b_wptr += adjust;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that caller adjusts ira_pktlen and
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ira_ip_hdr_length
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * For AF_INET6 note that tsol_remove_secopt_v6
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * adjusted ip6_plen.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (af == AF_INET) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha = (ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk iplen = ntohs(ipha->ipha_length) + adjust;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha->ipha_length = htons(iplen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha->ipha_hdr_checksum = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__info__forward__adjust,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) adjusted(2) for CIPSO option removal",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *, mp, int, adjust);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto keep_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(label_type == OPT_NONE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(dst_rhtp != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We need to add CIPSO option if the destination or the next hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gateway is labeled. Otherwise, pass the packet as is.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (dst_rhtp->tpc_tp.host_type == UNLABELED &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (!off_link || gw_rhtp->tpc_tp.host_type == UNLABELED))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto keep_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since we are forwarding packets we use GLOBAL_ZONEID for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the IRE lookup in tsol_check_label.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since mac_exempt is false the zoneid isn't used for anything
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * but the IRE lookup, hence we set zone_is_global to false.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (af == AF_INET) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark err = tsol_check_label_v4(tsl, GLOBAL_ZONEID, &mp,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark err = tsol_check_label_v6(tsl, GLOBAL_ZONEID, &mp,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (err != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_drop_output("tsol_check_label", mp, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark freemsg(mp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto keep_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The effective_tsl must never affect the routing decision, hence
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * we ignore it here.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
222c5bce8762079550e5ccd485a12de1fff5a82ekp if (af == AF_INET) {
222c5bce8762079550e5ccd485a12de1fff5a82ekp ipha = (ipha_t *)mp->b_rptr;
222c5bce8762079550e5ccd485a12de1fff5a82ekp ipha->ipha_hdr_checksum = 0;
222c5bce8762079550e5ccd485a12de1fff5a82ekp ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkeep_label:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(dst_rhtp);
c793af95640863cd29868fc7c419c5d2496b207bsangeeta if (need_tpc_rele && gw_rhtp != NULL)
c793af95640863cd29868fc7c419c5d2496b207bsangeeta TPC_RELE(gw_rhtp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (mp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy/*
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Name: tsol_pmtu_adjust()
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy *
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Returns the adjusted mtu after removing security option.
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Removes/subtracts the option if the packet's cred indicates an unlabeled
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * sender or if pkt_diff indicates this system enlarged the packet.
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy */
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wyuint32_t
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wytsol_pmtu_adjust(mblk_t *mp, uint32_t mtu, int pkt_diff, int af)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy{
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy int label_adj = 0;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy uint32_t min_mtu = IP_MIN_MTU;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy tsol_tpc_t *src_rhtp;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy void *src;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy /*
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Note: label_adj is non-positive, indicating the number of
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * bytes removed by removing the security option from the
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * header.
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy */
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if (af == AF_INET6) {
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy ip6_t *ip6h;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy min_mtu = IPV6_MIN_MTU;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy ip6h = (ip6_t *)mp->b_rptr;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy src = &ip6h->ip6_src;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if ((src_rhtp = find_tpc(src, IPV6_VERSION, B_FALSE)) == NULL)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy return (mtu);
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED) {
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy label_adj = tsol_remove_secopt_v6(
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy (ip6_t *)mp->b_rptr, MBLKL(mp));
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy }
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy } else {
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy ipha_t *ipha;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy ASSERT(af == AF_INET);
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy ipha = (ipha_t *)mp->b_rptr;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy src = &ipha->ipha_src;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if ((src_rhtp = find_tpc(src, IPV4_VERSION, B_FALSE)) == NULL)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy return (mtu);
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy label_adj = tsol_remove_secopt(
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy (ipha_t *)mp->b_rptr, MBLKL(mp));
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy }
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy /*
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Make pkt_diff non-negative and the larger of the bytes
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * previously added (if any) or just removed, since label
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * addition + subtraction may not be completely idempotent.
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy */
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if (pkt_diff < -label_adj)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy pkt_diff = -label_adj;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if (pkt_diff > 0 && pkt_diff < mtu)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy mtu -= pkt_diff;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy TPC_RELE(src_rhtp);
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy return (MAX(mtu, min_mtu));
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy}
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Name: tsol_rtsa_init()
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Normal: Sanity checks on the route security attributes provided by
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * user. Convert it into a route security parameter list to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * be returned to caller.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Output: EINVAL if bad security attributes in the routing message
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * ENOMEM if unable to allocate data structures
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 0 otherwise.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: On input, cp must point to the end of any addresses in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the rt_msghdr_t structure.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_rtsa_init(rt_msghdr_t *rtm, tsol_rtsecattr_t *sp, caddr_t cp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t sacnt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int err;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk caddr_t lim;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_rtsecattr_t *tp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT((cp >= (caddr_t)&rtm[1]) && sp != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In theory, we could accept as many security attributes configured
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * per route destination. However, the current design is limited
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * such that at most only one set security attributes is allowed to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * be associated with a prefix IRE. We therefore assert for now.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(TSOL_RTSA_REQUEST_MAX == 1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sp->rtsa_cnt = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk lim = (caddr_t)rtm + rtm->rtm_msglen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(cp <= lim);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((lim - cp) < sizeof (rtm_ext_t) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ((rtm_ext_t *)cp)->rtmex_type != RTMEX_GATEWAY_SECATTR)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (((rtm_ext_t *)cp)->rtmex_len < sizeof (tsol_rtsecattr_t))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cp += sizeof (rtm_ext_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((lim - cp) < sizeof (*tp) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (tp = (tsol_rtsecattr_t *)cp, (sacnt = tp->rtsa_cnt) == 0) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (lim - cp) < TSOL_RTSECATTR_SIZE(sacnt))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Trying to add route security attributes when system
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * labeling service is not available, or when user supllies
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * more than the maximum number of security attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * allowed per request.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((sacnt > 0 && !is_system_labeled()) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sacnt > TSOL_RTSA_REQUEST_MAX)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Ensure valid credentials */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((err = rtsa_validate(&((tsol_rtsecattr_t *)cp)->
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rtsa_attr[0])) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cp += sizeof (*sp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (err);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(cp, sp, sizeof (*sp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cp += sizeof (*sp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ire_gw_secattr_t *attrp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t exists = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk in_addr_t ga_addr4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk void *paddr = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark tsol_gcgrp_t *gcgrp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ire != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The only time that attrp can be NULL is when this routine is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * called for the first time during the creation/initialization
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the corresponding IRE. It will only get cleared when the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * IRE is deleted.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((attrp = ire->ire_gw_secattr) == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp = ire_gw_secattr_alloc(KM_NOSLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (attrp == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOMEM);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire->ire_gw_secattr = attrp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk exists = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&attrp->igsa_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (attrp->igsa_rhc != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(attrp->igsa_rhc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_rhc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (attrp->igsa_gc != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk GC_REFRELE(attrp->igsa_gc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(!exists || MUTEX_HELD(&attrp->igsa_lock));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * References already held by caller and we keep them;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * note that gc may be set to NULL to clear out igsa_gc.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk attrp->igsa_gc = gc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (gc != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp = gc->gc_grp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Intialize the template for gateway; we use the gateway's
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address found in either the passed in gateway credential
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or group pointer, or the ire_gateway_addr{_v6} field.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gcgrp != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Caller is holding a reference, and that we don't
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * need to hold any lock to access the address.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ipversion == IPV4_VERSION) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga->ga_af == AF_INET);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk paddr = &ga_addr4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(ga->ga_af == AF_INET6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk paddr = &ga->ga_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else if (ire->ire_type & IRE_OFFLINK) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ipversion == IPV6_VERSION)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark paddr = &ire->ire_gateway_addr_v6;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else if (ipversion == IPV4_VERSION)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark paddr = &ire->ire_gateway_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Lookup the gateway template; note that we could get an internal
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * template here, which we cache anyway. During IRE matching, we'll
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * try to update this gateway template cache and hopefully get a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * real one.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (paddr != NULL) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp attrp->igsa_rhc = find_rhc(paddr, ipversion, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (exists)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&attrp->igsa_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This function figures the type of MLP that we'll be using based on the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address that the user is binding and the zone. If the address is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * unspecified, then we're looking at both private and shared. If it's one
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the zone's private addresses, then it's private only. If it's one
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu * of the global addresses, then it's shared only. Multicast addresses are
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu * treated same as unspecified address.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we can't figure out what it is, then return mlptSingle. That's actually
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * an error case.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The callers are assumed to pass in zone->zone_id and not the zoneid that
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * is stored in a conn_t (since the latter will be GLOBAL_ZONEID in an
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * exclusive stack zone).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkmlp_type_t
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhtsol_mlp_addr_type(zoneid_t zoneid, uchar_t version, const void *addr,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ip_stack_t *ipst)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk in_addr_t in4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_t *ire;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipif_t *ipif;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zoneid_t addrzone;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh zoneid_t ip_zoneid;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(addr != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /*
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * For exclusive stacks we set the zoneid to zero
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * to operate as if in the global zone for IRE and conn_t comparisons.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ipst->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ip_zoneid = GLOBAL_ZONEID;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh else
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ip_zoneid = zoneid;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (version == IPV6_VERSION &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk IN6_IS_ADDR_V4MAPPED((const in6_addr_t *)addr)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk IN6_V4MAPPED_TO_IPADDR((const in6_addr_t *)addr, in4);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addr = &in4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk version = IPV4_VERSION;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Check whether the IRE_LOCAL (or ipif) is ALL_ZONES */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (version == IPV4_VERSION) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk in4 = *(const in_addr_t *)addr;
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu if ((in4 == INADDR_ANY) || CLASSD(in4)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (mlptBoth);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_ftable_lookup_v4(in4, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark 0, ipst, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu if (IN6_IS_ADDR_UNSPECIFIED((const in6_addr_t *)addr) ||
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu IN6_IS_ADDR_MULTICAST((const in6_addr_t *)addr)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (mlptBoth);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_ftable_lookup_v6(addr, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark 0, ipst, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we can't find the IRE, then we have to behave exactly like
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_laddr_verify_{v4,v6}. That means looking up the IPIF so that
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * users can bind to addresses on "down" interfaces.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we can't find that either, then the bind is going to fail, so
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * just give up. Note that there's a miniscule chance that the address
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * is in transition, but we don't bother handling that.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ire == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (version == IPV4_VERSION)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipif = ipif_lookup_addr(*(const in_addr_t *)addr, NULL,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_zoneid, ipst);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipif = ipif_lookup_addr_v6((const in6_addr_t *)addr,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark NULL, ip_zoneid, ipst);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ipif == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (mlptSingle);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addrzone = ipif->ipif_zoneid;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipif_refrele(ipif);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addrzone = ire->ire_zoneid;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_refrele(ire);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (addrzone == ALL_ZONES ? mlptShared : mlptPrivate);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Since we are configuring local interfaces, and we know trusted
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * extension CDE requires local interfaces to be cipso host type in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * order to function correctly, we'll associate a cipso template
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to each local interface and let the interface come up. Configuring
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a local interface to be "unlabeled" host type is a configuration error.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We'll override that error and make the interface host type to be cipso
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * here.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The code is optimized for the usual "success" case and unwinds things on
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * error. We don't want to go to the trouble and expense of formatting the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * interface name for the usual case where everything is configured correctly.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkboolean_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_check_interface_address(const ipif_t *ipif)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char addrbuf[INET6_ADDRSTRLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int af;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const void *addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *plabel;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const bslabel_t *label;
e899e59309fcb43081a58c5d5c252dca3071aaf6Girish Moodalbail char ifname[LIFNAMSIZ];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t retval;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_rhent_t rhent;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (IN6_IS_ADDR_V4MAPPED(&ipif->ipif_v6lcl_addr)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk af = AF_INET;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addr = &V4_PART_OF_V6(ipif->ipif_v6lcl_addr);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk af = AF_INET6;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addr = &ipif->ipif_v6lcl_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tp = find_tpc(&ipif->ipif_v6lcl_addr, IPV6_VERSION, B_FALSE);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* assumes that ALL_ZONES implies that there is no exclusive stack */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ipif->ipif_zoneid == ALL_ZONES) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh zone = NULL;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh } else if (ns->netstack_stackid == GLOBAL_NETSTACKID) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Shared stack case */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh zone = zone_find_by_id(ipif->ipif_zoneid);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh } else {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Exclusive stack case */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh zone = zone_find_by_id(crgetzoneid(ipif->ipif_ill->ill_credp));
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zone != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk plabel = zone->zone_slabel;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(plabel != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label = label2bslabel(plabel);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If it's CIPSO and an all-zones address, then we're done.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If it's a CIPSO zone specific address, the zone's label
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * must be in the range or set specified in the template.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When the remote host entry is missing or the template
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * type is incorrect for this interface, we create a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CIPSO host entry in kernel and allow the interface to be
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * brought up as CIPSO type.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp != NULL && (
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* The all-zones case */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (tp->tpc_tp.host_type == SUN_CIPSO &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tp->tpc_tp.tp_doi == default_doi &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipif->ipif_zoneid == ALL_ZONES) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* The local-zone case */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (zone != NULL && plabel->tsl_doi == tp->tpc_tp.tp_doi &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ((tp->tpc_tp.host_type == SUN_CIPSO &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk blinlset(label, tp->tpc_tp.tp_sl_set_cipso))))))) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zone != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
e899e59309fcb43081a58c5d5c252dca3071aaf6Girish Moodalbail ipif_get_name(ipif, ifname, sizeof (ifname));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) inet_ntop(af, addr, addrbuf, sizeof (addrbuf));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "template entry for %s missing. Default to "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "CIPSO type for %s", ifname, addrbuf);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (tp->tpc_tp.host_type == UNLABELED) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "template type for %s incorrectly configured. "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "Change to CIPSO type for %s", ifname, addrbuf);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (ipif->ipif_zoneid == ALL_ZONES) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp->tpc_tp.host_type != SUN_CIPSO) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: %s isn't set to CIPSO for "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "all-zones. Converted to CIPSO.", ifname, addrbuf);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: %s has wrong DOI %d "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "instead of %d", ifname, addrbuf,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tp->tpc_tp.tp_doi, default_doi);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (zone == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: zoneid %d unknown",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ifname, ipif->ipif_zoneid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: zone %s has DOI %d but %s has "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "DOI %d", ifname, zone->zone_name, plabel->tsl_doi,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addrbuf, tp->tpc_tp.tp_doi);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: zone %s label incompatible with "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "%s", ifname, zone->zone_name, addrbuf);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_print_label(label, "zone label");
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zone != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retval) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * we've corrected a config error and let the interface
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * come up as cipso. Need to insert an rhent.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((rhent.rh_address.ta_family = af) == AF_INET) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhent.rh_prefix = 32;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhent.rh_address.ta_addr_v4 = *(struct in_addr *)addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhent.rh_prefix = 128;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhent.rh_address.ta_addr_v6 = *(in6_addr_t *)addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) strcpy(rhent.rh_template, "cipso");
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tnrh_load(&rhent) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: Cannot insert CIPSO "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "template for local addr %s", ifname, addrbuf);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retval);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}