45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER START
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The contents of this file are subject to the terms of the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Common Development and Distribution License (the "License").
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You may not use this file except in compliance with the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * See the License for the specific language governing permissions
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and limitations under the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When distributing Covered Code, include this CDDL HEADER in each
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If applicable, add the following below this CDDL HEADER, with the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * fields enclosed by brackets "[]" replaced with your own identifying
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information: Portions Copyright [yyyy] [name of copyright owner]
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER END
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Use is subject to license terms.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* tunable for strict error-reply behavior (TCP RST and ICMP Unreachable) */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Some notes on the Trusted Solaris IRE gateway security attributes:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When running in Trusted mode, the routing subsystem determines whether or
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * not a packet can be delivered to an off-link host (not directly reachable
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * through an interface) based on the accreditation checks of the packet's
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes against those associated with the next-hop gateway.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The next-hop gateway's security attributes can be derived from two sources
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * (in order of preference): route-related and the host database. A Trusted
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * system must be configured with at least the host database containing an
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * entry for the next-hop gateway, or otherwise no accreditation checks can
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * be performed, which may result in the inability to send packets to any
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * off-link destination host.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The major differences between the two sources are the number and type of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes used for accreditation checks. A host database entry
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * can contain at most one set of security attributes, specific only to the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * next-hop gateway. On contrast, route-related security attributes are made
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * up of a collection of security attributes for the distant networks, and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * are grouped together per next-hop gateway used to reach those networks.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This is the preferred method, and the routing subsystem will fallback to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the host database entry only if there are no route-related attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * associated with the next-hop gateway.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In Trusted mode, all of the IRE entries (except LOCAL/LOOPBACK/BROADCAST/
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * INTERFACE type) are initialized to contain a placeholder to store this
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information. The ire_gw_secattr structure gets allocated, initialized
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and associated with the IRE during the time of the IRE creation. The
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * initialization process also includes resolving the host database entry
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the next-hop gateway for fallback purposes. It does not include any
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * route-related attribute setup, as that process comes separately as part
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the route requests (add/change) made to the routing subsystem.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The underlying logic which involves associating IREs with the gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes are represented by the following data structures:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_gcdb_t, or "gcdb"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - This is a system-wide collection of records containing the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * currently used route-related security attributes, which are fed
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * through the routing socket interface, e.g. "route add/change".
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_gc_t, or "gc"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - This is the gateway credential structure, and it provides for the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * only mechanism to access the contents of gcdb. More than one gc
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * entries may refer to the same gcdb record. gc's in the system are
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * grouped according to the next-hop gateway address.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_gcgrp_t, or "gcgrp"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Group of gateway credentials, and is unique per next-hop gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address. When the group is not empty, i.e. when gcgrp_count is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * greater than zero, it contains one or more gc's, each pointing to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a gcdb record which indicates the gateway security attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * associated with the next-hop gateway.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The fields of the tsol_ire_gw_secattr_t used from within the IRE are:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * igsa_lock
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Lock that protects all fields within tsol_ire_gw_secattr_t.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * igsa_rhc
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Remote host cache database entry of next-hop gateway. This is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * used in the case when there are no route-related attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * configured for the IRE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - A set of route-related attributes that only get set for prefix
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * IREs. If this is non-NULL, the prefix IRE has been associated
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * with a set of gateway security attributes by way of route add/
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * change functionality.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (--((p)->gcdb_refcnt) == 0) \
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic uint_t gcdb_hash_by_secattr(void *, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int gcdb_hash_cmp(mod_hash_key_t, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic tsol_gcdb_t *gcdb_lookup(struct rtsa_s *, boolean_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic uint_t gcgrp_hash_by_addr(void *, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int gcgrp_hash_cmp(mod_hash_key_t, mod_hash_key_t);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int ire_gw_secattr_constructor(void *, void *, int);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void ire_gw_secattr_destructor(void *, void *);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ire_gw_secattr_cache = kmem_cache_create("ire_gw_secattr_cache",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sizeof (tsol_ire_gw_secattr_t), 64, ire_gw_secattr_constructor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcdb_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkire_gw_secattr_constructor(void *buf, void *cdrarg, int kmflags)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_init(&attrp->igsa_lock, NULL, MUTEX_DEFAULT, NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_ire_gw_secattr_t *attrp = (tsol_ire_gw_secattr_t *)buf;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (kmem_cache_alloc(ire_gw_secattr_cache, kmflags));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgcdb_hash_by_secattr(void *hash_data, mod_hash_key_t key)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* See comments in hash_bylabel in zone.c for details */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* using 2^n + 1, 1 <= n <= 16 as source of many primes */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* No match; not found */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* ARGSUSED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Address family must match */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ga1->ga_addr.s6_addr32[0] == ga2->ga_addr.s6_addr32[0] &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ga1->ga_addr.s6_addr32[1] == ga2->ga_addr.s6_addr32[1] &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ga1->ga_addr.s6_addr32[2] == ga2->ga_addr.s6_addr32[2] &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* No match; not found */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* RTSA_CIPSO must be set, and DOI must not be zero */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "rtsa(1) lacks flag or has 0 doi.",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * SL range must be specified, and it must have its
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * upper bound dominating its lower bound.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "rtsa(1) min_sl and max_sl not set or max_sl is "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * A brief explanation of the reference counting scheme:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Apart from dynamic references due to to reference holds done
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * actively by threads, we have the following references:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gcdb_refcnt:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Every tsol_gc_t pointing to a tsol_gcdb_t contributes a reference
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to the gcdb_refcnt.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gc_refcnt:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - A prefix IRE that points to an igsa_gc contributes a reference
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to the gc_refcnt.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gcgrp_refcnt:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a reference to the gcgrp_refcnt.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Find a copy in the cache; otherwise, create one and cache it */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__lookup, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "gcdb(1) is in gcdb_hash(global)", tsol_gcdb_t *, gcdb);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (alloc) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__insert, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "gcdb(1) inserted in gcdb_hash(global)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic void
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (void) mod_hash_remove(gcdb_hash, (mod_hash_key_t)&gcdb->gcdb_attr,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__remove, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "gcdb(1) removed from gcdb_hash(global)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgc_create(struct rtsa_s *rp, tsol_gcgrp_t *gcgrp, boolean_t *gcgrp_xtrarefp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk for (gc = gcgrp->gcgrp_head; gc != NULL; gc = gc->gc_next) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "found gc(1) in gcgrp(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* caller has incremented gcgrp reference for us */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* drop lock before it's destroyed */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "removed inactive gc(1) from gcgrp(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__lookup, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (alloc) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "inserted gcgrp(1) in hash(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(gcgrp->gcgrp_head == NULL && gcgrp->gcgrp_count == 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__remove, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "removed inactive gcgrp(1) from hash(2)",
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * Assign a sensitivity label to inbound traffic which arrived without
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * an explicit on-the-wire label.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * In the case of CIPSO-type hosts, we assume packets arriving without
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * a label are at the most sensitive label known for the host, most
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * likely involving out-of-band key management traffic (such as IKE,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeldtsol_find_unlabeled_label(tsol_tpc_t *rhtp, bslabel_t *sl, uint32_t *doi)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld *sl = rhtp->tpc_tp.tp_sl_range_cipso.upper_bound;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Converts CIPSO option to sensitivity label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Validity checks based on restrictions defined in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) (draft-ietf-cipso-ipsecurity)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const struct cipso_option *co = (const struct cipso_option *)option;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1 = (struct cipso_tag_type_1 *)&co->cipso_tag_type[0];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_length + TSOL_CIPSO_TAG_OFFSET > co->cipso_length)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bsllow(sl); /* assumed: sets compartments to all zeroes */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(tt1->tag_cat, &((_bslabel_impl_t *)sl)->compartments,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If present, parse the CIPSO label in the incoming packet and
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * construct a ts_label_t that reflects the CIPSO label and put it in
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the ip_recv_attr_t. Later as the packet flows up through the stack any
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * code that needs to examine the packet label can inspect the label
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * from the ira_tsl. This function is
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * called right in ip_input for all packets, i.e. locally destined and
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to be forwarded packets. The forwarding path needs to examine the label
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to determine how to forward the packet.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * This routine pulls all message text up into the first mblk.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * For IPv4, only the first 20 bytes of the IP header are guaranteed
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * to exist. For IPv6, only the IPv6 header is guaranteed to exist.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_get_pkt_label(mblk_t *mp, int version, ip_recv_attr_t *ira)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld uint32_t label_flags = 0; /* flags to set in label */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (mp->b_cont != NULL && !pullupmsg(mp, -1))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ASSERT(MBLKL(mp) >= IP_SIMPLE_HDR_LENGTH);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v4(mp, &label_type, &opt_ptr))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ASSERT(MBLKL(mp) >= IPV6_HDR_LEN);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v6(mp, &label_type, &opt_ptr))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Convert the CIPSO label to the internal format
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and attach it to the dblk cred.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Validity checks based on restrictions defined in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * (draft-ietf-cipso-ipsecurity)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * If the source was unlabeled, then flag as such,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * (since CIPSO routers may add headers)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (src_rhtp->tpc_tp.host_type == UNLABELED)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * Handle special cases that may not be labeled, even
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * though the sending system may otherwise be configured as
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * labeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - IPv4 ICMP Router Discovery
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - IPv6 Neighbor Discovery
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * - IPsec ESP
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if ((uchar_t *)icmp + ICMP_MINLEN > mp->b_wptr)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Look up the tnrhtp database and get the implicit label
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * that is associated with the sending host and attach
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * it to the packet.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * If peer is label-aware, mark as "implicit" rather than
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * "unlabeled" to cause appropriate mac-exempt processing
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (src_rhtp->tpc_tp.host_type == SUN_CIPSO)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld else if (src_rhtp->tpc_tp.host_type == UNLABELED)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "template(1) has unknown hosttype",
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (!tsol_find_unlabeled_label(src_rhtp, &sl, &doi)) {
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark credp = newcred_from_bslabel(&sl, doi, KM_NOSLEEP);
0e0e37a8f0c38eb919c913bbb67030114a6b74a9Erik Nordmark credp = copycred_from_bslabel(ira->ira_cred, &sl, doi,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Put the label in ira_tsl for convinience, while keeping
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the cred in ira_cred for getpeerucred which is used to get
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * labels with TX.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note: no explicit refcnt/free_flag for ira_tsl. The free_flag
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * for IRA_FREE_CRED is sufficient for both.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine determines whether the given packet should be accepted locally.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * It does a range/set check on the packet's label by looking up the given
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address in the remote host database.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark boolean_t shared_addr = (ira->ira_flags & IRAF_TX_SHARED_ADDR);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_get_pkt_label intentionally avoids the labeling process for:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IPv6 router and neighbor discovery as well as redirects.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - MLD packets. (Anything between ICMPv6 code 130 and 138.)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IGMP packets.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * - IPv4 router discovery.
0e0e37a8f0c38eb919c913bbb67030114a6b74a9Erik Nordmark * In those cases ira_cred is NULL.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If this packet is from the inside (not a remote host) and has the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * same zoneid as the selected destination, then no checks are
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * necessary. Membership in the zone is enough proof. This is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * intended to be a hot path through this function.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note: Using crgetzone here is ok since the peer is local.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * Implicitly labeled packets from label-aware sources
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * go only to privileged receivers
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if ((plabel->tsl_flags & TSLF_IMPLICIT_IN) &&
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld (connp->conn_mac_mode != CONN_MAC_IMPLICIT)) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac_impl,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "implicitly labeled packet mp(1) for conn(2) "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "which isn't in implicit mac mode",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * MLPs are always validated using the range and set of the local
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address, even when the remote host is unlabeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED: no consequent */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk connp->conn_mlp_type == (shared_addr ? mlptShared : mlptPrivate)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If this is a packet from an unlabeled sender, then we must apply
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * different rules. If the label is equal to the zone's label, then
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * it's allowed. If it's not equal, but the zone is either the global
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * zone or the label is dominated by the zone's label, then allow it
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * as long as it's in the range configured for the destination.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if ((connp->conn_mac_mode == CONN_MAC_DEFAULT) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "unlabeled packet mp(1) fails mac for conn(2)",
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * If this is a packet from a labeled sender, verify the
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * label on the packet matches the connection label.
e071b5fba24bf7b3147969da51eb5d194a13dcaakp "packet mp(1) failed label match to SLP conn(2)",
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * No further checks will be needed if this is a zone-
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * specific address because (1) The process for bringing up
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * the interface ensures the zone's label is within the zone-
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * specific address's valid label range; (2) For cases where
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * the conn is bound to the unspecified addresses, ip fanout
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * logic ensures conn's zoneid equals the dest addr's zoneid;
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * (3) Mac-exempt and mlp logic above already handle all
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * cases where the zone label may not be the same as the
e071b5fba24bf7b3147969da51eb5d194a13dcaakp * conn label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "dropping mp(1), host(2) lacks entry",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The local host address should not be unlabeled at this point. The
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * only way this can happen is that the destination isn't unicast. We
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * assume that the packet should not have had a label, and thus should
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * have been handled by the TSLF_UNLABELED logic above.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__flag, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) unlabeled source, but tp is not unlabeled.",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__tptype, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "delivering mp(1), found unrecognized tpc(2) type.",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) could not be delievered to tp(2), doi mismatch",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (!_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) could not be delievered to tp(2), bad mac",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_can_accept_raw(mblk_t *mp, ip_recv_attr_t *ira, boolean_t check_host)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We are bootstrapping or the internal template was never deleted */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Check that the packet's label is in the correct range for labeled
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * sender, or is equal to the default label for unlabeled sender.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk !blequal(&plabel->tsl_label, &src_rhtp->tpc_tp.tp_def_label))) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (check_host) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Until we have SL range in the Zone structure, pass it
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * when our own address lookup returned an internal entry.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine determines whether a response to a failed packet delivery or
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * connection should be sent back. By default, the policy is to allow such
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * messages to be sent at all times, as these messages reveal little useful
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information and are healthy parts of TCP/IP networking.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If tsol_strict_error is set, then we do strict tests: if the packet label is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * within the label range/set of this host/zone, return B_TRUE; otherwise
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * return B_FALSE, which causes the packet to be dropped silently.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note that tsol_get_pkt_label will cause the packet to drop if the sender is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * marked as labeled in the remote host database, but the packet lacks a label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This means that we don't need to do a lookup on the source; the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * TSLF_UNLABELED flag is sufficient.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_can_reply_error(const mblk_t *mp, ip_recv_attr_t *ira)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Caller must pull up at least the IP header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(MBLKL(mp) >= (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ?
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We are bootstrapping or the internal template was never deleted */
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(tx__ip__log__drop__replyerror__unresolved__label,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "cannot send error report for packet mp(1) with "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "unresolved security label sl(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rhtp == NULL || label2doi(plabel) != rhtp->tpc_tp.tp_doi) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we're in the midst of forwarding, then the destination
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address might not be labeled. In that case, allow unlabeled
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * packets through only if the default label is the same, and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * labeled ones if they dominate.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Finds the zone associated with the receive attributes. Returns GLOBAL_ZONEID
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * if the zone cannot be located.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This is used by the classifier when the packet matches an ALL_ZONES IRE, and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * there's no MLP defined.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note that we assume that this is only invoked in the ALL_ZONES case.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Handling other cases would require handling exclusive IP zones where either
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * this routine or the callers would have to map from
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * the zoneid (zone->zone_id) to what IP uses in conn_zoneid etc.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Not in Trusted mode or IRE is local/loopback/broadcast/interface */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST |
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we don't have a label to compare with, or the IRE does not
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * contain any gateway security attributes, there's not much that
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * we can do. We let the former case pass, and the latter fail,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * since the IRE doesn't qualify for a match due to the lack of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security attributes.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld tx__ip__log__drop__irematch__nogwsec, char *,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "ire(1) lacks ire_gw_secattr when matching "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "label(2)", ire_t *, ire, ts_label_t *, tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The possible lock order scenarios related to the tsol gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * attribute locks are documented at the beginning of ip.c in the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * lock order scenario section.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We seek the group
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * structure which contains all security credentials of the gateway.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * An offline IRE is associated with at most one gateway credential.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If our cached entry has grown stale, then discard it so we
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * can get a new one.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (gw_rhc->rhc_invalid || gw_rhc->rhc_tpc->tpc_invalid) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Last attempt at loading the template had failed; try again */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* We've found a gateway address to do the template lookup */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note that if the lookup above returned an
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * internal template, we'll use it for the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * time being, and do another lookup next
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * time around.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Another thread has loaded the template? */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* reload, it could be different */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Hold an extra reference just like we did
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * above prior to dropping the igsa_lock.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Gateway template not found */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If destination address is directly reachable through an
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * interface rather than through a learned route, pass it.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "ire(1), label(2) off-link with no gw_rhc",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In the case of IRE_CACHE we've got one or more gateway
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * security credentials to compare against the passed in label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Perform label range comparison against each security
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * credential of the gateway. In the case of a prefix ire
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * we need to match against the security attributes of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * just the route itself, so the loop is executed only once.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark !_blinrange(&tsl->tsl_label, &gcdb->gcdb_slrange)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "ire(1), tsl(2): all gc failed match",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We didn't find any gateway credentials in the IRE
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * attributes; fall back to the gateway's template for
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * label range checks, if we are required to do so.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "ire(1), tsl(2), gw_rhc(3) "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "failed match (cipso gw)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *, "ire(1), tsl(2), gw_rhc(3) "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "failed match (unlabeled gw)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Performs label accreditation checks for packet forwarding.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Add or remove a CIPSO option as needed.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns a pointer to the modified mblk if allowed for forwarding,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or NULL if the packet must be dropped.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_ip_forward(ire_t *ire, mblk_t *mp, const ip_recv_attr_t *ira)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that the ire is the first one found, i.e., an IRE_OFFLINK if
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the destination is offlink.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk af = (ire->ire_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v4(mp, &label_type, &opt_ptr))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* malformed packet; drop it */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_get_option_v6(mp, &label_type, &opt_ptr))
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * off_link is TRUE if destination not directly reachable.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(tx__ip__log__drop__forward__unresolved__label,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "cannot forward packet mp(1) with unresolved "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "security label sl(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Without a template we do not know if forwarding
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * violates MAC
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk DTRACE_PROBE3(tx__ip__log__drop__forward__nodst, char *,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) dropped, no template for destination ip4|6(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Gateway template must have existed for off-link destinations,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * since tsol_ire_match_gwattr has ensured such condition.
c793af95640863cd29868fc7c419c5d2496b207bsangeeta if (ire->ire_ipversion == IPV4_VERSION && off_link) {
c793af95640863cd29868fc7c419c5d2496b207bsangeeta * Surya note: first check if we can get the gw_rhtp from
c793af95640863cd29868fc7c419c5d2496b207bsangeeta * the ire_gw_secattr->igsa_rhc; if this is null, then
c793af95640863cd29868fc7c419c5d2496b207bsangeeta * do a lookup based on the ire_addr (address of gw)
c793af95640863cd29868fc7c419c5d2496b207bsangeeta gw_rhtp = find_tpc(gw, ire->ire_ipversion, B_FALSE);
c793af95640863cd29868fc7c419c5d2496b207bsangeeta DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *,
c793af95640863cd29868fc7c419c5d2496b207bsangeeta "mp(1) dropped, no gateway in ire attributes(2)",
c793af95640863cd29868fc7c419c5d2496b207bsangeeta ((attrp = ire->ire_gw_secattr) == NULL || attrp->igsa_rhc == NULL ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (gw_rhtp = attrp->igsa_rhc->rhc_tpc) == NULL) && off_link) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) dropped, no gateway in ire attributes(2)",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Check that the label for the packet is acceptable
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * by destination host; otherwise, drop it.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "labeled packet mp(1) dropped, label(2) fails "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "destination(3) accredation check",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "unlabeled packet mp(1) dropped, label(2) fails "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "destination(3) accredation check",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We keep the label on any of the following cases:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 1. The destination is labeled (on/off-link).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 2. The unlabeled destination is off-link,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and the next hop gateway is labeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Strip off the CIPSO option from the packet because: the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * unlabeled destination host is directly reachable through
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * an interface (on-link); or, the unlabeled destination host
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * is not directly reachable (off-link), and the next hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gateway is unlabeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk adjust = (af == AF_INET) ? tsol_remove_secopt(ipha, MBLKL(mp)) :
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (adjust != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* adjust is negative */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that caller adjusts ira_pktlen and
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ira_ip_hdr_length
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * For AF_INET6 note that tsol_remove_secopt_v6
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * adjusted ip6_plen.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "mp(1) adjusted(2) for CIPSO option removal",
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We need to add CIPSO option if the destination or the next hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gateway is labeled. Otherwise, pass the packet as is.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since we are forwarding packets we use GLOBAL_ZONEID for
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the IRE lookup in tsol_check_label.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Since mac_exempt is false the zoneid isn't used for anything
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * but the IRE lookup, hence we set zone_is_global to false.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark err = tsol_check_label_v4(tsl, GLOBAL_ZONEID, &mp,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark err = tsol_check_label_v6(tsl, GLOBAL_ZONEID, &mp,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The effective_tsl must never affect the routing decision, hence
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * we ignore it here.
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Name: tsol_pmtu_adjust()
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Returns the adjusted mtu after removing security option.
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Removes/subtracts the option if the packet's cred indicates an unlabeled
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * sender or if pkt_diff indicates this system enlarged the packet.
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wytsol_pmtu_adjust(mblk_t *mp, uint32_t mtu, int pkt_diff, int af)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Note: label_adj is non-positive, indicating the number of
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * bytes removed by removing the security option from the
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if ((src_rhtp = find_tpc(src, IPV6_VERSION, B_FALSE)) == NULL)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED) {
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if ((src_rhtp = find_tpc(src, IPV4_VERSION, B_FALSE)) == NULL)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED)
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * Make pkt_diff non-negative and the larger of the bytes
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * previously added (if any) or just removed, since label
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * addition + subtraction may not be completely idempotent.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Name: tsol_rtsa_init()
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Normal: Sanity checks on the route security attributes provided by
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * user. Convert it into a route security parameter list to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * be returned to caller.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Output: EINVAL if bad security attributes in the routing message
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * ENOMEM if unable to allocate data structures
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 0 otherwise.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Note: On input, cp must point to the end of any addresses in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the rt_msghdr_t structure.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_rtsa_init(rt_msghdr_t *rtm, tsol_rtsecattr_t *sp, caddr_t cp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In theory, we could accept as many security attributes configured
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * per route destination. However, the current design is limited
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * such that at most only one set security attributes is allowed to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * be associated with a prefix IRE. We therefore assert for now.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (((rtm_ext_t *)cp)->rtmex_len < sizeof (tsol_rtsecattr_t))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (tp = (tsol_rtsecattr_t *)cp, (sacnt = tp->rtsa_cnt) == 0) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Trying to add route security attributes when system
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * labeling service is not available, or when user supllies
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * more than the maximum number of security attributes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * allowed per request.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Ensure valid credentials */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rtsa_attr[0])) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The only time that attrp can be NULL is when this routine is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * called for the first time during the creation/initialization
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the corresponding IRE. It will only get cleared when the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * IRE is deleted.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * References already held by caller and we keep them;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * note that gc may be set to NULL to clear out igsa_gc.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Intialize the template for gateway; we use the gateway's
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address found in either the passed in gateway credential
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or group pointer, or the ire_gateway_addr{_v6} field.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Caller is holding a reference, and that we don't
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * need to hold any lock to access the address.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Lookup the gateway template; note that we could get an internal
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * template here, which we cache anyway. During IRE matching, we'll
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * try to update this gateway template cache and hopefully get a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * real one.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This function figures the type of MLP that we'll be using based on the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * address that the user is binding and the zone. If the address is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * unspecified, then we're looking at both private and shared. If it's one
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the zone's private addresses, then it's private only. If it's one
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu * of the global addresses, then it's shared only. Multicast addresses are
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu * treated same as unspecified address.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we can't figure out what it is, then return mlptSingle. That's actually
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * an error case.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The callers are assumed to pass in zone->zone_id and not the zoneid that
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * is stored in a conn_t (since the latter will be GLOBAL_ZONEID in an
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * exclusive stack zone).
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhtsol_mlp_addr_type(zoneid_t zoneid, uchar_t version, const void *addr,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * For exclusive stacks we set the zoneid to zero
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * to operate as if in the global zone for IRE and conn_t comparisons.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ipst->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Check whether the IRE_LOCAL (or ipif) is ALL_ZONES */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_ftable_lookup_v4(in4, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu if (IN6_IS_ADDR_UNSPECIFIED((const in6_addr_t *)addr) ||
7b564b02fa1b3eafeb28bf795b705ee91903bba6Jarrett Lu IN6_IS_ADDR_MULTICAST((const in6_addr_t *)addr)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_ftable_lookup_v6(addr, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we can't find the IRE, then we have to behave exactly like
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ip_laddr_verify_{v4,v6}. That means looking up the IPIF so that
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * users can bind to addresses on "down" interfaces.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If we can't find that either, then the bind is going to fail, so
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * just give up. Note that there's a miniscule chance that the address
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * is in transition, but we don't bother handling that.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (addrzone == ALL_ZONES ? mlptShared : mlptPrivate);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Since we are configuring local interfaces, and we know trusted
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * extension CDE requires local interfaces to be cipso host type in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * order to function correctly, we'll associate a cipso template
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to each local interface and let the interface come up. Configuring
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a local interface to be "unlabeled" host type is a configuration error.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We'll override that error and make the interface host type to be cipso
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The code is optimized for the usual "success" case and unwinds things on
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * error. We don't want to go to the trouble and expense of formatting the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * interface name for the usual case where everything is configured correctly.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tp = find_tpc(&ipif->ipif_v6lcl_addr, IPV6_VERSION, B_FALSE);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* assumes that ALL_ZONES implies that there is no exclusive stack */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Shared stack case */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Exclusive stack case */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh zone = zone_find_by_id(crgetzoneid(ipif->ipif_ill->ill_credp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If it's CIPSO and an all-zones address, then we're done.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If it's a CIPSO zone specific address, the zone's label
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * must be in the range or set specified in the template.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When the remote host entry is missing or the template
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * type is incorrect for this interface, we create a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CIPSO host entry in kernel and allow the interface to be
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * brought up as CIPSO type.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* The all-zones case */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* The local-zone case */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (zone != NULL && plabel->tsl_doi == tp->tpc_tp.tp_doi &&
e899e59309fcb43081a58c5d5c252dca3071aaf6Girish Moodalbail ipif_get_name(ipif, ifname, sizeof (ifname));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "template entry for %s missing. Default to "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "template type for %s incorrectly configured. "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: %s isn't set to CIPSO for "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: zone %s has DOI %d but %s has "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cmn_err(CE_NOTE, "%s failed: zone %s label incompatible with "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * we've corrected a config error and let the interface
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * come up as cipso. Need to insert an rhent.