diff options
| author | sowmini <none@none> | 2006-10-30 11:52:26 -0800 |
|---|---|---|
| committer | sowmini <none@none> | 2006-10-30 11:52:26 -0800 |
| commit | e5c25f801a29e79066f6782fd89cecbd8ae13ad9 (patch) | |
| tree | ff8b368a36e7f281be5db563ea8e958a40103499 /usr/src | |
| parent | 9ef7884d729f1f09cb82e5c2f57d12cb9f4c1fee (diff) | |
| download | illumos-joyent-e5c25f801a29e79066f6782fd89cecbd8ae13ad9.tar.gz | |
6484106 ICMP redirects are not sent consistently
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/uts/common/inet/ip.h | 4 | ||||
| -rw-r--r-- | usr/src/uts/common/inet/ip/ip.c | 76 |
2 files changed, 59 insertions, 21 deletions
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h index 8eba71500a..4a802f93e5 100644 --- a/usr/src/uts/common/inet/ip.h +++ b/usr/src/uts/common/inet/ip.h @@ -2126,10 +2126,6 @@ extern int ip_misc_ioctl_count; (ill)->ill_move_peer = NULL; \ peer_ill->ill_move_peer = NULL; \ } -/* The 2 ill's are same or belong to the same IPMP group */ -#define SAME_IPMP_GROUP(ill_1, ill_2) \ - (((ill_1)->ill_group != NULL) && \ - ((ill_1)->ill_group == (ill_2)->ill_group)) /* Passed down by ARP to IP during I_PLINK/I_PUNLINK */ typedef struct ipmx_s { diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c index 74f3cd8cb6..67f4947df5 100644 --- a/usr/src/uts/common/inet/ip/ip.c +++ b/usr/src/uts/common/inet/ip/ip.c @@ -13647,7 +13647,8 @@ ip_fast_forward(ire_t *ire, ipaddr_t dst, ill_t *ill, mblk_t *mp) * If either of the follwoing case is true, we take * the slowpath * o forwarding is not enabled - * o IPMP is enabled + * o incoming and outgoing interface are the same, or the same + * IPMP group * o corresponding ire is in incomplete state * o packet needs fragmentation * @@ -13656,7 +13657,9 @@ ip_fast_forward(ire_t *ire, ipaddr_t dst, ill_t *ill, mblk_t *mp) */ stq_ill = (ill_t *)ire->ire_stq->q_ptr; if (!(stq_ill->ill_flags & ILLF_ROUTER) || - !(ill->ill_flags & ILLF_ROUTER) || SAME_IPMP_GROUP(ill, stq_ill) || + !(ill->ill_flags & ILLF_ROUTER) || + (ill == stq_ill) || + (ill->ill_group != NULL && ill->ill_group == stq_ill->ill_group) || (ire->ire_nce == NULL) || (ire->ire_nce->nce_state != ND_REACHABLE) || (ntohs(ipha->ipha_length) > ire->ire_max_frag) || @@ -13732,6 +13735,7 @@ drop: * either the ire lacks the link-layer address, or the packet needs * further processing(eg. fragmentation), before transmission. */ + static void ip_rput_process_forward(queue_t *q, mblk_t *mp, ire_t *ire, ipha_t *ipha, ill_t *ill, boolean_t ll_multicast) @@ -13749,6 +13753,14 @@ ip_rput_process_forward(queue_t *q, mblk_t *mp, ire_t *ire, ipha_t *ipha, if (ll_multicast != 0) goto drop_pkt; + /* + * check if ipha_src is a broadcast address. Note that this + * check is redundant when we get here from ip_fast_forward() + * which has already done this check. However, since we can + * also get here from ip_rput_process_broadcast() or, for + * for the slow path through ip_fast_forward(), we perform + * the check again for code-reusability + */ src_ire = ire_ctable_lookup(ipha->ipha_src, 0, IRE_BROADCAST, NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE); if (src_ire != NULL || ntohl(ipha->ipha_dst) == INADDR_ANY || @@ -13758,6 +13770,7 @@ ip_rput_process_forward(queue_t *q, mblk_t *mp, ire_t *ire, ipha_t *ipha, BUMP_MIB(&ip_mib, ipForwProhibits); ip2dbg(("ip_rput_process_forward: Received packet with" " bad src/dst address on %s\n", ill->ill_name)); + goto drop_pkt; } ill_group = ill->ill_group; @@ -13807,13 +13820,14 @@ ip_rput_process_forward(queue_t *q, mblk_t *mp, ire_t *ire, ipha_t *ipha, * on the same logical subnet it is going back out on. * If so, we should be able to send it a redirect. * Avoid sending a redirect if the destination - * is directly connected (gw_addr == 0), - * or if the packet was source routed out this - * interface. + * is directly connected (i.e., ipha_dst is the same + * as ire_gateway_addr or the ire_addr of the + * nexthop IRE_CACHE ), or if the packet was source + * routed out this interface. */ - ipaddr_t src; + ipaddr_t src, nhop; mblk_t *mp1; - ire_t *src_ire = NULL; + ire_t *nhop_ire = NULL; /* * Check whether ire_rfq and q are from the same ill @@ -13822,15 +13836,44 @@ ip_rput_process_forward(queue_t *q, mblk_t *mp, ire_t *ire, ipha_t *ipha, */ if ((ire->ire_rfq == q || (ill_group != NULL && ill_group == ire_group)) && - (ire->ire_gateway_addr != 0) && !ip_source_routed(ipha)) { + nhop = (ire->ire_gateway_addr != 0 ? + ire->ire_gateway_addr : ire->ire_addr); + + if (ipha->ipha_dst == nhop) { + /* + * We avoid sending a redirect if the + * destination is directly connected + * because it is possible that multiple + * IP subnets may have been configured on + * the link, and the source may not + * be on the same subnet as ip destination, + * even though they are on the same + * physical link. + */ + goto sendit; + } + src = ipha->ipha_src; - src_ire = ire_ftable_lookup(src, 0, 0, - IRE_INTERFACE, ire->ire_ipif, NULL, ALL_ZONES, - 0, NULL, MATCH_IRE_IPIF | MATCH_IRE_TYPE); - if (src_ire != NULL) { + /* + * We look up the interface ire for the nexthop, + * to see if ipha_src is in the same subnet + * as the nexthop. + * + * Note that, if, in the future, IRE_CACHE entries + * are obsoleted, this lookup will not be needed, + * as the ire passed to this function will be the + * same as the nhop_ire computed below. + */ + nhop_ire = ire_ftable_lookup(nhop, 0, 0, + IRE_INTERFACE, NULL, NULL, ALL_ZONES, + 0, NULL, MATCH_IRE_TYPE); + + if (nhop_ire != NULL && + (src & nhop_ire->ire_mask) == + (nhop & nhop_ire->ire_mask)) { /* * The source is directly connected. * Just copy the ip header (which is @@ -13838,14 +13881,13 @@ ip_rput_process_forward(queue_t *q, mblk_t *mp, ire_t *ire, ipha_t *ipha, */ mp1 = copyb(mp); if (mp1 != NULL) { - icmp_send_redirect(WR(q), mp1, - ire->ire_gateway_addr); + icmp_send_redirect(WR(q), mp1, nhop); } - ire_refrele(src_ire); + ire_refrele(nhop_ire); } } } - +sendit: dev_q = ire->ire_stq->q_next; if ((dev_q->q_next || dev_q->q_first) && !canput(dev_q)) { BUMP_MIB(&ip_mib, ipInDiscards); @@ -13857,7 +13899,7 @@ ip_rput_process_forward(queue_t *q, mblk_t *mp, ire_t *ire, ipha_t *ipha, return; drop_pkt: - ip2dbg(("ip_rput_forward: drop pkt\n")); + ip2dbg(("ip_rput_process_forward: drop pkt\n")); freemsg(mp); } |
