summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/inet/ip.h9
-rw-r--r--usr/src/uts/common/inet/ip/ip6_input.c35
-rw-r--r--usr/src/uts/common/inet/ip/ip6_ire.c40
-rw-r--r--usr/src/uts/common/inet/ip/ip6_output.c4
-rw-r--r--usr/src/uts/common/inet/ip/ip_ftable.c54
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c8
-rw-r--r--usr/src/uts/common/inet/ip/ip_input.c22
-rw-r--r--usr/src/uts/common/inet/ip/ip_ire.c46
-rw-r--r--usr/src/uts/common/inet/ip/ip_mroute.c8
-rw-r--r--usr/src/uts/common/inet/ip/ip_netinfo.c10
-rw-r--r--usr/src/uts/common/inet/ip/ip_output.c4
-rw-r--r--usr/src/uts/common/inet/ip/ip_rts.c54
-rw-r--r--usr/src/uts/common/inet/ip/tn_ipopt.c8
-rw-r--r--usr/src/uts/common/inet/ip_ire.h14
14 files changed, 205 insertions, 111 deletions
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index 5557f941e2..a8ccd69aea 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -524,6 +524,13 @@ extern void ip_mcast_mapping(struct ill_s *, uchar_t *, uchar_t *);
#define IRE_FLUSH_GWCHANGE 2
/*
+ * Flags to ire_route_recursive
+ */
+#define IRR_NONE 0
+#define IRR_ALLOCATE 1 /* OK to allocate IRE_IF_CLONE */
+#define IRR_INCOMPLETE 2 /* OK to return incomplete chain */
+
+/*
* Open/close synchronization flags.
* These are kept in a separate field in the conn and the synchronization
* depends on the atomic 32 bit access to that field.
diff --git a/usr/src/uts/common/inet/ip/ip6_input.c b/usr/src/uts/common/inet/ip/ip6_input.c
index 46dcacbaf4..70955faa55 100644
--- a/usr/src/uts/common/inet/ip/ip6_input.c
+++ b/usr/src/uts/common/inet/ip/ip6_input.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -475,14 +475,14 @@ ip6_bad_address(in6_addr_t *addr, boolean_t is_src)
*/
static ire_t *
ire_linklocal(const in6_addr_t *nexthop, ill_t *ill, ip_recv_attr_t *ira,
- boolean_t allocate, ip_stack_t *ipst)
+ uint_t irr_flags, ip_stack_t *ipst)
{
int match_flags = MATCH_IRE_SECATTR | MATCH_IRE_ILL;
ire_t *ire;
ASSERT(IN6_IS_ADDR_LINKLOCAL(nexthop));
ire = ire_route_recursive_v6(nexthop, 0, ill, ALL_ZONES, ira->ira_tsl,
- match_flags, allocate, ira->ira_xmit_hint, ipst, NULL, NULL, NULL);
+ match_flags, irr_flags, ira->ira_xmit_hint, ipst, NULL, NULL, NULL);
if (!(ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) ||
!IS_UNDER_IPMP(ill))
return (ire);
@@ -500,7 +500,7 @@ ire_linklocal(const in6_addr_t *nexthop, ill_t *ill, ip_recv_attr_t *ira,
ire_refrele(ire);
ire = ire_route_recursive_v6(nexthop, 0, ill, ALL_ZONES, ira->ira_tsl,
- match_flags, allocate, ira->ira_xmit_hint, ipst, NULL, NULL, NULL);
+ match_flags, irr_flags, ira->ira_xmit_hint, ipst, NULL, NULL, NULL);
ill_refrele(ill);
return (ire);
}
@@ -521,6 +521,7 @@ ill_input_short_v6(mblk_t *mp, void *iph_arg, void *nexthop_arg,
ip6_t *ip6h = (ip6_t *)iph_arg;
in6_addr_t nexthop = *(in6_addr_t *)nexthop_arg;
ilb_stack_t *ilbs = ipst->ips_netstack->netstack_ilb;
+ uint_t irr_flags;
#define rptr ((uchar_t *)ip6h)
ASSERT(DB_TYPE(mp) == M_DATA);
@@ -755,19 +756,24 @@ ill_input_short_v6(mblk_t *mp, void *iph_arg, void *nexthop_arg,
}
}
+ if (ill->ill_flags & ILLF_ROUTER)
+ irr_flags = IRR_ALLOCATE;
+ else
+ irr_flags = IRR_NONE;
+
/* Can not use route cache with TX since the labels can differ */
if (ira->ira_flags & IRAF_SYSTEM_LABELED) {
if (IN6_IS_ADDR_MULTICAST(&nexthop)) {
ire = ire_multicast(ill);
} else if (IN6_IS_ADDR_LINKLOCAL(&nexthop)) {
- ire = ire_linklocal(&nexthop, ill, ira,
- (ill->ill_flags & ILLF_ROUTER), ipst);
+ ire = ire_linklocal(&nexthop, ill, ira, irr_flags,
+ ipst);
} else {
/* Match destination and label */
ire = ire_route_recursive_v6(&nexthop, 0, NULL,
- ALL_ZONES, ira->ira_tsl, MATCH_IRE_SECATTR,
- (ill->ill_flags & ILLF_ROUTER), ira->ira_xmit_hint,
- ipst, NULL, NULL, NULL);
+ ALL_ZONES, ira->ira_tsl, MATCH_IRE_SECATTR,
+ irr_flags, ira->ira_xmit_hint, ipst, NULL, NULL,
+ NULL);
}
/* Update the route cache so we do the ire_refrele */
ASSERT(ire != NULL);
@@ -784,12 +790,11 @@ ill_input_short_v6(mblk_t *mp, void *iph_arg, void *nexthop_arg,
if (IN6_IS_ADDR_MULTICAST(&nexthop)) {
ire = ire_multicast(ill);
} else if (IN6_IS_ADDR_LINKLOCAL(&nexthop)) {
- ire = ire_linklocal(&nexthop, ill, ira,
- (ill->ill_flags & ILLF_ROUTER), ipst);
+ ire = ire_linklocal(&nexthop, ill, ira, irr_flags,
+ ipst);
} else {
ire = ire_route_recursive_dstonly_v6(&nexthop,
- (ill->ill_flags & ILLF_ROUTER), ira->ira_xmit_hint,
- ipst);
+ irr_flags, ira->ira_xmit_hint, ipst);
}
ASSERT(ire != NULL);
if (rtc->rtc_ire != NULL)
@@ -917,8 +922,8 @@ ire_recv_forward_v6(ire_t *ire, mblk_t *mp, void *iph_arg, ip_recv_attr_t *ira)
*/
ire = ire_route_recursive_v6(&ip6h->ip6_dst, 0, NULL,
GLOBAL_ZONEID, ira->ira_tsl, MATCH_IRE_SECATTR,
- (ill->ill_flags & ILLF_ROUTER), ira->ira_xmit_hint, ipst,
- NULL, NULL, NULL);
+ (ill->ill_flags & ILLF_ROUTER) ? IRR_ALLOCATE : IRR_NONE,
+ ira->ira_xmit_hint, ipst, NULL, NULL, NULL);
ire->ire_ib_pkt_count++;
(*ire->ire_recvfn)(ire, mp, ip6h, ira);
ire_refrele(ire);
diff --git a/usr/src/uts/common/inet/ip/ip6_ire.c b/usr/src/uts/common/inet/ip/ip6_ire.c
index 533058ad1a..b24d859f4c 100644
--- a/usr/src/uts/common/inet/ip/ip6_ire.c
+++ b/usr/src/uts/common/inet/ip/ip6_ire.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -235,7 +235,7 @@ ire_lookup_multi_ill_v6(const in6_addr_t *group, zoneid_t zoneid,
ill_t *ill;
ire = ire_route_recursive_v6(group, 0, NULL, zoneid, NULL,
- MATCH_IRE_DSTONLY, B_FALSE, 0, ipst, setsrcp, NULL, NULL);
+ MATCH_IRE_DSTONLY, IRR_NONE, 0, ipst, setsrcp, NULL, NULL);
ASSERT(ire != NULL);
if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
@@ -1130,9 +1130,11 @@ ip_select_route_v6(const in6_addr_t *dst, ip_xmit_attr_t *ixa,
*
* If ill is set this means we will match it by adding MATCH_IRE_ILL.
*
- * If allocate is not set then we will only inspect the existing IREs; never
+ * If IRR_ALLOCATE is not set then we will only inspect the existing IREs; never
* create an IRE_IF_CLONE. This is used on the receive side when we are not
* forwarding.
+ * If IRR_INCOMPLETE is set then we return the IRE even if we can't correctly
+ * resolve the gateway.
*
* Note that this function never returns NULL. It returns an IRE_NOROUTE
* instead.
@@ -1145,7 +1147,7 @@ ire_t *
ire_route_recursive_impl_v6(ire_t *ire,
const in6_addr_t *nexthop, uint_t ire_type, const ill_t *ill_arg,
zoneid_t zoneid, const ts_label_t *tsl, uint_t match_args,
- boolean_t allocate, uint32_t xmit_hint, ip_stack_t *ipst,
+ uint_t irr_flags, uint32_t xmit_hint, ip_stack_t *ipst,
in6_addr_t *setsrcp, tsol_ire_gw_secattr_t **gwattrp, uint_t *generationp)
{
int i, j;
@@ -1206,7 +1208,12 @@ ire_route_recursive_impl_v6(ire_t *ire,
(IRE_LOCAL|IRE_LOOPBACK|IRE_BROADCAST)) ||
prefs[i] <= prefs[i-1]) {
ire_refrele(ire);
- ire = ire_reject(ipst, B_TRUE);
+ if (irr_flags & IRR_INCOMPLETE) {
+ ire = ires[0];
+ ire_refhold(ire);
+ } else {
+ ire = ire_reject(ipst, B_TRUE);
+ }
goto error;
}
}
@@ -1266,16 +1273,16 @@ ire_route_recursive_impl_v6(ire_t *ire,
/*
* In the case of ip_input and ILLF_FORWARDING not
- * being set, and in the case of RTM_GET,
- * there is no point in allocating
- * an IRE_IF_CLONE. We return the IRE_INTERFACE.
- * Note that !allocate can result in a ire_dep_parent
- * which is IRE_IF_* without an IRE_IF_CLONE.
+ * being set, and in the case of RTM_GET, there is
+ * no point in allocating an IRE_IF_CLONE. We return
+ * the IRE_INTERFACE. Note that !IRR_ALLOCATE can
+ * result in a ire_dep_parent which is IRE_IF_*
+ * without an IRE_IF_CLONE.
* We recover from that when we need to send packets
* by ensuring that the generations become
* IRE_GENERATION_VERIFY in this case.
*/
- if (!allocate) {
+ if (!(irr_flags & IRR_ALLOCATE)) {
invalidate = B_TRUE;
ire = NULL;
goto done;
@@ -1354,7 +1361,8 @@ cleanup:
for (j = 0; j < i; j++)
ire_refrele(ires[j]);
- ASSERT(ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE));
+ ASSERT((ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) ||
+ (irr_flags & IRR_INCOMPLETE));
/*
* Use IRE_GENERATION_VERIFY to ensure that ip_output will redo the
* ip_select_route since the reject or lack of memory might be gone.
@@ -1417,11 +1425,11 @@ done:
ire_t *
ire_route_recursive_v6(const in6_addr_t *nexthop, uint_t ire_type,
const ill_t *ill, zoneid_t zoneid, const ts_label_t *tsl, uint_t match_args,
- boolean_t allocate, uint32_t xmit_hint, ip_stack_t *ipst,
+ uint_t irr_flags, uint32_t xmit_hint, ip_stack_t *ipst,
in6_addr_t *setsrcp, tsol_ire_gw_secattr_t **gwattrp, uint_t *generationp)
{
return (ire_route_recursive_impl_v6(NULL, nexthop, ire_type, ill,
- zoneid, tsl, match_args, allocate, xmit_hint, ipst, setsrcp,
+ zoneid, tsl, match_args, irr_flags, xmit_hint, ipst, setsrcp,
gwattrp, generationp));
}
@@ -1438,7 +1446,7 @@ ire_route_recursive_v6(const in6_addr_t *nexthop, uint_t ire_type,
* Allow at most one RTF_INDIRECT.
*/
ire_t *
-ire_route_recursive_dstonly_v6(const in6_addr_t *nexthop, boolean_t allocate,
+ire_route_recursive_dstonly_v6(const in6_addr_t *nexthop, uint_t irr_flags,
uint32_t xmit_hint, ip_stack_t *ipst)
{
ire_t *ire;
@@ -1477,7 +1485,7 @@ ire_route_recursive_dstonly_v6(const in6_addr_t *nexthop, boolean_t allocate,
* we found. Normally this would return the same ire.
*/
ire1 = ire_route_recursive_impl_v6(ire, nexthop, 0, NULL, ALL_ZONES,
- NULL, MATCH_IRE_DSTONLY, allocate, xmit_hint, ipst, NULL, NULL,
+ NULL, MATCH_IRE_DSTONLY, irr_flags, xmit_hint, ipst, NULL, NULL,
&generation);
ire_refrele(ire);
return (ire1);
diff --git a/usr/src/uts/common/inet/ip/ip6_output.c b/usr/src/uts/common/inet/ip/ip6_output.c
index 50f9309586..6fdcfbc933 100644
--- a/usr/src/uts/common/inet/ip/ip6_output.c
+++ b/usr/src/uts/common/inet/ip/ip6_output.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -1232,7 +1232,7 @@ ip_postfrag_multirt_v6(mblk_t *mp, nce_t *nce, iaflags_t ixaflags,
ire2 = ire_route_recursive_impl_v6(ire1,
&ire1->ire_addr_v6, ire1->ire_type, ire1->ire_ill,
ire1->ire_zoneid, NULL, MATCH_IRE_DSTONLY,
- B_TRUE, 0, ipst, NULL, NULL, NULL);
+ IRR_ALLOCATE, 0, ipst, NULL, NULL, NULL);
if (ire2 != NULL)
ire_refrele(ire2);
ill1 = ire_nexthop_ill(ire1);
diff --git a/usr/src/uts/common/inet/ip/ip_ftable.c b/usr/src/uts/common/inet/ip/ip_ftable.c
index a84a15f513..0ee44e2c1e 100644
--- a/usr/src/uts/common/inet/ip/ip_ftable.c
+++ b/usr/src/uts/common/inet/ip/ip_ftable.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -342,7 +342,7 @@ ire_lookup_multi_ill_v4(ipaddr_t group, zoneid_t zoneid, ip_stack_t *ipst,
ill_t *ill;
ire = ire_route_recursive_v4(group, 0, NULL, zoneid, NULL,
- MATCH_IRE_DSTONLY, B_FALSE, 0, ipst, setsrcp, NULL, NULL);
+ MATCH_IRE_DSTONLY, IRR_NONE, 0, ipst, setsrcp, NULL, NULL);
ASSERT(ire != NULL);
if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
ire_refrele(ire);
@@ -524,13 +524,13 @@ route_to_dst(const struct sockaddr *dst_addr, zoneid_t zoneid, ip_stack_t *ipst)
if (dst_addr->sa_family == AF_INET) {
ire = ire_route_recursive_v4(
((struct sockaddr_in *)dst_addr)->sin_addr.s_addr, 0, NULL,
- zoneid, NULL, match_flags, B_TRUE, 0, ipst, NULL, NULL,
- NULL);
+ zoneid, NULL, match_flags, IRR_ALLOCATE, 0, ipst, NULL,
+ NULL, NULL);
} else {
ire = ire_route_recursive_v6(
&((struct sockaddr_in6 *)dst_addr)->sin6_addr, 0, NULL,
- zoneid, NULL, match_flags, B_TRUE, 0, ipst, NULL, NULL,
- NULL);
+ zoneid, NULL, match_flags, IRR_ALLOCATE, 0, ipst, NULL,
+ NULL, NULL);
}
ASSERT(ire != NULL);
if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
@@ -1118,13 +1118,13 @@ ip_select_route(const in6_addr_t *v6dst, ip_xmit_attr_t *ixa,
IN6_V4MAPPED_TO_IPADDR(&v6nexthop, v4nexthop);
ire = ire_route_recursive_v4(v4nexthop, ire_type, ill,
- ixa->ixa_zoneid, ixa->ixa_tsl, match_args, B_TRUE,
+ ixa->ixa_zoneid, ixa->ixa_tsl, match_args, IRR_ALLOCATE,
ixa->ixa_xmit_hint, ipst, &v4setsrc, NULL, generationp);
if (setsrcp != NULL)
IN6_IPADDR_TO_V4MAPPED(v4setsrc, setsrcp);
} else {
ire = ire_route_recursive_v6(&v6nexthop, ire_type, ill,
- ixa->ixa_zoneid, ixa->ixa_tsl, match_args, B_TRUE,
+ ixa->ixa_zoneid, ixa->ixa_tsl, match_args, IRR_ALLOCATE,
ixa->ixa_xmit_hint, ipst, setsrcp, NULL, generationp);
}
@@ -1210,6 +1210,12 @@ ip_select_route_v4(ipaddr_t dst, ip_xmit_attr_t *ixa, uint_t *generationp,
*
* If ill is set this means we will match it by adding MATCH_IRE_ILL.
*
+ * If IRR_ALLOCATE is not set then we will only inspect the existing IREs; never
+ * create an IRE_IF_CLONE. This is used on the receive side when we are not
+ * forwarding.
+ * If IRR_INCOMPLETE is set then we return the IRE even if we can't correctly
+ * resolve the gateway.
+ *
* Note that this function never returns NULL. It returns an IRE_NOROUTE
* instead.
*
@@ -1221,7 +1227,7 @@ ire_t *
ire_route_recursive_impl_v4(ire_t *ire,
ipaddr_t nexthop, uint_t ire_type, const ill_t *ill_arg,
zoneid_t zoneid, const ts_label_t *tsl, uint_t match_args,
- boolean_t allocate, uint32_t xmit_hint, ip_stack_t *ipst, ipaddr_t *setsrcp,
+ uint_t irr_flags, uint32_t xmit_hint, ip_stack_t *ipst, ipaddr_t *setsrcp,
tsol_ire_gw_secattr_t **gwattrp, uint_t *generationp)
{
int i, j;
@@ -1280,7 +1286,12 @@ ire_route_recursive_impl_v4(ire_t *ire,
(IRE_LOCAL|IRE_LOOPBACK|IRE_BROADCAST)) ||
prefs[i] <= prefs[i-1]) {
ire_refrele(ire);
- ire = ire_reject(ipst, B_FALSE);
+ if (irr_flags & IRR_INCOMPLETE) {
+ ire = ires[0];
+ ire_refhold(ire);
+ } else {
+ ire = ire_reject(ipst, B_FALSE);
+ }
goto error;
}
}
@@ -1340,16 +1351,16 @@ ire_route_recursive_impl_v4(ire_t *ire,
/*
* In the case of ip_input and ILLF_FORWARDING not
- * being set, and in the case of RTM_GET,
- * there is no point in allocating
- * an IRE_IF_CLONE. We return the IRE_INTERFACE.
- * Note that !allocate can result in a ire_dep_parent
- * which is IRE_IF_* without an IRE_IF_CLONE.
+ * being set, and in the case of RTM_GET, there is
+ * no point in allocating an IRE_IF_CLONE. We return
+ * the IRE_INTERFACE. Note that !IRR_ALLOCATE can
+ * result in a ire_dep_parent which is IRE_IF_*
+ * without an IRE_IF_CLONE.
* We recover from that when we need to send packets
* by ensuring that the generations become
* IRE_GENERATION_VERIFY in this case.
*/
- if (!allocate) {
+ if (!(irr_flags & IRR_ALLOCATE)) {
invalidate = B_TRUE;
ire = NULL;
goto done;
@@ -1430,7 +1441,8 @@ cleanup:
for (j = 0; j < i; j++)
ire_refrele(ires[j]);
- ASSERT(ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE));
+ ASSERT((ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) ||
+ (irr_flags & IRR_INCOMPLETE));
/*
* Use IRE_GENERATION_VERIFY to ensure that ip_output will redo the
* ip_select_route since the reject or lack of memory might be gone.
@@ -1495,11 +1507,11 @@ done:
ire_t *
ire_route_recursive_v4(ipaddr_t nexthop, uint_t ire_type, const ill_t *ill,
zoneid_t zoneid, const ts_label_t *tsl, uint_t match_args,
- boolean_t allocate, uint32_t xmit_hint, ip_stack_t *ipst, ipaddr_t *setsrcp,
+ uint_t irr_flags, uint32_t xmit_hint, ip_stack_t *ipst, ipaddr_t *setsrcp,
tsol_ire_gw_secattr_t **gwattrp, uint_t *generationp)
{
return (ire_route_recursive_impl_v4(NULL, nexthop, ire_type, ill,
- zoneid, tsl, match_args, allocate, xmit_hint, ipst, setsrcp,
+ zoneid, tsl, match_args, irr_flags, xmit_hint, ipst, setsrcp,
gwattrp, generationp));
}
@@ -1516,7 +1528,7 @@ ire_route_recursive_v4(ipaddr_t nexthop, uint_t ire_type, const ill_t *ill,
* Allow at most one RTF_INDIRECT.
*/
ire_t *
-ire_route_recursive_dstonly_v4(ipaddr_t nexthop, boolean_t allocate,
+ire_route_recursive_dstonly_v4(ipaddr_t nexthop, uint_t irr_flags,
uint32_t xmit_hint, ip_stack_t *ipst)
{
ire_t *ire;
@@ -1555,7 +1567,7 @@ ire_route_recursive_dstonly_v4(ipaddr_t nexthop, boolean_t allocate,
* we found. Normally this would return the same ire.
*/
ire1 = ire_route_recursive_impl_v4(ire, nexthop, 0, NULL, ALL_ZONES,
- NULL, MATCH_IRE_DSTONLY, allocate, xmit_hint, ipst, NULL, NULL,
+ NULL, MATCH_IRE_DSTONLY, irr_flags, xmit_hint, ipst, NULL, NULL,
&generation);
ire_refrele(ire);
return (ire1);
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index 427bc588a0..a4ffac1638 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -7928,13 +7928,13 @@ ip_sioctl_dstinfo(queue_t *q, mblk_t *mp)
IN6_V4MAPPED_TO_IPADDR(daddr, v4daddr);
v4setsrc = INADDR_ANY;
ire = ire_route_recursive_v4(v4daddr, 0, NULL, zoneid,
- NULL, match_ire, B_TRUE, 0, ipst, &v4setsrc, NULL,
- NULL);
+ NULL, match_ire, IRR_ALLOCATE, 0, ipst, &v4setsrc,
+ NULL, NULL);
} else {
v6setsrc = ipv6_all_zeros;
ire = ire_route_recursive_v6(daddr, 0, NULL, zoneid,
- NULL, match_ire, B_TRUE, 0, ipst, &v6setsrc, NULL,
- NULL);
+ NULL, match_ire, IRR_ALLOCATE, 0, ipst, &v6setsrc,
+ NULL, NULL);
}
ASSERT(ire != NULL);
if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
diff --git a/usr/src/uts/common/inet/ip/ip_input.c b/usr/src/uts/common/inet/ip/ip_input.c
index 65c566a3cb..e7cd69b0be 100644
--- a/usr/src/uts/common/inet/ip/ip_input.c
+++ b/usr/src/uts/common/inet/ip/ip_input.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -564,6 +564,7 @@ ill_input_short_v4(mblk_t *mp, void *iph_arg, void *nexthop_arg,
ipha_t *ipha = (ipha_t *)iph_arg;
ipaddr_t nexthop = *(ipaddr_t *)nexthop_arg;
ilb_stack_t *ilbs = ipst->ips_netstack->netstack_ilb;
+ uint_t irr_flags;
#define rptr ((uchar_t *)ipha)
ASSERT(DB_TYPE(mp) == M_DATA);
@@ -769,6 +770,12 @@ after_ilb:
return;
}
}
+
+ if (ill->ill_flags & ILLF_ROUTER)
+ irr_flags = IRR_ALLOCATE;
+ else
+ irr_flags = IRR_NONE;
+
/* Can not use route cache with TX since the labels can differ */
if (ira->ira_flags & IRAF_SYSTEM_LABELED) {
if (CLASSD(nexthop)) {
@@ -777,8 +784,8 @@ after_ilb:
/* Match destination and label */
ire = ire_route_recursive_v4(nexthop, 0, NULL,
ALL_ZONES, ira->ira_tsl, MATCH_IRE_SECATTR,
- (ill->ill_flags & ILLF_ROUTER),
- ira->ira_xmit_hint, ipst, NULL, NULL, NULL);
+ irr_flags, ira->ira_xmit_hint, ipst, NULL, NULL,
+ NULL);
}
/* Update the route cache so we do the ire_refrele */
ASSERT(ire != NULL);
@@ -796,9 +803,8 @@ after_ilb:
ire = ire_multicast(ill);
} else {
/* Just match the destination */
- ire = ire_route_recursive_dstonly_v4(nexthop,
- (ill->ill_flags & ILLF_ROUTER), ira->ira_xmit_hint,
- ipst);
+ ire = ire_route_recursive_dstonly_v4(nexthop, irr_flags,
+ ira->ira_xmit_hint, ipst);
}
ASSERT(ire != NULL);
if (rtc->rtc_ire != NULL)
@@ -939,8 +945,8 @@ ire_recv_forward_v4(ire_t *ire, mblk_t *mp, void *iph_arg, ip_recv_attr_t *ira)
}
ire = ire_route_recursive_v4(dst, 0, NULL, GLOBAL_ZONEID,
ira->ira_tsl, MATCH_IRE_SECATTR,
- (ill->ill_flags & ILLF_ROUTER), ira->ira_xmit_hint, ipst,
- NULL, NULL, NULL);
+ (ill->ill_flags & ILLF_ROUTER) ? IRR_ALLOCATE : IRR_NONE,
+ ira->ira_xmit_hint, ipst, NULL, NULL, NULL);
ire->ire_ib_pkt_count++;
(*ire->ire_recvfn)(ire, mp, ipha, ira);
ire_refrele(ire);
diff --git a/usr/src/uts/common/inet/ip/ip_ire.c b/usr/src/uts/common/inet/ip/ip_ire.c
index cea86d7529..d195d2543b 100644
--- a/usr/src/uts/common/inet/ip/ip_ire.c
+++ b/usr/src/uts/common/inet/ip/ip_ire.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -919,23 +919,49 @@ ire_walk_ill_match(uint_t match_flags, uint_t ire_type, ire_t *ire,
/*
* Except for ALL_ZONES, we only match the offlink routes
* where ire_gateway_addr has an IRE_INTERFACE for the zoneid.
+ * Since we can have leftover routes after the IP addresses have
+ * changed, the global zone will also match offlink routes where the
+ * gateway is unreachable from any zone.
*/
if ((ire->ire_type & IRE_OFFLINK) && zoneid != ALL_ZONES) {
in6_addr_t gw_addr_v6;
+ boolean_t reach;
if (ire->ire_ipversion == IPV4_VERSION) {
- if (!ire_gateway_ok_zone_v4(ire->ire_gateway_addr,
- zoneid, dst_ill, NULL, ipst, B_FALSE))
- return (B_FALSE);
+ reach = ire_gateway_ok_zone_v4(ire->ire_gateway_addr,
+ zoneid, dst_ill, NULL, ipst, B_FALSE);
} else {
ASSERT(ire->ire_ipversion == IPV6_VERSION);
mutex_enter(&ire->ire_lock);
gw_addr_v6 = ire->ire_gateway_addr_v6;
mutex_exit(&ire->ire_lock);
- if (!ire_gateway_ok_zone_v6(&gw_addr_v6, zoneid,
- dst_ill, NULL, ipst, B_FALSE))
+ reach = ire_gateway_ok_zone_v6(&gw_addr_v6, zoneid,
+ dst_ill, NULL, ipst, B_FALSE);
+ }
+ if (!reach) {
+ if (zoneid != GLOBAL_ZONEID)
+ return (B_FALSE);
+
+ /*
+ * Check if ALL_ZONES reachable - if not then let the
+ * global zone see it.
+ */
+ if (ire->ire_ipversion == IPV4_VERSION) {
+ reach = ire_gateway_ok_zone_v4(
+ ire->ire_gateway_addr, ALL_ZONES,
+ dst_ill, NULL, ipst, B_FALSE);
+ } else {
+ reach = ire_gateway_ok_zone_v6(&gw_addr_v6,
+ ALL_ZONES, dst_ill, NULL, ipst, B_FALSE);
+ }
+ if (reach) {
+ /*
+ * Some other zone could see it, hence hide it
+ * in the global zone.
+ */
return (B_FALSE);
+ }
}
}
@@ -2009,12 +2035,12 @@ ire_alt_local(ire_t *ire, zoneid_t zoneid, const ts_label_t *tsl,
if (ire->ire_ipversion == IPV4_VERSION) {
alt_ire = ire_route_recursive_v4(ire->ire_addr, ire_type,
- ill, zoneid, tsl, match_flags, B_TRUE, 0, ipst, NULL, NULL,
- &generation);
+ ill, zoneid, tsl, match_flags, IRR_ALLOCATE, 0, ipst, NULL,
+ NULL, &generation);
} else {
alt_ire = ire_route_recursive_v6(&ire->ire_addr_v6, ire_type,
- ill, zoneid, tsl, match_flags, B_TRUE, 0, ipst, NULL, NULL,
- &generation);
+ ill, zoneid, tsl, match_flags, IRR_ALLOCATE, 0, ipst, NULL,
+ NULL, &generation);
}
ASSERT(alt_ire != NULL);
diff --git a/usr/src/uts/common/inet/ip/ip_mroute.c b/usr/src/uts/common/inet/ip/ip_mroute.c
index 41f4f3f221..53df3bec4b 100644
--- a/usr/src/uts/common/inet/ip/ip_mroute.c
+++ b/usr/src/uts/common/inet/ip/ip_mroute.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -2506,8 +2506,8 @@ register_mforward(mblk_t *mp, ip_recv_attr_t *ira)
if (!CLASSD(ipha->ipha_dst)) {
ire = ire_route_recursive_v4(ipha->ipha_dst, 0, NULL, ALL_ZONES,
- ira->ira_tsl, MATCH_IRE_SECATTR, B_TRUE, 0, ipst, NULL,
- NULL, NULL);
+ ira->ira_tsl, MATCH_IRE_SECATTR, IRR_ALLOCATE, 0, ipst,
+ NULL, NULL, NULL);
} else {
ire = ire_multicast(ill);
}
@@ -2720,7 +2720,7 @@ ip_mroute_decap(mblk_t *mp, ip_recv_attr_t *ira)
ipst->ips_ipcl_proto_fanout_v4[IPPROTO_RSVP].connf_head != NULL) {
ire = ire_route_recursive_v4(INADDR_BROADCAST, 0, ill,
ALL_ZONES, ira->ira_tsl, MATCH_IRE_ILL|MATCH_IRE_SECATTR,
- B_TRUE, 0, ipst, NULL, NULL, NULL);
+ IRR_ALLOCATE, 0, ipst, NULL, NULL, NULL);
} else {
ire = ire_multicast(ill);
}
diff --git a/usr/src/uts/common/inet/ip/ip_netinfo.c b/usr/src/uts/common/inet/ip/ip_netinfo.c
index 33e791adac..0d0d943676 100644
--- a/usr/src/uts/common/inet/ip/ip_netinfo.c
+++ b/usr/src/uts/common/inet/ip/ip_netinfo.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1077,12 +1077,12 @@ ip_routeto_impl(struct sockaddr *address, struct sockaddr *nexthop,
if (address->sa_family == AF_INET6) {
ire = ire_route_recursive_v6(&sin6->sin6_addr, 0, NULL,
- zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, NULL,
- NULL, NULL);
+ zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst,
+ NULL, NULL, NULL);
} else {
ire = ire_route_recursive_v4(sin->sin_addr.s_addr, 0, NULL,
- zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, NULL,
- NULL, NULL);
+ zoneid, NULL, MATCH_IRE_DSTONLY, IRR_ALLOCATE, 0, ipst,
+ NULL, NULL, NULL);
}
ASSERT(ire != NULL);
/*
diff --git a/usr/src/uts/common/inet/ip/ip_output.c b/usr/src/uts/common/inet/ip/ip_output.c
index e5dd230ba6..59d95a4849 100644
--- a/usr/src/uts/common/inet/ip/ip_output.c
+++ b/usr/src/uts/common/inet/ip/ip_output.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -2299,7 +2299,7 @@ ip_postfrag_multirt_v4(mblk_t *mp, nce_t *nce, iaflags_t ixaflags,
ire2 = ire_route_recursive_impl_v4(ire1,
ire1->ire_addr, ire1->ire_type, ire1->ire_ill,
ire1->ire_zoneid, NULL, MATCH_IRE_DSTONLY,
- B_TRUE, 0, ipst, NULL, NULL, NULL);
+ IRR_ALLOCATE, 0, ipst, NULL, NULL, NULL);
if (ire2 != NULL)
ire_refrele(ire2);
ill1 = ire_nexthop_ill(ire1);
diff --git a/usr/src/uts/common/inet/ip/ip_rts.c b/usr/src/uts/common/inet/ip/ip_rts.c
index 1d2b405828..8a44a0bcd4 100644
--- a/usr/src/uts/common/inet/ip/ip_rts.c
+++ b/usr/src/uts/common/inet/ip/ip_rts.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -88,7 +88,7 @@ static int rts_getaddrs(rt_msghdr_t *rtm, in6_addr_t *dst_addrp,
in6_addr_t *if_addrp, in6_addr_t *src_addrp, ushort_t *indexp,
sa_family_t *afp, tsol_rtsecattr_t *rtsecattr, int *error);
static void rts_getifdata(if_data_t *if_data, const ipif_t *ipif);
-static int rts_getmetrics(ire_t *ire, rt_metrics_t *metrics);
+static int rts_getmetrics(ire_t *ire, ill_t *ill, rt_metrics_t *metrics);
static mblk_t *rts_rtmget(mblk_t *mp, ire_t *ire, ire_t *ifire,
const in6_addr_t *setsrc, tsol_ire_gw_secattr_t *attrp, sa_family_t af);
static void rts_setmetrics(ire_t *ire, uint_t which, rt_metrics_t *metrics);
@@ -1026,12 +1026,23 @@ ire_lookup_v4(ipaddr_t dst_addr, ipaddr_t net_mask, ipaddr_t gw_addr,
dst_addr = ire->ire_gateway_addr;
match_flags &= ~(MATCH_IRE_GW|MATCH_IRE_MASK);
ifire = ire_route_recursive_v4(dst_addr, ire_type, ill, zoneid,
- tsl, match_flags, B_FALSE, 0, ipst, v4setsrcp, gwattrp,
- NULL);
+ tsl, match_flags, IRR_INCOMPLETE, 0, ipst, v4setsrcp,
+ gwattrp, NULL);
+ /*
+ * Don't allow anything unusual past the first
+ * iteration. Clearing ifire means caller will not see a
+ * complete response - there will be no RTA_IFP returned.
+ */
+ if ((ifire->ire_type &
+ (IRE_LOCAL|IRE_LOOPBACK|IRE_BROADCAST)) ||
+ ire_pref(ifire) <= ire_pref(ire)) {
+ ire_refrele(ifire);
+ ifire = NULL;
+ }
} else {
ire = ire_route_recursive_v4(dst_addr, ire_type, ill, zoneid,
- tsl, match_flags, B_FALSE, 0, ipst, v4setsrcp, gwattrp,
- NULL);
+ tsl, match_flags, IRR_INCOMPLETE, 0, ipst, v4setsrcp,
+ gwattrp, NULL);
}
*pifire = ifire;
return (ire);
@@ -1091,11 +1102,23 @@ ire_lookup_v6(const in6_addr_t *dst_addr_v6,
mutex_exit(&ire->ire_lock);
match_flags &= ~(MATCH_IRE_GW|MATCH_IRE_MASK);
ifire = ire_route_recursive_v6(&dst, ire_type, ill, zoneid, tsl,
- match_flags, B_FALSE, 0, ipst, v6setsrcp, gwattrp, NULL);
+ match_flags, IRR_INCOMPLETE, 0, ipst, v6setsrcp, gwattrp,
+ NULL);
+ /*
+ * Don't allow anything unusual past the first
+ * iteration. Clearing ifire means caller will not see a
+ * complete response - there will be no RTA_IFP returned.
+ */
+ if ((ifire->ire_type &
+ (IRE_LOCAL|IRE_LOOPBACK|IRE_BROADCAST)) ||
+ ire_pref(ifire) <= ire_pref(ire)) {
+ ire_refrele(ifire);
+ ifire = NULL;
+ }
} else {
ire = ire_route_recursive_v6(dst_addr_v6, ire_type, ill, zoneid,
- tsl, match_flags, B_FALSE, 0, ipst, v6setsrcp, gwattrp,
- NULL);
+ tsl, match_flags, IRR_INCOMPLETE, 0, ipst, v6setsrcp,
+ gwattrp, NULL);
}
*pifire = ifire;
return (ire);
@@ -1311,7 +1334,7 @@ rts_rtmget(mblk_t *mp, ire_t *ire, ire_t *ifire, const in6_addr_t *setsrc,
new_rtm->rtm_use = rtm->rtm_use;
new_rtm->rtm_addrs = rtm_addrs;
new_rtm->rtm_flags = rtm_flags;
- new_rtm->rtm_inits = rts_getmetrics(ire, &new_rtm->rtm_rmx);
+ new_rtm->rtm_inits = rts_getmetrics(ire, ill, &new_rtm->rtm_rmx);
if (ill != NULL)
ill_refrele(ill);
return (new_mp);
@@ -1466,7 +1489,7 @@ rts_setmetrics(ire_t *ire, uint_t which, rt_metrics_t *metrics)
* Get the metrics from a forwarding table route.
*/
static int
-rts_getmetrics(ire_t *ire, rt_metrics_t *metrics)
+rts_getmetrics(ire_t *ire, ill_t *ill, rt_metrics_t *metrics)
{
int metrics_set = 0;
@@ -1479,8 +1502,13 @@ rts_getmetrics(ire_t *ire, rt_metrics_t *metrics)
*/
metrics->rmx_rtt = ire->ire_metrics.iulp_rtt * 1000;
metrics_set |= RTV_RTT;
- metrics->rmx_mtu = ire->ire_metrics.iulp_mtu;
- metrics_set |= RTV_MTU;
+ if (ire->ire_metrics.iulp_mtu != 0) {
+ metrics->rmx_mtu = ire->ire_metrics.iulp_mtu;
+ metrics_set |= RTV_MTU;
+ } else if (ill != NULL) {
+ metrics->rmx_mtu = ill->ill_mtu;
+ metrics_set |= RTV_MTU;
+ }
metrics->rmx_ssthresh = ire->ire_metrics.iulp_ssthresh;
metrics_set |= RTV_SSTHRESH;
metrics->rmx_rttvar = ire->ire_metrics.iulp_rtt_sd * 1000;
diff --git a/usr/src/uts/common/inet/ip/tn_ipopt.c b/usr/src/uts/common/inet/ip/tn_ipopt.c
index 32d32470e4..fe92c91f7c 100644
--- a/usr/src/uts/common/inet/ip/tn_ipopt.c
+++ b/usr/src/uts/common/inet/ip/tn_ipopt.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -493,7 +493,8 @@ tsol_compute_label_v4(const ts_label_t *tsl, zoneid_t zoneid, ipaddr_t dst,
* next-hop gateway is labeled.
*/
ire = ire_route_recursive_v4(dst, 0, NULL, zoneid, tsl,
- MATCH_IRE_SECATTR, B_TRUE, 0, ipst, NULL, &attrp, NULL);
+ MATCH_IRE_SECATTR, IRR_ALLOCATE, 0, ipst, NULL, &attrp,
+ NULL);
ASSERT(ire != NULL);
if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
/* no route to destination */
@@ -1003,7 +1004,8 @@ tsol_compute_label_v6(const ts_label_t *tsl, zoneid_t zoneid,
* next-hop gateway is labeled.
*/
ire = ire_route_recursive_v6(dst, 0, NULL, zoneid, tsl,
- MATCH_IRE_SECATTR, B_TRUE, 0, ipst, NULL, &attrp, NULL);
+ MATCH_IRE_SECATTR, IRR_ALLOCATE, 0, ipst, NULL, &attrp,
+ NULL);
ASSERT(ire != NULL);
if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
/* no route to destination */
diff --git a/usr/src/uts/common/inet/ip_ire.h b/usr/src/uts/common/inet/ip_ire.h
index bb27d8f766..b187f4eeb6 100644
--- a/usr/src/uts/common/inet/ip_ire.h
+++ b/usr/src/uts/common/inet/ip_ire.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -262,20 +262,20 @@ extern ire_t *ire_round_robin(irb_t *, ire_ftable_args_t *, uint_t,
ire_t *, ip_stack_t *);
extern ire_t *ire_route_recursive_v4(ipaddr_t, uint_t, const ill_t *,
- zoneid_t, const ts_label_t *, uint_t, boolean_t, uint32_t, ip_stack_t *,
+ zoneid_t, const ts_label_t *, uint_t, uint_t, uint32_t, ip_stack_t *,
ipaddr_t *, tsol_ire_gw_secattr_t **, uint_t *);
extern ire_t *ire_route_recursive_v6(const in6_addr_t *, uint_t,
- const ill_t *, zoneid_t, const ts_label_t *, uint_t, boolean_t, uint32_t,
+ const ill_t *, zoneid_t, const ts_label_t *, uint_t, uint_t, uint32_t,
ip_stack_t *, in6_addr_t *, tsol_ire_gw_secattr_t **, uint_t *);
-extern ire_t *ire_route_recursive_dstonly_v4(ipaddr_t, boolean_t,
+extern ire_t *ire_route_recursive_dstonly_v4(ipaddr_t, uint_t,
uint32_t, ip_stack_t *);
-extern ire_t *ire_route_recursive_dstonly_v6(const in6_addr_t *, boolean_t,
+extern ire_t *ire_route_recursive_dstonly_v6(const in6_addr_t *, uint_t,
uint32_t, ip_stack_t *);
extern ire_t *ire_route_recursive_impl_v4(ire_t *ire, ipaddr_t, uint_t,
- const ill_t *, zoneid_t, const ts_label_t *, uint_t, boolean_t, uint32_t,
+ const ill_t *, zoneid_t, const ts_label_t *, uint_t, uint_t, uint32_t,
ip_stack_t *, ipaddr_t *, tsol_ire_gw_secattr_t **, uint_t *);
extern ire_t *ire_route_recursive_impl_v6(ire_t *ire, const in6_addr_t *,
- uint_t, const ill_t *, zoneid_t, const ts_label_t *, uint_t, boolean_t,
+ uint_t, const ill_t *, zoneid_t, const ts_label_t *, uint_t, uint_t,
uint32_t, ip_stack_t *, in6_addr_t *, tsol_ire_gw_secattr_t **, uint_t *);
/* The different ire_sendfn functions */