Skip to content

Commit

Permalink
ipv4: Rearrange arguments to ip_rt_redirect()
Browse files Browse the repository at this point in the history
Pass in the SKB rather than just the IP addresses, so that policy
and other aspects can reside in ip_rt_redirect() rather then
icmp_redirect().

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 12, 2012
1 parent d0da720 commit 9420612
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 36 deletions.
3 changes: 1 addition & 2 deletions include/net/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ extern struct ip_rt_acct __percpu *ip_rt_acct;

struct in_device;
extern int ip_rt_init(void);
extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
__be32 src, struct net_device *dev);
extern void ip_rt_redirect(struct sk_buff *skb, __be32 new_gw);
extern void rt_cache_flush(struct net *net, int how);
extern void rt_cache_flush_batch(struct net *net);
extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
Expand Down
36 changes: 6 additions & 30 deletions net/ipv4/icmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,40 +755,16 @@ static void icmp_unreach(struct sk_buff *skb)

static void icmp_redirect(struct sk_buff *skb)
{
const struct iphdr *iph;

if (skb->len < sizeof(struct iphdr))
goto out_err;
if (skb->len < sizeof(struct iphdr)) {
ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
return;
}

/*
* Get the copied header of the packet that caused the redirect
*/
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto out;

iph = (const struct iphdr *)skb->data;

switch (icmp_hdr(skb)->code & 7) {
case ICMP_REDIR_NET:
case ICMP_REDIR_NETTOS:
/*
* As per RFC recommendations now handle it as a host redirect.
*/
case ICMP_REDIR_HOST:
case ICMP_REDIR_HOSTTOS:
ip_rt_redirect(ip_hdr(skb)->saddr, iph->daddr,
icmp_hdr(skb)->un.gateway,
iph->saddr, skb->dev);
break;
}
return;

ip_rt_redirect(skb, icmp_hdr(skb)->un.gateway);
icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway);

out:
return;
out_err:
ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
goto out;
}

/*
Expand Down
23 changes: 19 additions & 4 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -1292,18 +1292,33 @@ static void ip_do_redirect(struct rtable *rt, __be32 old_gw, __be32 new_gw)
}

/* called in rcu_read_lock() section */
void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
__be32 saddr, struct net_device *dev)
void ip_rt_redirect(struct sk_buff *skb, __be32 new_gw)
{
int s, i;
const struct iphdr *iph = (const struct iphdr *) skb->data;
__be32 old_gw = ip_hdr(skb)->saddr;
__be32 daddr = iph->daddr;
__be32 saddr = iph->saddr;
struct net_device *dev = skb->dev;
struct in_device *in_dev = __in_dev_get_rcu(dev);
__be32 skeys[2] = { saddr, 0 };
int ikeys[2] = { dev->ifindex, 0 };
__be32 skeys[2] = { saddr, 0 };
struct net *net;
int s, i;

if (!in_dev)
return;

switch (icmp_hdr(skb)->code & 7) {
case ICMP_REDIR_NET:
case ICMP_REDIR_NETTOS:
case ICMP_REDIR_HOST:
case ICMP_REDIR_HOSTTOS:
break;

default:
return;
}

net = dev_net(dev);
if (new_gw == old_gw || !IN_DEV_RX_REDIRECTS(in_dev) ||
ipv4_is_multicast(new_gw) || ipv4_is_lbcast(new_gw) ||
Expand Down

0 comments on commit 9420612

Please sign in to comment.