* [PATCH] ipv4: Make icmp route lookup code a bit clearer.
@ 2011-03-01 23:48 David Miller
2011-03-01 23:50 ` David Miller
0 siblings, 1 reply; 4+ messages in thread
From: David Miller @ 2011-03-01 23:48 UTC (permalink / raw)
To: herbert; +Cc: netdev
The route lookup code in icmp_send() is slightly tricky as a result of
having to handle all of the requirements of RFC 4301 host relookups.
Pull the route resolution into a seperate function, so that the error
handling and route reference counting is hopefully easier to see and
contained wholly within this new routine.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/ipv4/icmp.c | 175 ++++++++++++++++++++++++++++++-------------------------
1 files changed, 96 insertions(+), 79 deletions(-)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index ad2bcf1..527ffd1 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -369,6 +369,98 @@ out_unlock:
icmp_xmit_unlock(sk);
}
+struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
+ struct iphdr *iph,
+ __be32 saddr, u8 tos,
+ int type, int code,
+ struct icmp_bxm *param)
+{
+ struct flowi fl = {
+ .fl4_dst = (param->replyopts.srr ?
+ param->replyopts.faddr : iph->saddr),
+ .fl4_src = saddr,
+ .fl4_tos = RT_TOS(tos),
+ .proto = IPPROTO_ICMP,
+ .fl_icmp_type = type,
+ .fl_icmp_code = code,
+ };
+ struct rtable *rt, *rt2;
+ int err;
+
+ security_skb_classify_flow(skb_in, &fl);
+ err = __ip_route_output_key(net, &rt, &fl);
+ if (err)
+ return ERR_PTR(err);
+
+ /* No need to clone since we're just using its address. */
+ rt2 = rt;
+
+ if (!fl.fl4_src)
+ fl.fl4_src = rt->rt_src;
+
+ err = xfrm_lookup(net, (struct dst_entry **)&rt, &fl, NULL, 0);
+ switch (err) {
+ case 0:
+ if (rt != rt2)
+ return rt;
+ break;
+ case -EPERM:
+ rt = NULL;
+ break;
+ default:
+ return ERR_PTR(err);
+ }
+
+ err = xfrm_decode_session_reverse(skb_in, &fl, AF_INET);
+ if (err)
+ goto relookup_failed;
+
+ if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) {
+ err = __ip_route_output_key(net, &rt2, &fl);
+ } else {
+ struct flowi fl2 = {};
+ unsigned long orefdst;
+
+ fl2.fl4_dst = fl.fl4_src;
+ err = ip_route_output_key(net, &rt2, &fl2);
+ if (err)
+ goto relookup_failed;
+ /* Ugh! */
+ orefdst = skb_in->_skb_refdst; /* save old refdst */
+ err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src,
+ RT_TOS(tos), rt2->dst.dev);
+
+ dst_release(&rt2->dst);
+ rt2 = skb_rtable(skb_in);
+ skb_in->_skb_refdst = orefdst; /* restore old refdst */
+ }
+
+ if (err)
+ goto relookup_failed;
+
+ err = xfrm_lookup(net, (struct dst_entry **)&rt2, &fl, NULL,
+ XFRM_LOOKUP_ICMP);
+ switch (err) {
+ case 0:
+ dst_release(&rt->dst);
+ rt = rt2;
+ break;
+ case -EPERM:
+ return ERR_PTR(err);
+ default:
+ if (!rt)
+ return ERR_PTR(err);
+ break;
+ }
+
+
+ return rt;
+
+relookup_failed:
+ if (rt)
+ return rt;
+ return ERR_PTR(err);
+}
/*
* Send an ICMP message in response to a situation
@@ -506,86 +598,11 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
ipc.opt = &icmp_param.replyopts;
ipc.tx_flags = 0;
- {
- struct flowi fl = {
- .fl4_dst = icmp_param.replyopts.srr ?
- icmp_param.replyopts.faddr : iph->saddr,
- .fl4_src = saddr,
- .fl4_tos = RT_TOS(tos),
- .proto = IPPROTO_ICMP,
- .fl_icmp_type = type,
- .fl_icmp_code = code,
- };
- int err;
- struct rtable *rt2;
-
- security_skb_classify_flow(skb_in, &fl);
- if (__ip_route_output_key(net, &rt, &fl))
- goto out_unlock;
-
- /* No need to clone since we're just using its address. */
- rt2 = rt;
-
- if (!fl.nl_u.ip4_u.saddr)
- fl.nl_u.ip4_u.saddr = rt->rt_src;
-
- err = xfrm_lookup(net, (struct dst_entry **)&rt, &fl, NULL, 0);
- switch (err) {
- case 0:
- if (rt != rt2)
- goto route_done;
- break;
- case -EPERM:
- rt = NULL;
- break;
- default:
- goto out_unlock;
- }
-
- if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
- goto relookup_failed;
-
- if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL)
- err = __ip_route_output_key(net, &rt2, &fl);
- else {
- struct flowi fl2 = {};
- unsigned long orefdst;
-
- fl2.fl4_dst = fl.fl4_src;
- if (ip_route_output_key(net, &rt2, &fl2))
- goto relookup_failed;
-
- /* Ugh! */
- orefdst = skb_in->_skb_refdst; /* save old refdst */
- err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src,
- RT_TOS(tos), rt2->dst.dev);
-
- dst_release(&rt2->dst);
- rt2 = skb_rtable(skb_in);
- skb_in->_skb_refdst = orefdst; /* restore old refdst */
- }
-
- if (err)
- goto relookup_failed;
-
- err = xfrm_lookup(net, (struct dst_entry **)&rt2, &fl, NULL,
- XFRM_LOOKUP_ICMP);
- switch (err) {
- case 0:
- dst_release(&rt->dst);
- rt = rt2;
- break;
- case -EPERM:
- goto ende;
- default:
-relookup_failed:
- if (!rt)
- goto out_unlock;
- break;
- }
- }
+ rt = icmp_route_lookup(net, skb_in, iph, saddr, tos,
+ type, code, &icmp_param);
+ if (IS_ERR(rt))
+ goto out_unlock;
-route_done:
if (!icmpv4_xrlim_allow(net, rt, type, code))
goto ende;
--
1.7.4.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] ipv4: Make icmp route lookup code a bit clearer.
2011-03-01 23:48 [PATCH] ipv4: Make icmp route lookup code a bit clearer David Miller
@ 2011-03-01 23:50 ` David Miller
2011-03-02 0:43 ` Herbert Xu
0 siblings, 1 reply; 4+ messages in thread
From: David Miller @ 2011-03-01 23:50 UTC (permalink / raw)
To: herbert; +Cc: netdev
From: David Miller <davem@davemloft.net>
Date: Tue, 01 Mar 2011 15:48:16 -0800 (PST)
>
> The route lookup code in icmp_send() is slightly tricky as a result of
> having to handle all of the requirements of RFC 4301 host relookups.
>
> Pull the route resolution into a seperate function, so that the error
> handling and route reference counting is hopefully easier to see and
> contained wholly within this new routine.
>
> Signed-off-by: David S. Miller <davem@davemloft.net>
...
> +struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
Of course this should be static :-)
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ipv4: Make icmp route lookup code a bit clearer.
2011-03-01 23:50 ` David Miller
@ 2011-03-02 0:43 ` Herbert Xu
2011-03-02 4:53 ` David Miller
0 siblings, 1 reply; 4+ messages in thread
From: Herbert Xu @ 2011-03-02 0:43 UTC (permalink / raw)
To: David Miller; +Cc: netdev
On Tue, Mar 01, 2011 at 03:50:15PM -0800, David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Tue, 01 Mar 2011 15:48:16 -0800 (PST)
>
> >
> > The route lookup code in icmp_send() is slightly tricky as a result of
> > having to handle all of the requirements of RFC 4301 host relookups.
> >
> > Pull the route resolution into a seperate function, so that the error
> > handling and route reference counting is hopefully easier to see and
> > contained wholly within this new routine.
> >
> > Signed-off-by: David S. Miller <davem@davemloft.net>
> ...
> > +struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
>
> Of course this should be static :-)
Looks good to me.
Thanks!
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ipv4: Make icmp route lookup code a bit clearer.
2011-03-02 0:43 ` Herbert Xu
@ 2011-03-02 4:53 ` David Miller
0 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2011-03-02 4:53 UTC (permalink / raw)
To: herbert; +Cc: netdev
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 2 Mar 2011 08:43:25 +0800
> Looks good to me.
Thanks for reviewing.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-03-02 4:52 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-01 23:48 [PATCH] ipv4: Make icmp route lookup code a bit clearer David Miller
2011-03-01 23:50 ` David Miller
2011-03-02 0:43 ` Herbert Xu
2011-03-02 4:53 ` David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).