summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/inet/ip/ip.c43
-rw-r--r--usr/src/uts/common/inet/ip/ip6_if.c10
-rw-r--r--usr/src/uts/common/inet/ip/ip_ftable.c42
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c7
-rw-r--r--usr/src/uts/common/inet/ip/ip_ire.c3
-rw-r--r--usr/src/uts/common/inet/ip_ftable.h14
6 files changed, 77 insertions, 42 deletions
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 77beff2c4c..72e29875f2 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -13619,8 +13619,8 @@ ip_rput_noire(queue_t *q, mblk_t *mp, int ll_multicast, ipaddr_t dst)
ipha_t *ipha;
ill_t *ill;
ire_t *ire;
- boolean_t check_multirt = B_FALSE;
ip_stack_t *ipst;
+ enum ire_forward_action ret_action;
ipha = (ipha_t *)mp->b_rptr;
ill = (ill_t *)q->q_ptr;
@@ -13668,10 +13668,10 @@ ip_rput_noire(queue_t *q, mblk_t *mp, int ll_multicast, ipaddr_t dst)
*/
DB_CKSUMFLAGS(mp) = 0;
- ire = ire_forward(dst, &check_multirt, NULL, NULL,
+ ire = ire_forward(dst, &ret_action, NULL, NULL,
MBLK_GETLABEL(mp), ipst);
- if (ire == NULL && check_multirt) {
+ if (ire == NULL && ret_action == Forward_check_multirt) {
/* Let ip_newroute handle CGTP */
ip_newroute(q, mp, dst, NULL, GLOBAL_ZONEID, ipst);
return (NULL);
@@ -13681,6 +13681,11 @@ ip_rput_noire(queue_t *q, mblk_t *mp, int ll_multicast, ipaddr_t dst)
return (ire);
mp->b_prev = mp->b_next = 0;
+
+ if (ret_action == Forward_blackhole) {
+ freemsg(mp);
+ return (NULL);
+ }
/* send icmp unreachable */
q = WR(q);
/* Sent by forwarding path, and router is global zone */
@@ -13857,6 +13862,7 @@ ip_fast_forward(ire_t *ire, ipaddr_t dst, ill_t *ill, mblk_t *mp)
queue_t *dev_q;
ip_stack_t *ipst = ill->ill_ipst;
mblk_t *fpmp;
+ enum ire_forward_action ret_action;
ipha = (ipha_t *)mp->b_rptr;
@@ -13882,14 +13888,15 @@ ip_fast_forward(ire_t *ire, ipaddr_t dst, ill_t *ill, mblk_t *mp)
/* No ire cache of nexthop. So first create one */
if (ire == NULL) {
- boolean_t check_multirt;
- ire = ire_forward(dst, &check_multirt, NULL, NULL, NULL, ipst);
+ ire = ire_forward(dst, &ret_action, NULL, NULL,
+ NULL, ipst);
/*
- * We only come to ip_fast_forward if ip_cgtp_filter is
- * is not set. So upon return from ire_forward
- * check_multirt should remain as false.
+ * We only come to ip_fast_forward if ip_cgtp_filter
+ * is not set. So ire_forward() should not return with
+ * Forward_check_multirt as the next action.
*/
+ ASSERT(ret_action != Forward_check_multirt);
if (ire == NULL) {
/* An attempt was made to forward the packet */
BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInForwDatagrams);
@@ -13897,16 +13904,20 @@ ip_fast_forward(ire_t *ire, ipaddr_t dst, ill_t *ill, mblk_t *mp)
mp->b_prev = mp->b_next = 0;
/* send icmp unreachable */
/* Sent by forwarding path, and router is global zone */
- if (ip_source_routed(ipha, ipst)) {
- icmp_unreachable(ill->ill_wq, mp,
- ICMP_SOURCE_ROUTE_FAILED, GLOBAL_ZONEID,
- ipst);
+ if (ret_action == Forward_ret_icmp_err) {
+ if (ip_source_routed(ipha, ipst)) {
+ icmp_unreachable(ill->ill_wq, mp,
+ ICMP_SOURCE_ROUTE_FAILED,
+ GLOBAL_ZONEID, ipst);
+ } else {
+ icmp_unreachable(ill->ill_wq, mp,
+ ICMP_HOST_UNREACHABLE,
+ GLOBAL_ZONEID, ipst);
+ }
} else {
- icmp_unreachable(ill->ill_wq, mp,
- ICMP_HOST_UNREACHABLE, GLOBAL_ZONEID,
- ipst);
+ freemsg(mp);
}
- return (ire);
+ return (NULL);
}
}
diff --git a/usr/src/uts/common/inet/ip/ip6_if.c b/usr/src/uts/common/inet/ip/ip6_if.c
index 1a9b7876fa..51bb0cbe67 100644
--- a/usr/src/uts/common/inet/ip/ip6_if.c
+++ b/usr/src/uts/common/inet/ip/ip6_if.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -661,7 +661,9 @@ ip_rt_add_v6(const in6_addr_t *dst_addr, const in6_addr_t *mask,
* to create (what amount to) IRE_PREFIX routes with the
* loopback address as the gateway. This is primarily done to
* set up prefixes with the RTF_REJECT flag set (for example,
- * when generating aggregate routes.)
+ * when generating aggregate routes). We also OR in the
+ * RTF_BLACKHOLE flag as these interface routes, by
+ * definition, can only be that.
*
* If the IRE type (as defined by ipif->ipif_net_type) is
* IRE_LOOPBACK, then we map the request into a
@@ -670,8 +672,10 @@ ip_rt_add_v6(const in6_addr_t *dst_addr, const in6_addr_t *mask,
* Needless to say, the real IRE_LOOPBACK is NOT created by this
* routine, but rather using ire_create_v6() directly.
*/
- if (ipif->ipif_net_type == IRE_LOOPBACK)
+ if (ipif->ipif_net_type == IRE_LOOPBACK) {
ire->ire_type = IRE_IF_NORESOLVER;
+ ire->ire_flags |= RTF_BLACKHOLE;
+ }
error = ire_add(&ire, q, mp, func, B_FALSE);
if (error == 0)
goto save_ire;
diff --git a/usr/src/uts/common/inet/ip/ip_ftable.c b/usr/src/uts/common/inet/ip/ip_ftable.c
index 6d68d81951..325f5afe1d 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -790,8 +790,9 @@ ire_forward_src_ipif(ipaddr_t dst, ire_t *sire, ire_t *ire, ill_t *dst_ill,
*/
ire_t *
-ire_forward(ipaddr_t dst, boolean_t *check_multirt, ire_t *supplied_ire,
- ire_t *supplied_sire, const struct ts_label_s *tsl, ip_stack_t *ipst)
+ire_forward(ipaddr_t dst, enum ire_forward_action *ret_action,
+ ire_t *supplied_ire, ire_t *supplied_sire, const struct ts_label_s *tsl,
+ ip_stack_t *ipst)
{
ipaddr_t gw = 0;
ire_t *ire = NULL;
@@ -842,12 +843,10 @@ ire_forward(ipaddr_t dst, boolean_t *check_multirt, ire_t *supplied_ire,
* Inform caller about encountering of multirt so that
* ip_newroute() can be called.
*/
- *check_multirt = B_TRUE;
+ *ret_action = Forward_check_multirt;
return (NULL);
}
- *check_multirt = B_FALSE;
-
/*
* Verify that the returned IRE does not have either
* the RTF_REJECT or RTF_BLACKHOLE flags set and that the IRE is
@@ -938,6 +937,15 @@ create_irecache:
switch (ire->ire_type) {
case IRE_IF_NORESOLVER:
/* create ire_cache for ire_addr endpoint */
+ if (dst_ill->ill_phys_addr_length != IP_ADDR_LEN &&
+ dst_ill->ill_resolver_mp == NULL) {
+ ip1dbg(("ire_forward: dst_ill %p "
+ "for IRE_IF_NORESOLVER ire %p has "
+ "no ill_resolver_mp\n",
+ (void *)dst_ill, (void *)ire));
+ goto icmp_err_ret;
+ }
+ /* FALLTHRU */
case IRE_IF_RESOLVER:
/*
* We have the IRE_IF_RESOLVER of the nexthop gateway
@@ -961,9 +969,7 @@ create_irecache:
res_mp = dst_ill->ill_resolver_mp;
if (ire->ire_type == IRE_IF_RESOLVER &&
(!OK_RESOLVER_MP(res_mp))) {
- ire_refrele(ire);
- ire = NULL;
- goto out;
+ goto icmp_err_ret;
}
/*
* To be at this point in the code with a non-zero gw
@@ -1058,7 +1064,7 @@ create_irecache:
break;
}
-out:
+ *ret_action = Forward_ok;
if (sire != NULL)
ire_refrele(sire);
if (dst_ill != NULL)
@@ -1067,16 +1073,18 @@ out:
ipif_refrele(src_ipif);
return (ire);
icmp_err_ret:
- if (src_ipif != NULL)
- ipif_refrele(src_ipif);
- if (dst_ill != NULL)
- ill_refrele(dst_ill);
+ *ret_action = Forward_ret_icmp_err;
if (sire != NULL)
ire_refrele(sire);
+ if (dst_ill != NULL)
+ ill_refrele(dst_ill);
+ if (src_ipif != NULL)
+ ipif_refrele(src_ipif);
if (ire != NULL) {
+ if (ire->ire_flags & RTF_BLACKHOLE)
+ *ret_action = Forward_blackhole;
ire_refrele(ire);
}
- /* caller needs to send icmp error message */
return (NULL);
}
@@ -1257,12 +1265,12 @@ ipfil_sendpkt(const struct sockaddr *dst_addr, mblk_t *mp, uint_t ifindex,
{
ire_t *ire = NULL, *sire = NULL;
ire_t *ire_cache = NULL;
- boolean_t check_multirt = B_FALSE;
int value;
int match_flags;
ipaddr_t dst;
netstack_t *ns;
ip_stack_t *ipst;
+ enum ire_forward_action ret_action;
ASSERT(mp != NULL);
@@ -1407,7 +1415,7 @@ ipfil_sendpkt(const struct sockaddr *dst_addr, mblk_t *mp, uint_t ifindex,
* the nexthop and adds this incomplete ire
* to the ire cache table
*/
- ire_cache = ire_forward(dst, &check_multirt, ire, sire,
+ ire_cache = ire_forward(dst, &ret_action, ire, sire,
MBLK_GETLABEL(mp), ipst);
if (ire_cache == NULL) {
ip1dbg(("ipfil_sendpkt: failed to create the"
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index fde1ec4d19..be97d6bbbe 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -7057,14 +7057,17 @@ ip_rt_add(ipaddr_t dst_addr, ipaddr_t mask, ipaddr_t gw_addr,
*
* If the IRE type (as defined by ipif->ipif_net_type) is
* IRE_LOOPBACK, then we map the request into a
- * IRE_IF_NORESOLVER.
+ * IRE_IF_NORESOLVER. We also OR in the RTF_BLACKHOLE flag as
+ * these interface routes, by definition, can only be that.
*
* Needless to say, the real IRE_LOOPBACK is NOT created by this
* routine, but rather using ire_create() directly.
*
*/
- if (ipif->ipif_net_type == IRE_LOOPBACK)
+ if (ipif->ipif_net_type == IRE_LOOPBACK) {
ire->ire_type = IRE_IF_NORESOLVER;
+ ire->ire_flags |= RTF_BLACKHOLE;
+ }
error = ire_add(&ire, q, mp, func, B_FALSE);
if (error == 0)
diff --git a/usr/src/uts/common/inet/ip/ip_ire.c b/usr/src/uts/common/inet/ip/ip_ire.c
index ec877b6043..d8613ecd0f 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -1524,6 +1524,7 @@ ire_init(ire_t *ire, uchar_t *addr, uchar_t *mask, uchar_t *src_addr,
uint32_t ihandle, uint32_t flags, const iulp_t *ulp_info, tsol_gc_t *gc,
tsol_gcgrp_t *gcgrp, ip_stack_t *ipst)
{
+ ASSERT(type != IRE_CACHE || stq != NULL);
/*
* Reject IRE security attribute creation/initialization
* if system is not running in Trusted mode.
diff --git a/usr/src/uts/common/inet/ip_ftable.h b/usr/src/uts/common/inet/ip_ftable.h
index ed6e4c9876..e729761147 100644
--- a/usr/src/uts/common/inet/ip_ftable.h
+++ b/usr/src/uts/common/inet/ip_ftable.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -76,6 +76,14 @@ int rtfunc(struct radix_node *, void *);
typedef struct rt_entry rt_t;
typedef struct rtfuncarg rtf_t;
+/* For ire_forward() */
+enum ire_forward_action {
+ Forward_ok, /* OK to use this IRE to forward */
+ Forward_check_multirt, /* CGTP multirt check required */
+ Forward_ret_icmp_err, /* Callers to return an ICMP error */
+ Forward_blackhole /* Packet is silently discarded */
+};
+
struct ts_label_s;
extern ire_t *ire_ftable_lookup(ipaddr_t, ipaddr_t, ipaddr_t, int,
const ipif_t *, ire_t **, zoneid_t, uint32_t,
@@ -84,8 +92,8 @@ extern ire_t *ire_lookup_multi(ipaddr_t, zoneid_t, ip_stack_t *);
extern ire_t *ipif_lookup_multi_ire(ipif_t *, ipaddr_t);
extern void ire_delete_host_redirects(ipaddr_t, ip_stack_t *);
extern ire_t *ire_ihandle_lookup_onlink(ire_t *);
-extern ire_t *ire_forward(ipaddr_t, boolean_t *, ire_t *, ire_t *,
- const struct ts_label_s *, ip_stack_t *);
+extern ire_t *ire_forward(ipaddr_t, enum ire_forward_action *, ire_t *,
+ ire_t *, const struct ts_label_s *, ip_stack_t *);
extern irb_t *ire_get_bucket(ire_t *);
extern uint_t ifindex_lookup(const struct sockaddr *, zoneid_t);
extern int ipfil_sendpkt(const struct sockaddr *, mblk_t *, uint_t, zoneid_t);