ipv4: Pass flow keys down into datagram packet building engine.
This way ip_output.c no longer needs rt->rt_{src,dst}. We already have these keys sitting, ready and waiting, on the stack or in a socket structure. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -290,6 +290,7 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
|
||||
}
|
||||
|
||||
static void icmp_push_reply(struct icmp_bxm *icmp_param,
|
||||
struct flowi4 *fl4,
|
||||
struct ipcm_cookie *ipc, struct rtable **rt)
|
||||
{
|
||||
struct sock *sk;
|
||||
@@ -315,7 +316,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
|
||||
icmp_param->head_len, csum);
|
||||
icmph->checksum = csum_fold(csum);
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
ip_push_pending_frames(sk);
|
||||
ip_push_pending_frames(sk, fl4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,6 +329,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
|
||||
struct ipcm_cookie ipc;
|
||||
struct rtable *rt = skb_rtable(skb);
|
||||
struct net *net = dev_net(rt->dst.dev);
|
||||
struct flowi4 fl4;
|
||||
struct sock *sk;
|
||||
struct inet_sock *inet;
|
||||
__be32 daddr;
|
||||
@@ -351,57 +353,52 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
|
||||
if (ipc.opt->opt.srr)
|
||||
daddr = icmp_param->replyopts.opt.opt.faddr;
|
||||
}
|
||||
{
|
||||
struct flowi4 fl4 = {
|
||||
.daddr = daddr,
|
||||
.saddr = rt->rt_spec_dst,
|
||||
.flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
|
||||
.flowi4_proto = IPPROTO_ICMP,
|
||||
};
|
||||
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
|
||||
rt = ip_route_output_key(net, &fl4);
|
||||
if (IS_ERR(rt))
|
||||
goto out_unlock;
|
||||
}
|
||||
memset(&fl4, 0, sizeof(fl4));
|
||||
fl4.daddr = daddr;
|
||||
fl4.saddr = rt->rt_spec_dst;
|
||||
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
|
||||
fl4.flowi4_proto = IPPROTO_ICMP;
|
||||
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
|
||||
rt = ip_route_output_key(net, &fl4);
|
||||
if (IS_ERR(rt))
|
||||
goto out_unlock;
|
||||
if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type,
|
||||
icmp_param->data.icmph.code))
|
||||
icmp_push_reply(icmp_param, &ipc, &rt);
|
||||
icmp_push_reply(icmp_param, &fl4, &ipc, &rt);
|
||||
ip_rt_put(rt);
|
||||
out_unlock:
|
||||
icmp_xmit_unlock(sk);
|
||||
}
|
||||
|
||||
static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
|
||||
static struct rtable *icmp_route_lookup(struct net *net,
|
||||
struct flowi4 *fl4,
|
||||
struct sk_buff *skb_in,
|
||||
const struct iphdr *iph,
|
||||
__be32 saddr, u8 tos,
|
||||
int type, int code,
|
||||
struct icmp_bxm *param)
|
||||
{
|
||||
struct flowi4 fl4 = {
|
||||
.daddr = (param->replyopts.opt.opt.srr ?
|
||||
param->replyopts.opt.opt.faddr : iph->saddr),
|
||||
.saddr = saddr,
|
||||
.flowi4_tos = RT_TOS(tos),
|
||||
.flowi4_proto = IPPROTO_ICMP,
|
||||
.fl4_icmp_type = type,
|
||||
.fl4_icmp_code = code,
|
||||
};
|
||||
struct rtable *rt, *rt2;
|
||||
int err;
|
||||
|
||||
security_skb_classify_flow(skb_in, flowi4_to_flowi(&fl4));
|
||||
rt = __ip_route_output_key(net, &fl4);
|
||||
memset(fl4, 0, sizeof(*fl4));
|
||||
fl4->daddr = (param->replyopts.opt.opt.srr ?
|
||||
param->replyopts.opt.opt.faddr : iph->saddr);
|
||||
fl4->saddr = saddr;
|
||||
fl4->flowi4_tos = RT_TOS(tos);
|
||||
fl4->flowi4_proto = IPPROTO_ICMP;
|
||||
fl4->fl4_icmp_type = type;
|
||||
fl4->fl4_icmp_code = code;
|
||||
security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
|
||||
rt = __ip_route_output_key(net, fl4);
|
||||
if (IS_ERR(rt))
|
||||
return rt;
|
||||
|
||||
/* No need to clone since we're just using its address. */
|
||||
rt2 = rt;
|
||||
|
||||
if (!fl4.saddr)
|
||||
fl4.saddr = rt->rt_src;
|
||||
|
||||
rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
|
||||
flowi4_to_flowi(&fl4), NULL, 0);
|
||||
flowi4_to_flowi(fl4), NULL, 0);
|
||||
if (!IS_ERR(rt)) {
|
||||
if (rt != rt2)
|
||||
return rt;
|
||||
@@ -410,19 +407,19 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
|
||||
} else
|
||||
return rt;
|
||||
|
||||
err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4), AF_INET);
|
||||
err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET);
|
||||
if (err)
|
||||
goto relookup_failed;
|
||||
|
||||
if (inet_addr_type(net, fl4.saddr) == RTN_LOCAL) {
|
||||
rt2 = __ip_route_output_key(net, &fl4);
|
||||
if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) {
|
||||
rt2 = __ip_route_output_key(net, fl4);
|
||||
if (IS_ERR(rt2))
|
||||
err = PTR_ERR(rt2);
|
||||
} else {
|
||||
struct flowi4 fl4_2 = {};
|
||||
unsigned long orefdst;
|
||||
|
||||
fl4_2.daddr = fl4.saddr;
|
||||
fl4_2.daddr = fl4->saddr;
|
||||
rt2 = ip_route_output_key(net, &fl4_2);
|
||||
if (IS_ERR(rt2)) {
|
||||
err = PTR_ERR(rt2);
|
||||
@@ -430,7 +427,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
|
||||
}
|
||||
/* Ugh! */
|
||||
orefdst = skb_in->_skb_refdst; /* save old refdst */
|
||||
err = ip_route_input(skb_in, fl4.daddr, fl4.saddr,
|
||||
err = ip_route_input(skb_in, fl4->daddr, fl4->saddr,
|
||||
RT_TOS(tos), rt2->dst.dev);
|
||||
|
||||
dst_release(&rt2->dst);
|
||||
@@ -442,7 +439,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
|
||||
goto relookup_failed;
|
||||
|
||||
rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
|
||||
flowi4_to_flowi(&fl4), NULL,
|
||||
flowi4_to_flowi(fl4), NULL,
|
||||
XFRM_LOOKUP_ICMP);
|
||||
if (!IS_ERR(rt2)) {
|
||||
dst_release(&rt->dst);
|
||||
@@ -481,6 +478,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
|
||||
struct icmp_bxm icmp_param;
|
||||
struct rtable *rt = skb_rtable(skb_in);
|
||||
struct ipcm_cookie ipc;
|
||||
struct flowi4 fl4;
|
||||
__be32 saddr;
|
||||
u8 tos;
|
||||
struct net *net;
|
||||
@@ -599,7 +597,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
|
||||
ipc.opt = &icmp_param.replyopts.opt;
|
||||
ipc.tx_flags = 0;
|
||||
|
||||
rt = icmp_route_lookup(net, skb_in, iph, saddr, tos,
|
||||
rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
|
||||
type, code, &icmp_param);
|
||||
if (IS_ERR(rt))
|
||||
goto out_unlock;
|
||||
@@ -620,7 +618,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
|
||||
icmp_param.data_len = room;
|
||||
icmp_param.head_len = sizeof(struct icmphdr);
|
||||
|
||||
icmp_push_reply(&icmp_param, &ipc, &rt);
|
||||
icmp_push_reply(&icmp_param, &fl4, &ipc, &rt);
|
||||
ende:
|
||||
ip_rt_put(rt);
|
||||
out_unlock:
|
||||
|
Reference in New Issue
Block a user