summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/ip/tnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet/ip/tnet.c')
-rw-r--r--usr/src/uts/common/inet/ip/tnet.c311
1 files changed, 139 insertions, 172 deletions
diff --git a/usr/src/uts/common/inet/ip/tnet.c b/usr/src/uts/common/inet/ip/tnet.c
index 1e5c0eb170..262d5bc339 100644
--- a/usr/src/uts/common/inet/ip/tnet.c
+++ b/usr/src/uts/common/inet/ip/tnet.c
@@ -133,16 +133,7 @@ int tsol_strict_error;
* - 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. This field stays NULL for IRE_CACHEs.
- *
- * igsa_gcgrp
- *
- * - Group of gc's which only gets set for IRE_CACHEs. Each of the gc
- * points to a gcdb record that contains the security attributes
- * used to perform the credential checks of the packet which uses
- * the IRE. If the group is not empty, the list of gc's can be
- * traversed starting at gcgrp_head. This field stays NULL for
- * prefix IREs.
+ * change functionality.
*/
static kmem_cache_t *ire_gw_secattr_cache;
@@ -223,7 +214,6 @@ ire_gw_secattr_constructor(void *buf, void *cdrarg, int kmflags)
attrp->igsa_rhc = NULL;
attrp->igsa_gc = NULL;
- attrp->igsa_gcgrp = NULL;
return (0);
}
@@ -257,14 +247,9 @@ ire_gw_secattr_free(tsol_ire_gw_secattr_t *attrp)
GC_REFRELE(attrp->igsa_gc);
attrp->igsa_gc = NULL;
}
- if (attrp->igsa_gcgrp != NULL) {
- GCGRP_REFRELE(attrp->igsa_gcgrp);
- attrp->igsa_gcgrp = NULL;
- }
ASSERT(attrp->igsa_rhc == NULL);
ASSERT(attrp->igsa_gc == NULL);
- ASSERT(attrp->igsa_gcgrp == NULL);
kmem_cache_free(ire_gw_secattr_cache, attrp);
}
@@ -387,9 +372,6 @@ rtsa_validate(const struct rtsa_s *rp)
/*
* A brief explanation of the reference counting scheme:
*
- * Prefix IREs have a non-NULL igsa_gc and a NULL igsa_gcgrp;
- * IRE_CACHEs have it vice-versa.
- *
* Apart from dynamic references due to to reference holds done
* actively by threads, we have the following references:
*
@@ -402,8 +384,6 @@ rtsa_validate(const struct rtsa_s *rp)
* to the gc_refcnt.
*
* gcgrp_refcnt:
- * - An IRE_CACHE that points to an igsa_gcgrp contributes a reference
- * to the gcgrp_refcnt of the associated tsol_gcgrp_t.
* - Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes
* a reference to the gcgrp_refcnt.
*/
@@ -613,7 +593,6 @@ gcgrp_inactive(tsol_gcgrp_t *gcgrp)
mod_hash_t *hashp;
ASSERT(MUTEX_HELD(&gcgrp_lock));
- ASSERT(!RW_LOCK_HELD(&gcgrp->gcgrp_rwlock));
ASSERT(gcgrp != NULL && gcgrp->gcgrp_refcnt == 0);
ASSERT(gcgrp->gcgrp_head == NULL && gcgrp->gcgrp_count == 0);
@@ -686,21 +665,21 @@ cipso_to_sl(const uchar_t *option, bslabel_t *sl)
}
/*
- * If present, parse a CIPSO label in the incoming packet and
- * construct a ts_label_t that reflects the CIPSO label and attach it
- * to the dblk cred. Later as the mblk flows up through the stack any
+ * 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 dblk cred. This function is called right in ip_rput 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.
+ * 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.
*/
boolean_t
-tsol_get_pkt_label(mblk_t *mp, int version)
+tsol_get_pkt_label(mblk_t *mp, int version, ip_recv_attr_t *ira)
{
tsol_tpc_t *src_rhtp = NULL;
uchar_t *opt_ptr = NULL;
@@ -713,7 +692,6 @@ tsol_get_pkt_label(mblk_t *mp, int version)
const void *src;
const ip6_t *ip6h;
cred_t *credp;
- pid_t cpid;
int proto;
ASSERT(DB_TYPE(mp) == M_DATA);
@@ -846,28 +824,37 @@ tsol_get_pkt_label(mblk_t *mp, int version)
return (B_FALSE);
}
- /* Make sure no other thread is messing with this mblk */
- ASSERT(DB_REF(mp) == 1);
- /* Preserve db_cpid */
- credp = msg_extractcred(mp, &cpid);
- if (credp == NULL) {
+ if (ira->ira_cred == NULL) {
credp = newcred_from_bslabel(&sl, doi, KM_NOSLEEP);
+ if (credp == NULL)
+ return (B_FALSE);
} else {
cred_t *newcr;
- newcr = copycred_from_bslabel(credp, &sl, doi,
+ newcr = copycred_from_bslabel(ira->ira_cred, &sl, doi,
KM_NOSLEEP);
- crfree(credp);
+ if (newcr == NULL)
+ return (B_FALSE);
+ if (ira->ira_free_flags & IRA_FREE_CRED) {
+ crfree(ira->ira_cred);
+ ira->ira_free_flags &= ~IRA_FREE_CRED;
+ ira->ira_cred = NULL;
+ }
credp = newcr;
}
- if (credp == NULL)
- return (B_FALSE);
- crgetlabel(credp)->tsl_flags |= label_flags;
-
- mblk_setcred(mp, credp, cpid);
- crfree(credp); /* mblk has ref on cred */
+ /*
+ * 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.
+ * Note: no explicit refcnt/free_flag for ira_tsl. The free_flag
+ * for IRA_FREE_CRED is sufficient for both.
+ */
+ ira->ira_tsl = crgetlabel(credp);
+ ira->ira_cred = credp;
+ ira->ira_free_flags |= IRA_FREE_CRED;
+ ira->ira_tsl->tsl_flags |= label_flags;
return (B_TRUE);
}
@@ -878,25 +865,25 @@ tsol_get_pkt_label(mblk_t *mp, int version)
*/
boolean_t
tsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
- boolean_t shared_addr, const conn_t *connp)
+ ip_recv_attr_t *ira, const conn_t *connp)
{
const cred_t *credp;
ts_label_t *plabel, *conn_plabel;
tsol_tpc_t *tp;
boolean_t retv;
const bslabel_t *label, *conn_label;
+ boolean_t shared_addr = (ira->ira_flags & IRAF_TX_SHARED_ADDR);
/*
- * The cases in which this can happen are:
- * - IPv6 Router Alert, where ip_rput_data_v6 deliberately skips
- * over the label attachment process.
- * - MLD output looped-back to ourselves.
- * - IPv4 Router Discovery, where tsol_get_pkt_label intentionally
- * avoids the labeling process.
- * We trust that all valid paths in the code set the cred pointer when
- * needed.
+ * 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 ire_cred is NULL.
*/
- if ((credp = msg_getcred(mp, NULL)) == NULL)
+ credp = ira->ira_cred;
+ if (credp == NULL)
return (B_TRUE);
/*
@@ -904,17 +891,18 @@ tsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
* 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) &&
crgetzone(credp) == crgetzone(connp->conn_cred))
return (B_TRUE);
- plabel = crgetlabel(credp);
+ plabel = ira->ira_tsl;
conn_plabel = crgetlabel(connp->conn_cred);
ASSERT(plabel != NULL && conn_plabel != NULL);
label = label2bslabel(plabel);
- conn_label = label2bslabel(crgetlabel(connp->conn_cred));
+ conn_label = label2bslabel(conn_plabel);
/*
@@ -954,12 +942,8 @@ tsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
blequal(label, conn_label))
return (B_TRUE);
- /*
- * conn_zoneid is global for an exclusive stack, thus we use
- * conn_cred to get the zoneid
- */
if ((connp->conn_mac_mode == CONN_MAC_DEFAULT) ||
- (crgetzoneid(connp->conn_cred) != GLOBAL_ZONEID &&
+ (!connp->conn_zone_is_global &&
(plabel->tsl_doi != conn_plabel->tsl_doi ||
!bldominates(conn_label, label)))) {
DTRACE_PROBE3(
@@ -1046,16 +1030,13 @@ tsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
}
boolean_t
-tsol_can_accept_raw(mblk_t *mp, boolean_t check_host)
+tsol_can_accept_raw(mblk_t *mp, ip_recv_attr_t *ira, boolean_t check_host)
{
ts_label_t *plabel = NULL;
tsol_tpc_t *src_rhtp, *dst_rhtp;
boolean_t retv;
- cred_t *credp;
- credp = msg_getcred(mp, NULL);
- if (credp != NULL)
- plabel = crgetlabel(credp);
+ plabel = ira->ira_tsl;
/* We are bootstrapping or the internal template was never deleted */
if (plabel == NULL)
@@ -1144,7 +1125,7 @@ tsol_can_accept_raw(mblk_t *mp, boolean_t check_host)
* TSLF_UNLABELED flag is sufficient.
*/
boolean_t
-tsol_can_reply_error(const mblk_t *mp)
+tsol_can_reply_error(const mblk_t *mp, ip_recv_attr_t *ira)
{
ts_label_t *plabel = NULL;
tsol_tpc_t *rhtp;
@@ -1152,7 +1133,6 @@ tsol_can_reply_error(const mblk_t *mp)
const ip6_t *ip6h;
boolean_t retv;
bslabel_t *pktbs;
- cred_t *credp;
/* Caller must pull up at least the IP header */
ASSERT(MBLKL(mp) >= (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ?
@@ -1161,9 +1141,7 @@ tsol_can_reply_error(const mblk_t *mp)
if (!tsol_strict_error)
return (B_TRUE);
- credp = msg_getcred(mp, NULL);
- if (credp != NULL)
- plabel = crgetlabel(credp);
+ plabel = ira->ira_tsl;
/* We are bootstrapping or the internal template was never deleted */
if (plabel == NULL)
@@ -1227,33 +1205,30 @@ tsol_can_reply_error(const mblk_t *mp)
}
/*
- * Finds the zone associated with the given packet. Returns GLOBAL_ZONEID if
- * the zone cannot be located.
+ * 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 handle exclusive stack zones where either
+ * 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.
*/
zoneid_t
-tsol_packet_to_zoneid(const mblk_t *mp)
+tsol_attr_to_zoneid(const ip_recv_attr_t *ira)
{
- cred_t *cr = msg_getcred(mp, NULL);
zone_t *zone;
ts_label_t *label;
- if (cr != NULL) {
- if ((label = crgetlabel(cr)) != NULL) {
- zone = zone_find_by_label(label);
- if (zone != NULL) {
- zoneid_t zoneid = zone->zone_id;
+ if ((label = ira->ira_tsl) != NULL) {
+ zone = zone_find_by_label(label);
+ if (zone != NULL) {
+ zoneid_t zoneid = zone->zone_id;
- zone_rele(zone);
- return (zoneid);
- }
+ zone_rele(zone);
+ return (zoneid);
}
}
return (GLOBAL_ZONEID);
@@ -1273,7 +1248,7 @@ tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
/* Not in Trusted mode or IRE is local/loopback/broadcast/interface */
if (!is_system_labeled() ||
(ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST |
- IRE_INTERFACE)))
+ IRE_IF_ALL | IRE_MULTICAST | IRE_NOROUTE)))
goto done;
/*
@@ -1304,29 +1279,16 @@ tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
mutex_enter(&attrp->igsa_lock);
/*
- * Depending on the IRE type (prefix vs. cache), we seek the group
+ * We seek the group
* structure which contains all security credentials of the gateway.
- * A prefix IRE is associated with at most one gateway credential,
- * while a cache IRE is associated with every credentials that the
- * gateway has.
+ * An offline IRE is associated with at most one gateway credential.
*/
- if ((gc = attrp->igsa_gc) != NULL) { /* prefix */
+ if ((gc = attrp->igsa_gc) != NULL) {
gcgrp = gc->gc_grp;
ASSERT(gcgrp != NULL);
rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
- } else if ((gcgrp = attrp->igsa_gcgrp) != NULL) { /* cache */
- rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
- gc = gcgrp->gcgrp_head;
- if (gc == NULL) {
- /* gc group is empty, so the drop lock now */
- ASSERT(gcgrp->gcgrp_count == 0);
- rw_exit(&gcgrp->gcgrp_rwlock);
- gcgrp = NULL;
- }
- }
-
- if (gcgrp != NULL)
GCGRP_REFHOLD(gcgrp);
+ }
if ((gw_rhc = attrp->igsa_rhc) != NULL) {
/*
@@ -1354,12 +1316,11 @@ tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
ASSERT(ga->ga_af == AF_INET6);
paddr = &ga->ga_addr;
}
- } else if (ire->ire_ipversion == IPV6_VERSION &&
- !IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6)) {
- paddr = &ire->ire_gateway_addr_v6;
- } else if (ire->ire_ipversion == IPV4_VERSION &&
- ire->ire_gateway_addr != INADDR_ANY) {
- paddr = &ire->ire_gateway_addr;
+ } else if (ire->ire_type & IRE_OFFLINK) {
+ if (ire->ire_ipversion == IPV6_VERSION)
+ paddr = &ire->ire_gateway_addr_v6;
+ else if (ire->ire_ipversion == IPV4_VERSION)
+ paddr = &ire->ire_gateway_addr;
}
/* We've found a gateway address to do the template lookup */
@@ -1408,6 +1369,7 @@ tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
}
if (gc != NULL) {
+
tsol_gcdb_t *gcdb;
/*
* In the case of IRE_CACHE we've got one or more gateway
@@ -1418,18 +1380,9 @@ tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
* just the route itself, so the loop is executed only once.
*/
ASSERT(gcgrp != NULL);
- do {
- gcdb = gc->gc_db;
- if (tsl->tsl_doi == gcdb->gcdb_doi &&
- _blinrange(&tsl->tsl_label, &gcdb->gcdb_slrange))
- break;
- if (ire->ire_type == IRE_CACHE)
- gc = gc->gc_next;
- else
- gc = NULL;
- } while (gc != NULL);
-
- if (gc == NULL) {
+ gcdb = gc->gc_db;
+ if (tsl->tsl_doi != gcdb->gcdb_doi ||
+ !_blinrange(&tsl->tsl_label, &gcdb->gcdb_slrange)) {
DTRACE_PROBE3(
tx__ip__log__drop__irematch__nogcmatched,
char *, "ire(1), tsl(2): all gc failed match",
@@ -1493,12 +1446,13 @@ done:
/*
* 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 *
-tsol_ip_forward(ire_t *ire, mblk_t *mp)
+tsol_ip_forward(ire_t *ire, mblk_t *mp, const ip_recv_attr_t *ira)
{
tsol_ire_gw_secattr_t *attrp = NULL;
ipha_t *ipha;
@@ -1516,11 +1470,14 @@ tsol_ip_forward(ire_t *ire, mblk_t *mp)
boolean_t need_tpc_rele = B_FALSE;
ipaddr_t *gw;
ip_stack_t *ipst = ire->ire_ipst;
- cred_t *credp;
- pid_t pid;
+ int err;
+ ts_label_t *effective_tsl = NULL;
ASSERT(ire != NULL && mp != NULL);
- ASSERT(ire->ire_stq != NULL);
+ /*
+ * Note that the ire is the first one found, i.e., an IRE_OFFLINK if
+ * the destination is offlink.
+ */
af = (ire->ire_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6;
@@ -1530,16 +1487,6 @@ tsol_ip_forward(ire_t *ire, mblk_t *mp)
psrc = &ipha->ipha_src;
pdst = &ipha->ipha_dst;
proto = ipha->ipha_protocol;
-
- /*
- * off_link is TRUE if destination not directly reachable.
- * Surya note: we avoid creation of per-dst IRE_CACHE entries
- * for forwarded packets, so we set off_link to be TRUE
- * if the packet dst is different from the ire_addr of
- * the ire for the nexthop.
- */
- off_link = ((ipha->ipha_dst != ire->ire_addr) ||
- (ire->ire_gateway_addr != INADDR_ANY));
if (!tsol_get_option_v4(mp, &label_type, &opt_ptr))
return (NULL);
} else {
@@ -1561,14 +1508,15 @@ tsol_ip_forward(ire_t *ire, mblk_t *mp)
}
proto = *nexthdrp;
}
-
- /* destination not directly reachable? */
- off_link = !IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6);
if (!tsol_get_option_v6(mp, &label_type, &opt_ptr))
return (NULL);
}
+ /*
+ * off_link is TRUE if destination not directly reachable.
+ */
+ off_link = (ire->ire_type & IRE_OFFLINK);
- if ((tsl = msg_getlabel(mp)) == NULL)
+ if ((tsl = ira->ira_tsl) == NULL)
return (mp);
if (tsl->tsl_flags & TSLF_IMPLICIT_IN) {
@@ -1611,11 +1559,7 @@ tsol_ip_forward(ire_t *ire, mblk_t *mp)
attrp = ire->ire_gw_secattr;
gw_rhtp = attrp->igsa_rhc->rhc_tpc;
} else {
- /*
- * use the ire_addr if this is the IRE_CACHE of nexthop
- */
- gw = (ire->ire_gateway_addr == NULL? &ire->ire_addr :
- &ire->ire_gateway_addr);
+ gw = &ire->ire_gateway_addr;
gw_rhtp = find_tpc(gw, ire->ire_ipversion, B_FALSE);
need_tpc_rele = B_TRUE;
}
@@ -1702,7 +1646,13 @@ tsol_ip_forward(ire_t *ire, mblk_t *mp)
/* adjust is negative */
ASSERT((mp->b_wptr + adjust) >= mp->b_rptr);
mp->b_wptr += adjust;
-
+ /*
+ * Note that caller adjusts ira_pktlen and
+ * ira_ip_hdr_length
+ *
+ * For AF_INET6 note that tsol_remove_secopt_v6
+ * adjusted ip6_plen.
+ */
if (af == AF_INET) {
ipha = (ipha_t *)mp->b_rptr;
iplen = ntohs(ipha->ipha_length) + adjust;
@@ -1729,17 +1679,34 @@ tsol_ip_forward(ire_t *ire, mblk_t *mp)
(!off_link || gw_rhtp->tpc_tp.host_type == UNLABELED))
goto keep_label;
-
- credp = msg_getcred(mp, &pid);
- if ((af == AF_INET &&
- tsol_check_label(credp, &mp, CONN_MAC_DEFAULT, ipst, pid) != 0) ||
- (af == AF_INET6 &&
- tsol_check_label_v6(credp, &mp, CONN_MAC_DEFAULT, ipst,
- pid) != 0)) {
+ /*
+ * 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.
+ */
+ if (af == AF_INET) {
+ err = tsol_check_label_v4(tsl, GLOBAL_ZONEID, &mp,
+ CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
+ } else {
+ err = tsol_check_label_v6(tsl, GLOBAL_ZONEID, &mp,
+ CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl);
+ }
+ if (err != 0) {
+ BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
+ ip_drop_output("tsol_check_label", mp, NULL);
+ freemsg(mp);
mp = NULL;
goto keep_label;
}
+ /*
+ * The effective_tsl must never affect the routing decision, hence
+ * we ignore it here.
+ */
+ if (effective_tsl != NULL)
+ label_rele(effective_tsl);
+
if (af == AF_INET) {
ipha = (ipha_t *)mp->b_rptr;
ipha->ipha_hdr_checksum = 0;
@@ -1885,13 +1852,13 @@ tsol_rtsa_init(rt_msghdr_t *rtm, tsol_rtsecattr_t *sp, caddr_t cp)
}
int
-tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc,
- tsol_gcgrp_t *gcgrp)
+tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc)
{
tsol_ire_gw_secattr_t *attrp;
boolean_t exists = B_FALSE;
in_addr_t ga_addr4;
void *paddr = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
ASSERT(ire != NULL);
@@ -1917,20 +1884,16 @@ tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc,
if (attrp->igsa_gc != NULL)
GC_REFRELE(attrp->igsa_gc);
- if (attrp->igsa_gcgrp != NULL)
- GCGRP_REFRELE(attrp->igsa_gcgrp);
}
ASSERT(!exists || MUTEX_HELD(&attrp->igsa_lock));
/*
* References already held by caller and we keep them;
- * note that both gc and gcgrp may be set to NULL to
- * clear out igsa_gc and igsa_gcgrp, respectively.
+ * note that gc may be set to NULL to clear out igsa_gc.
*/
attrp->igsa_gc = gc;
- attrp->igsa_gcgrp = gcgrp;
- if (gcgrp == NULL && gc != NULL) {
+ if (gc != NULL) {
gcgrp = gc->gc_grp;
ASSERT(gcgrp != NULL);
}
@@ -1955,12 +1918,11 @@ tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc,
ASSERT(ga->ga_af == AF_INET6);
paddr = &ga->ga_addr;
}
- } else if (ipversion == IPV6_VERSION &&
- !IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6)) {
- paddr = &ire->ire_gateway_addr_v6;
- } else if (ipversion == IPV4_VERSION &&
- ire->ire_gateway_addr != INADDR_ANY) {
- paddr = &ire->ire_gateway_addr;
+ } else if (ire->ire_type & IRE_OFFLINK) {
+ if (ipversion == IPV6_VERSION)
+ paddr = &ire->ire_gateway_addr_v6;
+ else if (ipversion == IPV4_VERSION)
+ paddr = &ire->ire_gateway_addr;
}
/*
@@ -1990,7 +1952,7 @@ tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc,
* If we can't figure out what it is, then return mlptSingle. That's actually
* an error case.
*
- * The callers are assume to pass in zone->zone_id and not the zoneid that
+ * 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).
*/
@@ -2022,23 +1984,28 @@ tsol_mlp_addr_type(zoneid_t zoneid, uchar_t version, const void *addr,
version = IPV4_VERSION;
}
+ /* Check whether the IRE_LOCAL (or ipif) is ALL_ZONES */
if (version == IPV4_VERSION) {
in4 = *(const in_addr_t *)addr;
if ((in4 == INADDR_ANY) || CLASSD(in4)) {
return (mlptBoth);
}
- ire = ire_cache_lookup(in4, ip_zoneid, NULL, ipst);
+ ire = ire_ftable_lookup_v4(in4, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
+ NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
+ 0, ipst, NULL);
} else {
if (IN6_IS_ADDR_UNSPECIFIED((const in6_addr_t *)addr) ||
IN6_IS_ADDR_MULTICAST((const in6_addr_t *)addr)) {
return (mlptBoth);
}
- ire = ire_cache_lookup_v6(addr, ip_zoneid, NULL, ipst);
+ ire = ire_ftable_lookup_v6(addr, 0, 0, IRE_LOCAL|IRE_LOOPBACK,
+ NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY,
+ 0, ipst, NULL);
}
/*
* If we can't find the IRE, then we have to behave exactly like
- * ip_bind_laddr{,_v6}. That means looking up the IPIF so that users
- * can bind to addresses on "down" interfaces.
+ * 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
@@ -2047,10 +2014,10 @@ tsol_mlp_addr_type(zoneid_t zoneid, uchar_t version, const void *addr,
if (ire == NULL) {
if (version == IPV4_VERSION)
ipif = ipif_lookup_addr(*(const in_addr_t *)addr, NULL,
- ip_zoneid, NULL, NULL, NULL, NULL, ipst);
+ ip_zoneid, ipst);
else
ipif = ipif_lookup_addr_v6((const in6_addr_t *)addr,
- NULL, ip_zoneid, NULL, NULL, NULL, NULL, ipst);
+ NULL, ip_zoneid, ipst);
if (ipif == NULL) {
return (mlptSingle);
}