/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <netinet/in_systm.h>
#include <inet/ipclassifier.h>
/* tunable for strict error-reply behavior (TCP RST and ICMP Unreachable) */
int tsol_strict_error;
/*
* Some notes on the Trusted Solaris IRE gateway security attributes:
*
* When running in Trusted mode, the routing subsystem determines whether or
* not a packet can be delivered to an off-link host (not directly reachable
* through an interface) based on the accreditation checks of the packet's
* security attributes against those associated with the next-hop gateway.
*
* The next-hop gateway's security attributes can be derived from two sources
* (in order of preference): route-related and the host database. A Trusted
* system must be configured with at least the host database containing an
* entry for the next-hop gateway, or otherwise no accreditation checks can
* be performed, which may result in the inability to send packets to any
* off-link destination host.
*
* The major differences between the two sources are the number and type of
* security attributes used for accreditation checks. A host database entry
* can contain at most one set of security attributes, specific only to the
* next-hop gateway. On contrast, route-related security attributes are made
* up of a collection of security attributes for the distant networks, and
* are grouped together per next-hop gateway used to reach those networks.
* This is the preferred method, and the routing subsystem will fallback to
* the host database entry only if there are no route-related attributes
* associated with the next-hop gateway.
*
* INTERFACE type) are initialized to contain a placeholder to store this
* information. The ire_gw_secattr structure gets allocated, initialized
* and associated with the IRE during the time of the IRE creation. The
* initialization process also includes resolving the host database entry
* of the next-hop gateway for fallback purposes. It does not include any
* route-related attribute setup, as that process comes separately as part
*
* The underlying logic which involves associating IREs with the gateway
* security attributes are represented by the following data structures:
*
* tsol_gcdb_t, or "gcdb"
*
* - This is a system-wide collection of records containing the
* currently used route-related security attributes, which are fed
*
* tsol_gc_t, or "gc"
*
* - This is the gateway credential structure, and it provides for the
* only mechanism to access the contents of gcdb. More than one gc
* entries may refer to the same gcdb record. gc's in the system are
* grouped according to the next-hop gateway address.
*
* tsol_gcgrp_t, or "gcgrp"
*
* - Group of gateway credentials, and is unique per next-hop gateway
* address. When the group is not empty, i.e. when gcgrp_count is
* greater than zero, it contains one or more gc's, each pointing to
* a gcdb record which indicates the gateway security attributes
* associated with the next-hop gateway.
*
* The fields of the tsol_ire_gw_secattr_t used from within the IRE are:
*
* igsa_lock
*
* - Lock that protects all fields within tsol_ire_gw_secattr_t.
*
* igsa_rhc
*
* - Remote host cache database entry of next-hop gateway. This is
* used in the case when there are no route-related attributes
* configured for the IRE.
*
* igsa_gc
*
* - A set of route-related attributes that only get set for prefix
* IREs. If this is non-NULL, the prefix IRE has been associated
* with a set of gateway security attributes by way of route add/
* change functionality.
*/
#define GCDB_REFRELE(p) { \
mutex_enter(&gcdb_lock); \
ASSERT((p)->gcdb_refcnt > 0); \
if (--((p)->gcdb_refcnt) == 0) \
gcdb_inactive(p); \
mutex_exit(&gcdb_lock); \
}
static void gcdb_inactive(tsol_gcdb_t *);
static int ire_gw_secattr_constructor(void *, void *, int);
static void ire_gw_secattr_destructor(void *, void *);
void
tnet_init(void)
{
}
void
tnet_fini(void)
{
}
/* ARGSUSED */
static int
{
return (0);
}
/* ARGSUSED */
static void
{
}
{
}
void
{
}
}
}
/* ARGSUSED */
static uint_t
{
int i;
/* See comments in hash_bylabel in zone.c for details */
i = 1;
/* using 2^n + 1, 1 <= n <= 16 as source of many primes */
up++;
i++;
}
return (hash);
}
static int
{
return (0);
/* No match; not found */
return (-1);
}
/* ARGSUSED */
static uint_t
{
return (idx);
}
static int
{
/* Address family must match */
return (-1);
return (0);
/* No match; not found */
return (-1);
}
int
{
/* RTSA_CIPSO must be set, and DOI must not be zero */
"rtsa(1) lacks flag or has 0 doi.",
return (EINVAL);
}
/*
* SL range must be specified, and it must have its
* upper bound dominating its lower bound.
*/
"rtsa(1) min_sl and max_sl not set or max_sl is "
return (EINVAL);
}
return (0);
}
/*
* A brief explanation of the reference counting scheme:
*
* Apart from dynamic references due to to reference holds done
* actively by threads, we have the following references:
*
* gcdb_refcnt:
* - Every tsol_gc_t pointing to a tsol_gcdb_t contributes a reference
* to the gcdb_refcnt.
*
* gc_refcnt:
* - A prefix IRE that points to an igsa_gc contributes a reference
* to the gc_refcnt.
*
* gcgrp_refcnt:
* - Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes
* a reference to the gcgrp_refcnt.
*/
static tsol_gcdb_t *
{
if (rtsa_validate(rp) != 0)
return (NULL);
/* Find a copy in the cache; otherwise, create one and cache it */
(mod_hash_val_t *)&gcdb) == 0) {
gcdb->gcdb_refcnt++;
} else if (alloc) {
if (mod_hash_insert(gcdb_hash,
(mod_hash_val_t)gcdb) != 0) {
return (NULL);
}
"gcdb(1) inserted in gcdb_hash(global)",
tsol_gcdb_t *, gcdb);
}
}
return (gcdb);
}
static void
{
(mod_hash_val_t *)&gcdb);
"gcdb(1) removed from gcdb_hash(global)",
tsol_gcdb_t *, gcdb);
}
{
*gcgrp_xtrarefp = B_TRUE;
return (NULL);
}
char *, "found gc(1) in gcgrp(2)",
return (gc);
}
}
} else {
}
gcgrp->gcgrp_count++;
/* caller has incremented gcgrp reference for us */
tsol_gcgrp_t *, gcgrp);
}
return (gc);
}
void
{
else
else
gcgrp->gcgrp_count--;
/* drop lock before it's destroyed */
"removed inactive gc(1) from gcgrp(2)",
}
{
(mod_hash_val_t *)&gcgrp) == 0) {
gcgrp->gcgrp_refcnt++;
mod_hash_t *, hashp);
} else if (alloc) {
if (mod_hash_insert(hashp,
(mod_hash_val_t)gcgrp) != 0) {
return (NULL);
}
char *, "inserted gcgrp(1) in hash(2)",
}
}
return (gcgrp);
}
void
{
(mod_hash_val_t *)&gcgrp);
"removed inactive gcgrp(1) from hash(2)",
}
/*
* Assign a sensitivity label to inbound traffic which arrived without
* an explicit on-the-wire label.
*
* In the case of CIPSO-type hosts, we assume packets arriving without
* a label are at the most sensitive label known for the host, most
* likely involving out-of-band key management traffic (such as IKE,
* etc.,)
*/
static boolean_t
{
case UNLABELED:
break;
case SUN_CIPSO:
break;
default:
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Converts CIPSO option to sensitivity label.
* Validity checks based on restrictions defined in
* COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) (draft-ietf-cipso-ipsecurity)
*/
static boolean_t
{
return (B_FALSE);
return (B_TRUE);
}
/*
* If present, parse the CIPSO label in the incoming packet and
* construct a ts_label_t that reflects the CIPSO label and put it in
* the ip_recv_attr_t. Later as the packet flows up through the stack any
* code that needs to examine the packet label can inspect the label
* from the ira_tsl. This function is
* called right in ip_input for all packets, i.e. locally destined and
* to be forwarded packets. The forwarding path needs to examine the label
* to determine how to forward the packet.
*
* This routine pulls all message text up into the first mblk.
* For IPv4, only the first 20 bytes of the IP header are guaranteed
* to exist. For IPv6, only the IPv6 header is guaranteed to exist.
*/
{
const void *src;
int proto;
return (B_FALSE);
if (version == IPV4_VERSION) {
return (B_FALSE);
} else {
return (B_FALSE);
}
switch (label_type) {
case OPT_CIPSO:
/*
* Convert the CIPSO label to the internal format
* and attach it to the dblk cred.
* Validity checks based on restrictions defined in
* COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
* (draft-ietf-cipso-ipsecurity)
*/
return (B_FALSE);
if ((co->cipso_length <
return (B_FALSE);
return (B_FALSE);
/*
* If the source was unlabeled, then flag as such,
* (since CIPSO routers may add headers)
*/
return (B_FALSE);
break;
case OPT_NONE:
/*
* Handle special cases that may not be labeled, even
* though the sending system may otherwise be configured as
* labeled.
* - IGMP
* - IPv4 ICMP Router Discovery
* - IPv6 Neighbor Discovery
* - IPsec ESP
*/
if (version == IPV4_VERSION) {
if (proto == IPPROTO_IGMP)
return (B_TRUE);
if (proto == IPPROTO_ICMP) {
return (B_FALSE);
return (B_TRUE);
}
} else {
if (proto == IPPROTO_ICMPV6) {
return (B_FALSE);
return (B_TRUE);
}
}
/*
* Look up the tnrhtp database and get the implicit label
* that is associated with the sending host and attach
* it to the packet.
*/
return (B_FALSE);
/*
* If peer is label-aware, mark as "implicit" rather than
* "unlabeled" to cause appropriate mac-exempt processing
* to happen.
*/
else {
DTRACE_PROBE2(tx__get__pkt__label, char *,
"template(1) has unknown hosttype",
tsol_tpc_t *, src_rhtp);
}
return (B_FALSE);
}
break;
default:
return (B_FALSE);
}
return (B_FALSE);
} else {
return (B_FALSE);
}
}
/*
* Put the label in ira_tsl for convinience, while keeping
* the cred in ira_cred for getpeerucred which is used to get
* labels with TX.
* for IRA_FREE_CRED is sufficient for both.
*/
return (B_TRUE);
}
/*
* This routine determines whether the given packet should be accepted locally.
* address in the remote host database.
*/
{
/*
* tsol_get_pkt_label intentionally avoids the labeling process for:
* - IPv6 router and neighbor discovery as well as redirects.
* - MLD packets. (Anything between ICMPv6 code 130 and 138.)
* - IGMP packets.
* - IPv4 router discovery.
* In those cases ira_cred is NULL.
*/
return (B_TRUE);
/*
* If this packet is from the inside (not a remote host) and has the
* same zoneid as the selected destination, then no checks are
* necessary. Membership in the zone is enough proof. This is
* intended to be a hot path through this function.
* Note: Using crgetzone here is ok since the peer is local.
*/
if (!crisremote(credp) &&
return (B_TRUE);
/*
* Implicitly labeled packets from label-aware sources
* go only to privileged receivers
*/
char *,
"implicitly labeled packet mp(1) for conn(2) "
"which isn't in implicit mac mode",
return (B_FALSE);
}
/*
* MLPs are always validated using the range and set of the local
* address, even when the remote host is unlabeled.
*/
/* LINTED: no consequent */
;
/*
* If this is a packet from an unlabeled sender, then we must apply
* different rules. If the label is equal to the zone's label, then
* it's allowed. If it's not equal, but the zone is either the global
* zone or the label is dominated by the zone's label, then allow it
* as long as it's in the range configured for the destination.
*/
return (B_TRUE);
(!connp->conn_zone_is_global &&
char *,
"unlabeled packet mp(1) fails mac for conn(2)",
return (B_FALSE);
}
/*
* If this is a packet from a labeled sender, verify the
* label on the packet matches the connection label.
*/
} else {
char *,
"packet mp(1) failed label match to SLP conn(2)",
return (B_FALSE);
}
/*
* No further checks will be needed if this is a zone-
* specific address because (1) The process for bringing up
* the interface ensures the zone's label is within the zone-
* specific address's valid label range; (2) For cases where
* the conn is bound to the unspecified addresses, ip fanout
* logic ensures conn's zoneid equals the dest addr's zoneid;
* (3) Mac-exempt and mlp logic above already handle all
* cases where the zone label may not be the same as the
* conn label.
*/
if (!shared_addr)
return (B_TRUE);
}
char *, "dropping mp(1), host(2) lacks entry",
return (B_FALSE);
}
/*
* The local host address should not be unlabeled at this point. The
* only way this can happen is that the destination isn't unicast. We
* assume that the packet should not have had a label, and thus should
* have been handled by the TSLF_UNLABELED logic above.
*/
"mp(1) unlabeled source, but tp is not unlabeled.",
"delivering mp(1), found unrecognized tpc(2) type.",
"mp(1) could not be delievered to tp(2), doi mismatch",
"mp(1) could not be delievered to tp(2), bad mac",
} else {
}
return (retv);
}
{
/* We are bootstrapping or the internal template was never deleted */
return (B_TRUE);
B_FALSE);
return (B_FALSE);
B_FALSE);
} else {
B_FALSE);
return (B_FALSE);
B_FALSE);
}
return (B_FALSE);
}
/*
* Check that the packet's label is in the correct range for labeled
* sender, or is equal to the default label for unlabeled sender.
*/
} else if (check_host) {
/*
* Until we have SL range in the Zone structure, pass it
* when our own address lookup returned an internal entry.
*/
case UNLABELED:
break;
case SUN_CIPSO:
break;
default:
}
return (retv);
}
/*
* This routine determines whether a response to a failed packet delivery or
* connection should be sent back. By default, the policy is to allow such
* messages to be sent at all times, as these messages reveal little useful
*
* If tsol_strict_error is set, then we do strict tests: if the packet label is
* return B_FALSE, which causes the packet to be dropped silently.
*
* Note that tsol_get_pkt_label will cause the packet to drop if the sender is
* marked as labeled in the remote host database, but the packet lacks a label.
* This means that we don't need to do a lookup on the source; the
* TSLF_UNLABELED flag is sufficient.
*/
{
/* Caller must pull up at least the IP header */
if (!tsol_strict_error)
return (B_TRUE);
/* We are bootstrapping or the internal template was never deleted */
return (B_TRUE);
char *,
"cannot send error report for packet mp(1) with "
"unresolved security label sl(2)",
return (B_FALSE);
}
} else {
}
} else {
/*
* If we're in the midst of forwarding, then the destination
* address might not be labeled. In that case, allow unlabeled
* packets through only if the default label is the same, and
* labeled ones if they dominate.
*/
case UNLABELED:
} else {
}
break;
case SUN_CIPSO:
break;
default:
break;
}
}
return (retv);
}
/*
* Finds the zone associated with the receive attributes. Returns GLOBAL_ZONEID
* if the zone cannot be located.
*
* This is used by the classifier when the packet matches an ALL_ZONES IRE, and
* there's no MLP defined.
*
* Note that we assume that this is only invoked in the ALL_ZONES case.
* Handling other cases would require handling exclusive IP zones where either
* this routine or the callers would have to map from
* the zoneid (zone->zone_id) to what IP uses in conn_zoneid etc.
*/
{
return (zoneid);
}
}
return (GLOBAL_ZONEID);
}
int
{
int error = 0;
if (!is_system_labeled() ||
goto done;
/*
* If we don't have a label to compare with, or the IRE does not
* contain any gateway security attributes, there's not much that
* we can do. We let the former case pass, and the latter fail,
* since the IRE doesn't qualify for a match due to the lack of
* security attributes.
*/
tx__ip__log__drop__irematch__nogwsec, char *,
"ire(1) lacks ire_gw_secattr when matching "
}
goto done;
}
/*
* The possible lock order scenarios related to the tsol gateway
* attribute locks are documented at the beginning of ip.c in the
* lock order scenario section.
*/
/*
* We seek the group
* structure which contains all security credentials of the gateway.
* An offline IRE is associated with at most one gateway credential.
*/
}
/*
* If our cached entry has grown stale, then discard it so we
* can get a new one.
*/
} else {
}
}
/* Last attempt at loading the template had failed; try again */
} else {
}
}
/* We've found a gateway address to do the template lookup */
/*
* Note that if the lookup above returned an
* internal template, we'll use it for the
* time being, and do another lookup next
* time around.
*/
/* Another thread has loaded the template? */
/* reload, it could be different */
} else {
}
/*
* Hold an extra reference just like we did
* above prior to dropping the igsa_lock.
*/
}
}
}
/* Gateway template not found */
/*
* If destination address is directly reachable through an
* interface rather than through a learned route, pass it.
*/
"ire(1), label(2) off-link with no gw_rhc",
}
goto done;
}
/*
* In the case of IRE_CACHE we've got one or more gateway
* security credentials to compare against the passed in label.
* Perform label range comparison against each security
* credential of the gateway. In the case of a prefix ire
* we need to match against the security attributes of
* just the route itself, so the loop is executed only once.
*/
char *, "ire(1), tsl(2): all gc failed match",
}
} else {
/*
* We didn't find any gateway credentials in the IRE
* attributes; fall back to the gateway's template for
* label range checks, if we are required to do so.
*/
case SUN_CIPSO:
char *, "ire(1), tsl(2), gw_rhc(3) "
"failed match (cipso gw)",
tsol_tnrhc_t *, gw_rhc);
}
break;
case UNLABELED:
char *, "ire(1), tsl(2), gw_rhc(3) "
"failed match (unlabeled gw)",
tsol_tnrhc_t *, gw_rhc);
}
break;
}
}
done:
}
return (error);
}
/*
* Performs label accreditation checks for packet forwarding.
* Add or remove a CIPSO option as needed.
*
* Returns a pointer to the modified mblk if allowed for forwarding,
* or NULL if the packet must be dropped.
*/
mblk_t *
{
const void *pdst;
const void *psrc;
int err;
/*
* Note that the ire is the first one found, i.e., an IRE_OFFLINK if
* the destination is offlink.
*/
return (NULL);
} else {
proto != IPPROTO_ICMPV6) {
&nexthdrp)) {
/* malformed packet; drop it */
return (NULL);
}
}
return (NULL);
}
/*
* off_link is TRUE if destination not directly reachable.
*/
return (mp);
char *,
"cannot forward packet mp(1) with unresolved "
"security label sl(2)",
return (NULL);
}
/*
* Without a template we do not know if forwarding
* violates MAC
*/
"mp(1) dropped, no template for destination ip4|6(2)",
return (NULL);
}
/*
* Gateway template must have existed for off-link destinations,
* since tsol_ire_match_gwattr has ensured such condition.
*/
/*
* Surya note: first check if we can get the gw_rhtp from
* the ire_gw_secattr->igsa_rhc; if this is null, then
* do a lookup based on the ire_addr (address of gw)
*/
} else {
}
"mp(1) dropped, no gateway in ire attributes(2)",
goto keep_label;
}
}
"mp(1) dropped, no gateway in ire attributes(2)",
goto keep_label;
}
/*
* Check that the label for the packet is acceptable
* by destination host; otherwise, drop it.
*/
case SUN_CIPSO:
"labeled packet mp(1) dropped, label(2) fails "
"destination(3) accredation check",
tsol_tpc_t *, dst_rhtp);
goto keep_label;
}
break;
case UNLABELED:
"unlabeled packet mp(1) dropped, label(2) fails "
"destination(3) accredation check",
tsol_tpc_t *, dst_rhtp);
goto keep_label;
}
break;
}
if (label_type == OPT_CIPSO) {
/*
* We keep the label on any of the following cases:
*
* 2. The unlabeled destination is off-link,
* and the next hop gateway is labeled.
*/
(off_link &&
goto keep_label;
/*
* Strip off the CIPSO option from the packet because: the
* unlabeled destination host is directly reachable through
* an interface (on-link); or, the unlabeled destination host
* is not directly reachable (off-link), and the next hop
* gateway is unlabeled.
*/
if (adjust != 0) {
/* adjust is negative */
/*
* Note that caller adjusts ira_pktlen and
* ira_ip_hdr_length
*
* For AF_INET6 note that tsol_remove_secopt_v6
* adjusted ip6_plen.
*/
ipha->ipha_hdr_checksum = 0;
}
char *,
"mp(1) adjusted(2) for CIPSO option removal",
}
goto keep_label;
}
/*
* We need to add CIPSO option if the destination or the next hop
* gateway is labeled. Otherwise, pass the packet as is.
*/
goto keep_label;
/*
* Since we are forwarding packets we use GLOBAL_ZONEID for
* the IRE lookup in tsol_check_label.
* Since mac_exempt is false the zoneid isn't used for anything
* but the IRE lookup, hence we set zone_is_global to false.
*/
} else {
}
if (err != 0) {
goto keep_label;
}
/*
* The effective_tsl must never affect the routing decision, hence
* we ignore it here.
*/
if (effective_tsl != NULL)
ipha->ipha_hdr_checksum = 0;
}
return (mp);
}
/*
* Name: tsol_pmtu_adjust()
*
* Returns the adjusted mtu after removing security option.
* sender or if pkt_diff indicates this system enlarged the packet.
*/
{
int label_adj = 0;
void *src;
/*
* Note: label_adj is non-positive, indicating the number of
* bytes removed by removing the security option from the
* header.
*/
return (mtu);
}
} else {
return (mtu);
}
/*
* Make pkt_diff non-negative and the larger of the bytes
* previously added (if any) or just removed, since label
* addition + subtraction may not be completely idempotent.
*/
}
/*
* Name: tsol_rtsa_init()
*
* Normal: Sanity checks on the route security attributes provided by
* user. Convert it into a route security parameter list to
* be returned to caller.
*
* Output: EINVAL if bad security attributes in the routing message
* ENOMEM if unable to allocate data structures
* 0 otherwise.
*
* Note: On input, cp must point to the end of any addresses in
* the rt_msghdr_t structure.
*/
int
{
int err;
/*
* In theory, we could accept as many security attributes configured
* per route destination. However, the current design is limited
* such that at most only one set security attributes is allowed to
* be associated with a prefix IRE. We therefore assert for now.
*/
/* LINTED */
return (0);
return (EINVAL);
return (EINVAL);
/*
* Trying to add route security attributes when system
* labeling service is not available, or when user supllies
* more than the maximum number of security attributes
* allowed per request.
*/
if ((sacnt > 0 && !is_system_labeled()) ||
return (EINVAL);
/* Ensure valid credentials */
rtsa_attr[0])) != 0) {
return (err);
}
return (0);
}
int
{
/*
* The only time that attrp can be NULL is when this routine is
* called for the first time during the creation/initialization
* of the corresponding IRE. It will only get cleared when the
* IRE is deleted.
*/
return (ENOMEM);
} else {
}
}
/*
* References already held by caller and we keep them;
* note that gc may be set to NULL to clear out igsa_gc.
*/
}
/*
* Intialize the template for gateway; we use the gateway's
* address found in either the passed in gateway credential
* or group pointer, or the ire_gateway_addr{_v6} field.
*/
/*
* Caller is holding a reference, and that we don't
* need to hold any lock to access the address.
*/
if (ipversion == IPV4_VERSION) {
} else {
}
if (ipversion == IPV6_VERSION)
else if (ipversion == IPV4_VERSION)
}
/*
* Lookup the gateway template; note that we could get an internal
* template here, which we cache anyway. During IRE matching, we'll
* try to update this gateway template cache and hopefully get a
* real one.
*/
}
if (exists)
return (0);
}
/*
* This function figures the type of MLP that we'll be using based on the
* address that the user is binding and the zone. If the address is
* unspecified, then we're looking at both private and shared. If it's one
* of the zone's private addresses, then it's private only. If it's one
* of the global addresses, then it's shared only. Multicast addresses are
* treated same as unspecified address.
*
* If we can't figure out what it is, then return mlptSingle. That's actually
* an error case.
*
* The callers are assumed to pass in zone->zone_id and not the zoneid that
* is stored in a conn_t (since the latter will be GLOBAL_ZONEID in an
* exclusive stack zone).
*/
{
/*
* For exclusive stacks we set the zoneid to zero
* to operate as if in the global zone for IRE and conn_t comparisons.
*/
else
if (version == IPV6_VERSION &&
}
/* Check whether the IRE_LOCAL (or ipif) is ALL_ZONES */
if (version == IPV4_VERSION) {
return (mlptBoth);
}
} else {
return (mlptBoth);
}
}
/*
* If we can't find the IRE, then we have to behave exactly like
* ip_laddr_verify_{v4,v6}. That means looking up the IPIF so that
* users can bind to addresses on "down" interfaces.
*
* If we can't find that either, then the bind is going to fail, so
* just give up. Note that there's a miniscule chance that the address
* is in transition, but we don't bother handling that.
*/
if (version == IPV4_VERSION)
else
return (mlptSingle);
}
} else {
}
}
/*
* Since we are configuring local interfaces, and we know trusted
* extension CDE requires local interfaces to be cipso host type in
* order to function correctly, we'll associate a cipso template
* to each local interface and let the interface come up. Configuring
* a local interface to be "unlabeled" host type is a configuration error.
* We'll override that error and make the interface host type to be cipso
* here.
*
* The code is optimized for the usual "success" case and unwinds things on
* error. We don't want to go to the trouble and expense of formatting the
* interface name for the usual case where everything is configured correctly.
*/
{
int af;
const void *addr;
} else {
}
/* assumes that ALL_ZONES implies that there is no exclusive stack */
/* Shared stack case */
} else {
/* Exclusive stack case */
}
}
/*
* If it's CIPSO and an all-zones address, then we're done.
* If it's a CIPSO zone specific address, the zone's label
* must be in the range or set specified in the template.
* When the remote host entry is missing or the template
* type is incorrect for this interface, we create a
* CIPSO host entry in kernel and allow the interface to be
* brought up as CIPSO type.
*/
/* The all-zones case */
/* The local-zone case */
return (B_TRUE);
}
} else {
}
} else {
}
if (retval) {
/*
* we've corrected a config error and let the interface
* come up as cipso. Need to insert an rhent.
*/
} else {
}
}
}
return (retval);
}