From mboxrd@z Thu Jan 1 00:00:00 1970 From: Patrick McHardy Subject: Re: [IPV4] LVS: Allow to send ICMP unreachable responses when real-servers are removed Date: Mon, 14 May 2007 19:41:48 +0200 Message-ID: <46489F5C.4000801@trash.net> References: <200704271705.l3RH5Brw026873@hera.kernel.org> <4648382E.8030009@trash.net> <20070514.033504.48528120.davem@davemloft.net> <4648714E.9050200@tis.icnet.pl> <464872E2.2030502@trash.net> <464884EE.3030606@tis.icnet.pl> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------030806000307070800080209" Cc: David Miller , horms@verge.net.au, netdev@vger.kernel.org To: Janusz Krzysztofik Return-path: Received: from stinky.trash.net ([213.144.137.162]:45045 "EHLO stinky.trash.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758747AbXENRl5 (ORCPT ); Mon, 14 May 2007 13:41:57 -0400 In-Reply-To: <464884EE.3030606@tis.icnet.pl> Sender: netdev-owner@vger.kernel.org List-Id: netdev.vger.kernel.org This is a multi-part message in MIME format. --------------030806000307070800080209 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit Janusz Krzysztofik wrote: > Patrick McHardy wrote: > >> Janusz Krzysztofik wrote: >> >>> ... ICMP port unreachable messages are not generated inside >>> IPVS code, they are just sent, with help of the patch in question, from >>> udp_input() or netfilter REJECT. >> >> >> Both use icmp_send(), which should always pick a local source, so I >> don't understand why this change was needed. Could you describe >> the specific case when the packet generated by icmp_send() does >> not have a local source? > > > Yes, it happens when a packet with a non-local destination IP address is > routed localy in order to reach ip_vs_in(), but is not catched there > because of no associated connection and no matching service, so it is > passed through and ends up in udp_input(). Then, inside udp_input(), > icmp_send() is invoked with original non-local destination IP as source > address. So you're adding a local route for non-local destination and the address selection in icmp_send() uses the original destination address as source because the route has RTCF_LOCAL set, resulting in an error in ip_route_output_slow(). If thats correct than this patch should also work, it changes icmp_send() to check if the original destination address is non-local when deciding whether to pick a new address (and reverts the routing changes). Signed-off-by: Patrick McHardy --------------030806000307070800080209 Content-Type: text/plain; name="x" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="x" diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index d38cbba..b964863 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -513,7 +513,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) */ saddr = iph->daddr; - if (!(rt->rt_flags & RTCF_LOCAL)) { + if (inet_addr_type(saddr) != RTN_LOCAL) { if (sysctl_icmp_errors_use_inbound_ifaddr) saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK); else diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cb76e3c..df9fe4f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2396,7 +2396,7 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp) /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ dev_out = ip_dev_find(oldflp->fl4_src); - if ((dev_out == NULL) && !(sysctl_ip_nonlocal_bind)) + if (dev_out == NULL) goto out; /* I removed check for oif == dev_out->oif here. @@ -2407,7 +2407,7 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp) of another iface. --ANK */ - if (dev_out && oldflp->oif == 0 + if (oldflp->oif == 0 && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF))) { /* Special hack: user can direct multicasts and limited broadcast via necessary interface --------------030806000307070800080209--