summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Kosyh <p.kosyh@gmail.com>2019-07-19 04:11:47 -0400
committerDavid S. Miller <davem@davemloft.net>2019-07-21 16:32:51 -0400
commit107e47cc80ec37cb332bd41b22b1c7779e22e018 (patch)
treead7e68bbfcbb8e66acce7611af31597eadfd9ca9
parent903e9d1bffb557220af276eda97b9d6b103ec9e0 (diff)
vrf: make sure skb->data contains ip header to make routing
vrf_process_v4_outbound() and vrf_process_v6_outbound() do routing using ip/ipv6 addresses, but don't make sure the header is available in skb->data[] (skb_headlen() is less then header size). Case: 1) igb driver from intel. 2) Packet size is greater then 255. 3) MPLS forwards to VRF device. So, patch adds pskb_may_pull() calls in vrf_process_v4/v6_outbound() functions. Signed-off-by: Peter Kosyh <p.kosyh@gmail.com> Reviewed-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/vrf.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 54edf8956a25..6e84328bdd40 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -165,23 +165,29 @@ static int vrf_ip6_local_out(struct net *net, struct sock *sk,
165static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb, 165static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
166 struct net_device *dev) 166 struct net_device *dev)
167{ 167{
168 const struct ipv6hdr *iph = ipv6_hdr(skb); 168 const struct ipv6hdr *iph;
169 struct net *net = dev_net(skb->dev); 169 struct net *net = dev_net(skb->dev);
170 struct flowi6 fl6 = { 170 struct flowi6 fl6;
171 /* needed to match OIF rule */
172 .flowi6_oif = dev->ifindex,
173 .flowi6_iif = LOOPBACK_IFINDEX,
174 .daddr = iph->daddr,
175 .saddr = iph->saddr,
176 .flowlabel = ip6_flowinfo(iph),
177 .flowi6_mark = skb->mark,
178 .flowi6_proto = iph->nexthdr,
179 .flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF,
180 };
181 int ret = NET_XMIT_DROP; 171 int ret = NET_XMIT_DROP;
182 struct dst_entry *dst; 172 struct dst_entry *dst;
183 struct dst_entry *dst_null = &net->ipv6.ip6_null_entry->dst; 173 struct dst_entry *dst_null = &net->ipv6.ip6_null_entry->dst;
184 174
175 if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct ipv6hdr)))
176 goto err;
177
178 iph = ipv6_hdr(skb);
179
180 memset(&fl6, 0, sizeof(fl6));
181 /* needed to match OIF rule */
182 fl6.flowi6_oif = dev->ifindex;
183 fl6.flowi6_iif = LOOPBACK_IFINDEX;
184 fl6.daddr = iph->daddr;
185 fl6.saddr = iph->saddr;
186 fl6.flowlabel = ip6_flowinfo(iph);
187 fl6.flowi6_mark = skb->mark;
188 fl6.flowi6_proto = iph->nexthdr;
189 fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
190
185 dst = ip6_route_output(net, NULL, &fl6); 191 dst = ip6_route_output(net, NULL, &fl6);
186 if (dst == dst_null) 192 if (dst == dst_null)
187 goto err; 193 goto err;
@@ -237,21 +243,27 @@ static int vrf_ip_local_out(struct net *net, struct sock *sk,
237static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, 243static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
238 struct net_device *vrf_dev) 244 struct net_device *vrf_dev)
239{ 245{
240 struct iphdr *ip4h = ip_hdr(skb); 246 struct iphdr *ip4h;
241 int ret = NET_XMIT_DROP; 247 int ret = NET_XMIT_DROP;
242 struct flowi4 fl4 = { 248 struct flowi4 fl4;
243 /* needed to match OIF rule */
244 .flowi4_oif = vrf_dev->ifindex,
245 .flowi4_iif = LOOPBACK_IFINDEX,
246 .flowi4_tos = RT_TOS(ip4h->tos),
247 .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF,
248 .flowi4_proto = ip4h->protocol,
249 .daddr = ip4h->daddr,
250 .saddr = ip4h->saddr,
251 };
252 struct net *net = dev_net(vrf_dev); 249 struct net *net = dev_net(vrf_dev);
253 struct rtable *rt; 250 struct rtable *rt;
254 251
252 if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct iphdr)))
253 goto err;
254
255 ip4h = ip_hdr(skb);
256
257 memset(&fl4, 0, sizeof(fl4));
258 /* needed to match OIF rule */
259 fl4.flowi4_oif = vrf_dev->ifindex;
260 fl4.flowi4_iif = LOOPBACK_IFINDEX;
261 fl4.flowi4_tos = RT_TOS(ip4h->tos);
262 fl4.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF;
263 fl4.flowi4_proto = ip4h->protocol;
264 fl4.daddr = ip4h->daddr;
265 fl4.saddr = ip4h->saddr;
266
255 rt = ip_route_output_flow(net, &fl4, NULL); 267 rt = ip_route_output_flow(net, &fl4, NULL);
256 if (IS_ERR(rt)) 268 if (IS_ERR(rt))
257 goto err; 269 goto err;