Home | History | Annotate | Download | only in ip
      1   1676         jpk /*
      2   1676         jpk  * CDDL HEADER START
      3   1676         jpk  *
      4   1676         jpk  * The contents of this file are subject to the terms of the
      5   1676         jpk  * Common Development and Distribution License (the "License").
      6   1676         jpk  * You may not use this file except in compliance with the License.
      7   1676         jpk  *
      8   1676         jpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9   1676         jpk  * or http://www.opensolaris.org/os/licensing.
     10   1676         jpk  * See the License for the specific language governing permissions
     11   1676         jpk  * and limitations under the License.
     12   1676         jpk  *
     13   1676         jpk  * When distributing Covered Code, include this CDDL HEADER in each
     14   1676         jpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15   1676         jpk  * If applicable, add the following below this CDDL HEADER, with the
     16   1676         jpk  * fields enclosed by brackets "[]" replaced with your own identifying
     17   1676         jpk  * information: Portions Copyright [yyyy] [name of copyright owner]
     18   1676         jpk  *
     19   1676         jpk  * CDDL HEADER END
     20   1676         jpk  */
     21   1676         jpk /*
     22   8778        Erik  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23   1676         jpk  * Use is subject to license terms.
     24   1676         jpk  */
     25   1676         jpk 
     26   1676         jpk #include <sys/types.h>
     27   1676         jpk #include <sys/stream.h>
     28   1676         jpk #include <sys/strsubr.h>
     29   1676         jpk #include <sys/stropts.h>
     30   1676         jpk #include <sys/sunddi.h>
     31   1676         jpk #include <sys/cred.h>
     32   1676         jpk #include <sys/debug.h>
     33   1676         jpk #include <sys/kmem.h>
     34   1676         jpk #include <sys/errno.h>
     35   1676         jpk #include <sys/disp.h>
     36   1676         jpk #include <netinet/in.h>
     37   1676         jpk #include <netinet/in_systm.h>
     38   1676         jpk #include <netinet/ip.h>
     39   1676         jpk #include <netinet/ip_icmp.h>
     40   1676         jpk #include <netinet/tcp.h>
     41   1676         jpk #include <inet/common.h>
     42   1676         jpk #include <inet/ipclassifier.h>
     43   1676         jpk #include <inet/ip.h>
     44   1676         jpk #include <inet/mib2.h>
     45   1676         jpk #include <inet/nd.h>
     46   1676         jpk #include <inet/tcp.h>
     47   1676         jpk #include <inet/ip_rts.h>
     48   1676         jpk #include <inet/ip_ire.h>
     49   1676         jpk #include <inet/ip_if.h>
     50   1676         jpk #include <sys/modhash.h>
     51   1676         jpk 
     52   1676         jpk #include <sys/tsol/label.h>
     53   1676         jpk #include <sys/tsol/label_macro.h>
     54   1676         jpk #include <sys/tsol/tnet.h>
     55   1676         jpk #include <sys/tsol/tndb.h>
     56   1676         jpk #include <sys/strsun.h>
     57   1676         jpk 
     58   1676         jpk /* tunable for strict error-reply behavior (TCP RST and ICMP Unreachable) */
     59   1676         jpk int tsol_strict_error;
     60   1676         jpk 
     61   1676         jpk /*
     62   1676         jpk  * Some notes on the Trusted Solaris IRE gateway security attributes:
     63   1676         jpk  *
     64   1676         jpk  * When running in Trusted mode, the routing subsystem determines whether or
     65   1676         jpk  * not a packet can be delivered to an off-link host (not directly reachable
     66   1676         jpk  * through an interface) based on the accreditation checks of the packet's
     67   1676         jpk  * security attributes against those associated with the next-hop gateway.
     68   1676         jpk  *
     69   1676         jpk  * The next-hop gateway's security attributes can be derived from two sources
     70   1676         jpk  * (in order of preference): route-related and the host database.  A Trusted
     71   1676         jpk  * system must be configured with at least the host database containing an
     72   1676         jpk  * entry for the next-hop gateway, or otherwise no accreditation checks can
     73   1676         jpk  * be performed, which may result in the inability to send packets to any
     74   1676         jpk  * off-link destination host.
     75   1676         jpk  *
     76   1676         jpk  * The major differences between the two sources are the number and type of
     77   1676         jpk  * security attributes used for accreditation checks.  A host database entry
     78   1676         jpk  * can contain at most one set of security attributes, specific only to the
     79   1676         jpk  * next-hop gateway.  On contrast, route-related security attributes are made
     80   1676         jpk  * up of a collection of security attributes for the distant networks, and
     81   1676         jpk  * are grouped together per next-hop gateway used to reach those networks.
     82   1676         jpk  * This is the preferred method, and the routing subsystem will fallback to
     83   1676         jpk  * the host database entry only if there are no route-related attributes
     84   1676         jpk  * associated with the next-hop gateway.
     85   1676         jpk  *
     86   1676         jpk  * In Trusted mode, all of the IRE entries (except LOCAL/LOOPBACK/BROADCAST/
     87   1676         jpk  * INTERFACE type) are initialized to contain a placeholder to store this
     88   1676         jpk  * information.  The ire_gw_secattr structure gets allocated, initialized
     89   1676         jpk  * and associated with the IRE during the time of the IRE creation.  The
     90   1676         jpk  * initialization process also includes resolving the host database entry
     91   1676         jpk  * of the next-hop gateway for fallback purposes.  It does not include any
     92   1676         jpk  * route-related attribute setup, as that process comes separately as part
     93   1676         jpk  * of the route requests (add/change) made to the routing subsystem.
     94   1676         jpk  *
     95   1676         jpk  * The underlying logic which involves associating IREs with the gateway
     96   1676         jpk  * security attributes are represented by the following data structures:
     97   1676         jpk  *
     98   1676         jpk  * tsol_gcdb_t, or "gcdb"
     99   1676         jpk  *
    100   1676         jpk  *	- This is a system-wide collection of records containing the
    101   1676         jpk  *	  currently used route-related security attributes, which are fed
    102   1676         jpk  *	  through the routing socket interface, e.g. "route add/change".
    103   1676         jpk  *
    104   1676         jpk  * tsol_gc_t, or "gc"
    105   1676         jpk  *
    106   1676         jpk  *	- This is the gateway credential structure, and it provides for the
    107   1676         jpk  *	  only mechanism to access the contents of gcdb.  More than one gc
    108   1676         jpk  *	  entries may refer to the same gcdb record.  gc's in the system are
    109   1676         jpk  *	  grouped according to the next-hop gateway address.
    110   1676         jpk  *
    111   1676         jpk  * tsol_gcgrp_t, or "gcgrp"
    112   1676         jpk  *
    113   1676         jpk  *	- Group of gateway credentials, and is unique per next-hop gateway
    114   1676         jpk  *	  address.  When the group is not empty, i.e. when gcgrp_count is
    115   1676         jpk  *	  greater than zero, it contains one or more gc's, each pointing to
    116   1676         jpk  *	  a gcdb record which indicates the gateway security attributes
    117   1676         jpk  *	  associated with the next-hop gateway.
    118   1676         jpk  *
    119   1676         jpk  * The fields of the tsol_ire_gw_secattr_t used from within the IRE are:
    120   1676         jpk  *
    121   1676         jpk  * igsa_lock
    122   1676         jpk  *
    123   1676         jpk  *	- Lock that protects all fields within tsol_ire_gw_secattr_t.
    124   1676         jpk  *
    125   1676         jpk  * igsa_rhc
    126   1676         jpk  *
    127   1676         jpk  *	- Remote host cache database entry of next-hop gateway.  This is
    128   1676         jpk  *	  used in the case when there are no route-related attributes
    129   1676         jpk  *	  configured for the IRE.
    130   1676         jpk  *
    131   1676         jpk  * igsa_gc
    132   1676         jpk  *
    133   1676         jpk  *	- A set of route-related attributes that only get set for prefix
    134   1676         jpk  *	  IREs.  If this is non-NULL, the prefix IRE has been associated
    135   1676         jpk  *	  with a set of gateway security attributes by way of route add/
    136  11042        Erik  *	  change functionality.
    137   1676         jpk  */
    138   1676         jpk 
    139   1676         jpk static kmem_cache_t *ire_gw_secattr_cache;
    140   1676         jpk 
    141   1676         jpk #define	GCDB_HASH_SIZE	101
    142   1676         jpk #define	GCGRP_HASH_SIZE	101
    143   1676         jpk 
    144   1676         jpk #define	GCDB_REFRELE(p) {		\
    145   1676         jpk 	mutex_enter(&gcdb_lock);	\
    146   1676         jpk 	ASSERT((p)->gcdb_refcnt > 0);	\
    147   1676         jpk 	if (--((p)->gcdb_refcnt) == 0)	\
    148   1676         jpk 		gcdb_inactive(p);	\
    149   1676         jpk 	ASSERT(MUTEX_HELD(&gcdb_lock));	\
    150   1676         jpk 	mutex_exit(&gcdb_lock);		\
    151   1676         jpk }
    152   1676         jpk 
    153   1676         jpk static int gcdb_hash_size = GCDB_HASH_SIZE;
    154   1676         jpk static int gcgrp_hash_size = GCGRP_HASH_SIZE;
    155   1676         jpk static mod_hash_t *gcdb_hash;
    156   1676         jpk static mod_hash_t *gcgrp4_hash;
    157   1676         jpk static mod_hash_t *gcgrp6_hash;
    158   1676         jpk 
    159   1676         jpk static kmutex_t gcdb_lock;
    160   1676         jpk kmutex_t gcgrp_lock;
    161   1676         jpk 
    162   1676         jpk static uint_t gcdb_hash_by_secattr(void *, mod_hash_key_t);
    163   1676         jpk static int gcdb_hash_cmp(mod_hash_key_t, mod_hash_key_t);
    164   1676         jpk static tsol_gcdb_t *gcdb_lookup(struct rtsa_s *, boolean_t);
    165   1676         jpk static void gcdb_inactive(tsol_gcdb_t *);
    166   1676         jpk 
    167   1676         jpk static uint_t gcgrp_hash_by_addr(void *, mod_hash_key_t);
    168   1676         jpk static int gcgrp_hash_cmp(mod_hash_key_t, mod_hash_key_t);
    169   1676         jpk 
    170   1676         jpk static int ire_gw_secattr_constructor(void *, void *, int);
    171   1676         jpk static void ire_gw_secattr_destructor(void *, void *);
    172   1676         jpk 
    173   1676         jpk void
    174   1676         jpk tnet_init(void)
    175   1676         jpk {
    176   1676         jpk 	ire_gw_secattr_cache = kmem_cache_create("ire_gw_secattr_cache",
    177   1676         jpk 	    sizeof (tsol_ire_gw_secattr_t), 64, ire_gw_secattr_constructor,
    178   1676         jpk 	    ire_gw_secattr_destructor, NULL, NULL, NULL, 0);
    179   1676         jpk 
    180   1676         jpk 	gcdb_hash = mod_hash_create_extended("gcdb_hash",
    181   1676         jpk 	    gcdb_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
    182   1676         jpk 	    gcdb_hash_by_secattr, NULL, gcdb_hash_cmp, KM_SLEEP);
    183   1676         jpk 
    184   1676         jpk 	gcgrp4_hash = mod_hash_create_extended("gcgrp4_hash",
    185   1676         jpk 	    gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
    186   1676         jpk 	    gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP);
    187   1676         jpk 
    188   1676         jpk 	gcgrp6_hash = mod_hash_create_extended("gcgrp6_hash",
    189   1676         jpk 	    gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
    190   1676         jpk 	    gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP);
    191   1676         jpk 
    192   1676         jpk 	mutex_init(&gcdb_lock, NULL, MUTEX_DEFAULT, NULL);
    193   1676         jpk 	mutex_init(&gcgrp_lock, NULL, MUTEX_DEFAULT, NULL);
    194   1676         jpk }
    195   1676         jpk 
    196   1676         jpk void
    197   1676         jpk tnet_fini(void)
    198   1676         jpk {
    199   1676         jpk 	kmem_cache_destroy(ire_gw_secattr_cache);
    200   1676         jpk 	mod_hash_destroy_hash(gcdb_hash);
    201   1676         jpk 	mod_hash_destroy_hash(gcgrp4_hash);
    202   1676         jpk 	mod_hash_destroy_hash(gcgrp6_hash);
    203   1676         jpk 	mutex_destroy(&gcdb_lock);
    204   1676         jpk 	mutex_destroy(&gcgrp_lock);
    205   1676         jpk }
    206   1676         jpk 
    207   1676         jpk /* ARGSUSED */
    208   1676         jpk static int
    209   1676         jpk ire_gw_secattr_constructor(void *buf, void *cdrarg, int kmflags)
    210   1676         jpk {
    211   1676         jpk 	tsol_ire_gw_secattr_t *attrp = buf;
    212   1676         jpk 
    213   1676         jpk 	mutex_init(&attrp->igsa_lock, NULL, MUTEX_DEFAULT, NULL);
    214   1676         jpk 
    215   1676         jpk 	attrp->igsa_rhc = NULL;
    216   1676         jpk 	attrp->igsa_gc = NULL;
    217   1676         jpk 
    218   1676         jpk 	return (0);
    219   1676         jpk }
    220   1676         jpk 
    221   1676         jpk /* ARGSUSED */
    222   1676         jpk static void
    223   1676         jpk ire_gw_secattr_destructor(void *buf, void *cdrarg)
    224   1676         jpk {
    225   1676         jpk 	tsol_ire_gw_secattr_t *attrp = (tsol_ire_gw_secattr_t *)buf;
    226   1676         jpk 
    227   1676         jpk 	mutex_destroy(&attrp->igsa_lock);
    228   1676         jpk }
    229   1676         jpk 
    230   1676         jpk tsol_ire_gw_secattr_t *
    231   1676         jpk ire_gw_secattr_alloc(int kmflags)
    232   1676         jpk {
    233   1676         jpk 	return (kmem_cache_alloc(ire_gw_secattr_cache, kmflags));
    234   1676         jpk }
    235   1676         jpk 
    236   1676         jpk void
    237   1676         jpk ire_gw_secattr_free(tsol_ire_gw_secattr_t *attrp)
    238   1676         jpk {
    239   1676         jpk 	ASSERT(MUTEX_NOT_HELD(&attrp->igsa_lock));
    240   1676         jpk 
    241   1676         jpk 	if (attrp->igsa_rhc != NULL) {
    242   1676         jpk 		TNRHC_RELE(attrp->igsa_rhc);
    243   1676         jpk 		attrp->igsa_rhc = NULL;
    244   1676         jpk 	}
    245   1676         jpk 
    246   1676         jpk 	if (attrp->igsa_gc != NULL) {
    247   1676         jpk 		GC_REFRELE(attrp->igsa_gc);
    248   1676         jpk 		attrp->igsa_gc = NULL;
    249   1676         jpk 	}
    250   1676         jpk 
    251   1676         jpk 	ASSERT(attrp->igsa_rhc == NULL);
    252   1676         jpk 	ASSERT(attrp->igsa_gc == NULL);
    253   1676         jpk 
    254   1676         jpk 	kmem_cache_free(ire_gw_secattr_cache, attrp);
    255   1676         jpk }
    256   1676         jpk 
    257   1676         jpk /* ARGSUSED */
    258   1676         jpk static uint_t
    259   1676         jpk gcdb_hash_by_secattr(void *hash_data, mod_hash_key_t key)
    260   1676         jpk {
    261   1676         jpk 	const struct rtsa_s *rp = (struct rtsa_s *)key;
    262   1676         jpk 	const uint32_t *up, *ue;
    263   1676         jpk 	uint_t hash;
    264   1676         jpk 	int i;
    265   1676         jpk 
    266   1676         jpk 	ASSERT(rp != NULL);
    267   1676         jpk 
    268   1676         jpk 	/* See comments in hash_bylabel in zone.c for details */
    269   1676         jpk 	hash = rp->rtsa_doi + (rp->rtsa_doi << 1);
    270   1676         jpk 	up = (const uint32_t *)&rp->rtsa_slrange;
    271   1676         jpk 	ue = up + sizeof (rp->rtsa_slrange) / sizeof (*up);
    272   1676         jpk 	i = 1;
    273   1676         jpk 	while (up < ue) {
    274   1676         jpk 		/* using 2^n + 1, 1 <= n <= 16 as source of many primes */
    275   1676         jpk 		hash += *up + (*up << ((i % 16) + 1));
    276   1676         jpk 		up++;
    277   1676         jpk 		i++;
    278   1676         jpk 	}
    279   1676         jpk 	return (hash);
    280   1676         jpk }
    281   1676         jpk 
    282   1676         jpk static int
    283   1676         jpk gcdb_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
    284   1676         jpk {
    285   1676         jpk 	struct rtsa_s *rp1 = (struct rtsa_s *)key1;
    286   1676         jpk 	struct rtsa_s *rp2 = (struct rtsa_s *)key2;
    287   1676         jpk 
    288   1676         jpk 	ASSERT(rp1 != NULL && rp2 != NULL);
    289   1676         jpk 
    290   1676         jpk 	if (blequal(&rp1->rtsa_slrange.lower_bound,
    291   1676         jpk 	    &rp2->rtsa_slrange.lower_bound) &&
    292   1676         jpk 	    blequal(&rp1->rtsa_slrange.upper_bound,
    293   1676         jpk 	    &rp2->rtsa_slrange.upper_bound) &&
    294   1676         jpk 	    rp1->rtsa_doi == rp2->rtsa_doi)
    295   1676         jpk 		return (0);
    296   1676         jpk 
    297   1676         jpk 	/* No match; not found */
    298   1676         jpk 	return (-1);
    299   1676         jpk }
    300   1676         jpk 
    301   1676         jpk /* ARGSUSED */
    302   1676         jpk static uint_t
    303   1676         jpk gcgrp_hash_by_addr(void *hash_data, mod_hash_key_t key)
    304   1676         jpk {
    305   1676         jpk 	tsol_gcgrp_addr_t *ga = (tsol_gcgrp_addr_t *)key;
    306   1676         jpk 	uint_t		idx = 0;
    307   1676         jpk 	uint32_t	*ap;
    308   1676         jpk 
    309   1676         jpk 	ASSERT(ga != NULL);
    310   1676         jpk 	ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
    311   1676         jpk 
    312   1676         jpk 	ap = (uint32_t *)&ga->ga_addr.s6_addr32[0];
    313   1676         jpk 	idx ^= *ap++;
    314   1676         jpk 	idx ^= *ap++;
    315   1676         jpk 	idx ^= *ap++;
    316   1676         jpk 	idx ^= *ap;
    317   1676         jpk 
    318   1676         jpk 	return (idx);
    319   1676         jpk }
    320   1676         jpk 
    321   1676         jpk static int
    322   1676         jpk gcgrp_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
    323   1676         jpk {
    324   1676         jpk 	tsol_gcgrp_addr_t *ga1 = (tsol_gcgrp_addr_t *)key1;
    325   1676         jpk 	tsol_gcgrp_addr_t *ga2 = (tsol_gcgrp_addr_t *)key2;
    326   1676         jpk 
    327   1676         jpk 	ASSERT(ga1 != NULL && ga2 != NULL);
    328   1676         jpk 
    329   1676         jpk 	/* Address family must match */
    330   1676         jpk 	if (ga1->ga_af != ga2->ga_af)
    331   1676         jpk 		return (-1);
    332   1676         jpk 
    333   1676         jpk 	if (ga1->ga_addr.s6_addr32[0] == ga2->ga_addr.s6_addr32[0] &&
    334   1676         jpk 	    ga1->ga_addr.s6_addr32[1] == ga2->ga_addr.s6_addr32[1] &&
    335   1676         jpk 	    ga1->ga_addr.s6_addr32[2] == ga2->ga_addr.s6_addr32[2] &&
    336   1676         jpk 	    ga1->ga_addr.s6_addr32[3] == ga2->ga_addr.s6_addr32[3])
    337   1676         jpk 		return (0);
    338   1676         jpk 
    339   1676         jpk 	/* No match; not found */
    340   1676         jpk 	return (-1);
    341   1676         jpk }
    342   1676         jpk 
    343   1676         jpk #define	RTSAFLAGS	"\20\11cipso\3doi\2max_sl\1min_sl"
    344   1676         jpk 
    345   1676         jpk int
    346   1676         jpk rtsa_validate(const struct rtsa_s *rp)
    347   1676         jpk {
    348   1676         jpk 	uint32_t mask = rp->rtsa_mask;
    349   1676         jpk 
    350   1676         jpk 	/* RTSA_CIPSO must be set, and DOI must not be zero */
    351   1676         jpk 	if ((mask & RTSA_CIPSO) == 0 || rp->rtsa_doi == 0) {
    352   1676         jpk 		DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
    353   1676         jpk 		    "rtsa(1) lacks flag or has 0 doi.",
    354   1676         jpk 		    rtsa_s *, rp);
    355   1676         jpk 		return (EINVAL);
    356   1676         jpk 	}
    357   1676         jpk 	/*
    358   1676         jpk 	 * SL range must be specified, and it must have its
    359   1676         jpk 	 * upper bound dominating its lower bound.
    360   1676         jpk 	 */
    361   1676         jpk 	if ((mask & RTSA_SLRANGE) != RTSA_SLRANGE ||
    362   1676         jpk 	    !bldominates(&rp->rtsa_slrange.upper_bound,
    363   1676         jpk 	    &rp->rtsa_slrange.lower_bound)) {
    364   1676         jpk 		DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
    365   1676         jpk 		    "rtsa(1) min_sl and max_sl not set or max_sl is "
    366   1676         jpk 		    "not dominating.", rtsa_s *, rp);
    367   1676         jpk 		return (EINVAL);
    368   1676         jpk 	}
    369   1676         jpk 	return (0);
    370   1676         jpk }
    371   1676         jpk 
    372   1676         jpk /*
    373   1676         jpk  * A brief explanation of the reference counting scheme:
    374   1676         jpk  *
    375   1676         jpk  * Apart from dynamic references due to to reference holds done
    376   1676         jpk  * actively by threads, we have the following references:
    377   1676         jpk  *
    378   1676         jpk  * gcdb_refcnt:
    379   1676         jpk  *	- Every tsol_gc_t pointing to a tsol_gcdb_t contributes a reference
    380   1676         jpk  *	  to the gcdb_refcnt.
    381   1676         jpk  *
    382   1676         jpk  * gc_refcnt:
    383   1676         jpk  *	- A prefix IRE that points to an igsa_gc contributes a reference
    384   1676         jpk  *	  to the gc_refcnt.
    385   1676         jpk  *
    386   1676         jpk  * gcgrp_refcnt:
    387   1676         jpk  *	- Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes
    388   1676         jpk  *	  a reference to the gcgrp_refcnt.
    389   1676         jpk  */
    390   1676         jpk static tsol_gcdb_t *
    391   1676         jpk gcdb_lookup(struct rtsa_s *rp, boolean_t alloc)
    392   1676         jpk {
    393   1676         jpk 	tsol_gcdb_t *gcdb = NULL;
    394   1676         jpk 
    395   1676         jpk 	if (rtsa_validate(rp) != 0)
    396   1676         jpk 		return (NULL);
    397   1676         jpk 
    398   1676         jpk 	mutex_enter(&gcdb_lock);
    399   1676         jpk 	/* Find a copy in the cache; otherwise, create one and cache it */
    400   1676         jpk 	if (mod_hash_find(gcdb_hash, (mod_hash_key_t)rp,
    401   1676         jpk 	    (mod_hash_val_t *)&gcdb) == 0) {
    402   1676         jpk 		gcdb->gcdb_refcnt++;
    403   1676         jpk 		ASSERT(gcdb->gcdb_refcnt != 0);
    404   1676         jpk 
    405   1676         jpk 		DTRACE_PROBE2(tx__gcdb__log__info__gcdb__lookup, char *,
    406   1676         jpk 		    "gcdb(1) is in gcdb_hash(global)", tsol_gcdb_t *, gcdb);
    407   1676         jpk 	} else if (alloc) {
    408   1676         jpk 		gcdb = kmem_zalloc(sizeof (*gcdb), KM_NOSLEEP);
    409   1676         jpk 		if (gcdb != NULL) {
    410   1676         jpk 			gcdb->gcdb_refcnt = 1;
    411   1676         jpk 			gcdb->gcdb_mask = rp->rtsa_mask;
    412   1676         jpk 			gcdb->gcdb_doi = rp->rtsa_doi;
    413   1676         jpk 			gcdb->gcdb_slrange = rp->rtsa_slrange;
    414   1676         jpk 
    415   1676         jpk 			if (mod_hash_insert(gcdb_hash,
    416   1676         jpk 			    (mod_hash_key_t)&gcdb->gcdb_attr,
    417   1676         jpk 			    (mod_hash_val_t)gcdb) != 0) {
    418   1676         jpk 				mutex_exit(&gcdb_lock);
    419   1676         jpk 				kmem_free(gcdb, sizeof (*gcdb));
    420   1676         jpk 				return (NULL);
    421   1676         jpk 			}
    422   1676         jpk 
    423   1676         jpk 			DTRACE_PROBE2(tx__gcdb__log__info__gcdb__insert, char *,
    424   1676         jpk 			    "gcdb(1) inserted in gcdb_hash(global)",
    425   1676         jpk 			    tsol_gcdb_t *, gcdb);
    426   1676         jpk 		}
    427   1676         jpk 	}
    428   1676         jpk 	mutex_exit(&gcdb_lock);
    429   1676         jpk 	return (gcdb);
    430   1676         jpk }
    431   1676         jpk 
    432   1676         jpk static void
    433   1676         jpk gcdb_inactive(tsol_gcdb_t *gcdb)
    434   1676         jpk {
    435   1676         jpk 	ASSERT(MUTEX_HELD(&gcdb_lock));
    436   1676         jpk 	ASSERT(gcdb != NULL && gcdb->gcdb_refcnt == 0);
    437   1676         jpk 
    438   1676         jpk 	(void) mod_hash_remove(gcdb_hash, (mod_hash_key_t)&gcdb->gcdb_attr,
    439   1676         jpk 	    (mod_hash_val_t *)&gcdb);
    440   1676         jpk 
    441   1676         jpk 	DTRACE_PROBE2(tx__gcdb__log__info__gcdb__remove, char *,
    442   1676         jpk 	    "gcdb(1) removed from gcdb_hash(global)",
    443   1676         jpk 	    tsol_gcdb_t *, gcdb);
    444   1676         jpk 	kmem_free(gcdb, sizeof (*gcdb));
    445   1676         jpk }
    446   1676         jpk 
    447   1676         jpk tsol_gc_t *
    448   1676         jpk gc_create(struct rtsa_s *rp, tsol_gcgrp_t *gcgrp, boolean_t *gcgrp_xtrarefp)
    449   1676         jpk {
    450   1676         jpk 	tsol_gc_t *gc;
    451   1676         jpk 	tsol_gcdb_t *gcdb;
    452   1676         jpk 
    453   1676         jpk 	*gcgrp_xtrarefp = B_TRUE;
    454   1676         jpk 
    455   1676         jpk 	rw_enter(&gcgrp->gcgrp_rwlock, RW_WRITER);
    456   1676         jpk 	if ((gcdb = gcdb_lookup(rp, B_TRUE)) == NULL) {
    457   1676         jpk 		rw_exit(&gcgrp->gcgrp_rwlock);
    458   1676         jpk 		return (NULL);
    459   1676         jpk 	}
    460   1676         jpk 
    461   1676         jpk 	for (gc = gcgrp->gcgrp_head; gc != NULL; gc = gc->gc_next) {
    462   1676         jpk 		if (gc->gc_db == gcdb) {
    463   1676         jpk 			ASSERT(gc->gc_grp == gcgrp);
    464   1676         jpk 
    465   1676         jpk 			gc->gc_refcnt++;
    466   1676         jpk 			ASSERT(gc->gc_refcnt != 0);
    467   1676         jpk 
    468   1676         jpk 			GCDB_REFRELE(gcdb);
    469   1676         jpk 
    470   1676         jpk 			DTRACE_PROBE3(tx__gcdb__log__info__gc__create,
    471   1676         jpk 			    char *, "found gc(1) in gcgrp(2)",
    472   1676         jpk 			    tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp);
    473   1676         jpk 			rw_exit(&gcgrp->gcgrp_rwlock);
    474   1676         jpk 			return (gc);
    475   1676         jpk 		}
    476   1676         jpk 	}
    477   1676         jpk 
    478   1676         jpk 	gc = kmem_zalloc(sizeof (*gc), KM_NOSLEEP);
    479   1676         jpk 	if (gc != NULL) {
    480   1676         jpk 		if (gcgrp->gcgrp_head == NULL) {
    481   1676         jpk 			gcgrp->gcgrp_head = gcgrp->gcgrp_tail = gc;
    482   1676         jpk 		} else {
    483   1676         jpk 			gcgrp->gcgrp_tail->gc_next = gc;
    484   1676         jpk 			gc->gc_prev = gcgrp->gcgrp_tail;
    485   1676         jpk 			gcgrp->gcgrp_tail = gc;
    486   1676         jpk 		}
    487   1676         jpk 		gcgrp->gcgrp_count++;
    488   1676         jpk 		ASSERT(gcgrp->gcgrp_count != 0);
    489   1676         jpk 
    490   1676         jpk 		/* caller has incremented gcgrp reference for us */
    491   1676         jpk 		gc->gc_grp = gcgrp;
    492   1676         jpk 
    493   1676         jpk 		gc->gc_db = gcdb;
    494   1676         jpk 		gc->gc_refcnt = 1;
    495   1676         jpk 
    496   1676         jpk 		DTRACE_PROBE3(tx__gcdb__log__info__gc__create, char *,
    497   1676         jpk 		    "added gc(1) to gcgrp(2)", tsol_gc_t *, gc,
    498   1676         jpk 		    tsol_gcgrp_t *, gcgrp);
    499   1676         jpk 
    500   1676         jpk 		*gcgrp_xtrarefp = B_FALSE;
    501   1676         jpk 	}
    502   1676         jpk 	rw_exit(&gcgrp->gcgrp_rwlock);
    503   1676         jpk 
    504   1676         jpk 	return (gc);
    505   1676         jpk }
    506   1676         jpk 
    507   1676         jpk void
    508   1676         jpk gc_inactive(tsol_gc_t *gc)
    509   1676         jpk {
    510   1676         jpk 	tsol_gcgrp_t *gcgrp = gc->gc_grp;
    511   1676         jpk 
    512   1676         jpk 	ASSERT(gcgrp != NULL);
    513   1676         jpk 	ASSERT(RW_WRITE_HELD(&gcgrp->gcgrp_rwlock));
    514   1676         jpk 	ASSERT(gc->gc_refcnt == 0);
    515   1676         jpk 
    516   1676         jpk 	if (gc->gc_prev != NULL)
    517   1676         jpk 		gc->gc_prev->gc_next = gc->gc_next;
    518   1676         jpk 	else
    519   1676         jpk 		gcgrp->gcgrp_head = gc->gc_next;
    520   1676         jpk 	if (gc->gc_next != NULL)
    521   1676         jpk 		gc->gc_next->gc_prev = gc->gc_prev;
    522   1676         jpk 	else
    523   1676         jpk 		gcgrp->gcgrp_tail = gc->gc_prev;
    524   1676         jpk 	ASSERT(gcgrp->gcgrp_count > 0);
    525   1676         jpk 	gcgrp->gcgrp_count--;
    526   1676         jpk 
    527   1676         jpk 	/* drop lock before it's destroyed */
    528   1676         jpk 	rw_exit(&gcgrp->gcgrp_rwlock);
    529   1676         jpk 
    530   1676         jpk 	DTRACE_PROBE3(tx__gcdb__log__info__gc__remove, char *,
    531   1676         jpk 	    "removed inactive gc(1) from gcgrp(2)",
    532   1676         jpk 	    tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp);
    533   1676         jpk 
    534   1676         jpk 	GCGRP_REFRELE(gcgrp);
    535   1676         jpk 
    536   1676         jpk 	gc->gc_grp = NULL;
    537   1676         jpk 	gc->gc_prev = gc->gc_next = NULL;
    538   1676         jpk 
    539   1676         jpk 	if (gc->gc_db != NULL)
    540   1676         jpk 		GCDB_REFRELE(gc->gc_db);
    541   1676         jpk 
    542   1676         jpk 	kmem_free(gc, sizeof (*gc));
    543   1676         jpk }
    544   1676         jpk 
    545   1676         jpk tsol_gcgrp_t *
    546   1676         jpk gcgrp_lookup(tsol_gcgrp_addr_t *ga, boolean_t alloc)
    547   1676         jpk {
    548   1676         jpk 	tsol_gcgrp_t *gcgrp = NULL;
    549   1676         jpk 	mod_hash_t *hashp;
    550   1676         jpk 
    551   1676         jpk 	ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
    552   1676         jpk 
    553   1676         jpk 	hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
    554   1676         jpk 
    555   1676         jpk 	mutex_enter(&gcgrp_lock);
    556   1676         jpk 	if (mod_hash_find(hashp, (mod_hash_key_t)ga,
    557   1676         jpk 	    (mod_hash_val_t *)&gcgrp) == 0) {
    558   1676         jpk 		gcgrp->gcgrp_refcnt++;
    559   1676         jpk 		ASSERT(gcgrp->gcgrp_refcnt != 0);
    560   1676         jpk 
    561   1676         jpk 		DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__lookup, char *,
    562   1676         jpk 		    "found gcgrp(1) in hash(2)", tsol_gcgrp_t *, gcgrp,
    563   1676         jpk 		    mod_hash_t *, hashp);
    564   1676         jpk 
    565   1676         jpk 	} else if (alloc) {
    566   1676         jpk 		gcgrp = kmem_zalloc(sizeof (*gcgrp), KM_NOSLEEP);
    567   1676         jpk 		if (gcgrp != NULL) {
    568   1676         jpk 			gcgrp->gcgrp_refcnt = 1;
    569   1676         jpk 			rw_init(&gcgrp->gcgrp_rwlock, NULL, RW_DEFAULT, NULL);
    570   1676         jpk 			bcopy(ga, &gcgrp->gcgrp_addr, sizeof (*ga));
    571   1676         jpk 
    572   1676         jpk 			if (mod_hash_insert(hashp,
    573   1676         jpk 			    (mod_hash_key_t)&gcgrp->gcgrp_addr,
    574   1676         jpk 			    (mod_hash_val_t)gcgrp) != 0) {
    575   1676         jpk 				mutex_exit(&gcgrp_lock);
    576   1676         jpk 				kmem_free(gcgrp, sizeof (*gcgrp));
    577   1676         jpk 				return (NULL);
    578   1676         jpk 			}
    579   1676         jpk 
    580   1676         jpk 			DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__insert,
    581   1676         jpk 			    char *, "inserted gcgrp(1) in hash(2)",
    582   1676         jpk 			    tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp);
    583   1676         jpk 		}
    584   1676         jpk 	}
    585   1676         jpk 	mutex_exit(&gcgrp_lock);
    586   1676         jpk 	return (gcgrp);
    587   1676         jpk }
    588   1676         jpk 
    589   1676         jpk void
    590   1676         jpk gcgrp_inactive(tsol_gcgrp_t *gcgrp)
    591   1676         jpk {
    592   1676         jpk 	tsol_gcgrp_addr_t *ga;
    593   1676         jpk 	mod_hash_t *hashp;
    594   1676         jpk 
    595   1676         jpk 	ASSERT(MUTEX_HELD(&gcgrp_lock));
    596   1676         jpk 	ASSERT(gcgrp != NULL && gcgrp->gcgrp_refcnt == 0);
    597   1676         jpk 	ASSERT(gcgrp->gcgrp_head == NULL && gcgrp->gcgrp_count == 0);
    598   1676         jpk 
    599   1676         jpk 	ga = &gcgrp->gcgrp_addr;
    600   1676         jpk 	ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
    601   1676         jpk 
    602   1676         jpk 	hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
    603   1676         jpk 	(void) mod_hash_remove(hashp, (mod_hash_key_t)ga,
    604   1676         jpk 	    (mod_hash_val_t *)&gcgrp);
    605   1676         jpk 	rw_destroy(&gcgrp->gcgrp_rwlock);
    606   1676         jpk 
    607   1676         jpk 	DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__remove, char *,
    608   1676         jpk 	    "removed inactive gcgrp(1) from hash(2)",
    609   1676         jpk 	    tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp);
    610   1676         jpk 
    611   1676         jpk 	kmem_free(gcgrp, sizeof (*gcgrp));
    612   1676         jpk }
    613   1676         jpk 
    614  10934  sommerfeld 
    615  10934  sommerfeld /*
    616  10934  sommerfeld  * Assign a sensitivity label to inbound traffic which arrived without
    617  10934  sommerfeld  * an explicit on-the-wire label.
    618  10934  sommerfeld  *
    619  10934  sommerfeld  * In the case of CIPSO-type hosts, we assume packets arriving without
    620  10934  sommerfeld  * a label are at the most sensitive label known for the host, most
    621  10934  sommerfeld  * likely involving out-of-band key management traffic (such as IKE,
    622  10934  sommerfeld  * etc.,)
    623  10934  sommerfeld  */
    624  10934  sommerfeld static boolean_t
    625  10934  sommerfeld tsol_find_unlabeled_label(tsol_tpc_t *rhtp, bslabel_t *sl, uint32_t *doi)
    626  10934  sommerfeld {
    627  10934  sommerfeld 	*doi = rhtp->tpc_tp.tp_doi;
    628  10934  sommerfeld 	switch (rhtp->tpc_tp.host_type) {
    629  10934  sommerfeld 	case UNLABELED:
    630  10934  sommerfeld 		*sl = rhtp->tpc_tp.tp_def_label;
    631  10934  sommerfeld 		break;
    632  10934  sommerfeld 	case SUN_CIPSO:
    633  10934  sommerfeld 		*sl = rhtp->tpc_tp.tp_sl_range_cipso.upper_bound;
    634  10934  sommerfeld 		break;
    635  10934  sommerfeld 	default:
    636  10934  sommerfeld 		return (B_FALSE);
    637  10934  sommerfeld 	}
    638  10934  sommerfeld 	setbltype(sl, SUN_SL_ID);
    639  10934  sommerfeld 	return (B_TRUE);
    640  10934  sommerfeld }
    641  10934  sommerfeld 
    642   1676         jpk /*
    643   1676         jpk  * Converts CIPSO option to sensitivity label.
    644   1676         jpk  * Validity checks based on restrictions defined in
    645   1676         jpk  * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) (draft-ietf-cipso-ipsecurity)
    646   1676         jpk  */
    647   1676         jpk static boolean_t
    648   1676         jpk cipso_to_sl(const uchar_t *option, bslabel_t *sl)
    649   1676         jpk {
    650   1676         jpk 	const struct cipso_option *co = (const struct cipso_option *)option;
    651   1676         jpk 	const struct cipso_tag_type_1 *tt1;
    652   1676         jpk 
    653   1676         jpk 	tt1 = (struct cipso_tag_type_1 *)&co->cipso_tag_type[0];
    654   1676         jpk 	if (tt1->tag_type != 1 ||
    655   1676         jpk 	    tt1->tag_length < TSOL_TT1_MIN_LENGTH ||
    656   1676         jpk 	    tt1->tag_length > TSOL_TT1_MAX_LENGTH ||
    657   1676         jpk 	    tt1->tag_length + TSOL_CIPSO_TAG_OFFSET > co->cipso_length)
    658   1676         jpk 		return (B_FALSE);
    659   1676         jpk 
    660   1676         jpk 	bsllow(sl);	/* assumed: sets compartments to all zeroes */
    661   1676         jpk 	LCLASS_SET((_bslabel_impl_t *)sl, tt1->tag_sl);
    662   1676         jpk 	bcopy(tt1->tag_cat, &((_bslabel_impl_t *)sl)->compartments,
    663   1676         jpk 	    tt1->tag_length - TSOL_TT1_MIN_LENGTH);
    664   1676         jpk 	return (B_TRUE);
    665   1676         jpk }
    666   1676         jpk 
    667   1676         jpk /*
    668  11042        Erik  * If present, parse the CIPSO label in the incoming packet and
    669  11042        Erik  * construct a ts_label_t that reflects the CIPSO label and put it in
    670  11042        Erik  * the ip_recv_attr_t. Later as the packet flows up through the stack any
    671  10934  sommerfeld  * code that needs to examine the packet label can inspect the label
    672  11042        Erik  * from the ira_tsl. This function is
    673  11042        Erik  * called right in ip_input for all packets, i.e. locally destined and
    674  11042        Erik  * to be forwarded packets. The forwarding path needs to examine the label
    675  11042        Erik  * to determine how to forward the packet.
    676   1676         jpk  *
    677  10181         Ken  * This routine pulls all message text up into the first mblk.
    678  10181         Ken  * For IPv4, only the first 20 bytes of the IP header are guaranteed
    679  10181         Ken  * to exist. For IPv6, only the IPv6 header is guaranteed to exist.
    680   1676         jpk  */
    681   1676         jpk boolean_t
    682  11042        Erik tsol_get_pkt_label(mblk_t *mp, int version, ip_recv_attr_t *ira)
    683   1676         jpk {
    684  10934  sommerfeld 	tsol_tpc_t	*src_rhtp = NULL;
    685   1676         jpk 	uchar_t		*opt_ptr = NULL;
    686   1676         jpk 	const ipha_t	*ipha;
    687   1676         jpk 	bslabel_t	sl;
    688   1676         jpk 	uint32_t	doi;
    689   1676         jpk 	tsol_ip_label_t	label_type;
    690  10934  sommerfeld 	uint32_t	label_flags = 0; /* flags to set in label */
    691   1676         jpk 	const cipso_option_t *co;
    692   1676         jpk 	const void	*src;
    693   1676         jpk 	const ip6_t	*ip6h;
    694   8778        Erik 	cred_t		*credp;
    695  10934  sommerfeld 	int 		proto;
    696   1676         jpk 
    697   1676         jpk 	ASSERT(DB_TYPE(mp) == M_DATA);
    698   9710         Ken 
    699   9710         Ken 	if (mp->b_cont != NULL && !pullupmsg(mp, -1))
    700   9710         Ken 		return (B_FALSE);
    701   1676         jpk 
    702   1676         jpk 	if (version == IPV4_VERSION) {
    703  10181         Ken 		ASSERT(MBLKL(mp) >= IP_SIMPLE_HDR_LENGTH);
    704   1676         jpk 		ipha = (const ipha_t *)mp->b_rptr;
    705   1676         jpk 		src = &ipha->ipha_src;
    706  10181         Ken 		if (!tsol_get_option_v4(mp, &label_type, &opt_ptr))
    707  10181         Ken 			return (B_FALSE);
    708   1676         jpk 	} else {
    709  10181         Ken 		ASSERT(MBLKL(mp) >= IPV6_HDR_LEN);
    710   1676         jpk 		ip6h = (const ip6_t *)mp->b_rptr;
    711   1676         jpk 		src = &ip6h->ip6_src;
    712  10181         Ken 		if (!tsol_get_option_v6(mp, &label_type, &opt_ptr))
    713  10181         Ken 			return (B_FALSE);
    714   1676         jpk 	}
    715   1676         jpk 
    716   1676         jpk 	switch (label_type) {
    717   1676         jpk 	case OPT_CIPSO:
    718   1676         jpk 		/*
    719   1676         jpk 		 * Convert the CIPSO label to the internal format
    720   1676         jpk 		 * and attach it to the dblk cred.
    721   1676         jpk 		 * Validity checks based on restrictions defined in
    722   1676         jpk 		 * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
    723   1676         jpk 		 * (draft-ietf-cipso-ipsecurity)
    724   1676         jpk 		 */
    725   1676         jpk 		if (version == IPV6_VERSION && ip6opt_ls == 0)
    726   1676         jpk 			return (B_FALSE);
    727   1676         jpk 		co = (const struct cipso_option *)opt_ptr;
    728   1676         jpk 		if ((co->cipso_length <
    729   1676         jpk 		    TSOL_CIPSO_TAG_OFFSET + TSOL_TT1_MIN_LENGTH) ||
    730   1676         jpk 		    (co->cipso_length > IP_MAX_OPT_LENGTH))
    731   1676         jpk 			return (B_FALSE);
    732   1676         jpk 		bcopy(co->cipso_doi, &doi, sizeof (doi));
    733   1676         jpk 		doi = ntohl(doi);
    734   1676         jpk 		if (!cipso_to_sl(opt_ptr, &sl))
    735   1676         jpk 			return (B_FALSE);
    736   1676         jpk 		setbltype(&sl, SUN_SL_ID);
    737  10934  sommerfeld 
    738  10934  sommerfeld 		/*
    739  10934  sommerfeld 		 * If the source was unlabeled, then flag as such,
    740  10934  sommerfeld 		 * (since CIPSO routers may add headers)
    741  10934  sommerfeld 		 */
    742  10934  sommerfeld 
    743  10934  sommerfeld 		if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
    744  10934  sommerfeld 			return (B_FALSE);
    745  10934  sommerfeld 
    746  10934  sommerfeld 		if (src_rhtp->tpc_tp.host_type == UNLABELED)
    747  10934  sommerfeld 			label_flags = TSLF_UNLABELED;
    748  10934  sommerfeld 
    749  10934  sommerfeld 		TPC_RELE(src_rhtp);
    750  10934  sommerfeld 
    751   1676         jpk 		break;
    752   1676         jpk 
    753   1676         jpk 	case OPT_NONE:
    754   1676         jpk 		/*
    755  10934  sommerfeld 		 * Handle special cases that may not be labeled, even
    756   1676         jpk 		 * though the sending system may otherwise be configured as
    757   1676         jpk 		 * labeled.
    758   1676         jpk 		 *	- IGMP
    759   1676         jpk 		 *	- IPv4 ICMP Router Discovery
    760   1676         jpk 		 *	- IPv6 Neighbor Discovery
    761  10934  sommerfeld 		 *	- IPsec ESP
    762   1676         jpk 		 */
    763   1676         jpk 		if (version == IPV4_VERSION) {
    764  10934  sommerfeld 			proto = ipha->ipha_protocol;
    765  10934  sommerfeld 			if (proto == IPPROTO_IGMP)
    766   1676         jpk 				return (B_TRUE);
    767  10934  sommerfeld 			if (proto == IPPROTO_ICMP) {
    768   1676         jpk 				const struct icmp *icmp = (const struct icmp *)
    769   1676         jpk 				    (mp->b_rptr + IPH_HDR_LENGTH(ipha));
    770   1676         jpk 
    771  10181         Ken 				if ((uchar_t *)icmp + ICMP_MINLEN > mp->b_wptr)
    772  10181         Ken 					return (B_FALSE);
    773   1676         jpk 				if (icmp->icmp_type == ICMP_ROUTERADVERT ||
    774   1676         jpk 				    icmp->icmp_type == ICMP_ROUTERSOLICIT)
    775   1676         jpk 					return (B_TRUE);
    776   1676         jpk 			}
    777   1676         jpk 		} else {
    778  10934  sommerfeld 			proto = ip6h->ip6_nxt;
    779  10934  sommerfeld 			if (proto == IPPROTO_ICMPV6) {
    780   1676         jpk 				const icmp6_t *icmp6 = (const icmp6_t *)
    781   1676         jpk 				    (mp->b_rptr + IPV6_HDR_LEN);
    782   1676         jpk 
    783   1676         jpk 				if ((uchar_t *)icmp6 + ICMP6_MINLEN >
    784  10181         Ken 				    mp->b_wptr)
    785  10181         Ken 					return (B_FALSE);
    786   1676         jpk 				if (icmp6->icmp6_type >= MLD_LISTENER_QUERY &&
    787   1676         jpk 				    icmp6->icmp6_type <= ICMP6_MAX_INFO_TYPE)
    788   1676         jpk 					return (B_TRUE);
    789   1676         jpk 			}
    790   1676         jpk 		}
    791   1676         jpk 
    792   1676         jpk 		/*
    793   1676         jpk 		 * Look up the tnrhtp database and get the implicit label
    794  10934  sommerfeld 		 * that is associated with the sending host and attach
    795   1676         jpk 		 * it to the packet.
    796   1676         jpk 		 */
    797   1676         jpk 		if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
    798   1676         jpk 			return (B_FALSE);
    799   1676         jpk 
    800  10934  sommerfeld 		/*
    801  10934  sommerfeld 		 * If peer is label-aware, mark as "implicit" rather than
    802  10934  sommerfeld 		 * "unlabeled" to cause appropriate mac-exempt processing
    803  10934  sommerfeld 		 * to happen.
    804  10934  sommerfeld 		 */
    805  10934  sommerfeld 		if (src_rhtp->tpc_tp.host_type == SUN_CIPSO)
    806  10934  sommerfeld 			label_flags = TSLF_IMPLICIT_IN;
    807  10934  sommerfeld 		else if (src_rhtp->tpc_tp.host_type == UNLABELED)
    808  10934  sommerfeld 			label_flags = TSLF_UNLABELED;
    809  10934  sommerfeld 		else {
    810  10934  sommerfeld 			DTRACE_PROBE2(tx__get__pkt__label, char *,
    811  10934  sommerfeld 			    "template(1) has unknown hosttype",
    812  10934  sommerfeld 			    tsol_tpc_t *, src_rhtp);
    813  10934  sommerfeld 		}
    814  10934  sommerfeld 
    815  10934  sommerfeld 
    816  10934  sommerfeld 		if (!tsol_find_unlabeled_label(src_rhtp, &sl, &doi)) {
    817   1676         jpk 			TPC_RELE(src_rhtp);
    818   1676         jpk 			return (B_FALSE);
    819   1676         jpk 		}
    820   1676         jpk 		TPC_RELE(src_rhtp);
    821   1676         jpk 		break;
    822   1676         jpk 
    823   1676         jpk 	default:
    824   1676         jpk 		return (B_FALSE);
    825   1676         jpk 	}
    826   1676         jpk 
    827  11042        Erik 	if (ira->ira_cred == NULL) {
    828   8778        Erik 		credp = newcred_from_bslabel(&sl, doi, KM_NOSLEEP);
    829  11042        Erik 		if (credp == NULL)
    830  11042        Erik 			return (B_FALSE);
    831   1676         jpk 	} else {
    832  11077        Erik 		credp = copycred_from_bslabel(ira->ira_cred, &sl, doi,
    833   1676         jpk 		    KM_NOSLEEP);
    834  11077        Erik 		if (credp == NULL)
    835  11042        Erik 			return (B_FALSE);
    836  11042        Erik 		if (ira->ira_free_flags & IRA_FREE_CRED) {
    837  11042        Erik 			crfree(ira->ira_cred);
    838  11042        Erik 			ira->ira_free_flags &= ~IRA_FREE_CRED;
    839  11042        Erik 			ira->ira_cred = NULL;
    840  11042        Erik 		}
    841   1676         jpk 	}
    842  10934  sommerfeld 
    843  11042        Erik 	/*
    844  11042        Erik 	 * Put the label in ira_tsl for convinience, while keeping
    845  11042        Erik 	 * the cred in ira_cred for getpeerucred which is used to get
    846  11042        Erik 	 * labels with TX.
    847  11042        Erik 	 * Note: no explicit refcnt/free_flag for ira_tsl. The free_flag
    848  11042        Erik 	 * for IRA_FREE_CRED is sufficient for both.
    849  11042        Erik 	 */
    850  11042        Erik 	ira->ira_tsl = crgetlabel(credp);
    851  11042        Erik 	ira->ira_cred = credp;
    852  11042        Erik 	ira->ira_free_flags |= IRA_FREE_CRED;
    853  10934  sommerfeld 
    854  11042        Erik 	ira->ira_tsl->tsl_flags |= label_flags;
    855   1676         jpk 	return (B_TRUE);
    856   1676         jpk }
    857   1676         jpk 
    858   1676         jpk /*
    859   1676         jpk  * This routine determines whether the given packet should be accepted locally.
    860   1676         jpk  * It does a range/set check on the packet's label by looking up the given
    861   1676         jpk  * address in the remote host database.
    862   1676         jpk  */
    863   1676         jpk boolean_t
    864   1676         jpk tsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
    865  11042        Erik     ip_recv_attr_t *ira, const conn_t *connp)
    866   1676         jpk {
    867   1676         jpk 	const cred_t *credp;
    868   1676         jpk 	ts_label_t *plabel, *conn_plabel;
    869   1676         jpk 	tsol_tpc_t *tp;
    870   1676         jpk 	boolean_t retv;
    871   1676         jpk 	const bslabel_t *label, *conn_label;
    872  11042        Erik 	boolean_t shared_addr = (ira->ira_flags & IRAF_TX_SHARED_ADDR);
    873   1676         jpk 
    874   1676         jpk 	/*
    875  11042        Erik 	 * tsol_get_pkt_label intentionally avoids the labeling process for:
    876  11042        Erik 	 *	- IPv6 router and neighbor discovery as well as redirects.
    877  11042        Erik 	 *	- MLD packets. (Anything between ICMPv6 code 130 and 138.)
    878  11042        Erik 	 *	- IGMP packets.
    879  11042        Erik 	 *	- IPv4 router discovery.
    880  11077        Erik 	 * In those cases ira_cred is NULL.
    881   1676         jpk 	 */
    882  11042        Erik 	credp = ira->ira_cred;
    883  11042        Erik 	if (credp == NULL)
    884   1676         jpk 		return (B_TRUE);
    885   1676         jpk 
    886   1676         jpk 	/*
    887   1676         jpk 	 * If this packet is from the inside (not a remote host) and has the
    888   1676         jpk 	 * same zoneid as the selected destination, then no checks are
    889   1676         jpk 	 * necessary.  Membership in the zone is enough proof.  This is
    890   1676         jpk 	 * intended to be a hot path through this function.
    891  11042        Erik 	 * Note: Using crgetzone here is ok since the peer is local.
    892   1676         jpk 	 */
    893   1676         jpk 	if (!crisremote(credp) &&
    894   1676         jpk 	    crgetzone(credp) == crgetzone(connp->conn_cred))
    895   1676         jpk 		return (B_TRUE);
    896   1676         jpk 
    897  11042        Erik 	plabel = ira->ira_tsl;
    898   1676         jpk 	conn_plabel = crgetlabel(connp->conn_cred);
    899   1676         jpk 	ASSERT(plabel != NULL && conn_plabel != NULL);
    900   1676         jpk 
    901   1676         jpk 	label = label2bslabel(plabel);
    902  11042        Erik 	conn_label = label2bslabel(conn_plabel);
    903   1676         jpk 
    904  10934  sommerfeld 
    905  10934  sommerfeld 	/*
    906  10934  sommerfeld 	 * Implicitly labeled packets from label-aware sources
    907  10934  sommerfeld 	 * go only to privileged receivers
    908  10934  sommerfeld 	 */
    909  10934  sommerfeld 	if ((plabel->tsl_flags & TSLF_IMPLICIT_IN) &&
    910  10934  sommerfeld 	    (connp->conn_mac_mode != CONN_MAC_IMPLICIT)) {
    911  10934  sommerfeld 		DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac_impl,
    912  10934  sommerfeld 		    char *,
    913  10934  sommerfeld 		    "implicitly labeled packet mp(1) for conn(2) "
    914  10934  sommerfeld 		    "which isn't in implicit mac mode",
    915  10934  sommerfeld 		    mblk_t *, mp, conn_t *, connp);
    916  10934  sommerfeld 
    917  10934  sommerfeld 		return (B_FALSE);
    918  10934  sommerfeld 	}
    919  10934  sommerfeld 
    920  10934  sommerfeld 
    921   1676         jpk 	/*
    922   1676         jpk 	 * MLPs are always validated using the range and set of the local
    923   1676         jpk 	 * address, even when the remote host is unlabeled.
    924   1676         jpk 	 */
    925   1676         jpk 	if (connp->conn_mlp_type == mlptBoth ||
    926   1676         jpk 	/* LINTED: no consequent */
    927   1676         jpk 	    connp->conn_mlp_type == (shared_addr ? mlptShared : mlptPrivate)) {
    928   1676         jpk 		;
    929   1676         jpk 
    930   1676         jpk 	/*
    931   1676         jpk 	 * If this is a packet from an unlabeled sender, then we must apply
    932   1676         jpk 	 * different rules.  If the label is equal to the zone's label, then
    933   1676         jpk 	 * it's allowed.  If it's not equal, but the zone is either the global
    934   1676         jpk 	 * zone or the label is dominated by the zone's label, then allow it
    935   1676         jpk 	 * as long as it's in the range configured for the destination.
    936   1676         jpk 	 */
    937   1676         jpk 	} else if (plabel->tsl_flags & TSLF_UNLABELED) {
    938   1676         jpk 		if (plabel->tsl_doi == conn_plabel->tsl_doi &&
    939   1676         jpk 		    blequal(label, conn_label))
    940   1676         jpk 			return (B_TRUE);
    941   1676         jpk 
    942  10934  sommerfeld 		if ((connp->conn_mac_mode == CONN_MAC_DEFAULT) ||
    943  11042        Erik 		    (!connp->conn_zone_is_global &&
    944   1676         jpk 		    (plabel->tsl_doi != conn_plabel->tsl_doi ||
    945   1676         jpk 		    !bldominates(conn_label, label)))) {
    946   1676         jpk 			DTRACE_PROBE3(
    947   1676         jpk 			    tx__ip__log__drop__receivelocal__mac_unl,
    948   1676         jpk 			    char *,
    949   1676         jpk 			    "unlabeled packet mp(1) fails mac for conn(2)",
    950   1676         jpk 			    mblk_t *, mp, conn_t *, connp);
    951   1676         jpk 			return (B_FALSE);
    952   1676         jpk 		}
    953   1676         jpk 
    954   1676         jpk 	/*
    955   4448    kp158701 	 * If this is a packet from a labeled sender, verify the
    956   4448    kp158701 	 * label on the packet matches the connection label.
    957   1676         jpk 	 */
    958   4448    kp158701 	} else {
    959   4448    kp158701 		if (plabel->tsl_doi != conn_plabel->tsl_doi ||
    960   4448    kp158701 		    !blequal(label, conn_label)) {
    961   4448    kp158701 			DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac__slp,
    962   4448    kp158701 			    char *,
    963   4448    kp158701 			    "packet mp(1) failed label match to SLP conn(2)",
    964   4448    kp158701 			    mblk_t *, mp, conn_t *, connp);
    965   4448    kp158701 			return (B_FALSE);
    966   4448    kp158701 		}
    967   1676         jpk 		/*
    968   4448    kp158701 		 * No further checks will be needed if this is a zone-
    969   4448    kp158701 		 * specific address because (1) The process for bringing up
    970   4448    kp158701 		 * the interface ensures the zone's label is within the zone-
    971   4448    kp158701 		 * specific address's valid label range; (2) For cases where
    972   4448    kp158701 		 * the conn is bound to the unspecified addresses, ip fanout
    973   4448    kp158701 		 * logic ensures conn's zoneid equals the dest addr's zoneid;
    974   4448    kp158701 		 * (3) Mac-exempt and mlp logic above already handle all
    975   4448    kp158701 		 * cases where the zone label may not be the same as the
    976   4448    kp158701 		 * conn label.
    977   1676         jpk 		 */
    978   4448    kp158701 		if (!shared_addr)
    979   1676         jpk 			return (B_TRUE);
    980   1676         jpk 	}
    981   1676         jpk 
    982   1676         jpk 	tp = find_tpc(addr, version, B_FALSE);
    983   1676         jpk 	if (tp == NULL) {
    984   1676         jpk 		DTRACE_PROBE3(tx__ip__log__drop__receivelocal__no__tnr,
    985   1676         jpk 		    char *, "dropping mp(1), host(2) lacks entry",
    986   1676         jpk 		    mblk_t *, mp, void *, addr);
    987   1676         jpk 		return (B_FALSE);
    988   1676         jpk 	}
    989   1676         jpk 
    990   1676         jpk 	/*
    991   1676         jpk 	 * The local host address should not be unlabeled at this point.  The
    992   1676         jpk 	 * only way this can happen is that the destination isn't unicast.  We
    993   1676         jpk 	 * assume that the packet should not have had a label, and thus should
    994   1676         jpk 	 * have been handled by the TSLF_UNLABELED logic above.
    995   1676         jpk 	 */
    996   1676         jpk 	if (tp->tpc_tp.host_type == UNLABELED) {
    997   1676         jpk 		retv = B_FALSE;
    998   1676         jpk 		DTRACE_PROBE3(tx__ip__log__drop__receivelocal__flag, char *,
    999   1676         jpk 		    "mp(1) unlabeled source, but tp is not unlabeled.",
   1000   1676         jpk 		    mblk_t *, mp, tsol_tpc_t *, tp);
   1001   1676         jpk 
   1002   1676         jpk 	} else if (tp->tpc_tp.host_type != SUN_CIPSO) {
   1003   1676         jpk 		retv = B_FALSE;
   1004   1676         jpk 		DTRACE_PROBE3(tx__ip__log__drop__receivelocal__tptype, char *,
   1005   1676         jpk 		    "delivering mp(1), found unrecognized tpc(2) type.",
   1006   1676         jpk 		    mblk_t *, mp, tsol_tpc_t *, tp);
   1007   1676         jpk 
   1008   1676         jpk 	} else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) {
   1009   1676         jpk 		retv = B_FALSE;
   1010   1676         jpk 		DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
   1011   1676         jpk 		    "mp(1) could not be delievered to tp(2), doi mismatch",
   1012   1676         jpk 		    mblk_t *, mp, tsol_tpc_t *, tp);
   1013   1676         jpk 
   1014   1676         jpk 	} else if (!_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) &&
   1015   1676         jpk 	    !blinlset(label, tp->tpc_tp.tp_sl_set_cipso)) {
   1016   1676         jpk 		retv = B_FALSE;
   1017   1676         jpk 		DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
   1018   1676         jpk 		    "mp(1) could not be delievered to tp(2), bad mac",
   1019   1676         jpk 		    mblk_t *, mp, tsol_tpc_t *, tp);
   1020   1676         jpk 	} else {
   1021   1676         jpk 		retv = B_TRUE;
   1022   1676         jpk 	}
   1023   1676         jpk 
   1024   1676         jpk 	TPC_RELE(tp);
   1025   1676         jpk 
   1026   1676         jpk 	return (retv);
   1027   1676         jpk }
   1028   1676         jpk 
   1029   1676         jpk boolean_t
   1030  11042        Erik tsol_can_accept_raw(mblk_t *mp, ip_recv_attr_t *ira, boolean_t check_host)
   1031   1676         jpk {
   1032   1676         jpk 	ts_label_t	*plabel = NULL;
   1033   1676         jpk 	tsol_tpc_t	*src_rhtp, *dst_rhtp;
   1034   1676         jpk 	boolean_t	retv;
   1035   1676         jpk 
   1036  11042        Erik 	plabel = ira->ira_tsl;
   1037   1676         jpk 
   1038   1676         jpk 	/* We are bootstrapping or the internal template was never deleted */
   1039   1676         jpk 	if (plabel == NULL)
   1040   1676         jpk 		return (B_TRUE);
   1041   1676         jpk 
   1042   1676         jpk 	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
   1043   1676         jpk 		ipha_t *ipha = (ipha_t *)mp->b_rptr;
   1044   1676         jpk 
   1045   1676         jpk 		src_rhtp = find_tpc(&ipha->ipha_src, IPV4_VERSION,
   1046   1676         jpk 		    B_FALSE);
   1047   1676         jpk 		if (src_rhtp == NULL)
   1048   1676         jpk 			return (B_FALSE);
   1049   1676         jpk 		dst_rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION,
   1050   1676         jpk 		    B_FALSE);
   1051   1676         jpk 	} else {
   1052   1676         jpk 		ip6_t *ip6h = (ip6_t *)mp->b_rptr;
   1053   1676         jpk 
   1054   1676         jpk 		src_rhtp = find_tpc(&ip6h->ip6_src, IPV6_VERSION,
   1055   1676         jpk 		    B_FALSE);
   1056   1676         jpk 		if (src_rhtp == NULL)
   1057   1676         jpk 			return (B_FALSE);
   1058   1676         jpk 		dst_rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION,
   1059   1676         jpk 		    B_FALSE);
   1060   1676         jpk 	}
   1061   1676         jpk 	if (dst_rhtp == NULL) {
   1062   1676         jpk 		TPC_RELE(src_rhtp);
   1063   1676         jpk 		return (B_FALSE);
   1064   1676         jpk 	}
   1065   1676         jpk 
   1066   1676         jpk 	if (label2doi(plabel) != src_rhtp->tpc_tp.tp_doi) {
   1067   1676         jpk 		retv = B_FALSE;
   1068   1676         jpk 
   1069   1676         jpk 	/*
   1070   1676         jpk 	 * Check that the packet's label is in the correct range for labeled
   1071   1676         jpk 	 * sender, or is equal to the default label for unlabeled sender.
   1072   1676         jpk 	 */
   1073   1676         jpk 	} else if ((src_rhtp->tpc_tp.host_type != UNLABELED &&
   1074   1676         jpk 	    !_blinrange(label2bslabel(plabel),
   1075   1676         jpk 	    &src_rhtp->tpc_tp.tp_sl_range_cipso) &&
   1076   1676         jpk 	    !blinlset(label2bslabel(plabel),
   1077   1676         jpk 	    src_rhtp->tpc_tp.tp_sl_set_cipso)) ||
   1078   1676         jpk 	    (src_rhtp->tpc_tp.host_type == UNLABELED &&
   1079   1676         jpk 	    !blequal(&plabel->tsl_label, &src_rhtp->tpc_tp.tp_def_label))) {
   1080   1676         jpk 		retv = B_FALSE;
   1081   1676         jpk 
   1082   1676         jpk 	} else if (check_host) {
   1083   1676         jpk 		retv = B_TRUE;
   1084   1676         jpk 
   1085   1676         jpk 	/*
   1086   1676         jpk 	 * Until we have SL range in the Zone structure, pass it
   1087   1676         jpk 	 * when our own address lookup returned an internal entry.
   1088   1676         jpk 	 */
   1089   1676         jpk 	} else switch (dst_rhtp->tpc_tp.host_type) {
   1090   1676         jpk 	case UNLABELED:
   1091   1676         jpk 		retv = B_TRUE;
   1092   1676         jpk 		break;
   1093   1676         jpk 
   1094   1676         jpk 	case SUN_CIPSO:
   1095   1676         jpk 		retv = _blinrange(label2bslabel(plabel),
   1096   1676         jpk 		    &dst_rhtp->tpc_tp.tp_sl_range_cipso) ||
   1097   1676         jpk 		    blinlset(label2bslabel(plabel),
   1098   1676         jpk 		    dst_rhtp->tpc_tp.tp_sl_set_cipso);
   1099   1676         jpk 		break;
   1100   1676         jpk 
   1101   1676         jpk 	default:
   1102   1676         jpk 		retv = B_FALSE;
   1103   1676         jpk 	}
   1104   1676         jpk 	TPC_RELE(src_rhtp);
   1105   1676         jpk 	TPC_RELE(dst_rhtp);
   1106   1676         jpk 	return (retv);
   1107   1676         jpk }
   1108   1676         jpk 
   1109   1676         jpk /*
   1110   1676         jpk  * This routine determines whether a response to a failed packet delivery or
   1111   1676         jpk  * connection should be sent back.  By default, the policy is to allow such
   1112   1676         jpk  * messages to be sent at all times, as these messages reveal little useful
   1113   1676         jpk  * information and are healthy parts of TCP/IP networking.
   1114   1676         jpk  *
   1115   1676         jpk  * If tsol_strict_error is set, then we do strict tests: if the packet label is
   1116   1676         jpk  * within the label range/set of this host/zone, return B_TRUE; otherwise
   1117   1676         jpk  * return B_FALSE, which causes the packet to be dropped silently.
   1118   1676         jpk  *
   1119   1676         jpk  * Note that tsol_get_pkt_label will cause the packet to drop if the sender is
   1120   1676         jpk  * marked as labeled in the remote host database, but the packet lacks a label.
   1121   1676         jpk  * This means that we don't need to do a lookup on the source; the
   1122   1676         jpk  * TSLF_UNLABELED flag is sufficient.
   1123   1676         jpk  */
   1124   1676         jpk boolean_t
   1125  11042        Erik tsol_can_reply_error(const mblk_t *mp, ip_recv_attr_t *ira)
   1126   1676         jpk {
   1127   1676         jpk 	ts_label_t	*plabel = NULL;
   1128   1676         jpk 	tsol_tpc_t	*rhtp;
   1129   1676         jpk 	const ipha_t	*ipha;
   1130   1676         jpk 	const ip6_t	*ip6h;
   1131   1676         jpk 	boolean_t	retv;
   1132   1676         jpk 	bslabel_t	*pktbs;
   1133   1676         jpk 
   1134   1676         jpk 	/* Caller must pull up at least the IP header */
   1135   1676         jpk 	ASSERT(MBLKL(mp) >= (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ?
   1136   1676         jpk 	    sizeof (*ipha) : sizeof (*ip6h)));
   1137   1676         jpk 
   1138   1676         jpk 	if (!tsol_strict_error)
   1139   1676         jpk 		return (B_TRUE);
   1140   1676         jpk 
   1141  11042        Erik 	plabel = ira->ira_tsl;
   1142   1676         jpk 
   1143   1676         jpk 	/* We are bootstrapping or the internal template was never deleted */
   1144   1676         jpk 	if (plabel == NULL)
   1145   1676         jpk 		return (B_TRUE);
   1146   1676         jpk 
   1147  10934  sommerfeld 	if (plabel->tsl_flags & TSLF_IMPLICIT_IN) {
   1148  10934  sommerfeld 		DTRACE_PROBE3(tx__ip__log__drop__replyerror__unresolved__label,
   1149  10934  sommerfeld 		    char *,
   1150  10934  sommerfeld 		    "cannot send error report for packet mp(1) with "
   1151  10934  sommerfeld 		    "unresolved security label sl(2)",
   1152  10934  sommerfeld 		    mblk_t *, mp, ts_label_t *, plabel);
   1153  10934  sommerfeld 		return (B_FALSE);
   1154  10934  sommerfeld 	}
   1155  10934  sommerfeld 
   1156  10934  sommerfeld 
   1157   1676         jpk 	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
   1158   1676         jpk 		ipha = (const ipha_t *)mp->b_rptr;
   1159   1676         jpk 		rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION, B_FALSE);
   1160   1676         jpk 	} else {
   1161   1676         jpk 		ip6h = (const ip6_t *)mp->b_rptr;
   1162   1676         jpk 		rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION, B_FALSE);
   1163   1676         jpk 	}
   1164   1676         jpk 
   1165   1676         jpk 	if (rhtp == NULL || label2doi(plabel) != rhtp->tpc_tp.tp_doi) {
   1166   1676         jpk 		retv = B_FALSE;
   1167   1676         jpk 	} else {
   1168   1676         jpk 		/*
   1169   1676         jpk 		 * If we're in the midst of forwarding, then the destination
   1170   1676         jpk 		 * address might not be labeled.  In that case, allow unlabeled
   1171   1676         jpk 		 * packets through only if the default label is the same, and
   1172   1676         jpk 		 * labeled ones if they dominate.
   1173   1676         jpk 		 */
   1174   1676         jpk 		pktbs = label2bslabel(plabel);
   1175   1676         jpk 		switch (rhtp->tpc_tp.host_type) {
   1176   1676         jpk 		case UNLABELED:
   1177   1676         jpk 			if (plabel->tsl_flags & TSLF_UNLABELED) {
   1178   1676         jpk 				retv = blequal(pktbs,
   1179   1676         jpk 				    &rhtp->tpc_tp.tp_def_label);
   1180   1676         jpk 			} else {
   1181   1676         jpk 				retv = bldominates(pktbs,
   1182   1676         jpk 				    &rhtp->tpc_tp.tp_def_label);
   1183   1676         jpk 			}
   1184   1676         jpk 			break;
   1185   1676         jpk 
   1186   1676         jpk 		case SUN_CIPSO:
   1187   1676         jpk 			retv = _blinrange(pktbs,
   1188   1676         jpk 			    &rhtp->tpc_tp.tp_sl_range_cipso) ||
   1189   1676         jpk 			    blinlset(pktbs, rhtp->tpc_tp.tp_sl_set_cipso);
   1190   1676         jpk 			break;
   1191   1676         jpk 
   1192   1676         jpk 		default:
   1193   1676         jpk 			retv = B_FALSE;
   1194   1676         jpk 			break;
   1195   1676         jpk 		}
   1196   1676         jpk 	}
   1197   1676         jpk 
   1198   1676         jpk 	if (rhtp != NULL)
   1199   1676         jpk 		TPC_RELE(rhtp);
   1200   1676         jpk 
   1201   1676         jpk 	return (retv);
   1202   1676         jpk }
   1203   1676         jpk 
   1204   1676         jpk /*
   1205  11042        Erik  * Finds the zone associated with the receive attributes.  Returns GLOBAL_ZONEID
   1206  11042        Erik  * if the zone cannot be located.
   1207   1676         jpk  *
   1208   1676         jpk  * This is used by the classifier when the packet matches an ALL_ZONES IRE, and
   1209   1676         jpk  * there's no MLP defined.
   1210   3448    dh155122  *
   1211   3448    dh155122  * Note that we assume that this is only invoked in the ALL_ZONES case.
   1212  11042        Erik  * Handling other cases would require handling exclusive IP zones where either
   1213   3448    dh155122  * this routine or the callers would have to map from
   1214   3448    dh155122  * the zoneid (zone->zone_id) to what IP uses in conn_zoneid etc.
   1215   1676         jpk  */
   1216   1676         jpk zoneid_t
   1217  11042        Erik tsol_attr_to_zoneid(const ip_recv_attr_t *ira)
   1218   1676         jpk {
   1219   1676         jpk 	zone_t *zone;
   1220   1676         jpk 	ts_label_t *label;
   1221   1676         jpk 
   1222  11042        Erik 	if ((label = ira->ira_tsl) != NULL) {
   1223  11042        Erik 		zone = zone_find_by_label(label);
   1224  11042        Erik 		if (zone != NULL) {
   1225  11042        Erik 			zoneid_t zoneid = zone->zone_id;
   1226   1676         jpk 
   1227  11042        Erik 			zone_rele(zone);
   1228  11042        Erik 			return (zoneid);
   1229   1676         jpk 		}
   1230   1676         jpk 	}
   1231   1676         jpk 	return (GLOBAL_ZONEID);
   1232   1676         jpk }
   1233   1676         jpk 
   1234   1676         jpk int
   1235   1676         jpk tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
   1236   1676         jpk {
   1237   1676         jpk 	int		error = 0;
   1238   1676         jpk 	tsol_ire_gw_secattr_t *attrp = NULL;
   1239   1676         jpk 	tsol_tnrhc_t	*gw_rhc = NULL;
   1240   1676         jpk 	tsol_gcgrp_t	*gcgrp = NULL;
   1241   1676         jpk 	tsol_gc_t	*gc = NULL;
   1242   1676         jpk 	in_addr_t	ga_addr4;
   1243   1676         jpk 	void		*paddr = NULL;
   1244   1676         jpk 
   1245   1676         jpk 	/* Not in Trusted mode or IRE is local/loopback/broadcast/interface */
   1246   1676         jpk 	if (!is_system_labeled() ||
   1247   1676         jpk 	    (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST |
   1248  11042        Erik 	    IRE_IF_ALL | IRE_MULTICAST | IRE_NOROUTE)))
   1249   1676         jpk 		goto done;
   1250   1676         jpk 
   1251   1676         jpk 	/*
   1252   1676         jpk 	 * If we don't have a label to compare with, or the IRE does not
   1253   1676         jpk 	 * contain any gateway security attributes, there's not much that
   1254   1676         jpk 	 * we can do.  We let the former case pass, and the latter fail,
   1255   1676         jpk 	 * since the IRE doesn't qualify for a match due to the lack of
   1256   1676         jpk 	 * security attributes.
   1257   1676         jpk 	 */
   1258   1676         jpk 	if (tsl == NULL || ire->ire_gw_secattr == NULL) {
   1259   1676         jpk 		if (tsl != NULL) {
   1260  10934  sommerfeld 			DTRACE_PROBE3(
   1261  10934  sommerfeld 			    tx__ip__log__drop__irematch__nogwsec, char *,
   1262  10934  sommerfeld 			    "ire(1) lacks ire_gw_secattr when matching "
   1263  10934  sommerfeld 			    "label(2)", ire_t *, ire, ts_label_t *, tsl);
   1264   1676         jpk 			error = EACCES;
   1265   1676         jpk 		}
   1266   1676         jpk 		goto done;
   1267   1676         jpk 	}
   1268   1676         jpk 
   1269   1676         jpk 	attrp = ire->ire_gw_secattr;
   1270   1676         jpk 
   1271   1676         jpk 	/*
   1272   1676         jpk 	 * The possible lock order scenarios related to the tsol gateway
   1273   1676         jpk 	 * attribute locks are documented at the beginning of ip.c in the
   1274   1676         jpk 	 * lock order scenario section.
   1275   1676         jpk 	 */
   1276   1676         jpk 	mutex_enter(&attrp->igsa_lock);
   1277   1676         jpk 
   1278   1676         jpk 	/*
   1279  11042        Erik 	 * We seek the group
   1280   1676         jpk 	 * structure which contains all security credentials of the gateway.
   1281  11042        Erik 	 * An offline IRE is associated with at most one gateway credential.
   1282   1676         jpk 	 */
   1283  11042        Erik 	if ((gc = attrp->igsa_gc) != NULL) {
   1284   1676         jpk 		gcgrp = gc->gc_grp;
   1285   1676         jpk 		ASSERT(gcgrp != NULL);
   1286   1676         jpk 		rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
   1287  11042        Erik 		GCGRP_REFHOLD(gcgrp);
   1288   1676         jpk 	}
   1289   1676         jpk 
   1290   1676         jpk 	if ((gw_rhc = attrp->igsa_rhc) != NULL) {
   1291   1676         jpk 		/*
   1292   1676         jpk 		 * If our cached entry has grown stale, then discard it so we
   1293   1676         jpk 		 * can get a new one.
   1294   1676         jpk 		 */
   1295   1676         jpk 		if (gw_rhc->rhc_invalid || gw_rhc->rhc_tpc->tpc_invalid) {
   1296   1676         jpk 			TNRHC_RELE(gw_rhc);
   1297   1676         jpk 			attrp->igsa_rhc = gw_rhc = NULL;
   1298   1676         jpk 		} else {
   1299   1676         jpk 			TNRHC_HOLD(gw_rhc)
   1300   1676         jpk 		}
   1301   1676         jpk 	}
   1302   1676         jpk 
   1303   1676         jpk 	/* Last attempt at loading the template had failed; try again */
   1304   1676         jpk 	if (gw_rhc == NULL) {
   1305   1676         jpk 		if (gcgrp != NULL) {
   1306   1676         jpk 			tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr;
   1307   1676         jpk 
   1308   1676         jpk 			if (ire->ire_ipversion == IPV4_VERSION) {
   1309   1676         jpk 				ASSERT(ga->ga_af == AF_INET);
   1310   1676         jpk 				IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4);
   1311   1676         jpk 				paddr = &ga_addr4;
   1312   1676         jpk 			} else {
   1313   1676         jpk 				ASSERT(ga->ga_af == AF_INET6);
   1314   1676         jpk 				paddr = &ga->ga_addr;
   1315   1676         jpk 			}
   1316  11042        Erik 		} else if (ire->ire_type & IRE_OFFLINK) {
   1317  11042        Erik 			if (ire->ire_ipversion == IPV6_VERSION)
   1318  11042        Erik 				paddr = &ire->ire_gateway_addr_v6;
   1319  11042        Erik 			else if (ire->ire_ipversion == IPV4_VERSION)
   1320  11042        Erik 				paddr = &ire->ire_gateway_addr;
   1321   1676         jpk 		}
   1322   1676         jpk 
   1323   1676         jpk 		/* We've found a gateway address to do the template lookup */
   1324   1676         jpk 		if (paddr != NULL) {
   1325   1676         jpk 			ASSERT(gw_rhc == NULL);
   1326   3292    kp158701 			gw_rhc = find_rhc(paddr, ire->ire_ipversion, B_FALSE);
   1327   1676         jpk 			if (gw_rhc != NULL) {
   1328   1676         jpk 				/*
   1329   1676         jpk 				 * Note that if the lookup above returned an
   1330   1676         jpk 				 * internal template, we'll use it for the
   1331   1676         jpk 				 * time being, and do another lookup next
   1332   1676         jpk 				 * time around.
   1333   1676         jpk 				 */
   1334   1676         jpk 				/* Another thread has loaded the template? */
   1335   1676         jpk 				if (attrp->igsa_rhc != NULL) {
   1336   1676         jpk 					TNRHC_RELE(gw_rhc)
   1337   1676         jpk 					/* reload, it could be different */
   1338   1676         jpk 					gw_rhc = attrp->igsa_rhc;
   1339   1676         jpk 				} else {
   1340   1676         jpk 					attrp->igsa_rhc = gw_rhc;
   1341   1676         jpk 				}
   1342   1676         jpk 				/*
   1343   1676         jpk 				 * Hold an extra reference just like we did
   1344   1676         jpk 				 * above prior to dropping the igsa_lock.
   1345   1676         jpk 				 */
   1346   1676         jpk 				TNRHC_HOLD(gw_rhc)
   1347   1676         jpk 			}
   1348   1676         jpk 		}
   1349   1676         jpk 	}
   1350   1676         jpk 
   1351   1676         jpk 	mutex_exit(&attrp->igsa_lock);
   1352   1676         jpk 	/* Gateway template not found */
   1353   1676         jpk 	if (gw_rhc == NULL) {
   1354   1676         jpk 		/*
   1355   1676         jpk 		 * If destination address is directly reachable through an
   1356   1676         jpk 		 * interface rather than through a learned route, pass it.
   1357   1676         jpk 		 */
   1358   1676         jpk 		if (paddr != NULL) {
   1359   1676         jpk 			DTRACE_PROBE3(
   1360   1676         jpk 			    tx__ip__log__drop__irematch__nogwtmpl, char *,
   1361   1676         jpk 			    "ire(1), label(2) off-link with no gw_rhc",
   1362   1676         jpk 			    ire_t *, ire, ts_label_t *, tsl);
   1363   1676         jpk 			error = EINVAL;
   1364   1676         jpk 		}
   1365   1676         jpk 		goto done;
   1366   1676         jpk 	}
   1367   1676         jpk 
   1368   1676         jpk 	if (gc != NULL) {
   1369  11042        Erik 
   1370   1676         jpk 		tsol_gcdb_t *gcdb;
   1371   1676         jpk 		/*
   1372   1676         jpk 		 * In the case of IRE_CACHE we've got one or more gateway
   1373   1676         jpk 		 * security credentials to compare against the passed in label.
   1374   1676         jpk 		 * Perform label range comparison against each security
   1375   1676         jpk 		 * credential of the gateway. In the case of a prefix ire
   1376   1676         jpk 		 * we need to match against the security attributes of
   1377   1676         jpk 		 * just the route itself, so the loop is executed only once.
   1378   1676         jpk 		 */
   1379   1676         jpk 		ASSERT(gcgrp != NULL);
   1380  11042        Erik 		gcdb = gc->gc_db;
   1381  11042        Erik 		if (tsl->tsl_doi != gcdb->gcdb_doi ||
   1382  11042        Erik 		    !_blinrange(&tsl->tsl_label, &gcdb->gcdb_slrange)) {
   1383   1676         jpk 			DTRACE_PROBE3(
   1384   1676         jpk 			    tx__ip__log__drop__irematch__nogcmatched,
   1385   1676         jpk 			    char *, "ire(1), tsl(2): all gc failed match",
   1386   1676         jpk 			    ire_t *, ire, ts_label_t *, tsl);
   1387   1676         jpk 			error = EACCES;
   1388   1676         jpk 		}
   1389   1676         jpk 	} else {
   1390   1676         jpk 		/*
   1391   1676         jpk 		 * We didn't find any gateway credentials in the IRE
   1392   1676         jpk 		 * attributes; fall back to the gateway's template for
   1393   1676         jpk 		 * label range checks, if we are required to do so.
   1394   1676         jpk 		 */
   1395   1676         jpk 		ASSERT(gw_rhc != NULL);
   1396   1676         jpk 		switch (gw_rhc->rhc_tpc->tpc_tp.host_type) {
   1397   1676         jpk 		case SUN_CIPSO:
   1398   6596    kp158701 			if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
   1399   1676         jpk 			    (!_blinrange(&tsl->tsl_label,
   1400   6596    kp158701 			    &gw_rhc->rhc_tpc->tpc_tp.tp_sl_range_cipso) &&
   1401   1676         jpk 			    !blinlset(&tsl->tsl_label,
   1402   1676         jpk 			    gw_rhc->rhc_tpc->tpc_tp.tp_sl_set_cipso))) {
   1403   1676         jpk 				error = EACCES;
   1404   1676         jpk 				DTRACE_PROBE4(
   1405   1676         jpk 				    tx__ip__log__drop__irematch__deftmpl,
   1406   1676         jpk 				    char *, "ire(1), tsl(2), gw_rhc(3) "
   1407   1676         jpk 				    "failed match (cipso gw)",
   1408   1676         jpk 				    ire_t *, ire, ts_label_t *, tsl,
   1409   1676         jpk 				    tsol_tnrhc_t *, gw_rhc);
   1410   1676         jpk 			}
   1411   1676         jpk 			break;
   1412   1676         jpk 
   1413   1676         jpk 		case UNLABELED:
   1414   6596    kp158701 			if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
   1415   1676         jpk 			    (!_blinrange(&tsl->tsl_label,
   1416   1676         jpk 			    &gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_range) &&
   1417   1676         jpk 			    !blinlset(&tsl->tsl_label,
   1418   1676         jpk 			    gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_set))) {
   1419   1676         jpk 				error = EACCES;
   1420   1676         jpk 				DTRACE_PROBE4(
   1421   1676         jpk 				    tx__ip__log__drop__irematch__deftmpl,
   1422   1676         jpk 				    char *, "ire(1), tsl(2), gw_rhc(3) "
   1423   1676         jpk 				    "failed match (unlabeled gw)",
   1424   1676         jpk 				    ire_t *, ire, ts_label_t *, tsl,
   1425   1676         jpk 				    tsol_tnrhc_t *, gw_rhc);
   1426   1676         jpk 			}
   1427   1676         jpk 			break;
   1428   1676         jpk 		}
   1429   1676         jpk 	}
   1430   1676         jpk 
   1431   1676         jpk done:
   1432   1676         jpk 
   1433   1676         jpk 	if (gcgrp != NULL) {
   1434   1676         jpk 		rw_exit(&gcgrp->gcgrp_rwlock);
   1435   1676         jpk 		GCGRP_REFRELE(gcgrp);
   1436   1676         jpk 	}
   1437   1676         jpk 
   1438   1676         jpk 	if (gw_rhc != NULL)
   1439   1676         jpk 		TNRHC_RELE(gw_rhc)
   1440   1676         jpk 
   1441   1676         jpk 	return (error);
   1442   1676         jpk }
   1443   1676         jpk 
   1444   1676         jpk /*
   1445   1676         jpk  * Performs label accreditation checks for packet forwarding.
   1446  11042        Erik  * Add or remove a CIPSO option as needed.
   1447   1676         jpk  *
   1448   1676         jpk  * Returns a pointer to the modified mblk if allowed for forwarding,
   1449   1676         jpk  * or NULL if the packet must be dropped.
   1450   1676         jpk  */
   1451   1676         jpk mblk_t *
   1452  11042        Erik tsol_ip_forward(ire_t *ire, mblk_t *mp, const ip_recv_attr_t *ira)
   1453   1676         jpk {
   1454   1676         jpk 	tsol_ire_gw_secattr_t *attrp = NULL;
   1455   1676         jpk 	ipha_t		*ipha;
   1456   1676         jpk 	ip6_t		*ip6h;
   1457   1676         jpk 	const void	*pdst;
   1458   1676         jpk 	const void	*psrc;
   1459   1676         jpk 	boolean_t	off_link;
   1460   1676         jpk 	tsol_tpc_t	*dst_rhtp, *gw_rhtp;
   1461   1676         jpk 	tsol_ip_label_t label_type;
   1462   1676         jpk 	uchar_t		*opt_ptr = NULL;
   1463   1676         jpk 	ts_label_t	*tsl;
   1464   1676         jpk 	uint8_t		proto;
   1465   1676         jpk 	int		af, adjust;
   1466   1676         jpk 	uint16_t	iplen;
   1467   2535    sangeeta 	boolean_t	need_tpc_rele = B_FALSE;
   1468   2535    sangeeta 	ipaddr_t	*gw;
   1469   3448    dh155122 	ip_stack_t	*ipst = ire->ire_ipst;
   1470  11042        Erik 	int		err;
   1471  11042        Erik 	ts_label_t	*effective_tsl = NULL;
   1472   1676         jpk 
   1473   1676         jpk 	ASSERT(ire != NULL && mp != NULL);
   1474  11042        Erik 	/*
   1475  11042        Erik 	 * Note that the ire is the first one found, i.e., an IRE_OFFLINK if
   1476  11042        Erik 	 * the destination is offlink.
   1477  11042        Erik 	 */
   1478   1676         jpk 
   1479   1676         jpk 	af = (ire->ire_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6;
   1480   1676         jpk 
   1481   1676         jpk 	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
   1482   1676         jpk 		ASSERT(ire->ire_ipversion == IPV4_VERSION);
   1483   1676         jpk 		ipha = (ipha_t *)mp->b_rptr;
   1484   1676         jpk 		psrc = &ipha->ipha_src;
   1485   1676         jpk 		pdst = &ipha->ipha_dst;
   1486   1676         jpk 		proto = ipha->ipha_protocol;
   1487  10181         Ken 		if (!tsol_get_option_v4(mp, &label_type, &opt_ptr))
   1488  10181         Ken 			return (NULL);
   1489   1676         jpk 	} else {
   1490   1676         jpk 		ASSERT(ire->ire_ipversion == IPV6_VERSION);
   1491   1676         jpk 		ip6h = (ip6_t *)mp->b_rptr;
   1492   1676         jpk 		psrc = &ip6h->ip6_src;
   1493   1676         jpk 		pdst = &ip6h->ip6_dst;
   1494   1676         jpk 		proto = ip6h->ip6_nxt;
   1495   1676         jpk 
   1496   1676         jpk 		if (proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
   1497   1676         jpk 		    proto != IPPROTO_ICMPV6) {
   1498   1676         jpk 			uint8_t *nexthdrp;
   1499   1676         jpk 			uint16_t hdr_len;
   1500   1676         jpk 
   1501   1676         jpk 			if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_len,
   1502   1676         jpk 			    &nexthdrp)) {
   1503   1676         jpk 				/* malformed packet; drop it */
   1504   1676         jpk 				return (NULL);
   1505   1676         jpk 			}
   1506   1676         jpk 			proto = *nexthdrp;
   1507   1676         jpk 		}
   1508  10181         Ken 		if (!tsol_get_option_v6(mp, &label_type, &opt_ptr))
   1509  10181         Ken 			return (NULL);
   1510   1676         jpk 	}
   1511  11042        Erik 	/*
   1512  11042        Erik 	 * off_link is TRUE if destination not directly reachable.
   1513  11042        Erik 	 */
   1514  11042        Erik 	off_link = (ire->ire_type & IRE_OFFLINK);
   1515   1676         jpk 
   1516  11042        Erik 	if ((tsl = ira->ira_tsl) == NULL)
   1517   1676         jpk 		return (mp);
   1518   1676         jpk 
   1519  10934  sommerfeld 	if (tsl->tsl_flags & TSLF_IMPLICIT_IN) {
   1520  10934  sommerfeld 		DTRACE_PROBE3(tx__ip__log__drop__forward__unresolved__label,
   1521  10934  sommerfeld 		    char *,
   1522  10934  sommerfeld 		    "cannot forward packet mp(1) with unresolved "
   1523  10934  sommerfeld 		    "security label sl(2)",
   1524  10934  sommerfeld 		    mblk_t *, mp, ts_label_t *, tsl);
   1525  10934  sommerfeld 
   1526  10934  sommerfeld 		return (NULL);
   1527  10934  sommerfeld 	}
   1528  10934  sommerfeld 
   1529  10934  sommerfeld 
   1530   1676         jpk 	ASSERT(psrc != NULL && pdst != NULL);
   1531   1676         jpk 	dst_rhtp = find_tpc(pdst, ire->ire_ipversion, B_FALSE);
   1532   1676         jpk 
   1533   1676         jpk 	if (dst_rhtp == NULL) {
   1534   1676         jpk 		/*
   1535   1676         jpk 		 * Without a template we do not know if forwarding
   1536   1676         jpk 		 * violates MAC
   1537   1676         jpk 		 */
   1538   1676         jpk 		DTRACE_PROBE3(tx__ip__log__drop__forward__nodst, char *,
   1539   1676         jpk 		    "mp(1) dropped, no template for destination ip4|6(2)",
   1540   1676         jpk 		    mblk_t *, mp, void *, pdst);
   1541   1676         jpk 		return (NULL);
   1542   1676         jpk 	}
   1543   1676         jpk 
   1544   1676         jpk 	/*
   1545   1676         jpk 	 * Gateway template must have existed for off-link destinations,
   1546   1676         jpk 	 * since tsol_ire_match_gwattr has ensured such condition.
   1547   1676         jpk 	 */
   1548   2535    sangeeta 	if (ire->ire_ipversion == IPV4_VERSION && off_link) {
   1549   2535    sangeeta 		/*
   1550   2535    sangeeta 		 * Surya note: first check if we can get the gw_rhtp from
   1551   2535    sangeeta 		 * the ire_gw_secattr->igsa_rhc; if this is null, then
   1552   2535    sangeeta 		 * do a lookup based on the ire_addr (address of gw)
   1553   2535    sangeeta 		 */
   1554   2535    sangeeta 		if (ire->ire_gw_secattr != NULL &&
   1555   2535    sangeeta 		    ire->ire_gw_secattr->igsa_rhc != NULL) {
   1556   2535    sangeeta 			attrp = ire->ire_gw_secattr;
   1557   2535    sangeeta 			gw_rhtp = attrp->igsa_rhc->rhc_tpc;
   1558   2535    sangeeta 		} else  {
   1559  11042        Erik 			gw = &ire->ire_gateway_addr;
   1560   2535    sangeeta 			gw_rhtp = find_tpc(gw, ire->ire_ipversion, B_FALSE);
   1561   2535    sangeeta 			need_tpc_rele = B_TRUE;
   1562   2535    sangeeta 		}
   1563   2535    sangeeta 		if (gw_rhtp == NULL) {
   1564   2535    sangeeta 			DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *,
   1565   2535    sangeeta 			    "mp(1) dropped, no gateway in ire attributes(2)",
   1566   2535    sangeeta 			    mblk_t *, mp, tsol_ire_gw_secattr_t *, attrp);
   1567   2535    sangeeta 			mp = NULL;
   1568   2535    sangeeta 			goto keep_label;
   1569   2535    sangeeta 		}
   1570   2535    sangeeta 	}
   1571   2535    sangeeta 	if (ire->ire_ipversion == IPV6_VERSION &&
   1572   2535    sangeeta 	    ((attrp = ire->ire_gw_secattr) == NULL || attrp->igsa_rhc == NULL ||
   1573   1676         jpk 	    (gw_rhtp = attrp->igsa_rhc->rhc_tpc) == NULL) && off_link) {
   1574   1676         jpk 		DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *,
   1575   1676         jpk 		    "mp(1) dropped, no gateway in ire attributes(2)",
   1576   1676         jpk 		    mblk_t *, mp, tsol_ire_gw_secattr_t *, attrp);
   1577   1676         jpk 		mp = NULL;
   1578   1676         jpk 		goto keep_label;
   1579   1676         jpk 	}
   1580   1676         jpk 
   1581   1676         jpk 	/*
   1582   1676         jpk 	 * Check that the label for the packet is acceptable
   1583   1676         jpk 	 * by destination host; otherwise, drop it.
   1584   1676         jpk 	 */
   1585   1676         jpk 	switch (dst_rhtp->tpc_tp.host_type) {
   1586   1676         jpk 	case SUN_CIPSO:
   1587   1676         jpk 		if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi ||
   1588   1676         jpk 		    (!_blinrange(&tsl->tsl_label,
   1589   1676         jpk 		    &dst_rhtp->tpc_tp.tp_sl_range_cipso) &&
   1590   1676         jpk 		    !blinlset(&tsl->tsl_label,
   1591   1676         jpk 		    dst_rhtp->tpc_tp.tp_sl_set_cipso))) {
   1592   1676         jpk 			DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *,
   1593   1676         jpk 			    "labeled packet mp(1) dropped, label(2) fails "
   1594   1676         jpk 			    "destination(3) accredation check",
   1595   1676         jpk 			    mblk_t *, mp, ts_label_t *, tsl,
   1596   1676         jpk 			    tsol_tpc_t *, dst_rhtp);
   1597   1676         jpk 			mp = NULL;
   1598   1676         jpk 			goto keep_label;
   1599   1676         jpk 		}
   1600   1676         jpk 		break;
   1601   1676         jpk 
   1602   1676         jpk 
   1603   1676         jpk 	case UNLABELED:
   1604   1676         jpk 		if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi ||
   1605   1676         jpk 		    !blequal(&dst_rhtp->tpc_tp.tp_def_label,
   1606   1676         jpk 		    &tsl->tsl_label)) {
   1607   1676         jpk 			DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *,
   1608   1676         jpk 			    "unlabeled packet mp(1) dropped, label(2) fails "
   1609   1676         jpk 			    "destination(3) accredation check",
   1610   1676         jpk 			    mblk_t *, mp, ts_label_t *, tsl,
   1611   1676         jpk 			    tsol_tpc_t *, dst_rhtp);
   1612   1676         jpk 			mp = NULL;
   1613   1676         jpk 			goto keep_label;
   1614   1676         jpk 		}
   1615   1676         jpk 		break;
   1616   1676         jpk 	}
   1617   1676         jpk 	if (label_type == OPT_CIPSO) {
   1618   1676         jpk 		/*
   1619   1676         jpk 		 * We keep the label on any of the following cases:
   1620   1676         jpk 		 *
   1621   1676         jpk 		 *   1. The destination is labeled (on/off-link).
   1622   1676         jpk 		 *   2. The unlabeled destination is off-link,
   1623   1676         jpk 		 *	and the next hop gateway is labeled.
   1624   1676         jpk 		 */
   1625   1676         jpk 		if (dst_rhtp->tpc_tp.host_type != UNLABELED ||
   1626   1676         jpk 		    (off_link &&
   1627   1676         jpk 		    gw_rhtp->tpc_tp.host_type != UNLABELED))
   1628   1676         jpk 			goto keep_label;
   1629   1676         jpk 
   1630   1676         jpk 		/*
   1631   1676         jpk 		 * Strip off the CIPSO option from the packet because: the
   1632   1676         jpk 		 * unlabeled destination host is directly reachable through
   1633   1676         jpk 		 * an interface (on-link); or, the unlabeled destination host
   1634   1676         jpk 		 * is not directly reachable (off-link), and the next hop
   1635   1676         jpk 		 * gateway is unlabeled.
   1636   1676         jpk 		 */
   1637   1676         jpk 		adjust = (af == AF_INET) ? tsol_remove_secopt(ipha, MBLKL(mp)) :
   1638   1676         jpk 		    tsol_remove_secopt_v6(ip6h, MBLKL(mp));
   1639   1676         jpk 
   1640   1676         jpk 		ASSERT(adjust <= 0);
   1641   1676         jpk 		if (adjust != 0) {
   1642   1676         jpk 
   1643   1676         jpk 			/* adjust is negative */
   1644   1676         jpk 			ASSERT((mp->b_wptr + adjust) >= mp->b_rptr);
   1645   1676         jpk 			mp->b_wptr += adjust;
   1646  11042        Erik 			/*
   1647  11042        Erik 			 * Note that caller adjusts ira_pktlen and
   1648  11042        Erik 			 * ira_ip_hdr_length
   1649  11042        Erik 			 *
   1650  11042        Erik 			 * For AF_INET6 note that tsol_remove_secopt_v6
   1651  11042        Erik 			 * adjusted ip6_plen.
   1652  11042        Erik 			 */
   1653   1676         jpk 			if (af == AF_INET) {
   1654   1676         jpk 				ipha = (ipha_t *)mp->b_rptr;
   1655   1676         jpk 				iplen = ntohs(ipha->ipha_length) + adjust;
   1656   1676         jpk 				ipha->ipha_length = htons(iplen);
   1657   1676         jpk 				ipha->ipha_hdr_checksum = 0;
   1658   1676         jpk 				ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
   1659   1676         jpk 			}
   1660   1676         jpk 			DTRACE_PROBE3(tx__ip__log__info__forward__adjust,
   1661   1676         jpk 			    char *,
   1662   1676         jpk 			    "mp(1) adjusted(2) for CIPSO option removal",
   1663   1676         jpk 			    mblk_t *, mp, int, adjust);
   1664   1676         jpk 		}
   1665   1676         jpk 		goto keep_label;
   1666   1676         jpk 	}
   1667   1676         jpk 
   1668   1676         jpk 	ASSERT(label_type == OPT_NONE);
   1669   1676         jpk 	ASSERT(dst_rhtp != NULL);
   1670   1676         jpk 
   1671   1676         jpk 	/*
   1672   1676         jpk 	 * We need to add CIPSO option if the destination or the next hop
   1673   1676         jpk 	 * gateway is labeled.  Otherwise, pass the packet as is.
   1674   1676         jpk 	 */
   1675   1676         jpk 	if (dst_rhtp->tpc_tp.host_type == UNLABELED &&
   1676   1676         jpk 	    (!off_link || gw_rhtp->tpc_tp.host_type == UNLABELED))
   1677   1676         jpk 		goto keep_label;
   1678   1676         jpk 
   1679  11042        Erik 	/*
   1680  11042        Erik 	 * Since we are forwarding packets we use GLOBAL_ZONEID for
   1681  11042        Erik 	 * the IRE lookup in tsol_check_label.
   1682  11042        Erik 	 * Since mac_exempt is false the zoneid isn't used for anything
   1683  11042        Erik 	 * but the IRE lookup, hence we set zone_is_global to false.
   1684  11042        Erik 	 */
   1685  11042        Erik 	if (af == AF_INET) {
   1686  11042        Erik 		err = tsol_check_label_v4(tsl, GLOBAL_ZONEID, &mp,
   1687  11042        Erik 		    CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
   1688  11042        Erik 	} else {
   1689  11042        Erik 		err = tsol_check_label_v6(tsl, GLOBAL_ZONEID, &mp,
   1690  11042        Erik 		    CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
   1691  11042        Erik 	}
   1692  11042        Erik 	if (err != 0) {
   1693  11042        Erik 		BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
   1694  11042        Erik 		ip_drop_output("tsol_check_label", mp, NULL);
   1695  11042        Erik 		freemsg(mp);
   1696   1676         jpk 		mp = NULL;
   1697   1676         jpk 		goto keep_label;
   1698   1676         jpk 	}
   1699  11042        Erik 
   1700  11042        Erik 	/*
   1701  11042        Erik 	 * The effective_tsl must never affect the routing decision, hence
   1702  11042        Erik 	 * we ignore it here.
   1703  11042        Erik 	 */
   1704  11042        Erik 	if (effective_tsl != NULL)
   1705  11042        Erik 		label_rele(effective_tsl);
   1706   1676         jpk 
   1707   6596    kp158701 	if (af == AF_INET) {
   1708   6596    kp158701 		ipha = (ipha_t *)mp->b_rptr;
   1709   6596    kp158701 		ipha->ipha_hdr_checksum = 0;
   1710   6596    kp158701 		ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
   1711   1676         jpk 	}
   1712   1676         jpk 
   1713   1676         jpk keep_label:
   1714   1676         jpk 	TPC_RELE(dst_rhtp);
   1715   2535    sangeeta 	if (need_tpc_rele && gw_rhtp != NULL)
   1716   2535    sangeeta 		TPC_RELE(gw_rhtp);
   1717   1676         jpk 	return (mp);
   1718   1676         jpk }
   1719   1676         jpk 
   1720   1676         jpk /*
   1721   4564     wy83408  * Name:	tsol_pmtu_adjust()
   1722   4564     wy83408  *
   1723   4564     wy83408  * Returns the adjusted mtu after removing security option.
   1724   4564     wy83408  * Removes/subtracts the option if the packet's cred indicates an unlabeled
   1725   4564     wy83408  * sender or if pkt_diff indicates this system enlarged the packet.
   1726   4564     wy83408  */
   1727   4564     wy83408 uint32_t
   1728   4564     wy83408 tsol_pmtu_adjust(mblk_t *mp, uint32_t mtu, int pkt_diff, int af)
   1729   4564     wy83408 {
   1730   4564     wy83408 	int		label_adj = 0;
   1731   4564     wy83408 	uint32_t	min_mtu = IP_MIN_MTU;
   1732   4564     wy83408 	tsol_tpc_t	*src_rhtp;
   1733   4564     wy83408 	void		*src;
   1734   4564     wy83408 
   1735   4564     wy83408 	/*
   1736   4564     wy83408 	 * Note: label_adj is non-positive, indicating the number of
   1737   4564     wy83408 	 * bytes removed by removing the security option from the
   1738   4564     wy83408 	 * header.
   1739   4564     wy83408 	 */
   1740   4564     wy83408 	if (af == AF_INET6) {
   1741   4564     wy83408 		ip6_t	*ip6h;
   1742   4564     wy83408 
   1743   4564     wy83408 		min_mtu = IPV6_MIN_MTU;
   1744   4564     wy83408 		ip6h = (ip6_t *)mp->b_rptr;
   1745   4564     wy83408 		src = &ip6h->ip6_src;
   1746   4564     wy83408 		if ((src_rhtp = find_tpc(src, IPV6_VERSION, B_FALSE)) == NULL)
   1747   4564     wy83408 			return (mtu);
   1748   4564     wy83408 		if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED) {
   1749   4564     wy83408 			label_adj = tsol_remove_secopt_v6(
   1750   4564     wy83408 			    (ip6_t *)mp->b_rptr, MBLKL(mp));
   1751   4564     wy83408 		}
   1752   4564     wy83408 	} else {
   1753   4564     wy83408 		ipha_t    *ipha;
   1754   4564     wy83408 
   1755   4564     wy83408 		ASSERT(af == AF_INET);
   1756   4564     wy83408 		ipha = (ipha_t *)mp->b_rptr;
   1757   4564     wy83408 		src = &ipha->ipha_src;
   1758   4564     wy83408 		if ((src_rhtp = find_tpc(src, IPV4_VERSION, B_FALSE)) == NULL)
   1759   4564     wy83408 			return (mtu);
   1760   4564     wy83408 		if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED)
   1761   4564     wy83408 			label_adj = tsol_remove_secopt(
   1762   4564     wy83408 			    (ipha_t *)mp->b_rptr, MBLKL(mp));
   1763   4564     wy83408 	}
   1764   4564     wy83408 	/*
   1765   4564     wy83408 	 * Make pkt_diff non-negative and the larger of the bytes
   1766   4564     wy83408 	 * previously added (if any) or just removed, since label
   1767   4564     wy83408 	 * addition + subtraction may not be completely idempotent.
   1768   4564     wy83408 	 */
   1769   4564     wy83408 	if (pkt_diff < -label_adj)
   1770   4564     wy83408 		pkt_diff = -label_adj;
   1771   4564     wy83408 	if (pkt_diff > 0 && pkt_diff < mtu)
   1772   4564     wy83408 		mtu -= pkt_diff;
   1773   4564     wy83408 
   1774   4564     wy83408 	TPC_RELE(src_rhtp);
   1775   4564     wy83408 	return (MAX(mtu, min_mtu));
   1776   4564     wy83408 }
   1777   4564     wy83408 
   1778   4564     wy83408 /*
   1779   1676         jpk  * Name:	tsol_rtsa_init()
   1780   1676         jpk  *
   1781   1676         jpk  * Normal:	Sanity checks on the route security attributes provided by
   1782   1676         jpk  *		user.  Convert it into a route security parameter list to
   1783   1676         jpk  *		be returned to caller.
   1784   1676         jpk  *
   1785   1676         jpk  * Output:	EINVAL if bad security attributes in the routing message
   1786   1676         jpk  *		ENOMEM if unable to allocate data structures
   1787   1676         jpk  *		0 otherwise.
   1788   1676         jpk  *
   1789   1676         jpk  * Note:	On input, cp must point to the end of any addresses in
   1790   1676         jpk  *		the rt_msghdr_t structure.
   1791   1676         jpk  */
   1792   1676         jpk int
   1793   1676         jpk tsol_rtsa_init(rt_msghdr_t *rtm, tsol_rtsecattr_t *sp, caddr_t cp)
   1794   1676         jpk {
   1795   1676         jpk 	uint_t	sacnt;
   1796   1676         jpk 	int	err;
   1797   1676         jpk 	caddr_t	lim;
   1798   1676         jpk 	tsol_rtsecattr_t *tp;
   1799   1676         jpk 
   1800   1676         jpk 	ASSERT((cp >= (caddr_t)&rtm[1]) && sp != NULL);
   1801   1676         jpk 
   1802   1676         jpk 	/*
   1803   1676         jpk 	 * In theory, we could accept as many security attributes configured
   1804   1676         jpk 	 * per route destination.  However, the current design is limited
   1805   1676         jpk 	 * such that at most only one set security attributes is allowed to
   1806   1676         jpk 	 * be associated with a prefix IRE.  We therefore assert for now.
   1807   1676         jpk 	 */
   1808   1676         jpk 	/* LINTED */
   1809   1676         jpk 	ASSERT(TSOL_RTSA_REQUEST_MAX == 1);
   1810   1676         jpk 
   1811   1676         jpk 	sp->rtsa_cnt = 0;
   1812   1676         jpk 	lim = (caddr_t)rtm + rtm->rtm_msglen;
   1813   1676         jpk 	ASSERT(cp <= lim);
   1814   1676         jpk 
   1815   1676         jpk 	if ((lim - cp) < sizeof (rtm_ext_t) ||
   1816   1676         jpk 	    ((rtm_ext_t *)cp)->rtmex_type != RTMEX_GATEWAY_SECATTR)
   1817   1676         jpk 		return (0);
   1818   1676         jpk 
   1819   1676         jpk 	if (((rtm_ext_t *)cp)->rtmex_len < sizeof (tsol_rtsecattr_t))
   1820   1676         jpk 		return (EINVAL);
   1821   1676         jpk 
   1822   1676         jpk 	cp += sizeof (rtm_ext_t);
   1823   1676         jpk 
   1824   1676         jpk 	if ((lim - cp) < sizeof (*tp) ||
   1825   1676         jpk 	    (tp = (tsol_rtsecattr_t *)cp, (sacnt = tp->rtsa_cnt) == 0) ||
   1826   1676         jpk 	    (lim - cp) < TSOL_RTSECATTR_SIZE(sacnt))
   1827   1676         jpk 		return (EINVAL);
   1828   1676         jpk 
   1829   1676         jpk 	/*
   1830   1676         jpk 	 * Trying to add route security attributes when system
   1831   1676         jpk 	 * labeling service is not available, or when user supllies
   1832   1676         jpk 	 * more than the maximum number of security attributes
   1833   1676         jpk 	 * allowed per request.
   1834   1676         jpk 	 */
   1835   1676         jpk 	if ((sacnt > 0 && !is_system_labeled()) ||
   1836   1676         jpk 	    sacnt > TSOL_RTSA_REQUEST_MAX)
   1837   1676         jpk 		return (EINVAL);
   1838   1676         jpk 
   1839   1676         jpk 	/* Ensure valid credentials */
   1840   1676         jpk 	if ((err = rtsa_validate(&((tsol_rtsecattr_t *)cp)->
   1841   1676         jpk 	    rtsa_attr[0])) != 0) {
   1842   1676         jpk 		cp += sizeof (*sp);
   1843   1676         jpk 		return (err);
   1844   1676         jpk 	}
   1845   1676         jpk 
   1846   1676         jpk 	bcopy(cp, sp, sizeof (*sp));
   1847   1676         jpk 	cp += sizeof (*sp);
   1848   1676         jpk 	return (0);
   1849   1676         jpk }
   1850   1676         jpk 
   1851   1676         jpk int
   1852  11042        Erik tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc)
   1853   1676         jpk {
   1854   1676         jpk 	tsol_ire_gw_secattr_t *attrp;
   1855   1676         jpk 	boolean_t exists = B_FALSE;
   1856   1676         jpk 	in_addr_t ga_addr4;
   1857   1676         jpk 	void *paddr = NULL;
   1858  11042        Erik 	tsol_gcgrp_t *gcgrp = NULL;
   1859   1676         jpk 
   1860   1676         jpk 	ASSERT(ire != NULL);
   1861   1676         jpk 
   1862   1676         jpk 	/*
   1863   1676         jpk 	 * The only time that attrp can be NULL is when this routine is
   1864   1676         jpk 	 * called for the first time during the creation/initialization
   1865   1676         jpk 	 * of the corresponding IRE.  It will only get cleared when the
   1866   1676         jpk 	 * IRE is deleted.
   1867   1676         jpk 	 */
   1868   1676         jpk 	if ((attrp = ire->ire_gw_secattr) == NULL) {
   1869   1676         jpk 		attrp = ire_gw_secattr_alloc(KM_NOSLEEP);
   1870   1676         jpk 		if (attrp == NULL)
   1871   1676         jpk 			return (ENOMEM);
   1872   1676         jpk 		ire->ire_gw_secattr = attrp;
   1873   1676         jpk 	} else {
   1874   1676         jpk 		exists = B_TRUE;
   1875   1676         jpk 		mutex_enter(&attrp->igsa_lock);
   1876   1676         jpk 
   1877   1676         jpk 		if (attrp->igsa_rhc != NULL) {
   1878   1676         jpk 			TNRHC_RELE(attrp->igsa_rhc);
   1879   1676         jpk 			attrp->igsa_rhc = NULL;
   1880   1676         jpk 		}
   1881   1676         jpk 
   1882   1676         jpk 		if (attrp->igsa_gc != NULL)
   1883   1676         jpk 			GC_REFRELE(attrp->igsa_gc);
   1884   1676         jpk 	}
   1885   1676         jpk 	ASSERT(!exists || MUTEX_HELD(&attrp->igsa_lock));
   1886   1676         jpk 
   1887   1676         jpk 	/*
   1888   1676         jpk 	 * References already held by caller and we keep them;
   1889  11042        Erik 	 * note that gc may be set to NULL to clear out igsa_gc.
   1890   1676         jpk 	 */
   1891   1676         jpk 	attrp->igsa_gc = gc;
   1892   1676         jpk 
   1893  11042        Erik 	if (gc != NULL) {
   1894   1676         jpk 		gcgrp = gc->gc_grp;
   1895   1676         jpk 		ASSERT(gcgrp != NULL);
   1896   1676         jpk 	}
   1897   1676         jpk 
   1898   1676         jpk 	/*
   1899   1676         jpk 	 * Intialize the template for gateway; we use the gateway's
   1900   1676         jpk 	 * address found in either the passed in gateway credential
   1901   1676         jpk 	 * or group pointer, or the ire_gateway_addr{_v6} field.
   1902   1676         jpk 	 */
   1903   1676         jpk 	if (gcgrp != NULL) {
   1904   1676         jpk 		tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr;
   1905   1676         jpk 
   1906   1676         jpk 		/*
   1907   1676         jpk 		 * Caller is holding a reference, and that we don't
   1908   1676         jpk 		 * need to hold any lock to access the address.
   1909   1676         jpk 		 */
   1910   1676         jpk 		if (ipversion == IPV4_VERSION) {
   1911   1676         jpk 			ASSERT(ga->ga_af == AF_INET);
   1912   1676         jpk 			IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4);
   1913   1676         jpk 			paddr = &ga_addr4;
   1914   1676         jpk 		} else {
   1915   1676         jpk 			ASSERT(ga->ga_af == AF_INET6);
   1916   1676         jpk 			paddr = &ga->ga_addr;
   1917   1676         jpk 		}
   1918  11042        Erik 	} else if (ire->ire_type & IRE_OFFLINK) {
   1919  11042        Erik 		if (ipversion == IPV6_VERSION)
   1920  11042        Erik 			paddr = &ire->ire_gateway_addr_v6;
   1921  11042        Erik 		else if (ipversion == IPV4_VERSION)
   1922  11042        Erik 			paddr = &ire->ire_gateway_addr;
   1923   1676         jpk 	}
   1924   1676         jpk 
   1925   1676         jpk 	/*
   1926   1676         jpk 	 * Lookup the gateway template; note that we could get an internal
   1927   1676         jpk 	 * template here, which we cache anyway.  During IRE matching, we'll
   1928   1676         jpk 	 * try to update this gateway template cache and hopefully get a
   1929   1676         jpk 	 * real one.
   1930   1676         jpk 	 */
   1931   1676         jpk 	if (paddr != NULL) {
   1932   3292    kp158701 		attrp->igsa_rhc = find_rhc(paddr, ipversion, B_FALSE);
   1933   1676         jpk 	}
   1934   1676         jpk 
   1935   1676         jpk 	if (exists)
   1936   1676         jpk 		mutex_exit(&attrp->igsa_lock);
   1937   1676         jpk 
   1938   1676         jpk 	return (0);
   1939   1676         jpk }
   1940   1676         jpk 
   1941   1676         jpk /*
   1942   1676         jpk  * This function figures the type of MLP that we'll be using based on the
   1943   1676         jpk  * address that the user is binding and the zone.  If the address is
   1944   1676         jpk  * unspecified, then we're looking at both private and shared.  If it's one
   1945   1676         jpk  * of the zone's private addresses, then it's private only.  If it's one
   1946  10493     Jarrett  * of the global addresses, then it's shared only. Multicast addresses are
   1947  10493     Jarrett  * treated same as unspecified address.
   1948   1676         jpk  *
   1949   1676         jpk  * If we can't figure out what it is, then return mlptSingle.  That's actually
   1950   1676         jpk  * an error case.
   1951   3448    dh155122  *
   1952  11042        Erik  * The callers are assumed to pass in zone->zone_id and not the zoneid that
   1953   3448    dh155122  * is stored in a conn_t (since the latter will be GLOBAL_ZONEID in an
   1954   3448    dh155122  * exclusive stack zone).
   1955   1676         jpk  */
   1956   1676         jpk mlp_type_t
   1957   3448    dh155122 tsol_mlp_addr_type(zoneid_t zoneid, uchar_t version, const void *addr,
   1958   3448    dh155122     ip_stack_t *ipst)
   1959   1676         jpk {
   1960   1676         jpk 	in_addr_t in4;
   1961   1676         jpk 	ire_t *ire;
   1962   1676         jpk 	ipif_t *ipif;
   1963   1676         jpk 	zoneid_t addrzone;
   1964   3448    dh155122 	zoneid_t ip_zoneid;
   1965   1676         jpk 
   1966   1676         jpk 	ASSERT(addr != NULL);
   1967   3448    dh155122 
   1968   3448    dh155122 	/*
   1969   3448    dh155122 	 * For exclusive stacks we set the zoneid to zero
   1970   3448    dh155122 	 * to operate as if in the global zone for IRE and conn_t comparisons.
   1971   3448    dh155122 	 */
   1972   3448    dh155122 	if (ipst->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID)
   1973   3448    dh155122 		ip_zoneid = GLOBAL_ZONEID;
   1974   3448    dh155122 	else
   1975   3448    dh155122 		ip_zoneid = zoneid;
   1976   1676         jpk 
   1977   1676         jpk 	if (version == IPV6_VERSION &&
   1978   1676         jpk 	    IN6_IS_ADDR_V4MAPPED((const in6_addr_t *)addr)) {
   1979   1676         jpk 		IN6_V4MAPPED_TO_IPADDR((const in6_addr_t *)addr, in4);
   1980   1676         jpk 		addr = &in4;
   1981   1676         jpk 		version = IPV4_VERSION;
   1982   1676         jpk 	}
   1983   1676         jpk 
   1984  11042        Erik 	/* Check whether the IRE_LOCAL (or ipif) is ALL_ZONES */
   1985   1676         jpk 	if (version == IPV4_VERSION) {
   1986   1676         jpk 		in4 = *(const in_addr_t *)addr;
   1987  10493     Jarrett 		if ((in4 == INADDR_ANY) || CLASSD(in4)) {
   1988   1676         jpk 			return (mlptBoth);
   1989   3448    dh155122 		}
   1990  11042        Erik 		ire = ire_ftable_lookup_v4(in4, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
   1991  11042        Erik 		    NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
   1992  11042        Erik 		    0, ipst, NULL);
   1993   1676         jpk 	} else {
   1994  10493     Jarrett 		if (IN6_IS_ADDR_UNSPECIFIED((const in6_addr_t *)addr) ||
   1995  10493     Jarrett 		    IN6_IS_ADDR_MULTICAST((const in6_addr_t *)addr)) {
   1996   1676         jpk 			return (mlptBoth);
   1997   3448    dh155122 		}
   1998  11042        Erik 		ire = ire_ftable_lookup_v6(addr, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
   1999  11042        Erik 		    NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
   2000  11042        Erik 		    0, ipst, NULL);
   2001   1676         jpk 	}
   2002   1676         jpk 	/*
   2003   1676         jpk 	 * If we can't find the IRE, then we have to behave exactly like
   2004  11042        Erik 	 * ip_laddr_verify_{v4,v6}.  That means looking up the IPIF so that
   2005  11042        Erik 	 * users can bind to addresses on "down" interfaces.
   2006   1676         jpk 	 *
   2007   1676         jpk 	 * If we can't find that either, then the bind is going to fail, so
   2008   1676         jpk 	 * just give up.  Note that there's a miniscule chance that the address
   2009   1676         jpk 	 * is in transition, but we don't bother handling that.
   2010   1676         jpk 	 */
   2011   1676         jpk 	if (ire == NULL) {
   2012   1676         jpk 		if (version == IPV4_VERSION)
   2013   1676         jpk 			ipif = ipif_lookup_addr(*(const in_addr_t *)addr, NULL,
   2014  11042        Erik 			    ip_zoneid, ipst);
   2015   1676         jpk 		else
   2016   1676         jpk 			ipif = ipif_lookup_addr_v6((const in6_addr_t *)addr,
   2017  11042        Erik 			    NULL, ip_zoneid, ipst);
   2018   3448    dh155122 		if (ipif == NULL) {
   2019   1676         jpk 			return (mlptSingle);
   2020   3448    dh155122 		}
   2021   1676         jpk 		addrzone = ipif->ipif_zoneid;
   2022   1676         jpk 		ipif_refrele(ipif);
   2023   1676         jpk 	} else {
   2024   1676         jpk 		addrzone = ire->ire_zoneid;
   2025   1676         jpk 		ire_refrele(ire);
   2026   1676         jpk 	}
   2027   1676         jpk 	return (addrzone == ALL_ZONES ? mlptShared : mlptPrivate);
   2028   1676         jpk }
   2029   1676         jpk 
   2030   1676         jpk /*
   2031   1676         jpk  * Since we are configuring local interfaces, and we know trusted
   2032   1676         jpk  * extension CDE requires local interfaces to be cipso host type in
   2033   1676         jpk  * order to function correctly, we'll associate a cipso template
   2034   1676         jpk  * to each local interface and let the interface come up.  Configuring
   2035   1676         jpk  * a local interface to be "unlabeled" host type is a configuration error.
   2036   1676         jpk  * We'll override that error and make the interface host type to be cipso
   2037   1676         jpk  * here.
   2038   1676         jpk  *
   2039   1676         jpk  * The code is optimized for the usual "success" case and unwinds things on
   2040   1676         jpk  * error.  We don't want to go to the trouble and expense of formatting the
   2041   1676         jpk  * interface name for the usual case where everything is configured correctly.
   2042   1676         jpk  */
   2043   1676         jpk boolean_t
   2044   1676         jpk tsol_check_interface_address(const ipif_t *ipif)
   2045   1676         jpk {
   2046   1676         jpk 	tsol_tpc_t *tp;
   2047   1676         jpk 	char addrbuf[INET6_ADDRSTRLEN];
   2048   1676         jpk 	int af;
   2049   1676         jpk 	const void *addr;
   2050   1676         jpk 	zone_t *zone;
   2051   1676         jpk 	ts_label_t *plabel;
   2052   1676         jpk 	const bslabel_t *label;
   2053   1676         jpk 	char ifbuf[LIFNAMSIZ + 10];
   2054   1676         jpk 	const char *ifname;
   2055   1676         jpk 	boolean_t retval;
   2056   1676         jpk 	tsol_rhent_t rhent;
   2057   3448    dh155122 	netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack;
   2058   1676         jpk 
   2059   1676         jpk 	if (IN6_IS_ADDR_V4MAPPED(&ipif->ipif_v6lcl_addr)) {
   2060   1676         jpk 		af = AF_INET;
   2061   1676         jpk 		addr = &V4_PART_OF_V6(ipif->ipif_v6lcl_addr);
   2062   1676         jpk 	} else {
   2063   1676         jpk 		af = AF_INET6;
   2064   1676         jpk 		addr = &ipif->ipif_v6lcl_addr;
   2065   1676         jpk 	}
   2066   1676         jpk 
   2067   1676         jpk 	tp = find_tpc(&ipif->ipif_v6lcl_addr, IPV6_VERSION, B_FALSE);
   2068   3448    dh155122 
   2069   3448    dh155122 	/* assumes that ALL_ZONES implies that there is no exclusive stack */
   2070   3448    dh155122 	if (ipif->ipif_zoneid == ALL_ZONES) {
   2071   3448    dh155122 		zone = NULL;
   2072   3448    dh155122 	} else if (ns->netstack_stackid == GLOBAL_NETSTACKID) {
   2073   3448    dh155122 		/* Shared stack case */
   2074   3448    dh155122 		zone = zone_find_by_id(ipif->ipif_zoneid);
   2075   3448    dh155122 	} else {
   2076   3448    dh155122 		/* Exclusive stack case */
   2077   3448    dh155122 		zone = zone_find_by_id(crgetzoneid(ipif->ipif_ill->ill_credp));
   2078   3448    dh155122 	}
   2079   1676         jpk 	if (zone != NULL) {
   2080   1676         jpk 		plabel = zone->zone_slabel;
   2081   1676         jpk 		ASSERT(plabel != NULL);
   2082   1676         jpk 		label = label2bslabel(plabel);
   2083   1676         jpk 	}
   2084   1676         jpk 
   2085   1676         jpk 	/*
   2086   1676         jpk 	 * If it's CIPSO and an all-zones address, then we're done.
   2087   1676         jpk 	 * If it's a CIPSO zone specific address, the zone's label
   2088   1676         jpk 	 * must be in the range or set specified in the template.
   2089   1676         jpk 	 * When the remote host entry is missing or the template
   2090   1676         jpk 	 * type is incorrect for this interface, we create a
   2091   1676         jpk 	 * CIPSO host entry in kernel and allow the interface to be
   2092   1676         jpk 	 * brought up as CIPSO type.
   2093   1676         jpk 	 */
   2094   1676         jpk 	if (tp != NULL && (
   2095   1676         jpk 	    /* The all-zones case */
   2096   1676         jpk 	    (tp->tpc_tp.host_type == SUN_CIPSO &&
   2097   1676         jpk 	    tp->tpc_tp.tp_doi == default_doi &&
   2098   1676         jpk 	    ipif->ipif_zoneid == ALL_ZONES) ||
   2099   1676         jpk 	    /* The local-zone case */
   2100   1676         jpk 	    (zone != NULL && plabel->tsl_doi == tp->tpc_tp.tp_doi &&
   2101   1676         jpk 	    ((tp->tpc_tp.host_type == SUN_CIPSO &&
   2102   1676         jpk 	    (_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) ||
   2103   1676         jpk 	    blinlset(label, tp->tpc_tp.tp_sl_set_cipso))))))) {
   2104   1676         jpk 		if (zone != NULL)
   2105   1676         jpk 			zone_rele(zone);
   2106   1676         jpk 		TPC_RELE(tp);
   2107   1676         jpk 		return (B_TRUE);
   2108   1676         jpk 	}
   2109   1676         jpk 
   2110   1676         jpk 	ifname = ipif->ipif_ill->ill_name;
   2111   1676         jpk 	if (ipif->ipif_id != 0) {
   2112   1676         jpk 		(void) snprintf(ifbuf, sizeof (ifbuf), "%s:%u", ifname,
   2113   1676         jpk 		    ipif->ipif_id);
   2114   1676         jpk 		ifname = ifbuf;
   2115   1676         jpk 	}
   2116   1676         jpk 	(void) inet_ntop(af, addr, addrbuf, sizeof (addrbuf));
   2117   1676         jpk 
   2118   1676         jpk 	if (tp == NULL) {
   2119   1676         jpk 		cmn_err(CE_NOTE, "template entry for %s missing. Default to "
   2120   1676         jpk 		    "CIPSO type for %s", ifname, addrbuf);
   2121   1676         jpk 		retval = B_TRUE;
   2122   1676         jpk 	} else if (tp->tpc_tp.host_type == UNLABELED) {
   2123   1676         jpk 		cmn_err(CE_NOTE, "template type for %s incorrectly configured. "
   2124   1676         jpk 		    "Change to CIPSO type for %s", ifname, addrbuf);
   2125   1676         jpk 		retval = B_TRUE;
   2126   1676         jpk 	} else if (ipif->ipif_zoneid == ALL_ZONES) {
   2127   1676         jpk 		if (tp->tpc_tp.host_type != SUN_CIPSO) {
   2128   1676         jpk 			cmn_err(CE_NOTE, "%s failed: %s isn't set to CIPSO for "
   2129   1676         jpk 			    "all-zones. Converted to CIPSO.", ifname, addrbuf);
   2130   1676         jpk 			retval = B_TRUE;
   2131   1676         jpk 		} else {
   2132   1676         jpk 			cmn_err(CE_NOTE, "%s failed: %s has wrong DOI %d "
   2133   1676         jpk 			    "instead of %d", ifname, addrbuf,
   2134   1676         jpk 			    tp->tpc_tp.tp_doi, default_doi);
   2135   1676         jpk 			retval = B_FALSE;
   2136   1676         jpk 		}
   2137   1676         jpk 	} else if (zone == NULL) {
   2138   1676         jpk 		cmn_err(CE_NOTE, "%s failed: zoneid %d unknown",
   2139   1676         jpk 		    ifname, ipif->ipif_zoneid);
   2140   1676         jpk 		retval = B_FALSE;
   2141   1676         jpk 	} else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) {
   2142   1676         jpk 		cmn_err(CE_NOTE, "%s failed: zone %s has DOI %d but %s has "
   2143   1676         jpk 		    "DOI %d", ifname, zone->zone_name, plabel->tsl_doi,
   2144   1676         jpk 		    addrbuf, tp->tpc_tp.tp_doi);
   2145   1676         jpk 		retval = B_FALSE;
   2146   1676         jpk 	} else {
   2147   1676         jpk 		cmn_err(CE_NOTE, "%s failed: zone %s label incompatible with "
   2148   1676         jpk 		    "%s", ifname, zone->zone_name, addrbuf);
   2149   1676         jpk 		tsol_print_label(label, "zone label");
   2150   1676         jpk 		retval = B_FALSE;
   2151   1676         jpk 	}
   2152   1676         jpk 
   2153   1676         jpk 	if (zone != NULL)
   2154   1676         jpk 		zone_rele(zone);
   2155   1676         jpk 	if (tp != NULL)
   2156   1676         jpk 		TPC_RELE(tp);
   2157   1676         jpk 	if (retval) {
   2158   1676         jpk 		/*
   2159   1676         jpk 		 * we've corrected a config error and let the interface
   2160   1676         jpk 		 * come up as cipso. Need to insert an rhent.
   2161   1676         jpk 		 */
   2162   1676         jpk 		if ((rhent.rh_address.ta_family = af) == AF_INET) {
   2163   1676         jpk 			rhent.rh_prefix = 32;
   2164   1676         jpk 			rhent.rh_address.ta_addr_v4 = *(struct in_addr *)addr;
   2165   1676         jpk 		} else {
   2166   1676         jpk 			rhent.rh_prefix = 128;
   2167   1676         jpk 			rhent.rh_address.ta_addr_v6 = *(in6_addr_t *)addr;
   2168   1676         jpk 		}
   2169   1676         jpk 		(void) strcpy(rhent.rh_template, "cipso");
   2170   1676         jpk 		if (tnrh_load(&rhent) != 0) {
   2171   1676         jpk 			cmn_err(CE_NOTE, "%s failed: Cannot insert CIPSO "
   2172   1676         jpk 			    "template for local addr %s", ifname, addrbuf);
   2173   1676         jpk 			retval = B_FALSE;
   2174   1676         jpk 		}
   2175   1676         jpk 	}
   2176   1676         jpk 	return (retval);
   2177   1676         jpk }
   2178