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/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Use is subject to license terms.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#pragma ident "%Z%%M% %I% %E% SMI"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/systm.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/types.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/stream.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/kmem.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/strsubr.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/cmn_err.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/debug.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/param.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/model.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/errno.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/modhash.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/policy.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/label.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tsyscall.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tndb.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tnet.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/disp.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip6.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/sdt.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic mod_hash_t *tpc_name_hash; /* hash of cache entries by name */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic kmutex_t tpc_lock;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic tsol_tpc_t *tpc_unlab;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tnrhc_table and tnrhc_table_v6 are similar to the IP forwarding tables
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * in organization and search. The tnrhc_table[_v6] is an array of 33/129
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * pointers to the 33/129 tnrhc tables indexed by the prefix length.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * A largest prefix match search is done by find_rhc and it walks the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tables from the most specific to the least specific table. Table 0
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * corresponds to the single entry for 0.0.0.0/0 or ::0/0.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhc_hash_t *tnrhc_table[TSOL_MASK_TABLE_SIZE];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhc_hash_t *tnrhc_table_v6[TSOL_MASK_TABLE_SIZE_V6];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkmutex_t tnrhc_g_lock;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void tsol_create_i_tmpls(void);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void tsol_create_i_tnrh(const tnaddr_t *);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* List of MLPs on valid on shared addresses */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic tsol_mlp_list_t shared_mlps;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Convert length for a mask to the mask.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic ipaddr_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_plen_to_mask(uint_t masklen)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (masklen == 0 ? 0 : htonl(IP_HOST_MASK << (IP_ABITS - masklen)));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Convert a prefix length to the mask for that prefix.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns the argument bitmask.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_plen_to_mask_v6(uint_t plen, in6_addr_t *bitmask)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t *ptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(plen <= IPV6_ABITS);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ptr = (uint32_t *)bitmask;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (plen >= 32) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *ptr++ = 0xffffffffU;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk plen -= 32;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (plen > 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *ptr++ = htonl(0xffffffff << (32 - plen));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (ptr < (uint32_t *)(bitmask + 1))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *ptr++ = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkboolean_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhc_init_table(tnrhc_hash_t *table[], short prefix_len, int kmflag)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int i;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tnrhc_g_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (table[prefix_len] == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk table[prefix_len] = (tnrhc_hash_t *)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_zalloc(TNRHC_SIZE * sizeof (tnrhc_hash_t), kmflag);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (table[prefix_len] == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tnrhc_g_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (i = 0; i < TNRHC_SIZE; i++) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&table[prefix_len][i].tnrh_lock,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk NULL, MUTEX_DEFAULT, 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tnrhc_g_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktcache_init(void)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnaddr_t address;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: unable to use mod_hash_create_strhash here, since it's
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * assymetric. It assumes that the user has allocated exactly
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * strlen(key) + 1 bytes for the key when inserted, and attempts to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * kmem_free that memory on a delete.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc_name_hash = mod_hash_create_extended("tnrhtpc_by_name", 256,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_null_keydtor, mod_hash_null_valdtor, mod_hash_bystr,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk NULL, mod_hash_strkey_cmp, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&tpc_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&tnrhc_g_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* label_init always called before tcache_init */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(l_admin_low != NULL && l_admin_high != NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Initialize the zeroth table prior to loading the 0.0.0.0 entry */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) tnrhc_init_table(tnrhc_table, 0, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) tnrhc_init_table(tnrhc_table_v6, 0, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * create an internal host template called "_unlab"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_create_i_tmpls();
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * create a host entry, 0.0.0.0 = _unlab
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bzero(&address, sizeof (tnaddr_t));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk address.ta_family = AF_INET;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_create_i_tnrh(&address);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * create a host entry, ::0 = _unlab
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk address.ta_family = AF_INET6;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_create_i_tnrh(&address);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_init(&shared_mlps.mlpl_rwlock, NULL, RW_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* Called only by the TNRHC_RELE macro when the refcount goes to zero. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhc_free(tsol_tnrhc_t *tnrhc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We assert rhc_invalid here to make sure that no new thread could
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * possibly end up finding this entry. If it could, then the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * mutex_destroy would panic.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l3__tnrhcfree, tsol_tnrhc_t *, tnrhc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(tnrhc->rhc_next == NULL && tnrhc->rhc_invalid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tnrhc->rhc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_destroy(&tnrhc->rhc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tnrhc->rhc_tpc != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tnrhc->rhc_tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(tnrhc, sizeof (*tnrhc));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* Called only by the TPC_RELE macro when the refcount goes to zero. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktpc_free(tsol_tpc_t *tpc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l3__tpcfree, tsol_tpc_t *, tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(tpc->tpc_invalid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tpc->tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_destroy(&tpc->tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(tpc, sizeof (*tpc));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Find and hold a reference to a template entry by name. Ignores entries that
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * are being deleted.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic tsol_tpc_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhtp_find(const char *name, mod_hash_t *hash)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_val_t hv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tpc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mod_hash_find(hash, (mod_hash_key_t)name, &hv) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc = (tsol_tpc_t *)hv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tpc->tpc_invalid)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_HOLD(tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrh_delete(const tsol_rhent_t *rhent)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *current;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t **prevp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipaddr_t tmpmask;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk in6_addr_t tmpmask_v6;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash_t *tnrhc_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rhent->rh_address.ta_family == AF_INET) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rhent->rh_prefix < 0 || rhent->rh_prefix > IP_ABITS)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tnrhc_table[rhent->rh_prefix] == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOENT);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tmpmask = tsol_plen_to_mask(rhent->rh_prefix);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash = &tnrhc_table[rhent->rh_prefix][
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TSOL_ADDR_HASH(rhent->rh_address.ta_addr_v4.s_addr &
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tmpmask, TNRHC_SIZE)];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (rhent->rh_address.ta_family == AF_INET6) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rhent->rh_prefix < 0 || rhent->rh_prefix > IPV6_ABITS)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tnrhc_table_v6[rhent->rh_prefix] == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOENT);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_plen_to_mask_v6(rhent->rh_prefix, &tmpmask_v6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash = &tnrhc_table_v6[rhent->rh_prefix][
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TSOL_ADDR_MASK_HASH_V6(rhent->rh_address.ta_addr_v6,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tmpmask_v6, TNRHC_SIZE)];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EAFNOSUPPORT);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* search for existing entry */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tnrhc_hash->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk prevp = &tnrhc_hash->tnrh_list;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while ((current = *prevp) != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (TNADDR_EQ(&rhent->rh_address, &current->rhc_host))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk prevp = &current->rhc_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (current != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l2__tnrhdelete_existingrhentry);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *prevp = current->rhc_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&current->rhc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk current->rhc_next = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk current->rhc_invalid = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&current->rhc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(current);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tnrhc_hash->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (current == NULL ? ENOENT : 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Flush all remote host entries from the database.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note that the htable arrays themselves do not have reference counters, so,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * unlike the remote host entries, they cannot be freed.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkflush_rh_table(tnrhc_hash_t **htable, int nbits)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash_t *hent, *hend;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *rhc, *rhnext;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (--nbits >= 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((hent = htable[nbits]) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hend = hent + TNRHC_SIZE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (hent < hend) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * List walkers hold this lock during the walk. It
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * protects tnrh_list and rhc_next.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&hent->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhnext = hent->tnrh_list;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hent->tnrh_list = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&hent->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * There may still be users of the rhcs at this point,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * but not of the list or its next pointer. Thus, the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * only thing that would need to be done under a lock
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * is setting the invalid bit, but that's atomic
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * anyway, so no locks needed here.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while ((rhc = rhnext) != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhnext = rhc->rhc_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhc->rhc_next = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhc->rhc_invalid = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(rhc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hent++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Load a remote host entry into kernel cache. Create a new one if a matching
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * entry isn't found, otherwise replace the contents of the previous one by
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * deleting it and recreating it. (Delete and recreate is used to avoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * allowing other threads to see an unstable data structure.)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * A "matching" entry is the one whose address matches that of the one
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * being loaded.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Return 0 for success, error code for failure.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kpstatic int
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kptnrh_hash_add(tsol_tnrhc_t *new, short prefix)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t **rhp;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_tnrhc_t *rh;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipaddr_t tmpmask;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk in6_addr_t tmpmask_v6;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash_t *tnrhc_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Find the existing entry, if any, leaving the hash locked */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (new->rhc_host.ta_family == AF_INET) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (prefix < 0 || prefix > IP_ABITS)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (tnrhc_table[prefix] == NULL &&
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp !tnrhc_init_table(tnrhc_table, prefix,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk KM_NOSLEEP))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOMEM);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tmpmask = tsol_plen_to_mask(prefix);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tnrhc_hash = &tnrhc_table[prefix][
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TSOL_ADDR_HASH(new->rhc_host.ta_addr_v4.s_addr &
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tmpmask, TNRHC_SIZE)];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tnrhc_hash->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (rhp = &tnrhc_hash->tnrh_list; (rh = *rhp) != NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhp = &rh->rhc_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(rh->rhc_host.ta_family == AF_INET);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (((rh->rhc_host.ta_addr_v4.s_addr ^
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp new->rhc_host.ta_addr_v4.s_addr) & tmpmask) ==
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp } else if (new->rhc_host.ta_family == AF_INET6) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (prefix < 0 || prefix > IPV6_ABITS)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (tnrhc_table_v6[prefix] == NULL &&
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp !tnrhc_init_table(tnrhc_table_v6, prefix,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk KM_NOSLEEP))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOMEM);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_plen_to_mask_v6(prefix, &tmpmask_v6);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tnrhc_hash = &tnrhc_table_v6[prefix][
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TSOL_ADDR_MASK_HASH_V6(new->rhc_host.ta_addr_v6,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tmpmask_v6, TNRHC_SIZE)];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tnrhc_hash->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (rhp = &tnrhc_hash->tnrh_list; (rh = *rhp) != NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhp = &rh->rhc_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(rh->rhc_host.ta_family == AF_INET6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (V6_MASK_EQ_2(rh->rhc_host.ta_addr_v6, tmpmask_v6,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp new->rhc_host.ta_addr_v6))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EAFNOSUPPORT);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Clobber the old remote host entry. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rh != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(!rh->rhc_invalid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rh->rhc_invalid = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *rhp = rh->rhc_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rh->rhc_next = NULL;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp DTRACE_PROBE1(tx__tndb__l2__tnrhhashadd__invalidaterh,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_tnrhc_t *, rh);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_RELE(rh);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_HOLD(new);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp new->rhc_next = tnrhc_hash->tnrh_list;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tnrhc_hash->tnrh_list = new;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp DTRACE_PROBE1(tx__tndb__l2__tnrhhashadd__addedrh, tsol_tnrhc_t *, new);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp mutex_exit(&tnrhc_hash->tnrh_lock);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (0);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp}
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp/*
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * Load a remote host entry into kernel cache.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp *
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * Return 0 for success, error code for failure.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kpint
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kptnrh_load(const tsol_rhent_t *rhent)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp{
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_tnrhc_t *new;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_tpc_t *tpc;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp int status;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp /* Find and bump the reference count on the named template */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((tpc = tnrhtp_find(rhent->rh_template, tpc_name_hash)) == NULL) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (EINVAL);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp ASSERT(tpc->tpc_tp.host_type == UNLABELED ||
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tpc->tpc_tp.host_type == SUN_CIPSO);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((new = kmem_zalloc(sizeof (*new), KM_NOSLEEP)) == NULL) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TPC_RELE(tpc);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (ENOMEM);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Initialize the new entry. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&new->rhc_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new->rhc_host = rhent->rh_address;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* The rhc now owns this tpc reference, so no TPC_RELE past here */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new->rhc_tpc = tpc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp /*
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * tnrh_hash_add handles the tnrh entry ref count for hash
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * table inclusion. The ref count is incremented and decremented
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * here to trigger deletion of the new hash table entry in the
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * event that tnrh_hash_add fails.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_HOLD(new);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp status = tnrh_hash_add(new, rhent->rh_prefix);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_RELE(new);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (status);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrh_get(tsol_rhent_t *rhent)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tpc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (rhent->rh_address.ta_family) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case AF_INET:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc = find_tpc(&rhent->rh_address.ta_addr_v4, IPV4_VERSION,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case AF_INET6:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc = find_tpc(&rhent->rh_address.ta_addr_v6, IPV6_VERSION,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tpc == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOENT);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__tndb__l4__tnrhget__foundtpc, tsol_rhent_t *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhent, tsol_tpc_t *, tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(tpc->tpc_tp.name, rhent->rh_template,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sizeof (rhent->rh_template));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic boolean_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktemplate_name_ok(const char *name)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const char *name_end = name + TNTNAMSIZ;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (name < name_end) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (*name == '\0')
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk name++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (name < name_end);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrh(int cmd, void *buf)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_rhent_t rhent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Make sure user has sufficient privilege */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (cmd != TNDB_GET &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (retv = secpolicy_net_config(CRED(), B_FALSE)) != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(retv));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Get arguments
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (cmd != TNDB_FLUSH &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk copyin(buf, &rhent, sizeof (rhent)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l0__tnrhdelete__copyin);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(EFAULT));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (cmd) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_LOAD:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l2__tnrhdelete__tndbload);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!template_name_ok(rhent.rh_template)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EINVAL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = tnrh_load(&rhent);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_DELETE:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l2__tnrhdelete__tndbdelete);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = tnrh_delete(&rhent);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_GET:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l4__tnrhdelete__tndbget);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!template_name_ok(rhent.rh_template)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EINVAL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = tnrh_get(&rhent);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retv != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Copy out result
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copyout(&rhent, buf, sizeof (rhent)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l0__tnrhdelete__copyout);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EFAULT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_FLUSH:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l2__tnrhdelete__flush);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk flush_rh_table(tnrhc_table, TSOL_MASK_TABLE_SIZE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk flush_rh_table(tnrhc_table_v6, TSOL_MASK_TABLE_SIZE_V6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l0__tnrhdelete__unknowncmd,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int, cmd);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EOPNOTSUPP;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retv != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(retv));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic tsol_tpc_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhtp_create(const tsol_tpent_t *tpent, int kmflags)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tpc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_val_t hv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We intentionally allocate a new entry before taking the lock on the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * entire database.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((tpc = kmem_zalloc(sizeof (*tpc), kmflags)) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mod_hash_find(tpc_name_hash, (mod_hash_key_t)tpent->name,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &hv) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *found_tpc = (tsol_tpc_t *)hv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk found_tpc->tpc_invalid = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) mod_hash_destroy(tpc_name_hash,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_key_t)tpent->name);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(found_tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&tpc->tpc_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* tsol_tpent_t is the same on LP64 and ILP32 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(tpent, &tpc->tpc_tp, sizeof (tpc->tpc_tp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) mod_hash_insert(tpc_name_hash, (mod_hash_key_t)tpc->tpc_tp.name,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_val_t)tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_HOLD(tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhtp_delete(const char *tname)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tpc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_val_t hv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv = ENOENT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mod_hash_find(tpc_name_hash, (mod_hash_key_t)tname, &hv) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc = (tsol_tpc_t *)hv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(!tpc->tpc_invalid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc->tpc_invalid = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) mod_hash_destroy(tpc_name_hash,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mod_hash_key_t)tpc->tpc_tp.name);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic uint_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktpc_delete(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tpc = (tsol_tpc_t *)val;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(!tpc->tpc_invalid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc->tpc_invalid = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (MH_WALK_CONTINUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhtp_flush(void)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_walk(tpc_name_hash, tpc_delete, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mod_hash_clear(tpc_name_hash);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tpc_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnrhtp(int cmd, void *buf)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int type;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpent_t rhtpent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tpc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Make sure user has sufficient privilege */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (cmd != TNDB_GET &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (retv = secpolicy_net_config(CRED(), B_FALSE)) != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(retv));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Get argument. Note that tsol_tpent_t is the same on LP64 and ILP32,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * so no special handling is required.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (cmd != TNDB_FLUSH) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copyin(buf, &rhtpent, sizeof (rhtpent)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l0__tnrhtp__copyin);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(EFAULT));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Don't let the user give us a bogus (unterminated) template
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * name.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!template_name_ok(rhtpent.name))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(EINVAL));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (cmd) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_LOAD:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l2__tnrhtp__tndbload, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.name);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk type = rhtpent.host_type;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (type != UNLABELED && type != SUN_CIPSO) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EINVAL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tnrhtp_create(&rhtpent, KM_NOSLEEP) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = ENOMEM;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_GET:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l4__tnrhtp__tndbget, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.name);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc = tnrhtp_find(rhtpent.name, tpc_name_hash);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tpc == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = ENOENT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Copy out result */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copyout(&tpc->tpc_tp, buf, sizeof (tpc->tpc_tp)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l0__tnrhtp__copyout);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EFAULT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_DELETE:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l4__tnrhtp__tndbdelete, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.name);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = tnrhtp_delete(rhtpent.name);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_FLUSH:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l4__tnrhtp__flush);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhtp_flush();
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l0__tnrhtp__unknowncmd, int,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmd);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EOPNOTSUPP;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retv != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(retv));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * MLP entry ordering logic
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * There are two loops in this routine. The first loop finds the entry that
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * either logically follows the new entry to be inserted, or is the entry that
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * precedes and overlaps the new entry, or is NULL to mean end-of-list. This
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * is 'tme.' The second loop scans ahead from that point to find any overlap
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * on the front or back of this new entry.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * For the first loop, we can have the following cases in the list (note that
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the port-portmax range is inclusive):
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * port portmax
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * +--------+
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 1: +------+ ................... precedes; skip to next
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 2: +------+ ............. overlaps; stop here if same protocol
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 3: +------+ ......... overlaps; stop if same or higher protocol
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 4: +-------+ .... overlaps or succeeds; stop here
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * For the second loop, we can have the following cases (note that we need not
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * care about other protocol entries at this point, because we're only looking
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * for overlap, not an insertion point):
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * port portmax
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * +--------+
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 5: +------+ ............. overlaps; stop if same protocol
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 6: +------+ ......... overlaps; stop if same protocol
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 7: +-------+ .... overlaps; stop if same protocol
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 8: +---+ . follows; search is done
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In other words, this second search needs to consider only whether the entry
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * has a starting port number that's greater than the end point of the new
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * entry. All others are overlaps.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkmlp_add_del(tsol_mlp_list_t *mlpl, zoneid_t zoneid, uint8_t proto,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint16_t port, uint16_t portmax, boolean_t addflag)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlp_entry_t *tme, *tme2, *newent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (addflag) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((newent = kmem_zalloc(sizeof (*newent), KM_NOSLEEP)) ==
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOMEM);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&mlpl->mlpl_rwlock, RW_WRITER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * First loop: find logical insertion point or overlap. Table is kept
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * in order of port number first, and then, within that, by protocol
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * number.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = mlpl->mlpl_first; tme != NULL; tme = tme->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* logically next (case 4) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme->mlpe_mlp.mlp_port > port)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* if this is logically next or overlap, then stop (case 3) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme->mlpe_mlp.mlp_port == port &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_mlp.mlp_ipp >= proto)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* earlier or same port sequence; check for overlap (case 2) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme->mlpe_mlp.mlp_ipp == proto &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_mlp.mlp_port_upper >= port)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* otherwise, loop again (case 1) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Second loop: scan ahead for overlap */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme2 = tme; tme2 != NULL; tme2 = tme2->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* check if entry follows; no overlap (case 8) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme2->mlpe_mlp.mlp_port > portmax) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2 = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* only exact protocol matches at this point (cases 5-7) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme2->mlpe_mlp.mlp_ipp == proto)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (addflag) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme2 != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EEXIST;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent->mlpe_zoneid = zoneid;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent->mlpe_mlp.mlp_ipp = proto;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent->mlpe_mlp.mlp_port = port;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent->mlpe_mlp.mlp_port_upper = portmax;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent->mlpe_next = tme;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2 = mlpl->mlpl_last;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl->mlpl_last = newent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2 = tme->mlpe_prev;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_prev = newent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent->mlpe_prev = tme2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme2 == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl->mlpl_first = newent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2->mlpe_next = newent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme2 == NULL || tme2->mlpe_mlp.mlp_port != port ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2->mlpe_mlp.mlp_port_upper != portmax) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = ENOENT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((tme2 = tme->mlpe_prev) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl->mlpl_first = tme->mlpe_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2->mlpe_next = tme->mlpe_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((tme2 = tme->mlpe_next) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl->mlpl_last = tme->mlpe_prev;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2->mlpe_prev = tme->mlpe_prev;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newent = tme;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&mlpl->mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (newent != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(newent, sizeof (*newent));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Add or remove an MLP entry from the database so that the classifier can find
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * it.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: port number is in host byte order.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_mlp_anon(zone_t *zone, mlp_type_t mlptype, uchar_t proto, uint16_t port,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t addflag)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mlptype == mlptBoth || mlptype == mlptPrivate)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = mlp_add_del(&zone->zone_mlps, zone->zone_id, proto,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port, port, addflag);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((retv == 0 || !addflag) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (mlptype == mlptBoth || mlptype == mlptShared)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = mlp_add_del(&shared_mlps, zone->zone_id, proto, port,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port, addflag);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retv != 0 && addflag)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) mlp_add_del(&zone->zone_mlps, zone->zone_id,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk proto, port, port, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkmlp_flush(tsol_mlp_list_t *mlpl, zoneid_t zoneid)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlp_entry_t *tme, *tme2, *tmnext;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&mlpl->mlpl_rwlock, RW_WRITER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = mlpl->mlpl_first; tme != NULL; tme = tmnext) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tmnext = tme->mlpe_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zoneid == ALL_ZONES || tme->mlpe_zoneid == zoneid) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((tme2 = tme->mlpe_prev) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl->mlpl_first = tmnext;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme2->mlpe_next = tmnext;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tmnext == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl->mlpl_last = tme2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tmnext->mlpe_prev = tme2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(tme, sizeof (*tme));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&mlpl->mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: user supplies port numbers in host byte order.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktnmlp(int cmd, void *buf)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlpent_t tsme;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlp_list_t *mlpl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlp_entry_t *tme;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Make sure user has sufficient privilege */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (cmd != TNDB_GET &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (retv = secpolicy_net_config(CRED(), B_FALSE)) != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(retv));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Get argument. Note that tsol_mlpent_t is the same on LP64 and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * ILP32, so no special handling is required.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copyin(buf, &tsme, sizeof (tsme)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l0__tnmlp__copyin);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(EFAULT));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* MLPs on shared IP addresses */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsme.tsme_flags & TSOL_MEF_SHARED) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl = &shared_mlps;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = zone_find_by_id(tsme.tsme_zoneid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zone == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(EINVAL));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlpl = &zone->zone_mlps;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsme.tsme_mlp.mlp_port_upper == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_mlp.mlp_port_upper = tsme.tsme_mlp.mlp_port;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (cmd) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_LOAD:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l2__tnmlp__tndbload,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlpent_t *, &tsme);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsme.tsme_mlp.mlp_ipp == 0 || tsme.tsme_mlp.mlp_port == 0 ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_mlp.mlp_port > tsme.tsme_mlp.mlp_port_upper) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EINVAL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = mlp_add_del(mlpl, tsme.tsme_zoneid,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_mlp.mlp_ipp, tsme.tsme_mlp.mlp_port,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_mlp.mlp_port_upper, B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_GET:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l2__tnmlp__tndbget,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlpent_t *, &tsme);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Search for the requested element or, failing that, the one
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * that's logically next in the sequence.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&mlpl->mlpl_rwlock, RW_READER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = mlpl->mlpl_first; tme != NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme = tme->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tsme.tsme_zoneid != ALL_ZONES &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_zoneid != tsme.tsme_zoneid)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme->mlpe_mlp.mlp_ipp >= tsme.tsme_mlp.mlp_ipp &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_mlp.mlp_port == tsme.tsme_mlp.mlp_port)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme->mlpe_mlp.mlp_port > tsme.tsme_mlp.mlp_port)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = ENOENT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_zoneid = tme->mlpe_zoneid;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_mlp = tme->mlpe_mlp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&mlpl->mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_DELETE:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l4__tnmlp__tndbdelete,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlpent_t *, &tsme);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = mlp_add_del(mlpl, tsme.tsme_zoneid,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_mlp.mlp_ipp, tsme.tsme_mlp.mlp_port,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsme.tsme_mlp.mlp_port_upper, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TNDB_FLUSH:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l4__tnmlp__tndbflush,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlpent_t *, &tsme);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlp_flush(mlpl, ALL_ZONES);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlp_flush(&shared_mlps, tsme.tsme_zoneid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE1(tx__tndb__l0__tnmlp__unknowncmd, int,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmd);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EOPNOTSUPP;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zone != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (cmd == TNDB_GET && retv == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Copy out result */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copyout(&tsme, buf, sizeof (tsme)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE(tx__tndb__l0__tnmlp__copyout);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retv = EFAULT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retv != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(retv));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns a tnrhc matching the addr address.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The returned rhc's refcnt is incremented.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_tnrhc_t *
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kpfind_rhc(const void *addr, uchar_t version, boolean_t staleok)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *rh = NULL;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_tnrhc_t *new;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_tpc_t *tpc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash_t *tnrhc_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipaddr_t tmpmask;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp in_addr_t *in4 = (in_addr_t *)addr;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp in6_addr_t *in6 = (in6_addr_t *)addr;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp in_addr_t tmpin4;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp in6_addr_t tmpmask6;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int i;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp int prefix;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp /*
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * An IPv4-mapped IPv6 address is really an IPv4 address
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * in IPv6 format.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (version == IPV6_VERSION &&
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp IN6_IS_ADDR_V4MAPPED(in6)) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp IN6_V4MAPPED_TO_IPADDR(in6, tmpin4);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp version = IPV4_VERSION;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp in4 = &tmpin4;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp /*
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * Search the tnrh hash table for each prefix length,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * starting at longest prefix length, until a matching
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * rhc entry is found.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (version == IPV4_VERSION) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp for (i = (TSOL_MASK_TABLE_SIZE - 1); i >= 0; i--) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((tnrhc_table[i]) == NULL)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tmpmask = tsol_plen_to_mask(i);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tnrhc_hash = &tnrhc_table[i][
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TSOL_ADDR_HASH(*in4 & tmpmask, TNRHC_SIZE)];
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp mutex_enter(&tnrhc_hash->tnrh_lock);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp for (rh = tnrhc_hash->tnrh_list; rh != NULL;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp rh = rh->rhc_next) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((rh->rhc_host.ta_family == AF_INET) &&
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp ((rh->rhc_host.ta_addr_v4.s_addr &
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tmpmask) == (*in4 & tmpmask))) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp prefix = i;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_HOLD(rh);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp break;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp mutex_exit(&tnrhc_hash->tnrh_lock);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (rh != NULL)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (rh == NULL)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp DTRACE_PROBE1(tx__tndb__l1__findrhc__norhv4ent,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp in_addr_t *, in4);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp } else {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp for (i = (TSOL_MASK_TABLE_SIZE_V6 - 1); i >= 0; i--) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((tnrhc_table_v6[i]) == NULL)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_plen_to_mask_v6(i, &tmpmask6);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tnrhc_hash = &tnrhc_table_v6[i][
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TSOL_ADDR_MASK_HASH_V6(*in6, tmpmask6, TNRHC_SIZE)];
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp mutex_enter(&tnrhc_hash->tnrh_lock);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp for (rh = tnrhc_hash->tnrh_list; rh != NULL;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp rh = rh->rhc_next) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((rh->rhc_host.ta_family == AF_INET6) &&
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp V6_MASK_EQ_2(rh->rhc_host.ta_addr_v6,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tmpmask6, *in6)) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp prefix = i;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_HOLD(rh);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp break;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp mutex_exit(&tnrhc_hash->tnrh_lock);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (rh != NULL)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp break;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (rh == NULL)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp DTRACE_PROBE1(tx__tndb__l1__findrhc__norhv6ent,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp in6_addr_t *, in6);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp /*
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * Does the tnrh entry point to a stale template?
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * This can happen any time the user deletes or modifies
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * a template that has existing tnrh entries pointing
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * to it. Try to find a new version of the template.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * If there is no template, then just give up.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * If the template exists, reload the tnrh entry.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (rh != NULL && rh->rhc_tpc->tpc_invalid) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tpc = tnrhtp_find(rh->rhc_tpc->tpc_tp.name, tpc_name_hash);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (tpc == NULL) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (!staleok) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp DTRACE_PROBE2(tx__tndb__l1__findrhc__staletpc,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tsol_tnrhc_t *, rh, tsol_tpc_t *,
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp rh->rhc_tpc);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_RELE(rh);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp rh = NULL;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp } else {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp ASSERT(tpc->tpc_tp.host_type == UNLABELED ||
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tpc->tpc_tp.host_type == SUN_CIPSO);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((new = kmem_zalloc(sizeof (*new),
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp KM_NOSLEEP)) == NULL) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp DTRACE_PROBE(tx__tndb__l1__findrhc__nomem);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_RELE(rh);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TPC_RELE(tpc);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (NULL);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp mutex_init(&new->rhc_lock, NULL, MUTEX_DEFAULT, NULL);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp new->rhc_host = rh->rhc_host;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp new->rhc_tpc = tpc;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp new->rhc_isbcast = rh->rhc_isbcast;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp new->rhc_local = rh->rhc_local;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_RELE(rh);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp rh = new;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp /*
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * This function increments the tnrh entry ref count
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * for the pointer returned to the caller.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * tnrh_hash_add increments the tnrh entry ref count
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp * for the pointer in the hash table.
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp */
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_HOLD(rh);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if (tnrh_hash_add(new, prefix) != 0) {
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_RELE(rh);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp rh = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (rh);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_tpc_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkfind_tpc(const void *addr, uchar_t version, boolean_t staleok)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tpc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *rhc;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp if ((rhc = find_rhc(addr, version, staleok)) == NULL)
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp tpc = rhc->rhc_tpc;
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TPC_HOLD(tpc);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp TNRHC_RELE(rhc);
bfabfc3590ad9189f6bb40cca26bd30cb46301c9kp return (tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * create an internal template called "_unlab":
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * _unlab;\
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * host_type = unlabeled;\
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * def_label = ADMIN_LOW[ADMIN_LOW];\
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * min_sl = ADMIN_LOW;\
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * max_sl = ADMIN_HIGH;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_create_i_tmpls(void)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpent_t rhtpent;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bzero(&rhtpent, sizeof (rhtpent));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* create _unlab */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) strcpy(rhtpent.name, "_unlab");
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.host_type = UNLABELED;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.tp_mask_unl = TSOL_MSK_DEF_LABEL | TSOL_MSK_DEF_CL |
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TSOL_MSK_SL_RANGE_TSOL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.tp_gw_sl_range.lower_bound = *label2bslabel(l_admin_low);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.tp_def_label = rhtpent.tp_gw_sl_range.lower_bound;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.tp_gw_sl_range.upper_bound = *label2bslabel(l_admin_high);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtpent.tp_cipso_doi_unl = default_doi;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tpc_unlab = tnrhtp_create(&rhtpent, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * set up internal host template, called from kernel only.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_create_i_tnrh(const tnaddr_t *sa)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tnrhc_t *rh, *new;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash_t *tnrhc_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Allocate a new entry before taking the lock */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new = kmem_zalloc(sizeof (*new), KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash = (sa->ta_family == AF_INET) ? &tnrhc_table[0][0] :
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk &tnrhc_table_v6[0][0];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&tnrhc_hash->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rh = tnrhc_hash->tnrh_list;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rh == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We're keeping the new entry. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rh = new;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rh->rhc_host = *sa;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&rh->rhc_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TNRHC_HOLD(rh);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tnrhc_hash->tnrh_list = rh;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Link the entry to internal_unlab
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rh->rhc_tpc != tpc_unlab) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rh->rhc_tpc != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(rh->rhc_tpc);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rh->rhc_tpc = tpc_unlab;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_HOLD(tpc_unlab);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tnrhc_hash->tnrh_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (new != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(new, sizeof (*new));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns 0 if the port is known to be SLP. Returns next possible port number
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * (wrapping through 1) if port is MLP on shared or global. Administrator
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * should not make all ports MLP. If that's done, then we'll just pretend
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * everything is SLP to avoid looping forever.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: port is in host byte order.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkin_port_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_next_port(zone_t *zone, in_port_t port, int proto, boolean_t upward)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t loop;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlp_entry_t *tme;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int newport = port;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk loop = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (;;) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zone != NULL && zone->zone_mlps.mlpl_first != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&zone->zone_mlps.mlpl_rwlock, RW_READER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = zone->zone_mlps.mlpl_first; tme != NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme = tme->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (proto == tme->mlpe_mlp.mlp_ipp &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newport >= tme->mlpe_mlp.mlp_port &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newport <= tme->mlpe_mlp.mlp_port_upper)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newport = upward ?
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_mlp.mlp_port_upper + 1 :
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_mlp.mlp_port - 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&zone->zone_mlps.mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (shared_mlps.mlpl_first != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&shared_mlps.mlpl_rwlock, RW_READER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = shared_mlps.mlpl_first; tme != NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme = tme->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (proto == tme->mlpe_mlp.mlp_ipp &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newport >= tme->mlpe_mlp.mlp_port &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newport <= tme->mlpe_mlp.mlp_port_upper)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newport = upward ?
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_mlp.mlp_port_upper + 1 :
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme->mlpe_mlp.mlp_port - 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&shared_mlps.mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (newport <= 65535 && newport > 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (loop)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk loop = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk newport = upward ? 1 : 65535;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (newport == port ? 0 : newport);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_mlp_port_type will check if the given (zone, proto, port) is a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * multilevel port. If it is, return the type (shared, private, or both), or
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * indicate that it's single-level.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: port is given in host byte order, not network byte order.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkmlp_type_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_mlp_port_type(zone_t *zone, uchar_t proto, uint16_t port,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlp_type_t mlptype)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlp_entry_t *tme;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mlptype == mlptBoth || mlptype == mlptPrivate) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (zone->zone_mlps.mlpl_first != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&zone->zone_mlps.mlpl_rwlock, RW_READER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = zone->zone_mlps.mlpl_first; tme != NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme = tme->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (proto == tme->mlpe_mlp.mlp_ipp &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port >= tme->mlpe_mlp.mlp_port &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port <= tme->mlpe_mlp.mlp_port_upper)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&zone->zone_mlps.mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mlptype == mlptBoth)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlptype = mlptShared;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else if (mlptype == mlptPrivate)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlptype = mlptSingle;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mlptype == mlptBoth || mlptype == mlptShared) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (shared_mlps.mlpl_first != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&shared_mlps.mlpl_rwlock, RW_READER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = shared_mlps.mlpl_first; tme != NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tme = tme->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (proto == tme->mlpe_mlp.mlp_ipp &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port >= tme->mlpe_mlp.mlp_port &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port <= tme->mlpe_mlp.mlp_port_upper)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&shared_mlps.mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tme == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mlptype == mlptBoth)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlptype = mlptPrivate;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else if (mlptype == mlptShared)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mlptype = mlptSingle;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (mlptype);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_mlp_findzone will check if the given (proto, port) is a multilevel port
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * on a shared address. If it is, return the owning zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: lport is in network byte order, unlike the other MLP functions,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * because the callers of this function are all dealing with packets off the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * wire.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkzoneid_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_mlp_findzone(uchar_t proto, uint16_t lport)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_mlp_entry_t *tme;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zoneid_t zoneid;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint16_t port;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (shared_mlps.mlpl_first == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ALL_ZONES);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port = ntohs(lport);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_enter(&shared_mlps.mlpl_rwlock, RW_READER);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (tme = shared_mlps.mlpl_first; tme != NULL; tme = tme->mlpe_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (proto == tme->mlpe_mlp.mlp_ipp &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port >= tme->mlpe_mlp.mlp_port &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk port <= tme->mlpe_mlp.mlp_port_upper)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zoneid = tme == NULL ? ALL_ZONES : tme->mlpe_zoneid;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rw_exit(&shared_mlps.mlpl_rwlock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (zoneid);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* Debug routine */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_print_label(const blevel_t *blev, const char *name)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const _blevel_impl_t *bli = (const _blevel_impl_t *)blev;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We really support only sensitivity labels */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s %x:%x:%08x%08x%08x%08x%08x%08x%08x%08x",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk name, bli->id, LCLASS(bli), ntohl(bli->_comps.c1),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ntohl(bli->_comps.c2), ntohl(bli->_comps.c3), ntohl(bli->_comps.c4),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ntohl(bli->_comps.c5), ntohl(bli->_comps.c6), ntohl(bli->_comps.c7),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ntohl(bli->_comps.c8));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Name: labelsys()
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Normal: Routes TSOL syscalls.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Output: As defined for each TSOL syscall.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns ENOSYS for unrecognized calls.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabelsys(int op, void *a1, void *a2, void *a3, void *a4, void *a5)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (op) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TSOL_SYSLABELING:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (sys_labeling);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TSOL_TNRH:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (tnrh((int)(uintptr_t)a1, a2));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TSOL_TNRHTP:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (tnrhtp((int)(uintptr_t)a1, a2));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TSOL_TNMLP:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (tnmlp((int)(uintptr_t)a1, a2));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TSOL_GETLABEL:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (getlabel((char *)a1, (bslabel_t *)a2));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case TSOL_FGETLABEL:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (fgetlabel((int)(uintptr_t)a1, (bslabel_t *)a2));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(ENOSYS));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* NOTREACHED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}